@go-to-k/cdkd 0.294.8 → 0.294.9
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-CsajFK4_.js → asg-provider-3uLGAhIx.js} +2 -2
- package/dist/{asg-provider-CsajFK4_.js.map → asg-provider-3uLGAhIx.js.map} +1 -1
- package/dist/cli.js +35 -4
- package/dist/cli.js.map +1 -1
- package/dist/{deploy-engine-C5kAhscq.js → deploy-engine-BTOCDCWf.js} +654 -508
- package/dist/deploy-engine-BTOCDCWf.js.map +1 -0
- package/dist/iam-policy-targets-CMSQGQnm.js.map +1 -1
- package/dist/{iam-role-provider-CPn7nqoS.js → iam-role-provider-CBT2LPe1.js} +2 -2
- package/dist/{iam-role-provider-CPn7nqoS.js.map → iam-role-provider-CBT2LPe1.js.map} +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/{neptune-provider-DlFQdgwe.js → neptune-provider-BQ-CGoYJ.js} +2 -2
- package/dist/{neptune-provider-DlFQdgwe.js.map → neptune-provider-BQ-CGoYJ.js.map} +1 -1
- package/dist/{program-CVOLJJ2z.js → program-DMJnrQOG.js} +254 -16
- package/dist/program-DMJnrQOG.js.map +1 -0
- package/dist/{provider-classes-DlVxBF89.js → provider-classes-DCbt28RB.js} +114 -14
- package/dist/provider-classes-DCbt28RB.js.map +1 -0
- package/dist/{rds-provider-a-vZsR9L.js → rds-provider-J6zl27x3.js} +2 -2
- package/dist/{rds-provider-a-vZsR9L.js.map → rds-provider-J6zl27x3.js.map} +1 -1
- package/dist/{version-DGxZ-zFN.js → version-QrNvZCe0.js} +2 -2
- package/dist/{version-DGxZ-zFN.js.map → version-QrNvZCe0.js.map} +1 -1
- package/package.json +2 -2
- package/dist/deploy-engine-C5kAhscq.js.map +0 -1
- package/dist/program-CVOLJJ2z.js.map +0 -1
- package/dist/provider-classes-DlVxBF89.js.map +0 -1
|
@@ -2,7 +2,7 @@ import { r as getAwsClients, s as __exportAll } from "./aws-clients-CnmtbrxD.js"
|
|
|
2
2
|
import { A as displaySafe, E as UNRENDERABLE, F as safeMsg, L as truncateCodePoints, M as isPasteableIdent, O as displayAwsMessage, P as plainIdentOr, S as withoutGeneratedFallbackName, T as STACK_REF_MAX_CODE_POINTS, _ as getCurrentSkipPrefix, b as withSkipPrefix, c as getLiveRenderer, f as applyDefaultNameForFallback, g as generateResourceNameWithFallback, h as generateResourceName, j as displayStackName, k as displayIdent, m as explicitNamePropertyFor, n as getLogger, r as isStdoutReservedForPayload, s as installLogLineMaskerSource, v as getCurrentStackName, w as SECRET_REF_MAX_CODE_POINTS, x as withStackName, y as looksLikeCdkdGeneratedName } from "./logger-B46YMG0h.js";
|
|
3
3
|
import { $t as StateError, A as isTerminalDeleteFailure, An as isAmbiguousCcHandlerErrorCode, At as clientDefaultsFor, Bn as isMarkedNonRetryable, Bt as IntrinsicResolutionRefusalError, C as refusalTypeShown, Cn as isNameCollisionErrorFrom, D as ProtectionFlipRegistry, Dt as withPasteableAwsProfile, En as isReplayedNameCollisionFrom, Fn as retryClassificationText, Gt as MalformedProducerRecordRefusalError, H as pasteableAwsCommand, Hn as markNonRetryable, In as describeAwsFailure, It as CrossAccountSecretRefusalError, J as isInterruptedWaitError, Jt as ProvisioningError, Lt as DependencyError, M as observeThenDisableProtection, Mn as isIamPropagationError, Mt as AccountIdUnavailableError, N as protectionFlipKey, Nn as isRetryableTransientError, Nt as AssetError, O as compensateProtectionFlip, On as markReplayMayCollide, Ot as ambientClientDefaults, Pn as isTransientServerError, Pt as CdkdError, Q as canonicalizeRoute53QueryName, R as DELETION_PROTECTION_DOC_POINTER, Rn as safeStringify$1, S as quotedRemedyLogicalId, Sn as hasReplayMayCollide, St as injectiveKey, T as resolveExplicitPhysicalId, Tn as isRecreateRetryableError, Tt as producerRecordKey, U as protectedReplacementAdvice, Un as markRedactedCause, Ut as LockError, Vn as isThrottlingError, Wn as wrapMaskedAwsError, Wt as MacroExpansionError, X as ElapsedBudgetRegistry, Xt as ResourceUpdateNotSupportedError, Y as startInterruptWatch, Yt as ResourceTimeoutError, Z as monotonicNowMs, _n as shellQuote, _t as formatLockOperation, at as segmentAfterAnchor, b as isQuotableImportValue, bt as CUSTOM_RESOURCE_RESPONSE_PREFIX, cn as UNSHOWABLE_VALUE, ct as isSecretDerivedValue, d as prepareRemovalForUpdate, dn as isInertUnquoted, dt as withDerivedNameMasks, en as SynthesisError, et as compositeIdSeparatorRefusal, f as removalWarning, fn as pasteableCommand, ft as UNREPRODUCIBLE_LOCK_CLAUSE, g as assertRegionMatch, gn as shellBoundedDisplay, gt as formatLockExpiry, h as RESOURCE_NOT_FOUND, hn as quotedOrDescribed, i as holdsSecretDerivedEntry, it as resourceTypeShown, jn as isAmbiguousOutcomeError, jt as credentialFingerprint, k as deleteWithProtectionCompensation, kn as formatRetryClassificationSignals, kt as ambientCredentialConfig, l as withUnchangedSecretPrincipalLists, ln as commandHole, lt as maskDeep, m as withoutInjectedRemovals, mn as plainOrDescribed, nt as logicalIdShown, on as SHELL_ACTIVE, ot as createMaskedLogSinks, pn as physicalIdShownBesideCommand, pt as buildForceUnlockCommand, rn as normalizeAwsError, sn as SHELL_ACTIVE_WHY, st as createMaskedRetryLogger, ut as maskerOrIdentity, vn as withheldTargetClause, vt as formatLockOwner, wn as isNameCooldownError, x as normalizeAwsTagsToCfn, xn as isUpdateUnsupportedError, xt as DEFAULT_STATE_PREFIX, yt as sanitizeRecoveryValue, zt as DynamicReferenceRegionAmbiguousError } from "./iam-policy-targets-CMSQGQnm.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-D0q0z4dG.js";
|
|
5
|
-
import { t as getCdkdVersion } from "./version-
|
|
5
|
+
import { t as getCdkdVersion } from "./version-QrNvZCe0.js";
|
|
6
6
|
import { createHash, randomUUID } from "node:crypto";
|
|
7
7
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
8
8
|
import { CreateBucketCommand, DeleteObjectCommand, DeleteObjectsCommand, GetBucketLocationCommand, GetBucketReplicationCommand, GetObjectCommand, HeadBucketCommand, HeadObjectCommand, ListObjectVersionsCommand, ListObjectsV2Command, NoSuchKey, PutBucketEncryptionCommand, PutBucketPolicyCommand, PutObjectCommand, PutPublicAccessBlockCommand, S3Client, S3ServiceException } from "@aws-sdk/client-s3";
|
|
@@ -4645,6 +4645,12 @@ function importableOutputKeys(state) {
|
|
|
4645
4645
|
if (state.exportNames === void 0) return Object.keys(outputs);
|
|
4646
4646
|
return state.exportNames.filter((name) => typeof name === "string" && Object.hasOwn(outputs, name));
|
|
4647
4647
|
}
|
|
4648
|
+
function acceptedCreateOnlyDropsOf(record) {
|
|
4649
|
+
if (record === null || typeof record !== "object") return /* @__PURE__ */ new Set();
|
|
4650
|
+
const value = record.acceptedCreateOnlyDrops;
|
|
4651
|
+
if (!Array.isArray(value)) return /* @__PURE__ */ new Set();
|
|
4652
|
+
return new Set(value.filter((entry) => typeof entry === "string"));
|
|
4653
|
+
}
|
|
4648
4654
|
function hasReadableExportSet(state) {
|
|
4649
4655
|
if (!isReadableBag(state.outputs)) return false;
|
|
4650
4656
|
if (state.exportNames === void 0) return true;
|
|
@@ -6077,18 +6083,24 @@ function isPlainObject$3(value) {
|
|
|
6077
6083
|
|
|
6078
6084
|
//#endregion
|
|
6079
6085
|
//#region src/deployment/secret-redaction/mask-only.ts
|
|
6080
|
-
const recordedSecretExpressions
|
|
6081
|
-
|
|
6082
|
-
|
|
6086
|
+
const recordedSecretExpressions = /* @__PURE__ */ new Set();
|
|
6087
|
+
const secretVerdictScopes = /* @__PURE__ */ new Map();
|
|
6088
|
+
function pinScopedSecretVerdict(scope, expression, secret) {
|
|
6089
|
+
const scopes = secretVerdictScopes.get(expression);
|
|
6090
|
+
if (secret) {
|
|
6091
|
+
if (scopes) scopes.add(scope);
|
|
6092
|
+
else secretVerdictScopes.set(expression, /* @__PURE__ */ new Set([scope]));
|
|
6093
|
+
recordedSecretExpressions.add(expression);
|
|
6094
|
+
return;
|
|
6095
|
+
}
|
|
6096
|
+
if (scopes?.delete(scope) && scopes.size === 0) secretVerdictScopes.delete(expression);
|
|
6097
|
+
recordedSecretExpressions.delete(expression);
|
|
6083
6098
|
}
|
|
6084
|
-
function
|
|
6085
|
-
|
|
6099
|
+
function isScopedSecretVerdict(scope, expression) {
|
|
6100
|
+
return secretVerdictScopes.get(expression)?.has(scope) === true;
|
|
6086
6101
|
}
|
|
6087
6102
|
function isRecordedSecretExpression(expression) {
|
|
6088
|
-
return recordedSecretExpressions
|
|
6089
|
-
}
|
|
6090
|
-
function clearRecordedSecretExpressions() {
|
|
6091
|
-
recordedSecretExpressions$1.clear();
|
|
6103
|
+
return recordedSecretExpressions.has(expression);
|
|
6092
6104
|
}
|
|
6093
6105
|
function recordMaskOnlyValue(secrets, plaintext) {
|
|
6094
6106
|
if (plaintext.length < 4) return;
|
|
@@ -6542,12 +6554,11 @@ function positionByRecordedParameterSpans(bag, source, secrets, associations) {
|
|
|
6542
6554
|
let persisted = "";
|
|
6543
6555
|
const gaps = [];
|
|
6544
6556
|
const certified = [];
|
|
6545
|
-
for (const { start, length,
|
|
6557
|
+
for (const { start, length, key } of recorded) {
|
|
6546
6558
|
if (!(start >= previousEnd && length > 0 && start + length <= bag.length)) return void 0;
|
|
6547
6559
|
previousEnd = start + length;
|
|
6548
6560
|
const text = bag.slice(start, start + length);
|
|
6549
|
-
const
|
|
6550
|
-
const association = key === void 0 ? void 0 : associations.get(key);
|
|
6561
|
+
const association = associations.get(key);
|
|
6551
6562
|
if (association === void 0 || typeof association === "symbol") continue;
|
|
6552
6563
|
const expression = certifiedExpressionForLeaf(secrets, association, text);
|
|
6553
6564
|
if (expression === void 0) continue;
|
|
@@ -7201,7 +7212,7 @@ function positionByIntrinsicSkeleton(bag, source, secrets, secretExpressions) {
|
|
|
7201
7212
|
if (!pattern) return void 0;
|
|
7202
7213
|
const plaintextOf = plaintextIndexOf(secrets);
|
|
7203
7214
|
let matched;
|
|
7204
|
-
for (const candidate of /* @__PURE__ */ new Set([...secretExpressions, ...recordedSecretExpressions
|
|
7215
|
+
for (const candidate of /* @__PURE__ */ new Set([...secretExpressions, ...recordedSecretExpressions])) {
|
|
7205
7216
|
if (candidate.length > MAX_SKELETON_CANDIDATE_LENGTH) return void 0;
|
|
7206
7217
|
if (!pattern.test(candidate)) continue;
|
|
7207
7218
|
const recordedPlaintext = plaintextOf.get(candidate);
|
|
@@ -7259,7 +7270,7 @@ function positionByIntrinsicFrame(bag, source, secrets, secretExpressions, bagIs
|
|
|
7259
7270
|
let matched;
|
|
7260
7271
|
for (const candidate of /* @__PURE__ */ new Set([
|
|
7261
7272
|
...secretExpressions,
|
|
7262
|
-
...recordedSecretExpressions
|
|
7273
|
+
...recordedSecretExpressions,
|
|
7263
7274
|
...resolvedExpressionsOf(secrets)
|
|
7264
7275
|
])) {
|
|
7265
7276
|
if (candidate.length > MAX_SKELETON_CANDIDATE_LENGTH) return void 0;
|
|
@@ -7327,10 +7338,10 @@ function recordIntrinsicLeafResolution(secrets, source, resolution) {
|
|
|
7327
7338
|
secret
|
|
7328
7339
|
})),
|
|
7329
7340
|
complete: resolution.complete,
|
|
7330
|
-
...resolution.parameterSpans === void 0 ? {} : { parameterSpans: resolution.parameterSpans.map(({ start, length,
|
|
7341
|
+
...resolution.parameterSpans === void 0 ? {} : { parameterSpans: resolution.parameterSpans.map(({ start, length, key }) => ({
|
|
7331
7342
|
start,
|
|
7332
7343
|
length,
|
|
7333
|
-
|
|
7344
|
+
key
|
|
7334
7345
|
})) }
|
|
7335
7346
|
};
|
|
7336
7347
|
const previous = leaves.get(source);
|
|
@@ -7359,7 +7370,7 @@ function sameLeafResolution(a, b) {
|
|
|
7359
7370
|
}
|
|
7360
7371
|
function sameParameterSpans(a, b) {
|
|
7361
7372
|
if (a === void 0 || b === void 0) return a === b;
|
|
7362
|
-
return a.length === b.length && a.every((s, i) => s.start === b[i].start && s.length === b[i].length && s.
|
|
7373
|
+
return a.length === b.length && a.every((s, i) => s.start === b[i].start && s.length === b[i].length && s.key === b[i].key);
|
|
7363
7374
|
}
|
|
7364
7375
|
function substitutedSpellingOf(secrets, source, resolvedValue) {
|
|
7365
7376
|
const resolution = intrinsicLeafResolutionsOf.get(secrets)?.get(source);
|
|
@@ -10063,8 +10074,8 @@ const REVERSE_REPLACEMENT_NAME_KEYS = {
|
|
|
10063
10074
|
"AWS::Glue::Job": flat("Name"),
|
|
10064
10075
|
"AWS::Glue::SecurityConfiguration": flat("Name"),
|
|
10065
10076
|
"AWS::Glue::Table": {
|
|
10066
|
-
name: [["TableInput", "Name"]],
|
|
10067
|
-
scope: [["DatabaseName"]]
|
|
10077
|
+
name: [["TableInput", "Name"], ["Name"]],
|
|
10078
|
+
scope: [["DatabaseName"], ["CatalogId"]]
|
|
10068
10079
|
},
|
|
10069
10080
|
"AWS::Glue::Trigger": flat("Name"),
|
|
10070
10081
|
"AWS::Glue::Workflow": flat("Name"),
|
|
@@ -10137,6 +10148,8 @@ const CASE_INSENSITIVE_NAME_TYPES = /* @__PURE__ */ new Set([
|
|
|
10137
10148
|
"AWS::RDS::DBInstance",
|
|
10138
10149
|
"AWS::RDS::DBSubnetGroup"
|
|
10139
10150
|
]);
|
|
10151
|
+
const ASCII_CASE_INSENSITIVE_NAME_TYPES = /* @__PURE__ */ new Set(["AWS::Glue::Table"]);
|
|
10152
|
+
const NO_PHYSICAL_ID_NAME_PROOF = /* @__PURE__ */ new Set(["AWS::Glue::Table"]);
|
|
10140
10153
|
const GENERATED_NAME_VERBATIM = /* @__PURE__ */ new Set([
|
|
10141
10154
|
"AWS::CloudWatch::Alarm",
|
|
10142
10155
|
"AWS::DocDB::DBCluster",
|
|
@@ -10566,16 +10579,18 @@ function holderVerdict(input, v) {
|
|
|
10566
10579
|
}
|
|
10567
10580
|
if (namePath === void 0 || wantName === void 0) return unproven(`${v.create} named no ${labels} (its provider picks one), so cdkd cannot show that ${newResource} holds it`);
|
|
10568
10581
|
const wanted = generatedName ? `${v.create} named no ${labels}, and the cdkd naming rule generates ${r.shown(namePath.join("."))} ${r.quoted(wantName)} for it` : `${v.create} asked for ${r.shown(namePath.join("."))} ${r.quoted(wantName)}`;
|
|
10569
|
-
const
|
|
10570
|
-
const inCase = CASE_INSENSITIVE_NAME_TYPES.has(oldResourceType) ? (value) => value.toLowerCase() : (value) => value;
|
|
10571
|
-
const
|
|
10572
|
-
|
|
10573
|
-
const
|
|
10574
|
-
return
|
|
10582
|
+
const asciiFold = ASCII_CASE_INSENSITIVE_NAME_TYPES.has(oldResourceType);
|
|
10583
|
+
const inCase = CASE_INSENSITIVE_NAME_TYPES.has(oldResourceType) ? (value) => value.toLowerCase() : asciiFold ? (value) => value.replace(/[A-Z]/g, (c) => c.toLowerCase()) : (value) => value;
|
|
10584
|
+
const same = (a, b) => inCase(a) === inCase(b);
|
|
10585
|
+
const namePathHeld = newKey.name.find((path) => {
|
|
10586
|
+
const h = heldAt(recorded, observed, path);
|
|
10587
|
+
return h.value !== void 0 || h.unreadable;
|
|
10575
10588
|
});
|
|
10576
|
-
|
|
10577
|
-
const
|
|
10578
|
-
if (
|
|
10589
|
+
const recordedName = namePathHeld && valueAt(recorded, namePathHeld);
|
|
10590
|
+
const observedName = namePathHeld && valueAt(observed, namePathHeld);
|
|
10591
|
+
if (namePathHeld !== void 0 && recordedName !== void 0 && observedName !== void 0 && !same(recordedName, observedName)) return unproven(`${wanted}, and the records of ${newResource} disagree on its ${r.shown(namePathHeld.join("."))} (recorded ${r.quoted(recordedName)}, read back ${r.quoted(observedName)}), so cdkd cannot show which name it holds`);
|
|
10592
|
+
const haveName = namePathHeld === void 0 ? void 0 : heldAt(recorded, observed, namePathHeld).value;
|
|
10593
|
+
if (!(haveName !== void 0 && same(haveName, wantName) || physicalId !== "" && !NO_PHYSICAL_ID_NAME_PROOF.has(newResourceType) && holderIdNames(inCase(physicalId), inCase(wantName)))) return haveName !== void 0 && !generatedName ? elsewhere(`${wanted}, while ${newResource} holds ${r.quoted(haveName)}`) : unproven(`${wanted}, and cdkd cannot show that ${newResource} holds that name`);
|
|
10579
10594
|
for (const [i, path] of (oldKey.scope ?? []).entries()) {
|
|
10580
10595
|
const label = r.shown(path.join("."));
|
|
10581
10596
|
const wantRaw = valueAt(requested, path);
|
|
@@ -14841,6 +14856,29 @@ function excludeCreateOnly(resourceType, names) {
|
|
|
14841
14856
|
if (createOnly === void 0 || createOnly.size === 0) return names;
|
|
14842
14857
|
return names.filter((property) => !createOnly.has(property));
|
|
14843
14858
|
}
|
|
14859
|
+
function withoutUnwrittenSilentDropProperties(resourceType, recordedProperties, desiredProperties, allowedKeys, evidence) {
|
|
14860
|
+
const drops = findSilentDropProperties(resourceType, recordedProperties);
|
|
14861
|
+
if (drops.length === 0) return recordedProperties;
|
|
14862
|
+
const createOnly = getPropertyCoverage(resourceType)?.createOnlyDrops;
|
|
14863
|
+
const accepted = new Set(findAcceptedSilentDrops(resourceType, desiredProperties, allowedKeys, recordedProperties));
|
|
14864
|
+
const removable = drops.map(({ property }) => property).filter((property) => createOnly?.has(property) !== true || evidence.has(property) && !accepted.has(property));
|
|
14865
|
+
if (removable.length === 0) return recordedProperties;
|
|
14866
|
+
const narrowed = { ...recordedProperties };
|
|
14867
|
+
for (const property of removable) delete narrowed[property];
|
|
14868
|
+
return narrowed;
|
|
14869
|
+
}
|
|
14870
|
+
function findUnwrittenCreateOnlyDrops(resourceType, recordedProperties, desiredProperties, allowedKeys, evidence) {
|
|
14871
|
+
const createOnly = getPropertyCoverage(resourceType)?.createOnlyDrops;
|
|
14872
|
+
if (createOnly === void 0 || createOnly.size === 0 || evidence.size === 0) return [];
|
|
14873
|
+
const accepted = new Set(findAcceptedSilentDrops(resourceType, desiredProperties, allowedKeys, recordedProperties));
|
|
14874
|
+
return findSilentDropProperties(resourceType, recordedProperties).map(({ property }) => property).filter((property) => createOnly.has(property) && evidence.has(property) && !accepted.has(property) && Object.hasOwn(desiredProperties, property) && sameJsonValue(recordedProperties[property], desiredProperties[property], "unchanged"));
|
|
14875
|
+
}
|
|
14876
|
+
function unwrittenCreateOnlyReplacement(resourceType, recordedProperties, desiredProperties, allowedKeys, evidence, replacingPaths) {
|
|
14877
|
+
if (replacingPaths.length === 0) return [];
|
|
14878
|
+
const unwritten = findUnwrittenCreateOnlyDrops(resourceType, recordedProperties, desiredProperties, allowedKeys, evidence);
|
|
14879
|
+
if (unwritten.length === 0) return [];
|
|
14880
|
+
return replacingPaths.every((path) => unwritten.includes(path)) ? unwritten : [];
|
|
14881
|
+
}
|
|
14844
14882
|
function unsupportedPropertyIssueUrl(resourceType, property) {
|
|
14845
14883
|
return `https://github.com/go-to-k/cdkd/issues/new?title=${encodeURIComponent(`Support property ${resourceType}.${property}`)}&labels=resource-support`;
|
|
14846
14884
|
}
|
|
@@ -15975,12 +16013,6 @@ function isDeliberateResolutionRefusal(err) {
|
|
|
15975
16013
|
}
|
|
15976
16014
|
const cachedAccountIdentities = /* @__PURE__ */ new Map();
|
|
15977
16015
|
const cachedAvailabilityZones = /* @__PURE__ */ new Map();
|
|
15978
|
-
const recordedSecretExpressions = {
|
|
15979
|
-
has: (expression) => isRecordedSecretExpression(expression),
|
|
15980
|
-
add: (expression) => recordSecretExpression(expression),
|
|
15981
|
-
delete: (expression) => forgetSecretExpression(expression),
|
|
15982
|
-
clear: () => clearRecordedSecretExpressions()
|
|
15983
|
-
};
|
|
15984
16016
|
const cachedEc2InstanceAttributes = Object.create(null);
|
|
15985
16017
|
const cachedVpcDefaultSecurityGroups = Object.create(null);
|
|
15986
16018
|
const cachedCloudFrontDomainNames = Object.create(null);
|
|
@@ -17109,10 +17141,9 @@ async function reresolveCrossStackValue(value, producerRegion, context, origin,
|
|
|
17109
17141
|
if (sourceKey !== void 0 && typeof value === "string" && isSingleDynamicReferenceToken(value) && typeof reresolved === "string" && context.recordedSecretValues?.has(reresolved) === true && isSecretExpressionByVerdictOrSpelling(value)) recordCrossStackExpression(context.recordedSecretValues, sourceKey, value, reresolved);
|
|
17110
17142
|
return reresolved;
|
|
17111
17143
|
}
|
|
17112
|
-
function pinSecretVerdict(expression, secret) {
|
|
17144
|
+
function pinSecretVerdict(expression, secret, scope) {
|
|
17113
17145
|
if (this.producerRegionGuest) return;
|
|
17114
|
-
|
|
17115
|
-
else recordedSecretExpressions.delete(expression);
|
|
17146
|
+
pinScopedSecretVerdict(scope, expression, secret);
|
|
17116
17147
|
}
|
|
17117
17148
|
async function resolveImportValue(importValueArg, context) {
|
|
17118
17149
|
const sourceKey = crossStackSourceKey({ "Fn::ImportValue": importValueArg });
|
|
@@ -17725,6 +17756,9 @@ function classifyReplaySecretRegion(expression, consumerRegion, importedProducer
|
|
|
17725
17756
|
|
|
17726
17757
|
//#endregion
|
|
17727
17758
|
//#region src/deployment/intrinsic-resolver/dynamic-refs.ts
|
|
17759
|
+
function secretVerdictScope(resolver) {
|
|
17760
|
+
return injectiveKey(credentialFingerprint(ambientCredentialConfig()), canonicalizeRegion(resolver.explicitRegion) ?? "");
|
|
17761
|
+
}
|
|
17728
17762
|
async function resolveDynamicReferences(value, context) {
|
|
17729
17763
|
return (await this.resolveDynamicReferencesWithLogTwin(value, value, context, void 0, true)).result;
|
|
17730
17764
|
}
|
|
@@ -17751,7 +17785,8 @@ async function resolveDynamicReferencesWithLogTwin(value, logTwin, context, inhe
|
|
|
17751
17785
|
const tokenLogText = inherited?.tokenLogText ?? (pairedTwin === void 0 ? "***" : this.straddleSafeTwin(fullMatch, pairedTwin, context));
|
|
17752
17786
|
const nameLogText = inherited?.nameLogText ?? (pairedTwin === void 0 ? () => "***" : this.dynamicReferenceNameLogText(inner, pairedTwin, context));
|
|
17753
17787
|
try {
|
|
17754
|
-
const
|
|
17788
|
+
const verdictScope = secretVerdictScope(this);
|
|
17789
|
+
const isKnownSecret = service === "secretsmanager" || service === "ssm-secure" || isScopedSecretVerdict(verdictScope, fullMatch);
|
|
17755
17790
|
if (isKnownSecret && context?.skipDynamicReferences) {
|
|
17756
17791
|
complete = false;
|
|
17757
17792
|
continue;
|
|
@@ -17804,8 +17839,8 @@ async function resolveDynamicReferencesWithLogTwin(value, logTwin, context, inhe
|
|
|
17804
17839
|
const param = await this.resolveSSMReference(parts, decrypt, "ssm", context, nameLogText);
|
|
17805
17840
|
if (param.type === "SecureString") {
|
|
17806
17841
|
if (decrypt) pinSecureVerdict = true;
|
|
17807
|
-
else if (persistedText || !this.tokenAssembledForRecording(fullMatch, tokenLogText, context)) this.pinSecretVerdict(fullMatch, true);
|
|
17808
|
-
} else if (!param.secure) this.pinSecretVerdict(fullMatch, false);
|
|
17842
|
+
else if (persistedText || !this.tokenAssembledForRecording(fullMatch, tokenLogText, context)) this.pinSecretVerdict(fullMatch, true, verdictScope);
|
|
17843
|
+
} else if (!param.secure) this.pinSecretVerdict(fullMatch, false, verdictScope);
|
|
17809
17844
|
else cacheable = false;
|
|
17810
17845
|
isSecret = param.secure;
|
|
17811
17846
|
if (param.secure) {
|
|
@@ -17827,7 +17862,7 @@ async function resolveDynamicReferencesWithLogTwin(value, logTwin, context, inhe
|
|
|
17827
17862
|
continue;
|
|
17828
17863
|
}
|
|
17829
17864
|
if (isSecret && resolved && !persistedText) this.refuseSecretAssembledReference(fullMatch, tokenLogText, context);
|
|
17830
|
-
if (pinSecureVerdict) this.pinSecretVerdict(fullMatch, true);
|
|
17865
|
+
if (pinSecureVerdict) this.pinSecretVerdict(fullMatch, true, verdictScope);
|
|
17831
17866
|
if (cacheable) this.cachedDynamicReferences.set(dynamicReferenceCacheKey, {
|
|
17832
17867
|
value: resolved,
|
|
17833
17868
|
secret: isSecret
|
|
@@ -17838,7 +17873,7 @@ async function resolveDynamicReferencesWithLogTwin(value, logTwin, context, inhe
|
|
|
17838
17873
|
recorded.set(resolved, fullMatch);
|
|
17839
17874
|
recordResolvedPair(recorded, fullMatch, resolved);
|
|
17840
17875
|
}
|
|
17841
|
-
if (service === "secretsmanager" || service === "ssm-secure") this.pinSecretVerdict(fullMatch, true);
|
|
17876
|
+
if (service === "secretsmanager" || service === "ssm-secure") this.pinSecretVerdict(fullMatch, true, verdictScope);
|
|
17842
17877
|
}
|
|
17843
17878
|
result = result.replace(fullMatch, () => resolved);
|
|
17844
17879
|
twin = twin.replace(fullMatch, () => isSecret && resolved ? "***" : resolved);
|
|
@@ -17977,11 +18012,20 @@ function partParameterSpans(context, part, resolved) {
|
|
|
17977
18012
|
if (own === void 0 || own.output !== resolved) return [];
|
|
17978
18013
|
return own.parameterSpans ?? [];
|
|
17979
18014
|
}
|
|
18015
|
+
function wholeReferenceSpans(source, value) {
|
|
18016
|
+
if (typeof value !== "string" || value === "") return [];
|
|
18017
|
+
const key = crossStackSourceKey(source);
|
|
18018
|
+
return key === void 0 ? [] : [{
|
|
18019
|
+
start: 0,
|
|
18020
|
+
length: value.length,
|
|
18021
|
+
key
|
|
18022
|
+
}];
|
|
18023
|
+
}
|
|
17980
18024
|
function appendShiftedSpans(out, spans, by) {
|
|
17981
18025
|
for (const span of spans) out.push({
|
|
17982
18026
|
start: span.start + by,
|
|
17983
18027
|
length: span.length,
|
|
17984
|
-
|
|
18028
|
+
key: span.key
|
|
17985
18029
|
});
|
|
17986
18030
|
}
|
|
17987
18031
|
async function resolveJoin(joinArgs, context, source) {
|
|
@@ -18276,11 +18320,7 @@ async function resolveSub(subArgs, context, source) {
|
|
|
18276
18320
|
listRefusal ??= refusal;
|
|
18277
18321
|
replacement = refusal ? match[0] : String(value);
|
|
18278
18322
|
if (!refusal) twinReplacement = this.productLogTwin(value, context);
|
|
18279
|
-
if (!refusal && fromParameter
|
|
18280
|
-
start: 0,
|
|
18281
|
-
length: value.length,
|
|
18282
|
-
parameter: varNameStr
|
|
18283
|
-
}];
|
|
18323
|
+
if (!refusal && fromParameter) parameterSpans = wholeReferenceSpans({ Ref: varNameStr }, value);
|
|
18284
18324
|
} catch (refError) {
|
|
18285
18325
|
if (refError instanceof IntrinsicResolutionRefusalError) throw refError;
|
|
18286
18326
|
if (varNameStr.includes(".")) try {
|
|
@@ -18288,7 +18328,10 @@ async function resolveSub(subArgs, context, source) {
|
|
|
18288
18328
|
const refusal = this.subListRefusal(`the variable \${${varNameStr}}`, value, context);
|
|
18289
18329
|
listRefusal ??= refusal;
|
|
18290
18330
|
replacement = refusal ? match[0] : String(value);
|
|
18291
|
-
if (!refusal)
|
|
18331
|
+
if (!refusal) {
|
|
18332
|
+
twinReplacement = this.productLogTwin(value, context);
|
|
18333
|
+
parameterSpans = wholeReferenceSpans({ "Fn::GetAtt": varNameStr }, value);
|
|
18334
|
+
}
|
|
18292
18335
|
} catch (getAttError) {
|
|
18293
18336
|
if (getAttError instanceof IntrinsicResolutionRefusalError) throw getAttError;
|
|
18294
18337
|
this.rethrowStructuralSubFailure(varNameStr, getAttError, context);
|
|
@@ -19118,6 +19161,16 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
19118
19161
|
const parts = pending === 1 ? "1 concurrent part was" : `${pending} concurrent parts were`;
|
|
19119
19162
|
this.logger.warn(`A resolution failed while ${parts} still running, and cdkd stopped waiting because the wait after a failure (capped at ${capSeconds}s) was used up. A secret such a part resolves from now on is still recorded, but only what runs after it arrives can mask it: output already printed or saved is not revisited.`);
|
|
19120
19163
|
}
|
|
19164
|
+
recordCrossStackReadSpan(context, source, value) {
|
|
19165
|
+
if (typeof value === "string") this.recordLeafResolution(context, source, {
|
|
19166
|
+
input: value,
|
|
19167
|
+
output: value,
|
|
19168
|
+
substitutions: [],
|
|
19169
|
+
complete: true,
|
|
19170
|
+
parameterSpans: wholeReferenceSpans(source, value)
|
|
19171
|
+
});
|
|
19172
|
+
return value;
|
|
19173
|
+
}
|
|
19121
19174
|
async resolveValue(value, context) {
|
|
19122
19175
|
if (typeof value !== "object" || value === null) {
|
|
19123
19176
|
if (typeof value === "string" && value.includes("{{resolve:")) return await this.resolveTemplateLeafReferences(value, context);
|
|
@@ -19136,15 +19189,11 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
19136
19189
|
output: value,
|
|
19137
19190
|
substitutions: [],
|
|
19138
19191
|
complete: true,
|
|
19139
|
-
parameterSpans:
|
|
19140
|
-
start: 0,
|
|
19141
|
-
length: value.length,
|
|
19142
|
-
parameter: logicalId
|
|
19143
|
-
}]
|
|
19192
|
+
parameterSpans: wholeReferenceSpans({ Ref: logicalId }, value)
|
|
19144
19193
|
});
|
|
19145
19194
|
return value;
|
|
19146
19195
|
}
|
|
19147
|
-
if ("Fn::GetAtt" in obj) return await this.resolveGetAtt(obj["Fn::GetAtt"], context);
|
|
19196
|
+
if ("Fn::GetAtt" in obj) return this.recordCrossStackReadSpan(context, obj, await this.resolveGetAtt(obj["Fn::GetAtt"], context));
|
|
19148
19197
|
if ("Fn::Join" in obj) return await this.resolveJoin(obj["Fn::Join"], context, obj);
|
|
19149
19198
|
if ("Fn::Sub" in obj) return await this.resolveSub(obj["Fn::Sub"], context, obj);
|
|
19150
19199
|
if ("Fn::Select" in obj) return await this.resolveSelect(obj["Fn::Select"], context);
|
|
@@ -19155,8 +19204,8 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
19155
19204
|
if ("Fn::And" in obj) return await this.resolveAnd(obj["Fn::And"], context);
|
|
19156
19205
|
if ("Fn::Or" in obj) return await this.resolveOr(obj["Fn::Or"], context);
|
|
19157
19206
|
if ("Fn::Not" in obj) return await this.resolveNot(obj["Fn::Not"], context);
|
|
19158
|
-
if ("Fn::ImportValue" in obj) return await this.resolveImportValue(obj["Fn::ImportValue"], context);
|
|
19159
|
-
if ("Fn::GetStackOutput" in obj) return await this.resolveGetStackOutput(obj["Fn::GetStackOutput"], context);
|
|
19207
|
+
if ("Fn::ImportValue" in obj) return this.recordCrossStackReadSpan(context, obj, await this.resolveImportValue(obj["Fn::ImportValue"], context));
|
|
19208
|
+
if ("Fn::GetStackOutput" in obj) return this.recordCrossStackReadSpan(context, obj, await this.resolveGetStackOutput(obj["Fn::GetStackOutput"], context));
|
|
19160
19209
|
if ("Fn::FindInMap" in obj) return await this.resolveFindInMap(obj["Fn::FindInMap"], context);
|
|
19161
19210
|
if ("Fn::Base64" in obj) return await this.resolveBase64(obj["Fn::Base64"], context);
|
|
19162
19211
|
if ("Fn::GetAZs" in obj) return await this.resolveGetAZs(obj["Fn::GetAZs"], context);
|
|
@@ -19417,7 +19466,7 @@ var DiffCalculator = class DiffCalculator {
|
|
|
19417
19466
|
const resolvedDesiredProps = resolveFn ? await this.resolveBestEffort(rawDesiredProps, resolveFn) : rawDesiredProps;
|
|
19418
19467
|
const sdkRouted = currentResource.provisionedBy !== "cc-api";
|
|
19419
19468
|
const desiredAfterDrops = sdkRouted && allowedUnsupportedProperties ? withoutAcceptedSilentDropProperties(desiredResource.Type, resolvedDesiredProps, allowedUnsupportedProperties, currentResource.properties) : resolvedDesiredProps;
|
|
19420
|
-
const currentAfterDrops = sdkRouted ?
|
|
19469
|
+
const currentAfterDrops = sdkRouted ? withoutUnwrittenSilentDropProperties(desiredResource.Type, currentResource.properties, resolvedDesiredProps, allowedUnsupportedProperties ?? /* @__PURE__ */ new Set(), acceptedCreateOnlyDropsOf(currentResource)) : currentResource.properties;
|
|
19421
19470
|
const desiredPropsForCompare = canonicalizeProperties ? canonicalizeProperties(desiredResource.Type, desiredAfterDrops) : desiredAfterDrops;
|
|
19422
19471
|
const currentPropsForCompare = canonicalizeProperties && sdkRouted ? canonicalizeProperties(desiredResource.Type, currentAfterDrops) : currentAfterDrops;
|
|
19423
19472
|
const droppedKeys = canonicalizeProperties ? Object.keys(desiredAfterDrops).filter((key) => !Object.hasOwn(desiredPropsForCompare, key)) : [];
|
|
@@ -20649,7 +20698,8 @@ var CloudControlProvider = class {
|
|
|
20649
20698
|
}
|
|
20650
20699
|
}
|
|
20651
20700
|
async update(logicalId, physicalId, resourceType, properties, previousProperties, context) {
|
|
20652
|
-
this.logger
|
|
20701
|
+
const idLog = updateIdLogSink(this.logger, physicalId, properties, previousProperties, context?.maskSecrets);
|
|
20702
|
+
idLog.debug(`Updating resource ${logicalId} (${resourceType}), physical ID: ${physicalId}`);
|
|
20653
20703
|
await this.assertRecordedRegionAgainstClient("pre-update", context?.expectedRegion, resourceType, logicalId, physicalId);
|
|
20654
20704
|
try {
|
|
20655
20705
|
const cleanPreviousProperties = stringifyJsonProperties(resourceType, stripNullValues(previousProperties));
|
|
@@ -20714,9 +20764,9 @@ var CloudControlProvider = class {
|
|
|
20714
20764
|
physicalId,
|
|
20715
20765
|
wasReplaced: false
|
|
20716
20766
|
};
|
|
20717
|
-
if (progressEvent.ResourceModel) result.attributes = this.parseResourceModel(progressEvent.ResourceModel);
|
|
20718
|
-
result.attributes = await this.mergeSparseModelReadback(resourceType, physicalId, result.attributes || {});
|
|
20719
|
-
result.attributes = await this.enrichResourceAttributes(resourceType, physicalId, result.attributes);
|
|
20767
|
+
if (progressEvent.ResourceModel) result.attributes = this.parseResourceModel(progressEvent.ResourceModel, idLog);
|
|
20768
|
+
result.attributes = await this.mergeSparseModelReadback(resourceType, physicalId, result.attributes || {}, idLog);
|
|
20769
|
+
result.attributes = await this.enrichResourceAttributes(resourceType, physicalId, result.attributes, idLog);
|
|
20720
20770
|
return result;
|
|
20721
20771
|
} catch (error) {
|
|
20722
20772
|
this.handleError(error, "UPDATE", resourceType, logicalId, physicalId);
|
|
@@ -20729,7 +20779,7 @@ var CloudControlProvider = class {
|
|
|
20729
20779
|
const indeterminateGuard = await this.confirmDeleteTargetIdentity(logicalId, resourceType, physicalId, context);
|
|
20730
20780
|
if (context?.removeProtection === true && resourceType === "AWS::AutoScaling::AutoScalingGroup") {
|
|
20731
20781
|
this.logger.debug(`Delegating protected AutoScalingGroup ${logicalId} delete to the SDK ASGProvider (Cloud Control cannot force-delete a protected ASG)`);
|
|
20732
|
-
const { ASGProvider } = await import("./asg-provider-
|
|
20782
|
+
const { ASGProvider } = await import("./asg-provider-3uLGAhIx.js");
|
|
20733
20783
|
const delegateRegion = ambientRegion();
|
|
20734
20784
|
let asgProvider = this.asgDeleteDelegates.get(delegateRegion);
|
|
20735
20785
|
if (asgProvider === void 0) {
|
|
@@ -20835,7 +20885,7 @@ var CloudControlProvider = class {
|
|
|
20835
20885
|
const family = SDK_DELETE_FAMILIES.get(resourceType);
|
|
20836
20886
|
const cached = this.sdkDeleteDelegates.get(family);
|
|
20837
20887
|
if (cached !== void 0 && cached.region === ccRegion) return cached.provider;
|
|
20838
|
-
const provider = family === "rds" ? new (await (import("./rds-provider-
|
|
20888
|
+
const provider = family === "rds" ? new (await (import("./rds-provider-J6zl27x3.js"))).RDSProvider({ region: ccRegion }) : new (await (import("./neptune-provider-BQ-CGoYJ.js"))).NeptuneProvider({ region: ccRegion });
|
|
20839
20889
|
this.sdkDeleteDelegates.set(family, {
|
|
20840
20890
|
region: ccRegion,
|
|
20841
20891
|
provider
|
|
@@ -21080,34 +21130,34 @@ var CloudControlProvider = class {
|
|
|
21080
21130
|
const regionFlag = safeRegion === void 0 ? "" : ` --region ${shellQuote(safeRegion)}`;
|
|
21081
21131
|
return `${withPasteableAwsProfile("aws cloudcontrol get-resource-request-status")} --request-token ${shellQuote(safeToken)}${regionFlag}`;
|
|
21082
21132
|
}
|
|
21083
|
-
parseResourceModel(resourceModel) {
|
|
21133
|
+
parseResourceModel(resourceModel, log = this.logger) {
|
|
21084
21134
|
try {
|
|
21085
21135
|
return JSON.parse(resourceModel);
|
|
21086
21136
|
} catch (error) {
|
|
21087
21137
|
const described = describeAwsFailure(error);
|
|
21088
|
-
|
|
21089
|
-
|
|
21138
|
+
log.warn(`Failed to parse resource model: ${described.redacted ? described.summary : error instanceof Error ? error.name : "Error"}\nModel shape: ${resourceModel.length} chars, ${describeJsonKeys(resourceModel)}`);
|
|
21139
|
+
if (log.withheld !== true) log.debug(`Resource model parse failure detail: ${displaySafe(described.detail)}`);
|
|
21090
21140
|
return {};
|
|
21091
21141
|
}
|
|
21092
21142
|
}
|
|
21093
|
-
async accountInfoForSynthesizedArn(resourceType, attributeName, physicalId) {
|
|
21143
|
+
async accountInfoForSynthesizedArn(resourceType, attributeName, physicalId, log = this.logger) {
|
|
21094
21144
|
const region = await this.cloudControlClient.config.region();
|
|
21095
21145
|
try {
|
|
21096
21146
|
return await getAccountInfo(region);
|
|
21097
21147
|
} catch (error) {
|
|
21098
21148
|
if (!(error instanceof AccountIdUnavailableError)) throw error;
|
|
21099
|
-
|
|
21149
|
+
log.warn(`Not enriching ${resourceType} ${attributeName} for ${physicalId}: ${error.message} The resource itself is unaffected; the record heals on its next update.`);
|
|
21100
21150
|
return;
|
|
21101
21151
|
}
|
|
21102
21152
|
}
|
|
21103
|
-
async enrichResourceAttributes(resourceType, physicalId, attributes) {
|
|
21153
|
+
async enrichResourceAttributes(resourceType, physicalId, attributes, log = this.logger) {
|
|
21104
21154
|
const enriched = { ...attributes };
|
|
21105
21155
|
switch (resourceType) {
|
|
21106
21156
|
case "AWS::S3::Bucket":
|
|
21107
21157
|
if (!enriched["Arn"]) try {
|
|
21108
21158
|
enriched["Arn"] = s3BucketArn(physicalId, await this.cloudControlClient.config.region());
|
|
21109
21159
|
} catch (error) {
|
|
21110
|
-
|
|
21160
|
+
log.debug(`Failed to construct S3 Bucket Arn for ${physicalId}: ${describeAwsFailure(error).detail}`);
|
|
21111
21161
|
}
|
|
21112
21162
|
break;
|
|
21113
21163
|
case "AWS::RDS::DBCluster":
|
|
@@ -21119,10 +21169,10 @@ var CloudControlProvider = class {
|
|
|
21119
21169
|
if (cluster.ReaderEndpoint) enriched["ReadEndpoint.Address"] = cluster.ReaderEndpoint;
|
|
21120
21170
|
if (cluster.DBClusterArn) enriched["Arn"] = cluster.DBClusterArn;
|
|
21121
21171
|
if (cluster.DbClusterResourceId) enriched["DBClusterResourceId"] = cluster.DbClusterResourceId;
|
|
21122
|
-
|
|
21172
|
+
log.debug(`Enriched RDS DBCluster ${physicalId} with Endpoint/Port/Arn from DescribeDBClusters`);
|
|
21123
21173
|
}
|
|
21124
21174
|
} catch (error) {
|
|
21125
|
-
|
|
21175
|
+
log.debug(`Failed to enrich RDS DBCluster ${physicalId}: ${describeAwsFailure(error).detail}`);
|
|
21126
21176
|
}
|
|
21127
21177
|
break;
|
|
21128
21178
|
case "AWS::RDS::DBInstance":
|
|
@@ -21133,10 +21183,10 @@ var CloudControlProvider = class {
|
|
|
21133
21183
|
if (inst.Endpoint?.Port !== void 0) enriched["Endpoint.Port"] = String(inst.Endpoint.Port);
|
|
21134
21184
|
if (inst.Endpoint?.HostedZoneId) enriched["Endpoint.HostedZoneId"] = inst.Endpoint.HostedZoneId;
|
|
21135
21185
|
if (inst.DBInstanceArn) enriched["Arn"] = inst.DBInstanceArn;
|
|
21136
|
-
|
|
21186
|
+
log.debug(`Enriched RDS DBInstance ${physicalId} with Endpoint/Port/Arn from DescribeDBInstances`);
|
|
21137
21187
|
}
|
|
21138
21188
|
} catch (error) {
|
|
21139
|
-
|
|
21189
|
+
log.debug(`Failed to enrich RDS DBInstance ${physicalId}: ${describeAwsFailure(error).detail}`);
|
|
21140
21190
|
}
|
|
21141
21191
|
break;
|
|
21142
21192
|
case "AWS::DynamoDB::Table":
|
|
@@ -21144,10 +21194,10 @@ var CloudControlProvider = class {
|
|
|
21144
21194
|
const latestStreamArn = (await getAwsClients().dynamoDB.send(new DescribeTableCommand({ TableName: physicalId }))).Table?.LatestStreamArn;
|
|
21145
21195
|
if (latestStreamArn) {
|
|
21146
21196
|
enriched["StreamArn"] = latestStreamArn;
|
|
21147
|
-
|
|
21197
|
+
log.debug(`Enriched DynamoDB StreamArn for ${physicalId}: ${latestStreamArn}`);
|
|
21148
21198
|
}
|
|
21149
21199
|
} catch (error) {
|
|
21150
|
-
|
|
21200
|
+
log.debug(`Failed to get DynamoDB StreamArn for ${physicalId}: ${describeAwsFailure(error).detail}`);
|
|
21151
21201
|
}
|
|
21152
21202
|
break;
|
|
21153
21203
|
case "AWS::ApiGateway::RestApi":
|
|
@@ -21155,10 +21205,10 @@ var CloudControlProvider = class {
|
|
|
21155
21205
|
const getRestApiResponse = await getAwsClients().apiGateway.send(new GetRestApiCommand({ restApiId: physicalId }));
|
|
21156
21206
|
if (getRestApiResponse.rootResourceId) {
|
|
21157
21207
|
enriched["RootResourceId"] = getRestApiResponse.rootResourceId;
|
|
21158
|
-
|
|
21208
|
+
log.debug(`Enriched RestApi RootResourceId for ${physicalId}: ${getRestApiResponse.rootResourceId}`);
|
|
21159
21209
|
}
|
|
21160
21210
|
} catch (error) {
|
|
21161
|
-
|
|
21211
|
+
log.debug(`Failed to get RestApi RootResourceId for ${physicalId}: ${describeAwsFailure(error).detail}`);
|
|
21162
21212
|
}
|
|
21163
21213
|
if (!enriched["RestApiId"]) enriched["RestApiId"] = physicalId;
|
|
21164
21214
|
break;
|
|
@@ -21167,21 +21217,21 @@ var CloudControlProvider = class {
|
|
|
21167
21217
|
const s3CanonicalUserId = (await getAwsClients().cloudFront.send(new GetCloudFrontOriginAccessIdentityCommand({ Id: physicalId }))).CloudFrontOriginAccessIdentity?.S3CanonicalUserId;
|
|
21168
21218
|
if (s3CanonicalUserId) {
|
|
21169
21219
|
enriched["S3CanonicalUserId"] = s3CanonicalUserId;
|
|
21170
|
-
|
|
21220
|
+
log.debug(`Enriched CloudFront OAI S3CanonicalUserId for ${physicalId}: ${s3CanonicalUserId}`);
|
|
21171
21221
|
}
|
|
21172
21222
|
} catch (error) {
|
|
21173
|
-
|
|
21223
|
+
log.debug(`Failed to get CloudFront OAI S3CanonicalUserId for ${physicalId}: ${describeAwsFailure(error).detail}`);
|
|
21174
21224
|
}
|
|
21175
21225
|
break;
|
|
21176
21226
|
case "AWS::KMS::Key":
|
|
21177
21227
|
if (!enriched["Arn"]) try {
|
|
21178
|
-
const kmsAccountInfo = await this.accountInfoForSynthesizedArn(resourceType, "Arn", physicalId);
|
|
21228
|
+
const kmsAccountInfo = await this.accountInfoForSynthesizedArn(resourceType, "Arn", physicalId, log);
|
|
21179
21229
|
if (kmsAccountInfo) {
|
|
21180
21230
|
enriched["Arn"] = `arn:${kmsAccountInfo.partition}:kms:${canonicalizeRegion(kmsAccountInfo.region)}:${kmsAccountInfo.accountId}:key/${physicalId}`;
|
|
21181
|
-
|
|
21231
|
+
log.debug(`Enriched KMS Key Arn for ${physicalId}: ${String(enriched["Arn"])}`);
|
|
21182
21232
|
}
|
|
21183
21233
|
} catch (error) {
|
|
21184
|
-
|
|
21234
|
+
log.debug(`Failed to construct KMS Key Arn for ${physicalId}: ${describeAwsFailure(error).detail}`);
|
|
21185
21235
|
}
|
|
21186
21236
|
if (!enriched["KeyId"]) enriched["KeyId"] = physicalId;
|
|
21187
21237
|
break;
|
|
@@ -21193,16 +21243,16 @@ var CloudControlProvider = class {
|
|
|
21193
21243
|
break;
|
|
21194
21244
|
case "AWS::ECR::Repository":
|
|
21195
21245
|
if (!enriched["Arn"]) try {
|
|
21196
|
-
const ecrAccountInfo = await this.accountInfoForSynthesizedArn(resourceType, "Arn", physicalId);
|
|
21246
|
+
const ecrAccountInfo = await this.accountInfoForSynthesizedArn(resourceType, "Arn", physicalId, log);
|
|
21197
21247
|
if (ecrAccountInfo) {
|
|
21198
21248
|
enriched["Arn"] = `arn:${ecrAccountInfo.partition}:ecr:${canonicalizeRegion(ecrAccountInfo.region)}:${ecrAccountInfo.accountId}:repository/${physicalId}`;
|
|
21199
|
-
|
|
21249
|
+
log.debug(`Enriched ECR Repository Arn for ${physicalId}: ${String(enriched["Arn"])}`);
|
|
21200
21250
|
}
|
|
21201
21251
|
} catch (error) {
|
|
21202
|
-
|
|
21252
|
+
log.debug(`Failed to construct ECR Repository Arn: ${describeAwsFailure(error).detail}`);
|
|
21203
21253
|
}
|
|
21204
21254
|
if (!enriched["RepositoryUri"]) try {
|
|
21205
|
-
const ecrAccountInfo = await this.accountInfoForSynthesizedArn(resourceType, "RepositoryUri", physicalId);
|
|
21255
|
+
const ecrAccountInfo = await this.accountInfoForSynthesizedArn(resourceType, "RepositoryUri", physicalId, log);
|
|
21206
21256
|
if (ecrAccountInfo) {
|
|
21207
21257
|
const { urlSuffix } = derivePartitionAndUrlSuffix(ecrAccountInfo.region);
|
|
21208
21258
|
enriched["RepositoryUri"] = `${ecrAccountInfo.accountId}.dkr.ecr.${canonicalizeRegion(ecrAccountInfo.region)}.${urlSuffix}/${physicalId}`;
|
|
@@ -21214,7 +21264,7 @@ var CloudControlProvider = class {
|
|
|
21214
21264
|
const [publicIp, allocationId] = physicalId.split("|");
|
|
21215
21265
|
if (!enriched["AllocationId"]) enriched["AllocationId"] = allocationId;
|
|
21216
21266
|
if (!enriched["PublicIp"]) enriched["PublicIp"] = publicIp;
|
|
21217
|
-
|
|
21267
|
+
log.debug(`Enriched EIP attributes: AllocationId=${allocationId}, PublicIp=${publicIp}`);
|
|
21218
21268
|
}
|
|
21219
21269
|
break;
|
|
21220
21270
|
case "AWS::Lambda::Version":
|
|
@@ -21222,18 +21272,18 @@ var CloudControlProvider = class {
|
|
|
21222
21272
|
const versionSegments = physicalId.split(":");
|
|
21223
21273
|
const versionNumber = versionSegments[versionSegments.length - 1];
|
|
21224
21274
|
enriched["Version"] = versionNumber;
|
|
21225
|
-
|
|
21275
|
+
log.debug(`Enriched Lambda Version for ${physicalId}: ${versionNumber}`);
|
|
21226
21276
|
}
|
|
21227
21277
|
break;
|
|
21228
21278
|
case "AWS::Kinesis::Stream":
|
|
21229
21279
|
if (!enriched["Arn"]) try {
|
|
21230
|
-
const kinesisAccountInfo = await this.accountInfoForSynthesizedArn(resourceType, "Arn", physicalId);
|
|
21280
|
+
const kinesisAccountInfo = await this.accountInfoForSynthesizedArn(resourceType, "Arn", physicalId, log);
|
|
21231
21281
|
if (kinesisAccountInfo) {
|
|
21232
21282
|
enriched["Arn"] = `arn:${kinesisAccountInfo.partition}:kinesis:${canonicalizeRegion(kinesisAccountInfo.region)}:${kinesisAccountInfo.accountId}:stream/${physicalId}`;
|
|
21233
|
-
|
|
21283
|
+
log.debug(`Enriched Kinesis Stream Arn for ${physicalId}: ${String(enriched["Arn"])}`);
|
|
21234
21284
|
}
|
|
21235
21285
|
} catch (error) {
|
|
21236
|
-
|
|
21286
|
+
log.debug(`Failed to construct Kinesis Stream Arn for ${physicalId}: ${describeAwsFailure(error).detail}`);
|
|
21237
21287
|
}
|
|
21238
21288
|
break;
|
|
21239
21289
|
case "AWS::Lambda::Url":
|
|
@@ -21241,11 +21291,11 @@ var CloudControlProvider = class {
|
|
|
21241
21291
|
const urlConfig = await getAwsClients().lambda.send(new GetFunctionUrlConfigCommand({ FunctionName: physicalId }));
|
|
21242
21292
|
if (urlConfig.FunctionUrl) {
|
|
21243
21293
|
enriched["FunctionUrl"] = urlConfig.FunctionUrl;
|
|
21244
|
-
|
|
21294
|
+
log.debug(`Enriched Lambda URL FunctionUrl for ${physicalId}: ${urlConfig.FunctionUrl}`);
|
|
21245
21295
|
}
|
|
21246
21296
|
if (urlConfig.FunctionArn) enriched["FunctionArn"] = urlConfig.FunctionArn;
|
|
21247
21297
|
} catch (error) {
|
|
21248
|
-
|
|
21298
|
+
log.debug(`Failed to get Lambda URL config for ${physicalId}: ${describeAwsFailure(error).detail}`);
|
|
21249
21299
|
}
|
|
21250
21300
|
break;
|
|
21251
21301
|
case "AWS::Events::Connection":
|
|
@@ -21259,9 +21309,9 @@ var CloudControlProvider = class {
|
|
|
21259
21309
|
}
|
|
21260
21310
|
}
|
|
21261
21311
|
if (conn.SecretArn && !enriched["SecretArn"]) enriched["SecretArn"] = conn.SecretArn;
|
|
21262
|
-
|
|
21312
|
+
log.debug(`Enriched Events Connection ${physicalId} with Arn/SecretArn/ArnForPolicy from DescribeConnection`);
|
|
21263
21313
|
} catch (error) {
|
|
21264
|
-
|
|
21314
|
+
log.debug(`Failed to enrich Events Connection ${physicalId}: ${describeAwsFailure(error).detail}`);
|
|
21265
21315
|
}
|
|
21266
21316
|
break;
|
|
21267
21317
|
case "AWS::Events::ApiDestination":
|
|
@@ -21274,9 +21324,9 @@ var CloudControlProvider = class {
|
|
|
21274
21324
|
if (lastSlash > 0) enriched["ArnForPolicy"] = dest.ApiDestinationArn.slice(0, lastSlash);
|
|
21275
21325
|
}
|
|
21276
21326
|
}
|
|
21277
|
-
|
|
21327
|
+
log.debug(`Enriched Events ApiDestination ${physicalId} with Arn/ArnForPolicy from DescribeApiDestination`);
|
|
21278
21328
|
} catch (error) {
|
|
21279
|
-
|
|
21329
|
+
log.debug(`Failed to enrich Events ApiDestination ${physicalId}: ${describeAwsFailure(error).detail}`);
|
|
21280
21330
|
}
|
|
21281
21331
|
break;
|
|
21282
21332
|
case "AWS::ElastiCache::ReplicationGroup":
|
|
@@ -21295,10 +21345,10 @@ var CloudControlProvider = class {
|
|
|
21295
21345
|
const readPorts = readEndpoints.map((ep) => ep?.Port).filter((p) => p !== void 0);
|
|
21296
21346
|
if (readAddrs.length > 0) enriched["ReadEndPoint.Addresses"] = readAddrs.join(",");
|
|
21297
21347
|
if (readPorts.length > 0) enriched["ReadEndPoint.Ports"] = readPorts.map(String).join(",");
|
|
21298
|
-
|
|
21348
|
+
log.debug(`Enriched ElastiCache ReplicationGroup ${physicalId} with endpoint attributes from DescribeReplicationGroups`);
|
|
21299
21349
|
}
|
|
21300
21350
|
} catch (error) {
|
|
21301
|
-
|
|
21351
|
+
log.debug(`Failed to enrich ElastiCache ReplicationGroup ${physicalId}: ${describeAwsFailure(error).detail}`);
|
|
21302
21352
|
}
|
|
21303
21353
|
break;
|
|
21304
21354
|
case "AWS::Redshift::Cluster":
|
|
@@ -21307,10 +21357,10 @@ var CloudControlProvider = class {
|
|
|
21307
21357
|
if (cluster?.Endpoint) {
|
|
21308
21358
|
if (cluster.Endpoint.Address) enriched["Endpoint.Address"] = cluster.Endpoint.Address;
|
|
21309
21359
|
if (cluster.Endpoint.Port !== void 0) enriched["Endpoint.Port"] = String(cluster.Endpoint.Port);
|
|
21310
|
-
|
|
21360
|
+
log.debug(`Enriched Redshift Cluster ${physicalId} with Endpoint.Address/Port from DescribeClusters`);
|
|
21311
21361
|
}
|
|
21312
21362
|
} catch (error) {
|
|
21313
|
-
|
|
21363
|
+
log.debug(`Failed to enrich Redshift Cluster ${physicalId}: ${describeAwsFailure(error).detail}`);
|
|
21314
21364
|
}
|
|
21315
21365
|
break;
|
|
21316
21366
|
case "AWS::OpenSearchService::Domain":
|
|
@@ -21324,31 +21374,31 @@ var CloudControlProvider = class {
|
|
|
21324
21374
|
enriched["DomainArn"] = domain.ARN;
|
|
21325
21375
|
}
|
|
21326
21376
|
if (domain.DomainId) enriched["Id"] = domain.DomainId;
|
|
21327
|
-
|
|
21377
|
+
log.debug(`Enriched OpenSearch Domain ${physicalId} with DomainEndpoint/Arn from DescribeDomain`);
|
|
21328
21378
|
}
|
|
21329
21379
|
} catch (error) {
|
|
21330
|
-
|
|
21380
|
+
log.debug(`Failed to enrich OpenSearch Domain ${physicalId}: ${describeAwsFailure(error).detail}`);
|
|
21331
21381
|
}
|
|
21332
21382
|
break;
|
|
21333
21383
|
case "AWS::Backup::BackupVault":
|
|
21334
21384
|
if (!enriched["BackupVaultArn"]) {
|
|
21335
|
-
const model = await this.readCcResourceModel(resourceType, physicalId);
|
|
21385
|
+
const model = await this.readCcResourceModel(resourceType, physicalId, log);
|
|
21336
21386
|
if (model) {
|
|
21337
21387
|
if (typeof model["BackupVaultArn"] === "string") enriched["BackupVaultArn"] = model["BackupVaultArn"];
|
|
21338
21388
|
if (!enriched["BackupVaultName"] && typeof model["BackupVaultName"] === "string") enriched["BackupVaultName"] = model["BackupVaultName"];
|
|
21339
|
-
|
|
21389
|
+
log.debug(`Enriched Backup BackupVault ${physicalId} with BackupVaultArn from CC GetResource`);
|
|
21340
21390
|
}
|
|
21341
21391
|
}
|
|
21342
21392
|
if (!enriched["BackupVaultName"]) enriched["BackupVaultName"] = physicalId;
|
|
21343
21393
|
break;
|
|
21344
21394
|
case "AWS::Backup::BackupPlan":
|
|
21345
21395
|
if (!enriched["BackupPlanArn"] || !enriched["VersionId"]) {
|
|
21346
|
-
const model = await this.readCcResourceModel(resourceType, physicalId);
|
|
21396
|
+
const model = await this.readCcResourceModel(resourceType, physicalId, log);
|
|
21347
21397
|
if (model) {
|
|
21348
21398
|
if (!enriched["BackupPlanArn"] && typeof model["BackupPlanArn"] === "string") enriched["BackupPlanArn"] = model["BackupPlanArn"];
|
|
21349
21399
|
if (!enriched["VersionId"] && typeof model["VersionId"] === "string") enriched["VersionId"] = model["VersionId"];
|
|
21350
21400
|
if (!enriched["BackupPlanId"] && typeof model["BackupPlanId"] === "string") enriched["BackupPlanId"] = model["BackupPlanId"];
|
|
21351
|
-
|
|
21401
|
+
log.debug(`Enriched Backup BackupPlan ${physicalId} with BackupPlanArn/VersionId from CC GetResource`);
|
|
21352
21402
|
}
|
|
21353
21403
|
}
|
|
21354
21404
|
if (!enriched["BackupPlanId"]) enriched["BackupPlanId"] = physicalId;
|
|
@@ -21360,53 +21410,53 @@ var CloudControlProvider = class {
|
|
|
21360
21410
|
if (!enriched["SelectionId"]) enriched["SelectionId"] = physicalId.substring(0, firstUnderscore);
|
|
21361
21411
|
if (!enriched["BackupPlanId"]) enriched["BackupPlanId"] = physicalId.substring(firstUnderscore + 1);
|
|
21362
21412
|
}
|
|
21363
|
-
const model = await this.readCcResourceModel(resourceType, physicalId);
|
|
21413
|
+
const model = await this.readCcResourceModel(resourceType, physicalId, log);
|
|
21364
21414
|
if (model) {
|
|
21365
21415
|
if (typeof model["SelectionId"] === "string") enriched["SelectionId"] = model["SelectionId"];
|
|
21366
21416
|
if (typeof model["BackupPlanId"] === "string") enriched["BackupPlanId"] = model["BackupPlanId"];
|
|
21367
|
-
|
|
21417
|
+
log.debug(`Enriched Backup BackupSelection ${physicalId} with SelectionId from CC GetResource`);
|
|
21368
21418
|
}
|
|
21369
21419
|
}
|
|
21370
21420
|
break;
|
|
21371
21421
|
case "AWS::Pipes::Pipe":
|
|
21372
21422
|
if (!enriched["Arn"]) {
|
|
21373
|
-
const model = await this.readCcResourceModel(resourceType, physicalId);
|
|
21423
|
+
const model = await this.readCcResourceModel(resourceType, physicalId, log);
|
|
21374
21424
|
if (model) {
|
|
21375
21425
|
if (typeof model["Arn"] === "string") enriched["Arn"] = model["Arn"];
|
|
21376
21426
|
if (!enriched["CurrentState"] && typeof model["CurrentState"] === "string") enriched["CurrentState"] = model["CurrentState"];
|
|
21377
21427
|
if (!enriched["StateReason"] && typeof model["StateReason"] === "string") enriched["StateReason"] = model["StateReason"];
|
|
21378
21428
|
if (!enriched["CreationTime"] && typeof model["CreationTime"] === "string") enriched["CreationTime"] = model["CreationTime"];
|
|
21379
21429
|
if (!enriched["LastModifiedTime"] && typeof model["LastModifiedTime"] === "string") enriched["LastModifiedTime"] = model["LastModifiedTime"];
|
|
21380
|
-
|
|
21430
|
+
log.debug(`Enriched Pipes Pipe ${physicalId} with Arn from CC GetResource`);
|
|
21381
21431
|
}
|
|
21382
21432
|
}
|
|
21383
21433
|
break;
|
|
21384
21434
|
case "AWS::S3::AccessPoint":
|
|
21385
21435
|
if (!enriched["Arn"] || !enriched["Alias"]) {
|
|
21386
|
-
const model = await this.readCcResourceModel(resourceType, physicalId);
|
|
21436
|
+
const model = await this.readCcResourceModel(resourceType, physicalId, log);
|
|
21387
21437
|
if (model) {
|
|
21388
21438
|
if (!enriched["Arn"] && typeof model["Arn"] === "string") enriched["Arn"] = model["Arn"];
|
|
21389
21439
|
if (!enriched["Alias"] && typeof model["Alias"] === "string") enriched["Alias"] = model["Alias"];
|
|
21390
21440
|
if (!enriched["NetworkOrigin"] && typeof model["NetworkOrigin"] === "string") enriched["NetworkOrigin"] = model["NetworkOrigin"];
|
|
21391
|
-
|
|
21441
|
+
log.debug(`Enriched S3 AccessPoint ${physicalId} with Arn/Alias from CC GetResource`);
|
|
21392
21442
|
}
|
|
21393
21443
|
}
|
|
21394
21444
|
break;
|
|
21395
21445
|
case "AWS::ResourceGroups::Group": if (!enriched["Arn"]) {
|
|
21396
|
-
const model = await this.readCcResourceModel(resourceType, physicalId);
|
|
21446
|
+
const model = await this.readCcResourceModel(resourceType, physicalId, log);
|
|
21397
21447
|
if (model) {
|
|
21398
21448
|
if (typeof model["Arn"] === "string") enriched["Arn"] = model["Arn"];
|
|
21399
|
-
|
|
21449
|
+
log.debug(`Enriched ResourceGroups Group ${physicalId} with Arn from CC GetResource`);
|
|
21400
21450
|
}
|
|
21401
21451
|
}
|
|
21402
21452
|
}
|
|
21403
21453
|
return enriched;
|
|
21404
21454
|
}
|
|
21405
|
-
async mergeSparseModelReadback(resourceType, physicalId, attributes) {
|
|
21455
|
+
async mergeSparseModelReadback(resourceType, physicalId, attributes, log = this.logger) {
|
|
21406
21456
|
if (!this.isSparseAttributeMap(attributes, physicalId)) return attributes;
|
|
21407
|
-
const model = await this.readCcResourceModel(resourceType, physicalId);
|
|
21457
|
+
const model = await this.readCcResourceModel(resourceType, physicalId, log);
|
|
21408
21458
|
if (!model) return attributes;
|
|
21409
|
-
|
|
21459
|
+
log.debug(`Merged CC GetResource read-back over sparse ${resourceType} attributes for ${physicalId}`);
|
|
21410
21460
|
return {
|
|
21411
21461
|
...attributes,
|
|
21412
21462
|
...model
|
|
@@ -21419,7 +21469,7 @@ var CloudControlProvider = class {
|
|
|
21419
21469
|
identifierEchoes.add(physicalId);
|
|
21420
21470
|
return values.every((value) => typeof value === "string" && identifierEchoes.has(value));
|
|
21421
21471
|
}
|
|
21422
|
-
async readCcResourceModel(resourceType, physicalId) {
|
|
21472
|
+
async readCcResourceModel(resourceType, physicalId, log = this.logger) {
|
|
21423
21473
|
try {
|
|
21424
21474
|
const raw = (await this.cloudControlClient.send(new GetResourceCommand({
|
|
21425
21475
|
TypeName: resourceType,
|
|
@@ -21430,7 +21480,7 @@ var CloudControlProvider = class {
|
|
|
21430
21480
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return;
|
|
21431
21481
|
return parsed;
|
|
21432
21482
|
} catch (error) {
|
|
21433
|
-
|
|
21483
|
+
log.debug(`Failed to read CC model for ${resourceType} ${physicalId}: ${describeAwsFailure(error).detail}`);
|
|
21434
21484
|
return;
|
|
21435
21485
|
}
|
|
21436
21486
|
}
|
|
@@ -21538,6 +21588,28 @@ var CloudControlProvider = class {
|
|
|
21538
21588
|
return masked;
|
|
21539
21589
|
}
|
|
21540
21590
|
};
|
|
21591
|
+
function updateIdLogSink(logger, physicalId, properties, previousProperties, maskSecrets) {
|
|
21592
|
+
const mask = maskerOrIdentity(maskSecrets);
|
|
21593
|
+
const raw = updateIdWithheld(properties, previousProperties, mask) ? [physicalId, ...physicalId.split("|")].filter((needle) => needle !== "") : [];
|
|
21594
|
+
const masked = raw.map((needle) => mask(needle));
|
|
21595
|
+
const needles = [.../* @__PURE__ */ new Set([...raw, ...masked.filter((m, i) => m !== "" && m !== raw[i] && m !== "***")])].sort((a, b) => b.length - a.length);
|
|
21596
|
+
const scrub = (message) => needles.reduce((text, needle) => text.split(needle).join("***"), mask(message));
|
|
21597
|
+
return {
|
|
21598
|
+
debug: (message) => logger.debug(scrub(message)),
|
|
21599
|
+
warn: (message) => logger.warn(scrub(message)),
|
|
21600
|
+
withheld: needles.length > 0
|
|
21601
|
+
};
|
|
21602
|
+
}
|
|
21603
|
+
function updateIdWithheld(properties, previousProperties, mask) {
|
|
21604
|
+
return holdsSecretDerivedLeaf(properties, mask) || holdsSecretDerivedLeaf(previousProperties, mask);
|
|
21605
|
+
}
|
|
21606
|
+
function holdsSecretDerivedLeaf(value, mask, depth = 0) {
|
|
21607
|
+
if (typeof value === "string") return isSecretDerivedValue(value, mask);
|
|
21608
|
+
if (value === null || typeof value !== "object") return false;
|
|
21609
|
+
if (depth > 64) return true;
|
|
21610
|
+
if (Array.isArray(value)) return value.some((entry) => holdsSecretDerivedLeaf(entry, mask, depth + 1));
|
|
21611
|
+
return Object.entries(value).some(([key, entry]) => isSecretDerivedValue(key, mask) || holdsSecretDerivedLeaf(entry, mask, depth + 1));
|
|
21612
|
+
}
|
|
21541
21613
|
const IMPORT_YIELDED_NO_ATTRIBUTES_CONSEQUENCE = "Attributes the stack's state already records for this physical id are kept; without them, an Fn::GetAtt against this resource falls back to a value constructed from its physical id.";
|
|
21542
21614
|
function maskLeavesDeep(value) {
|
|
21543
21615
|
if (Array.isArray(value)) return value.map((element) => maskLeavesDeep(element));
|
|
@@ -24458,7 +24530,7 @@ var ProviderRegistry = class {
|
|
|
24458
24530
|
if (reroutable.length > 0) remedies.push(`Remove the override for ${reroutable.join(", ")} to route this resource via Cloud Control API instead.`);
|
|
24459
24531
|
if (needsRecreate.length > 0) {
|
|
24460
24532
|
const one = needsRecreate.length === 1;
|
|
24461
|
-
remedies.push(`${needsRecreate.join(", ")} ${one ? "is" : "are"} create-only, so removing the override does not apply ${one ? "it" : "them"}
|
|
24533
|
+
remedies.push(`${needsRecreate.join(", ")} ${one ? "is" : "are"} create-only, so removing the override does not apply ${one ? "it" : "them"} in place -- a create-only property can only be applied by recreating the resource. Where cdkd created the resource without ${one ? "it" : "them"}, a deploy without the override refuses unless something else already forces a replacement or the recreate is opted into.`);
|
|
24462
24534
|
}
|
|
24463
24535
|
this.logger.warn(`${logicalId} (${resourceType}): ${overridden.join(", ")} will be silently dropped (--prefer-sdk-route override accepted). ${remedies.join(" ")}`);
|
|
24464
24536
|
}
|
|
@@ -26183,6 +26255,19 @@ function maskedRollbackEventError(error, mask) {
|
|
|
26183
26255
|
message
|
|
26184
26256
|
};
|
|
26185
26257
|
}
|
|
26258
|
+
function recordRollbackSkip(scope, op, reason) {
|
|
26259
|
+
scope.result.warnings++;
|
|
26260
|
+
scope.result.skipped++;
|
|
26261
|
+
scope.ctx.recordEvent?.({
|
|
26262
|
+
eventType: "ROLLBACK_RESOURCE_SKIPPED",
|
|
26263
|
+
stackName: scope.stackName,
|
|
26264
|
+
operation: op.changeType,
|
|
26265
|
+
logicalId: op.logicalId,
|
|
26266
|
+
resourceType: op.resourceType,
|
|
26267
|
+
...op.provisionedBy && { provisionedBy: op.provisionedBy },
|
|
26268
|
+
reason: scope.mask(reason)
|
|
26269
|
+
});
|
|
26270
|
+
}
|
|
26186
26271
|
function effectiveProvisionedBy(record, fallbackProvisionedBy) {
|
|
26187
26272
|
return record?.provisionedBy ?? fallbackProvisionedBy;
|
|
26188
26273
|
}
|
|
@@ -26721,6 +26806,7 @@ function addRecordNames(opMasker, op, current) {
|
|
|
26721
26806
|
});
|
|
26722
26807
|
}
|
|
26723
26808
|
}
|
|
26809
|
+
const ABSENT_BASELINE_SKIP_CAUSE = "Its recorded previous state has no `properties` bag, so there is nothing to restore it to; the rollback left the resource exactly as it is.";
|
|
26724
26810
|
function requireRestorableBaseline(bag, logger, { logicalId, consequence, remedy, retry }) {
|
|
26725
26811
|
if (isRestorableBag(bag)) return true;
|
|
26726
26812
|
if (bag === void 0) {
|
|
@@ -26916,10 +27002,10 @@ async function replayOrphanRetain(s) {
|
|
|
26916
27002
|
});
|
|
26917
27003
|
}
|
|
26918
27004
|
async function replayDelete(s) {
|
|
26919
|
-
const { op, stateResources, stackName, ctx,
|
|
27005
|
+
const { op, stateResources, stackName, ctx, inlinePolicyWriters, afterOp, action, logger, mask } = s;
|
|
26920
27006
|
if (!op.physicalId) {
|
|
26921
27007
|
logger.warn(` Rollback: Cannot delete ${safe(op.logicalId)} — no physical ID recorded`);
|
|
26922
|
-
|
|
27008
|
+
recordRollbackSkip(s, op, "No physical id is recorded for the rolled-back CREATE, so the rollback cannot address it to delete it.");
|
|
26923
27009
|
return;
|
|
26924
27010
|
}
|
|
26925
27011
|
const deleteProvisionedBy = effectiveProvisionedBy(stateResources[op.logicalId], op.provisionedBy);
|
|
@@ -27004,17 +27090,17 @@ async function replayReadopt(s) {
|
|
|
27004
27090
|
});
|
|
27005
27091
|
}
|
|
27006
27092
|
async function replayRevert(s) {
|
|
27007
|
-
const { op, stateResources, stackName, ctx, resolver,
|
|
27093
|
+
const { op, stateResources, stackName, ctx, resolver, inlinePolicyWriters, afterOp, isInterrupted, logger, secrets, opMasker, mask } = s;
|
|
27008
27094
|
if (!op.previousState) {
|
|
27009
27095
|
logger.warn(` Rollback: Cannot restore ${safe(op.logicalId)} — no previous state available`);
|
|
27010
|
-
|
|
27096
|
+
recordRollbackSkip(s, op, "No previous state is recorded for it, so there is nothing to restore it to.");
|
|
27011
27097
|
return;
|
|
27012
27098
|
}
|
|
27013
27099
|
const previousState = op.previousState;
|
|
27014
27100
|
const current = stateResources[op.logicalId];
|
|
27015
27101
|
if (!current) {
|
|
27016
27102
|
logger.warn(` Rollback: Cannot restore ${safe(op.logicalId)} — resource not found in current state`);
|
|
27017
|
-
|
|
27103
|
+
recordRollbackSkip(s, op, "The resource is not in the current state, so the rollback had nothing to restore.");
|
|
27018
27104
|
return;
|
|
27019
27105
|
}
|
|
27020
27106
|
if (!requireRestorableBaseline(previousState.properties, logger, {
|
|
@@ -27023,7 +27109,7 @@ async function replayRevert(s) {
|
|
|
27023
27109
|
remedy: "Re-run `cdkd deploy` to re-converge it.",
|
|
27024
27110
|
retry: `re-running ${rerunRollbackPhrase(ctx, "`cdkd rollback`")} retries this op`
|
|
27025
27111
|
})) {
|
|
27026
|
-
|
|
27112
|
+
recordRollbackSkip(s, op, ABSENT_BASELINE_SKIP_CAUSE);
|
|
27027
27113
|
return;
|
|
27028
27114
|
}
|
|
27029
27115
|
logger.info(` Rollback: Restoring ${safe(op.logicalId)} (${safe(op.resourceType)}) to previous state`);
|
|
@@ -27102,7 +27188,7 @@ async function replayReverseReplacement(s) {
|
|
|
27102
27188
|
remedy: "Re-run `cdkd deploy` to re-converge it.",
|
|
27103
27189
|
retry: `re-running ${rerunRollbackPhrase(ctx, "`cdkd rollback`")} retries this op`
|
|
27104
27190
|
})) {
|
|
27105
|
-
|
|
27191
|
+
recordRollbackSkip(s, op, ABSENT_BASELINE_SKIP_CAUSE);
|
|
27106
27192
|
return;
|
|
27107
27193
|
}
|
|
27108
27194
|
const resolvedPrevProps = await resolveReplayProps(prev.properties, resolver, secrets, ctx, op.logicalId) ?? {};
|
|
@@ -27261,7 +27347,8 @@ async function replayReverseReplacement(s) {
|
|
|
27261
27347
|
physicalId: current.physicalId,
|
|
27262
27348
|
reason: mask(survivorReason),
|
|
27263
27349
|
...survivorProvisionedBy && { provisionedBy: survivorProvisionedBy }
|
|
27264
|
-
}
|
|
27350
|
+
},
|
|
27351
|
+
...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.") }
|
|
27265
27352
|
});
|
|
27266
27353
|
}
|
|
27267
27354
|
|
|
@@ -27317,6 +27404,7 @@ async function replayRollbackUnbound(operations, stateResources, stackName, ctx,
|
|
|
27317
27404
|
const result = {
|
|
27318
27405
|
failures: 0,
|
|
27319
27406
|
warnings: 0,
|
|
27407
|
+
skipped: 0,
|
|
27320
27408
|
interrupted: false,
|
|
27321
27409
|
orphaned: []
|
|
27322
27410
|
};
|
|
@@ -27387,18 +27475,18 @@ async function replaySingle(op, stateResources, stackName, ctx, resolver, orphan
|
|
|
27387
27475
|
switch (action) {
|
|
27388
27476
|
case "unrecoverable-delete":
|
|
27389
27477
|
logger.warn(` Rollback: Cannot restore deleted resource ${safe(op.logicalId)} (${safe(op.resourceType)}) — resource has already been deleted`);
|
|
27390
|
-
|
|
27478
|
+
recordRollbackSkip(scope, op, "The failed deploy deleted this resource, and a rollback cannot re-create a deleted resource.");
|
|
27391
27479
|
return;
|
|
27392
27480
|
case "skip-already-done":
|
|
27393
27481
|
logger.debug(` Rollback: ${safe(op.logicalId)} already reverted, skipping`);
|
|
27394
27482
|
return;
|
|
27395
27483
|
case "skip-mismatch":
|
|
27396
27484
|
logger.warn(` Rollback: Skipping ${safe(op.logicalId)} — its physical id changed since the failed deploy (replaced by a later attempt); manual attention may be required`);
|
|
27397
|
-
|
|
27485
|
+
recordRollbackSkip(scope, op, "Its physical id changed since the failed deploy (replaced by a later attempt), so the rollback left it as it is; manual attention may be required.");
|
|
27398
27486
|
return;
|
|
27399
27487
|
case "skip-absent":
|
|
27400
27488
|
logger.warn(` Rollback: Cannot restore ${safe(op.logicalId)} — resource no longer in state, skipping`);
|
|
27401
|
-
|
|
27489
|
+
recordRollbackSkip(scope, op, "The resource is no longer in state, so the rollback had nothing to restore.");
|
|
27402
27490
|
return;
|
|
27403
27491
|
case "refuse-replacement-routing": {
|
|
27404
27492
|
const routing = resolveReplacementOldType(op);
|
|
@@ -27433,6 +27521,7 @@ async function replayFailedOperationsUnbound(failedOps, stateResources, stackNam
|
|
|
27433
27521
|
const result = {
|
|
27434
27522
|
failures: 0,
|
|
27435
27523
|
warnings: 0,
|
|
27524
|
+
skipped: 0,
|
|
27436
27525
|
interrupted: false,
|
|
27437
27526
|
remainingFailedOps: [],
|
|
27438
27527
|
orphaned: []
|
|
@@ -27456,6 +27545,12 @@ async function replayFailedOperationsUnbound(failedOps, stateResources, stackNam
|
|
|
27456
27545
|
const secrets = /* @__PURE__ */ new Map();
|
|
27457
27546
|
const opMasker = createOpMasker(logger, secrets);
|
|
27458
27547
|
const mask = opMasker.mask;
|
|
27548
|
+
const skipScope = {
|
|
27549
|
+
ctx,
|
|
27550
|
+
stackName,
|
|
27551
|
+
result,
|
|
27552
|
+
mask
|
|
27553
|
+
};
|
|
27459
27554
|
let createRollbackRoute;
|
|
27460
27555
|
try {
|
|
27461
27556
|
addRecordNames(opMasker, op, stateResources[op.logicalId]);
|
|
@@ -27465,15 +27560,15 @@ async function replayFailedOperationsUnbound(failedOps, stateResources, stackNam
|
|
|
27465
27560
|
break;
|
|
27466
27561
|
case "skip-failed-unknown":
|
|
27467
27562
|
logger.warn(` Rollback: failed CREATE of ${safe(op.logicalId)} (${safe(op.resourceType)}) recorded no physical id — if it was partially created in AWS, delete it manually`);
|
|
27468
|
-
|
|
27563
|
+
recordRollbackSkip(skipScope, op, "The failed CREATE recorded no physical id, so the rollback cannot address it; if it was partially created in AWS, delete it manually.");
|
|
27469
27564
|
break;
|
|
27470
27565
|
case "skip-failed-absent":
|
|
27471
27566
|
logger.warn(` Rollback: cannot revert failed UPDATE of ${safe(op.logicalId)} — no previous state available, skipping`);
|
|
27472
|
-
|
|
27567
|
+
recordRollbackSkip(skipScope, op, "No previous state is available for the failed UPDATE, so there is nothing to revert it to.");
|
|
27473
27568
|
break;
|
|
27474
27569
|
case "skip-failed-type-change":
|
|
27475
27570
|
logger.warn(` Rollback: cannot revert failed UPDATE of ${shownLogicalId(op.logicalId)} in place — it was a Type change (${refusalResourceType(op.previousState?.resourceType)} -> ${refusalResourceType(op.resourceType)}), which is a replacement, and its remote state is unknown. Inspect it with \`cdkd drift\` and re-converge with \`cdkd deploy\`. Skipping.`);
|
|
27476
|
-
|
|
27571
|
+
recordRollbackSkip(skipScope, op, `The failed UPDATE was a Type change (${String(op.previousState?.resourceType)} -> ${String(op.resourceType)}), which is a replacement, and its remote state is unknown, so it cannot be reverted in place.`);
|
|
27477
27572
|
break;
|
|
27478
27573
|
case "orphan-failed-create-retain": {
|
|
27479
27574
|
const failedCreateRecord = stateResources[op.logicalId];
|
|
@@ -27546,7 +27641,7 @@ async function replayFailedOperationsUnbound(failedOps, stateResources, stackNam
|
|
|
27546
27641
|
remedy: "Inspect it with `cdkd drift` (this op died mid-flight, so its remote state is unknown) and re-converge with `cdkd drift --revert` or `cdkd deploy`.",
|
|
27547
27642
|
retry: "re-running `cdkd rollback --revert-failed` retries this op (a plain `cdkd rollback` replays only the COMPLETED ops and then pops the whole segment, discarding this record)"
|
|
27548
27643
|
})) {
|
|
27549
|
-
|
|
27644
|
+
recordRollbackSkip(skipScope, op, ABSENT_BASELINE_SKIP_CAUSE);
|
|
27550
27645
|
break;
|
|
27551
27646
|
}
|
|
27552
27647
|
logger.info(` Rollback: force-reverting failed UPDATE of ${safe(op.logicalId)} (${safe(op.resourceType)}) to its pre-deploy properties (--revert-failed; remote state is unknown)`);
|
|
@@ -28096,6 +28191,7 @@ async function performRollback(completedOperations, stateResources, stackName, p
|
|
|
28096
28191
|
return {
|
|
28097
28192
|
failures: result.failures,
|
|
28098
28193
|
warnings: result.warnings + run.warnings,
|
|
28194
|
+
skipped: result.skipped,
|
|
28099
28195
|
orphaned: result.orphaned,
|
|
28100
28196
|
settledNested: run.settled
|
|
28101
28197
|
};
|
|
@@ -28145,7 +28241,7 @@ async function settleJournalAfterCleanRollback(stackName, failedOperations, init
|
|
|
28145
28241
|
this.logger.warn(safeMsg`Failed to settle the rollback journal after the clean rollback: ${err instanceof Error ? err.message : String(err)}. ` + `The journal keeps the full segment; a later rollback replay is idempotent.`);
|
|
28146
28242
|
return false;
|
|
28147
28243
|
}
|
|
28148
|
-
await this.writeRollbackJournalSegment(stackName, [], failedOperations, "auto-rollback-clean", initialDeploy);
|
|
28244
|
+
if (!await this.writeRollbackJournalSegment(stackName, [], failedOperations, "auto-rollback-clean", initialDeploy)) return true;
|
|
28149
28245
|
this.logger.info(`The automatic rollback restored the pre-deploy state. The failed resource's pre-failure record was kept — if it was left partially applied, revert it.\nRevert it with: ${pasteableCommand("cdkd rollback", [{
|
|
28150
28246
|
value: stackName,
|
|
28151
28247
|
hole: "stack"
|
|
@@ -28193,7 +28289,7 @@ function producerRegionEvidence(previousState) {
|
|
|
28193
28289
|
return inheritProducerRegions(own, this.options.inheritedProducerRegions?.());
|
|
28194
28290
|
}
|
|
28195
28291
|
async function writeRollbackJournalSegment(stackName, completedOperations, failedOperations, reason, initialDeploy, nestedPending) {
|
|
28196
|
-
if (!nestedPending && completedOperations.length === 0 && failedOperations.length === 0) return;
|
|
28292
|
+
if (!nestedPending && completedOperations.length === 0 && failedOperations.length === 0) return false;
|
|
28197
28293
|
const redactedCompleted = this.redactOperationsForJournal(completedOperations);
|
|
28198
28294
|
const redactedFailed = this.redactOperationsForJournal(failedOperations);
|
|
28199
28295
|
try {
|
|
@@ -28212,8 +28308,10 @@ async function writeRollbackJournalSegment(stackName, completedOperations, faile
|
|
|
28212
28308
|
};
|
|
28213
28309
|
await this.stateBackend.appendRollbackJournalSegment(stackName, this.stackRegion, segment);
|
|
28214
28310
|
this.logger.debug(`Rollback journal segment written (${reason})`);
|
|
28311
|
+
return true;
|
|
28215
28312
|
} catch (journalError) {
|
|
28216
28313
|
this.logger.warn(`Failed to write rollback journal: ${journalError instanceof Error ? journalError.message : String(journalError)}. 'cdkd rollback' will NOT be able to revert this deploy — use 'cdkd deploy' to resume or 'cdkd destroy' to clean up.`);
|
|
28314
|
+
return false;
|
|
28217
28315
|
}
|
|
28218
28316
|
}
|
|
28219
28317
|
|
|
@@ -29147,6 +29245,45 @@ function hasUnpersistedHeals(resources) {
|
|
|
29147
29245
|
return false;
|
|
29148
29246
|
}
|
|
29149
29247
|
|
|
29248
|
+
//#endregion
|
|
29249
|
+
//#region src/deployment/deploy-engine/record-shape.ts
|
|
29250
|
+
function auditResolvedAssetReferences(logicalId, resourceType, resolvedProps) {
|
|
29251
|
+
const redirect = this.options.assetRedirect;
|
|
29252
|
+
if (!redirect) return;
|
|
29253
|
+
const findings = findUnrewrittenAssetReferences(resolvedProps, redirect);
|
|
29254
|
+
if (findings.length === 0) return;
|
|
29255
|
+
const detail = findings.map((f) => ` - ${f.path}: still references '${f.source}'`).join("\n");
|
|
29256
|
+
throw new ProvisioningError(`Unrewritten asset reference on '${logicalId}' (${resourceType}): this region uses cdkd-owned asset storage, but the following resolved properties still point at the CDK bootstrap storage that 'cdk gc' may garbage-collect:\n${detail}\nThis is a template shape cdkd's asset-reference rewrite did not cover — deploying it would split-brain the stack (assets in cdkd storage, properties reading the CDK bucket). Please report this at https://github.com/go-to-k/cdkd/issues with the property shape. Workaround: deploy with --use-cdk-bootstrap-assets to pin the legacy destinations for this app.`, resourceType, logicalId);
|
|
29257
|
+
}
|
|
29258
|
+
function extractAllDependencies(template, logicalId) {
|
|
29259
|
+
const resource = template?.Resources?.[logicalId];
|
|
29260
|
+
if (!resource) return void 0;
|
|
29261
|
+
const parser = new TemplateParser();
|
|
29262
|
+
const parameterNames = new Set(Object.keys(template?.Parameters ?? {}));
|
|
29263
|
+
const deps = [...parser.extractDependencies(resource)].filter((dep) => !parameterNames.has(dep));
|
|
29264
|
+
return deps.length > 0 ? deps : void 0;
|
|
29265
|
+
}
|
|
29266
|
+
function propertiesToRecord(desiredProperties, result, resourceType, provisionedBy) {
|
|
29267
|
+
if (result.effectiveProperties) return provisionedBy === "sdk" ? withoutSilentDropProperties(resourceType, result.effectiveProperties) : result.effectiveProperties;
|
|
29268
|
+
const written = provisionedBy === "sdk" ? withoutSilentDropProperties(resourceType, desiredProperties) : desiredProperties;
|
|
29269
|
+
return markSameGenerationBag(written);
|
|
29270
|
+
}
|
|
29271
|
+
function extractTemplateAttributes(template, logicalId) {
|
|
29272
|
+
const resource = template?.Resources?.[logicalId];
|
|
29273
|
+
return {
|
|
29274
|
+
deletionPolicy: resource?.DeletionPolicy,
|
|
29275
|
+
updateReplacePolicy: resource?.UpdateReplacePolicy
|
|
29276
|
+
};
|
|
29277
|
+
}
|
|
29278
|
+
function acceptedCreateOnlyDropsField(recordedProperties, resourceType, provisionedBy, mode, previous) {
|
|
29279
|
+
if (provisionedBy !== "sdk") return { acceptedCreateOnlyDrops: void 0 };
|
|
29280
|
+
const createOnly = getPropertyCoverage(resourceType)?.createOnlyDrops;
|
|
29281
|
+
if (createOnly === void 0 || createOnly.size === 0) return { acceptedCreateOnlyDrops: void 0 };
|
|
29282
|
+
const carried = mode === "in-place" ? acceptedCreateOnlyDropsOf(previous) : void 0;
|
|
29283
|
+
const names = findSilentDropProperties(resourceType, recordedProperties).map(({ property }) => property).filter((property) => createOnly.has(property) && (carried === void 0 || carried.has(property)));
|
|
29284
|
+
return { acceptedCreateOnlyDrops: names.length > 0 ? names : void 0 };
|
|
29285
|
+
}
|
|
29286
|
+
|
|
29150
29287
|
//#endregion
|
|
29151
29288
|
//#region src/utils/resource-line.ts
|
|
29152
29289
|
function formatResourceLine(op, logicalId, resourceType, verbOverride) {
|
|
@@ -29160,6 +29297,75 @@ function formatResourceLine(op, logicalId, resourceType, verbOverride) {
|
|
|
29160
29297
|
}
|
|
29161
29298
|
}
|
|
29162
29299
|
|
|
29300
|
+
//#endregion
|
|
29301
|
+
//#region src/deployment/prior-attempt-scope.ts
|
|
29302
|
+
const priorAttemptStore = new AsyncLocalStorage();
|
|
29303
|
+
function withPriorAttempts(lookup, fn) {
|
|
29304
|
+
return priorAttemptStore.run(lookup, fn);
|
|
29305
|
+
}
|
|
29306
|
+
function priorAttemptLookup(logicalId, attempts) {
|
|
29307
|
+
let landed = false;
|
|
29308
|
+
return {
|
|
29309
|
+
logicalId,
|
|
29310
|
+
attempts,
|
|
29311
|
+
notePossiblyLanded: () => {
|
|
29312
|
+
landed = true;
|
|
29313
|
+
},
|
|
29314
|
+
possiblyLanded: () => landed
|
|
29315
|
+
};
|
|
29316
|
+
}
|
|
29317
|
+
function getPriorAttempts(logicalId) {
|
|
29318
|
+
const bound = priorAttemptStore.getStore();
|
|
29319
|
+
return bound?.logicalId === logicalId ? bound : void 0;
|
|
29320
|
+
}
|
|
29321
|
+
function priorAttemptsInJournal(journal, logicalId, resourceType) {
|
|
29322
|
+
let bags = [];
|
|
29323
|
+
for (const segment of journal?.segments ?? []) {
|
|
29324
|
+
if (segment.operations.some((op) => op.logicalId === logicalId)) bags = [];
|
|
29325
|
+
for (const op of segment.failedOperations ?? []) {
|
|
29326
|
+
if (op.logicalId !== logicalId || op.resourceType !== resourceType) continue;
|
|
29327
|
+
if (op.changeType === "DELETE" || !isBag(op.attemptedProperties)) continue;
|
|
29328
|
+
if (recordedAsNewResource(op)) continue;
|
|
29329
|
+
bags.push(op.attemptedProperties);
|
|
29330
|
+
}
|
|
29331
|
+
if (segment.supersededLogicalIds?.includes(logicalId)) bags = [];
|
|
29332
|
+
}
|
|
29333
|
+
return bags;
|
|
29334
|
+
}
|
|
29335
|
+
function recordedAsNewResource(op) {
|
|
29336
|
+
if (typeof op.physicalId !== "string" || op.physicalId === "") return false;
|
|
29337
|
+
if (op.changeType === "CREATE") return true;
|
|
29338
|
+
const previous = op.previousState?.physicalId;
|
|
29339
|
+
return typeof previous === "string" && previous !== op.physicalId;
|
|
29340
|
+
}
|
|
29341
|
+
function isBag(value) {
|
|
29342
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
29343
|
+
}
|
|
29344
|
+
const REFUSED_BEFORE_APPLYING = Symbol.for("cdkd.refusedBeforeApplying");
|
|
29345
|
+
const MAX_CAUSE_DEPTH = 10;
|
|
29346
|
+
function markRefusedBeforeApplying(error) {
|
|
29347
|
+
if (!Object.isExtensible(error)) return error;
|
|
29348
|
+
Object.defineProperty(error, REFUSED_BEFORE_APPLYING, {
|
|
29349
|
+
value: true,
|
|
29350
|
+
enumerable: false,
|
|
29351
|
+
configurable: true,
|
|
29352
|
+
writable: false
|
|
29353
|
+
});
|
|
29354
|
+
return error;
|
|
29355
|
+
}
|
|
29356
|
+
function isRefusedBeforeApplying(error, logicalId) {
|
|
29357
|
+
let current = error;
|
|
29358
|
+
for (let depth = 0; depth < MAX_CAUSE_DEPTH && current != null; depth++) {
|
|
29359
|
+
if (typeof current === "object" || typeof current === "function") {
|
|
29360
|
+
const linkId = current.logicalId;
|
|
29361
|
+
if (typeof linkId === "string" && linkId !== logicalId) return false;
|
|
29362
|
+
if (current[REFUSED_BEFORE_APPLYING] === true) return true;
|
|
29363
|
+
}
|
|
29364
|
+
current = current.cause;
|
|
29365
|
+
}
|
|
29366
|
+
return false;
|
|
29367
|
+
}
|
|
29368
|
+
|
|
29163
29369
|
//#endregion
|
|
29164
29370
|
//#region src/deployment/deploy-engine/create.ts
|
|
29165
29371
|
async function provisionCreate(logicalId, change, stateResources, stackName, template, parameterValues, conditions, counts, progress) {
|
|
@@ -29202,10 +29408,12 @@ async function provisionCreate(logicalId, change, stateResources, stackName, tem
|
|
|
29202
29408
|
this.registerNoEchoAttributes(logicalId, result, createSecrets, resolvedProps);
|
|
29203
29409
|
const dependencies = this.extractAllDependencies(template, logicalId);
|
|
29204
29410
|
const templateAttrs = this.extractTemplateAttributes(template, logicalId);
|
|
29411
|
+
const recordedProperties = this.propertiesToRecord(resolvedProps, result, resourceType, createDecision.provisionedBy);
|
|
29205
29412
|
stateResources[logicalId] = {
|
|
29206
29413
|
physicalId: result.physicalId,
|
|
29207
29414
|
resourceType,
|
|
29208
|
-
properties:
|
|
29415
|
+
properties: recordedProperties,
|
|
29416
|
+
...acceptedCreateOnlyDropsField(recordedProperties, resourceType, createDecision.provisionedBy, "new-resource"),
|
|
29209
29417
|
...result.attributes && { attributes: result.attributes },
|
|
29210
29418
|
...dependencies && dependencies.length > 0 && { dependencies },
|
|
29211
29419
|
...templateAttrs,
|
|
@@ -29239,7 +29447,7 @@ async function refuseTakenCreateName(input) {
|
|
|
29239
29447
|
const named = `${question.property} ${shown(question.desiredName)}`;
|
|
29240
29448
|
const adoptsText = "its create API hands back or overwrites an existing resource of that name instead of refusing it";
|
|
29241
29449
|
const refuse = (message, cause) => {
|
|
29242
|
-
throw markNonRetryable(new CdkdError(maskName(message), "NAMED_CREATE_COLLISION", cause instanceof Error ? cause : void 0));
|
|
29450
|
+
throw markNonRetryable(markRefusedBeforeApplying(new CdkdError(maskName(message), "NAMED_CREATE_COLLISION", cause instanceof Error ? cause : void 0)));
|
|
29243
29451
|
};
|
|
29244
29452
|
let knownPhysicalId;
|
|
29245
29453
|
const byArn = ["AWS::SNS::Topic", "AWS::StepFunctions::StateMachine"].includes(resourceType) ? createLookupArn(resourceType, question.desiredName, await getAccountInfo(this.stackRegion)) : void 0;
|
|
@@ -29272,262 +29480,6 @@ async function refuseTakenCreateName(input) {
|
|
|
29272
29480
|
return refuse(`${subject} is created with ${named}, and an existing resource (${shown(holderId)}) already holds that name. Since ${adoptsText}, creating it would take that resource over and record it as this stack's, for a later \`cdkd destroy\` to delete. Nothing was created. Choose a name no other resource holds; ` + ownRemedy);
|
|
29273
29481
|
}
|
|
29274
29482
|
|
|
29275
|
-
//#endregion
|
|
29276
|
-
//#region src/deployment/deploy-value-equality.ts
|
|
29277
|
-
function isReplacementCeiling(pc) {
|
|
29278
|
-
return pc.requiresReplacement && (pc.inPlacePropagated === true || pc.replacementPropagated === true);
|
|
29279
|
-
}
|
|
29280
|
-
function keyOrderFreeJson(value) {
|
|
29281
|
-
return JSON.stringify(value, (_key, node) => {
|
|
29282
|
-
if (node === null || typeof node !== "object" || Array.isArray(node)) return node;
|
|
29283
|
-
const sorted = Object.create(null);
|
|
29284
|
-
for (const key of Object.keys(node).sort()) sorted[key] = node[key];
|
|
29285
|
-
return sorted;
|
|
29286
|
-
});
|
|
29287
|
-
}
|
|
29288
|
-
function liveHoldsFreshLeaves(live, leaves) {
|
|
29289
|
-
for (const leaf of leaves) {
|
|
29290
|
-
let node = live;
|
|
29291
|
-
for (const segment of leaf.path) {
|
|
29292
|
-
if (typeof segment === "number") {
|
|
29293
|
-
if (!Array.isArray(node) || segment >= node.length) return false;
|
|
29294
|
-
node = node[segment];
|
|
29295
|
-
continue;
|
|
29296
|
-
}
|
|
29297
|
-
if (node === null || typeof node !== "object" || Array.isArray(node)) return false;
|
|
29298
|
-
if (!Object.prototype.hasOwnProperty.call(node, segment)) return false;
|
|
29299
|
-
node = node[segment];
|
|
29300
|
-
}
|
|
29301
|
-
if (typeof node !== "string" || node !== leaf.plaintext) return false;
|
|
29302
|
-
}
|
|
29303
|
-
return true;
|
|
29304
|
-
}
|
|
29305
|
-
function outputMapsEqual(a, b) {
|
|
29306
|
-
return deepEqualValue(a, b);
|
|
29307
|
-
}
|
|
29308
|
-
function deepEqualValue(a, b) {
|
|
29309
|
-
if (a === b) return true;
|
|
29310
|
-
if (a == null || b == null) return a === b;
|
|
29311
|
-
if (typeof a !== typeof b) return false;
|
|
29312
|
-
if (typeof a !== "object") return false;
|
|
29313
|
-
if (Array.isArray(a) || Array.isArray(b)) {
|
|
29314
|
-
if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return false;
|
|
29315
|
-
return a.every((v, i) => deepEqualValue(v, b[i]));
|
|
29316
|
-
}
|
|
29317
|
-
const ao = a;
|
|
29318
|
-
const bo = b;
|
|
29319
|
-
const ak = Object.keys(ao);
|
|
29320
|
-
if (ak.length !== Object.keys(bo).length) return false;
|
|
29321
|
-
for (const k of ak) {
|
|
29322
|
-
if (!Object.prototype.hasOwnProperty.call(bo, k)) return false;
|
|
29323
|
-
if (!deepEqualValue(ao[k], bo[k])) return false;
|
|
29324
|
-
}
|
|
29325
|
-
return true;
|
|
29326
|
-
}
|
|
29327
|
-
|
|
29328
|
-
//#endregion
|
|
29329
|
-
//#region src/deployment/deploy-engine/update.ts
|
|
29330
|
-
async function provisionUpdate(logicalId, change, stateResources, stackName, template, parameterValues, conditions, counts, progress) {
|
|
29331
|
-
const resourceType = change.resourceType;
|
|
29332
|
-
const existingState = stateResources[logicalId];
|
|
29333
|
-
const renderer = getLiveRenderer();
|
|
29334
|
-
const currentResource = existingState;
|
|
29335
|
-
if (!currentResource) throw new Error(`Cannot update ${logicalId}: resource not found in state`);
|
|
29336
|
-
const oldResourceType = currentResource.resourceType;
|
|
29337
|
-
const typeChanged = oldResourceType !== resourceType;
|
|
29338
|
-
const desiredProps = change.desiredProperties || {};
|
|
29339
|
-
const currentProps = change.currentProperties || {};
|
|
29340
|
-
const currentPropsAsWritten = currentResource.provisionedBy === "cc-api" ? currentProps : withoutSilentDropProperties(resourceType, currentProps);
|
|
29341
|
-
const context = this.buildResolverContext({
|
|
29342
|
-
template,
|
|
29343
|
-
resources: stateResources,
|
|
29344
|
-
...parameterValues && { parameters: parameterValues },
|
|
29345
|
-
...conditions && { conditions },
|
|
29346
|
-
redactedAttributeReads: []
|
|
29347
|
-
}, stackName);
|
|
29348
|
-
const updateSecrets = context.recordedSecretValues ?? /* @__PURE__ */ new Map();
|
|
29349
|
-
this.perResourceSecrets.set(logicalId, updateSecrets);
|
|
29350
|
-
const resolvedProps = await this.resolver.resolve(desiredProps, context);
|
|
29351
|
-
this.perResourceTemplateProps.set(logicalId, desiredProps);
|
|
29352
|
-
this.perResourceResolvedType.set(logicalId, resourceType);
|
|
29353
|
-
recordNestedStackParameterExpressions(updateSecrets, resourceType, resolvedProps, desiredProps);
|
|
29354
|
-
this.auditResolvedAssetReferences(logicalId, resourceType, resolvedProps);
|
|
29355
|
-
const lostCandidate = childLostWithRecreatedParent({
|
|
29356
|
-
resourceType,
|
|
29357
|
-
templateProperties: desiredProps,
|
|
29358
|
-
recreatedUnderSameId: this.recreatedUnderSameId,
|
|
29359
|
-
recordedTypeOf: (id) => Object.hasOwn(stateResources, id) ? stateResources[id]?.resourceType : void 0,
|
|
29360
|
-
conditions
|
|
29361
|
-
});
|
|
29362
|
-
const lostChild = lostCandidate?.mode === "reattach" || lostCandidate !== void 0 && Object.hasOwn(resolvedProps, lostCandidate.property) && Object.hasOwn(currentProps, lostCandidate.property) && keyOrderFreeJson(resolvedProps[lostCandidate.property]) === keyOrderFreeJson(currentProps[lostCandidate.property]) ? lostCandidate : void 0;
|
|
29363
|
-
const lostWithParent = lostChild?.mode === "recreate" ? lostChild.parent : void 0;
|
|
29364
|
-
const suppliesFreshMaskOnlyValue = carriesFreshNoEchoValue(resolvedProps, updateSecrets);
|
|
29365
|
-
const desiredForSkipCheck = redactSecretsForState(markSameGenerationBag({ ...resolvedProps }), updateSecrets, desiredProps);
|
|
29366
|
-
const allowedSilentDrops = this.providerRegistry.getAllowedUnsupportedProperties?.();
|
|
29367
|
-
const desiredForSkipCheckAsWritten = currentResource.provisionedBy !== "cc-api" && allowedSilentDrops ? withoutAcceptedSilentDropProperties(resourceType, desiredForSkipCheck, allowedSilentDrops, currentResource.properties) : desiredForSkipCheck;
|
|
29368
|
-
const applyAttributeOnlyUpdate = (attributeChanges) => {
|
|
29369
|
-
const attrSummary = attributeChanges.map((a) => `${a.attribute}: ${a.oldValue ?? "(unset)"} → ${a.newValue ?? "(unset)"}`).join(", ");
|
|
29370
|
-
this.logger.info(safeMsg` ↻ ${logicalId} (${resourceType}) attribute update: ${attrSummary}`);
|
|
29371
|
-
stateResources[logicalId] = {
|
|
29372
|
-
...currentResource,
|
|
29373
|
-
...this.extractTemplateAttributes(template, logicalId)
|
|
29374
|
-
};
|
|
29375
|
-
if (counts) counts.updated++;
|
|
29376
|
-
if (progress) progress.current++;
|
|
29377
|
-
const attrPrefix = progress ? `[${progress.current}/${progress.total}] ` : " ";
|
|
29378
|
-
renderer.removeTask(logicalId);
|
|
29379
|
-
this.logger.info(safeMsg`${attrPrefix}${formatResourceLine("updated", logicalId, resourceType, "updated (metadata)")}`);
|
|
29380
|
-
};
|
|
29381
|
-
if (!typeChanged && !suppliesFreshMaskOnlyValue && lostChild === void 0 && this.recreateDirectionFor(stackName, logicalId) === void 0 && keyOrderFreeJson(desiredForSkipCheckAsWritten) === keyOrderFreeJson(currentPropsAsWritten)) {
|
|
29382
|
-
if (change.attributeChanges && change.attributeChanges.length > 0) {
|
|
29383
|
-
applyAttributeOnlyUpdate(change.attributeChanges);
|
|
29384
|
-
return;
|
|
29385
|
-
}
|
|
29386
|
-
this.logger.debug(`Skipping ${logicalId}: no actual changes after intrinsic function resolution`);
|
|
29387
|
-
if (counts) counts.skipped++;
|
|
29388
|
-
return;
|
|
29389
|
-
}
|
|
29390
|
-
this.refuseRedactedAttributeReads(logicalId, resourceType, context);
|
|
29391
|
-
this.attemptedResolvedProps.set(logicalId, resolvedProps);
|
|
29392
|
-
const noEchoHeldPaths = /* @__PURE__ */ new Set();
|
|
29393
|
-
if (change.propertyChanges?.some((pc) => pc.requiresReplacement) === true) {
|
|
29394
|
-
let readback;
|
|
29395
|
-
const lowered = [];
|
|
29396
|
-
for (const pc of change.propertyChanges) {
|
|
29397
|
-
if (!pc.requiresReplacement) {
|
|
29398
|
-
lowered.push(pc);
|
|
29399
|
-
continue;
|
|
29400
|
-
}
|
|
29401
|
-
const freshLeaves = freshNoEchoLeafPositions(resolvedProps[pc.path], updateSecrets);
|
|
29402
|
-
if (!isReplacementCeiling(pc) && freshLeaves.length === 0) {
|
|
29403
|
-
lowered.push(pc);
|
|
29404
|
-
continue;
|
|
29405
|
-
}
|
|
29406
|
-
const moved = keyOrderFreeJson(desiredForSkipCheckAsWritten[pc.path]) !== keyOrderFreeJson(currentPropsAsWritten[pc.path]);
|
|
29407
|
-
const conditionalVerdict = moved && !typeChanged && isReplacementCeiling(pc) ? this.diffCalculator.conditionalReplacementVerdict?.(resourceType, pc.path, currentPropsAsWritten[pc.path], desiredForSkipCheckAsWritten[pc.path]) : void 0;
|
|
29408
|
-
if (moved && conditionalVerdict !== false) {
|
|
29409
|
-
lowered.push(pc);
|
|
29410
|
-
continue;
|
|
29411
|
-
}
|
|
29412
|
-
if (freshLeaves.length > 0) {
|
|
29413
|
-
if (typeChanged) {
|
|
29414
|
-
lowered.push(pc);
|
|
29415
|
-
continue;
|
|
29416
|
-
}
|
|
29417
|
-
readback ??= this.readReaderForFreshNoEchoCeiling(logicalId, currentResource, updateSecrets);
|
|
29418
|
-
const read = await readback;
|
|
29419
|
-
let verdict;
|
|
29420
|
-
if ("failure" in read) verdict = read.failure;
|
|
29421
|
-
else if (!Object.prototype.hasOwnProperty.call(read.live, pc.path)) verdict = "not-readable";
|
|
29422
|
-
else verdict = liveHoldsFreshLeaves(read.live[pc.path], freshLeaves) ? "held" : "differs";
|
|
29423
|
-
if (verdict !== "held") {
|
|
29424
|
-
this.logger.warn(safeMsg`${logicalId}.${pc.path} carries a NoEcho value that AWS could not confirm unchanged (${verdict}): replacement kept.`);
|
|
29425
|
-
lowered.push(pc);
|
|
29426
|
-
continue;
|
|
29427
|
-
}
|
|
29428
|
-
this.logger.debug(safeMsg`${logicalId}.${pc.path} carries a NoEcho value AWS already holds: not replaced.`);
|
|
29429
|
-
noEchoHeldPaths.add(pc.path);
|
|
29430
|
-
}
|
|
29431
|
-
lowered.push({
|
|
29432
|
-
...pc,
|
|
29433
|
-
requiresReplacement: false
|
|
29434
|
-
});
|
|
29435
|
-
}
|
|
29436
|
-
change.propertyChanges = lowered;
|
|
29437
|
-
}
|
|
29438
|
-
if (noEchoHeldPaths.size > 0 && !typeChanged && lostChild === void 0 && this.recreateDirectionFor(stackName, logicalId) === void 0 && keyOrderFreeJson(desiredForSkipCheckAsWritten) === keyOrderFreeJson(currentPropsAsWritten) && Object.entries(resolvedProps).every(([key, value]) => noEchoHeldPaths.has(key) || freshNoEchoLeafPositions(value, updateSecrets).length === 0)) {
|
|
29439
|
-
this.logger.debug(safeMsg`Skipping ${logicalId}: AWS already holds every NoEcho value it carries, and nothing else changed`);
|
|
29440
|
-
this.attemptedResolvedProps.delete(logicalId);
|
|
29441
|
-
if (change.attributeChanges && change.attributeChanges.length > 0) {
|
|
29442
|
-
applyAttributeOnlyUpdate(change.attributeChanges);
|
|
29443
|
-
return;
|
|
29444
|
-
}
|
|
29445
|
-
if (counts) counts.skipped++;
|
|
29446
|
-
return;
|
|
29447
|
-
}
|
|
29448
|
-
const propertyDrivenReplacement = typeChanged || change.propertyChanges?.some((pc) => pc.requiresReplacement);
|
|
29449
|
-
const recreateTargets = this.options.recreateTargets?.stackName === stackName ? this.options.recreateTargets : void 0;
|
|
29450
|
-
const recreateViaCcApi = recreateTargets?.viaCcApi.has(logicalId) ?? false;
|
|
29451
|
-
const recreateViaSdkProvider = recreateTargets?.viaSdkProvider.has(logicalId) ?? false;
|
|
29452
|
-
const recreateFlagged = recreateViaCcApi || recreateViaSdkProvider;
|
|
29453
|
-
const needsReplacement = propertyDrivenReplacement || recreateFlagged || lostWithParent !== void 0;
|
|
29454
|
-
const liveLabel = this.liveTaskLabels.get(logicalId);
|
|
29455
|
-
if (needsReplacement && liveLabel !== void 0 && !liveLabel.replacing) {
|
|
29456
|
-
const label = `Replacing ${logicalId} (${resourceType})${this.peekRoutingForLabel(change, currentResource, stackName, logicalId, true, this.recreateDirectionFor(stackName, logicalId)) === "cc-api" ? " [CC API]" : ""}`;
|
|
29457
|
-
this.liveTaskLabels.set(logicalId, {
|
|
29458
|
-
label,
|
|
29459
|
-
replacing: true,
|
|
29460
|
-
...liveLabel.warnSuffix !== void 0 && { warnSuffix: liveLabel.warnSuffix }
|
|
29461
|
-
});
|
|
29462
|
-
renderer.updateTaskLabel(logicalId, `${label}${liveLabel.warnSuffix ?? ""}`);
|
|
29463
|
-
} else if (!needsReplacement && liveLabel !== void 0 && liveLabel.replacing) {
|
|
29464
|
-
const label = `Updating ${logicalId} (${resourceType})${this.peekRoutingForLabel(change, currentResource, stackName, logicalId, false, this.recreateDirectionFor(stackName, logicalId)) === "cc-api" ? " [CC API]" : ""}`;
|
|
29465
|
-
this.liveTaskLabels.set(logicalId, {
|
|
29466
|
-
label,
|
|
29467
|
-
replacing: false,
|
|
29468
|
-
...liveLabel.warnSuffix !== void 0 && { warnSuffix: liveLabel.warnSuffix }
|
|
29469
|
-
});
|
|
29470
|
-
renderer.updateTaskLabel(logicalId, `${label}${liveLabel.warnSuffix ?? ""}`);
|
|
29471
|
-
}
|
|
29472
|
-
const dependencies = this.extractAllDependencies(template, logicalId);
|
|
29473
|
-
const updateReplacePolicy = template?.Resources?.[logicalId]?.UpdateReplacePolicy;
|
|
29474
|
-
const markRestored = (outcome) => {
|
|
29475
|
-
if (lostChild === void 0) return outcome;
|
|
29476
|
-
if (this.updatesThatSentNothing.has(logicalId)) {
|
|
29477
|
-
this.logger.warn(survivesParent(resourceType) ? safeMsg` ⚠ ${logicalId} lost its attachment to ${lostChild.parent}, which was re-created, but its update sent no change (it is recorded on Cloud Control, which patches record against template); it may no longer be attached to ${lostChild.parent}. Attach it there by hand.` : safeMsg` ⚠ ${logicalId} went with ${lostChild.parent}, which was re-created, but its update sent no change (it is recorded on Cloud Control, which patches record against template); its policy may be missing from ${lostChild.parent}. Re-run with --recreate-via-sdk-provider ${logicalId} to write it again.`);
|
|
29478
|
-
return outcome;
|
|
29479
|
-
}
|
|
29480
|
-
this.restoredLostChildren.add(logicalId);
|
|
29481
|
-
return outcome;
|
|
29482
|
-
};
|
|
29483
|
-
if (needsReplacement) return markRestored(await this.updateByReplacement({
|
|
29484
|
-
change,
|
|
29485
|
-
counts,
|
|
29486
|
-
currentProps,
|
|
29487
|
-
currentResource,
|
|
29488
|
-
dependencies,
|
|
29489
|
-
logicalId,
|
|
29490
|
-
oldResourceType,
|
|
29491
|
-
progress,
|
|
29492
|
-
propertyDrivenReplacement,
|
|
29493
|
-
recreateFlagged,
|
|
29494
|
-
recreateViaCcApi,
|
|
29495
|
-
recreateViaSdkProvider,
|
|
29496
|
-
renderer,
|
|
29497
|
-
resolvedProps,
|
|
29498
|
-
resourceType,
|
|
29499
|
-
stackName,
|
|
29500
|
-
stateResources,
|
|
29501
|
-
template,
|
|
29502
|
-
typeChanged,
|
|
29503
|
-
updateReplacePolicy,
|
|
29504
|
-
updateSecrets,
|
|
29505
|
-
lostWithParent
|
|
29506
|
-
}));
|
|
29507
|
-
return markRestored(await this.updateInPlace({
|
|
29508
|
-
conditions,
|
|
29509
|
-
counts,
|
|
29510
|
-
currentProps,
|
|
29511
|
-
currentPropsAsWritten,
|
|
29512
|
-
currentResource,
|
|
29513
|
-
dependencies,
|
|
29514
|
-
desiredForSkipCheckAsWritten,
|
|
29515
|
-
logicalId,
|
|
29516
|
-
noEchoHeldPaths,
|
|
29517
|
-
parameterValues,
|
|
29518
|
-
progress,
|
|
29519
|
-
renderer,
|
|
29520
|
-
resolvedProps,
|
|
29521
|
-
resourceType,
|
|
29522
|
-
stackName,
|
|
29523
|
-
stateResources,
|
|
29524
|
-
template,
|
|
29525
|
-
updateReplacePolicy,
|
|
29526
|
-
updateSecrets,
|
|
29527
|
-
reattach: lostChild?.mode === "reattach"
|
|
29528
|
-
}));
|
|
29529
|
-
}
|
|
29530
|
-
|
|
29531
29483
|
//#endregion
|
|
29532
29484
|
//#region src/provisioning/data-delete-intent.ts
|
|
29533
29485
|
const S3_AUTO_DELETE_OBJECTS_TAG = "aws-cdk:auto-delete-objects";
|
|
@@ -32235,6 +32187,284 @@ function recordedProtectionNote(evidence, flags) {
|
|
|
32235
32187
|
return `${evidence}. AWS refuses to delete the resource while that protection is on, and cdkd deploy has no --remove-protection flag to clear it (only cdkd destroy and cdkd state destroy act on one), so ${flags} alone does not remove the old resource: depending on the replacement order, the deploy either fails at that delete or completes leaving the old resource, and its data, in AWS and no longer tracked by cdkd. Read ${DELETION_PROTECTION_DOC_POINTER} before you disable anything, then turn the protection off out of band (the console, or the service's own API) and re-run with ${flags}.`;
|
|
32236
32188
|
}
|
|
32237
32189
|
|
|
32190
|
+
//#endregion
|
|
32191
|
+
//#region src/deployment/deploy-value-equality.ts
|
|
32192
|
+
function isReplacementCeiling(pc) {
|
|
32193
|
+
return pc.requiresReplacement && (pc.inPlacePropagated === true || pc.replacementPropagated === true);
|
|
32194
|
+
}
|
|
32195
|
+
function keyOrderFreeJson(value) {
|
|
32196
|
+
return JSON.stringify(value, (_key, node) => {
|
|
32197
|
+
if (node === null || typeof node !== "object" || Array.isArray(node)) return node;
|
|
32198
|
+
const sorted = Object.create(null);
|
|
32199
|
+
for (const key of Object.keys(node).sort()) sorted[key] = node[key];
|
|
32200
|
+
return sorted;
|
|
32201
|
+
});
|
|
32202
|
+
}
|
|
32203
|
+
function liveHoldsFreshLeaves(live, leaves) {
|
|
32204
|
+
for (const leaf of leaves) {
|
|
32205
|
+
let node = live;
|
|
32206
|
+
for (const segment of leaf.path) {
|
|
32207
|
+
if (typeof segment === "number") {
|
|
32208
|
+
if (!Array.isArray(node) || segment >= node.length) return false;
|
|
32209
|
+
node = node[segment];
|
|
32210
|
+
continue;
|
|
32211
|
+
}
|
|
32212
|
+
if (node === null || typeof node !== "object" || Array.isArray(node)) return false;
|
|
32213
|
+
if (!Object.prototype.hasOwnProperty.call(node, segment)) return false;
|
|
32214
|
+
node = node[segment];
|
|
32215
|
+
}
|
|
32216
|
+
if (typeof node !== "string" || node !== leaf.plaintext) return false;
|
|
32217
|
+
}
|
|
32218
|
+
return true;
|
|
32219
|
+
}
|
|
32220
|
+
function outputMapsEqual(a, b) {
|
|
32221
|
+
return deepEqualValue(a, b);
|
|
32222
|
+
}
|
|
32223
|
+
function deepEqualValue(a, b) {
|
|
32224
|
+
if (a === b) return true;
|
|
32225
|
+
if (a == null || b == null) return a === b;
|
|
32226
|
+
if (typeof a !== typeof b) return false;
|
|
32227
|
+
if (typeof a !== "object") return false;
|
|
32228
|
+
if (Array.isArray(a) || Array.isArray(b)) {
|
|
32229
|
+
if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return false;
|
|
32230
|
+
return a.every((v, i) => deepEqualValue(v, b[i]));
|
|
32231
|
+
}
|
|
32232
|
+
const ao = a;
|
|
32233
|
+
const bo = b;
|
|
32234
|
+
const ak = Object.keys(ao);
|
|
32235
|
+
if (ak.length !== Object.keys(bo).length) return false;
|
|
32236
|
+
for (const k of ak) {
|
|
32237
|
+
if (!Object.prototype.hasOwnProperty.call(bo, k)) return false;
|
|
32238
|
+
if (!deepEqualValue(ao[k], bo[k])) return false;
|
|
32239
|
+
}
|
|
32240
|
+
return true;
|
|
32241
|
+
}
|
|
32242
|
+
|
|
32243
|
+
//#endregion
|
|
32244
|
+
//#region src/deployment/deploy-engine/update.ts
|
|
32245
|
+
async function provisionUpdate(logicalId, change, stateResources, stackName, template, parameterValues, conditions, counts, progress) {
|
|
32246
|
+
const resourceType = change.resourceType;
|
|
32247
|
+
const existingState = stateResources[logicalId];
|
|
32248
|
+
const renderer = getLiveRenderer();
|
|
32249
|
+
const currentResource = existingState;
|
|
32250
|
+
if (!currentResource) throw new Error(`Cannot update ${logicalId}: resource not found in state`);
|
|
32251
|
+
const oldResourceType = currentResource.resourceType;
|
|
32252
|
+
const typeChanged = oldResourceType !== resourceType;
|
|
32253
|
+
const desiredProps = change.desiredProperties || {};
|
|
32254
|
+
const currentProps = change.currentProperties || {};
|
|
32255
|
+
const context = this.buildResolverContext({
|
|
32256
|
+
template,
|
|
32257
|
+
resources: stateResources,
|
|
32258
|
+
...parameterValues && { parameters: parameterValues },
|
|
32259
|
+
...conditions && { conditions },
|
|
32260
|
+
redactedAttributeReads: []
|
|
32261
|
+
}, stackName);
|
|
32262
|
+
const updateSecrets = context.recordedSecretValues ?? /* @__PURE__ */ new Map();
|
|
32263
|
+
this.perResourceSecrets.set(logicalId, updateSecrets);
|
|
32264
|
+
const resolvedProps = await this.resolver.resolve(desiredProps, context);
|
|
32265
|
+
this.perResourceTemplateProps.set(logicalId, desiredProps);
|
|
32266
|
+
this.perResourceResolvedType.set(logicalId, resourceType);
|
|
32267
|
+
recordNestedStackParameterExpressions(updateSecrets, resourceType, resolvedProps, desiredProps);
|
|
32268
|
+
this.auditResolvedAssetReferences(logicalId, resourceType, resolvedProps);
|
|
32269
|
+
const lostCandidate = childLostWithRecreatedParent({
|
|
32270
|
+
resourceType,
|
|
32271
|
+
templateProperties: desiredProps,
|
|
32272
|
+
recreatedUnderSameId: this.recreatedUnderSameId,
|
|
32273
|
+
recordedTypeOf: (id) => Object.hasOwn(stateResources, id) ? stateResources[id]?.resourceType : void 0,
|
|
32274
|
+
conditions
|
|
32275
|
+
});
|
|
32276
|
+
const lostChild = lostCandidate?.mode === "reattach" || lostCandidate !== void 0 && Object.hasOwn(resolvedProps, lostCandidate.property) && Object.hasOwn(currentProps, lostCandidate.property) && keyOrderFreeJson(resolvedProps[lostCandidate.property]) === keyOrderFreeJson(currentProps[lostCandidate.property]) ? lostCandidate : void 0;
|
|
32277
|
+
const lostWithParent = lostChild?.mode === "recreate" ? lostChild.parent : void 0;
|
|
32278
|
+
const suppliesFreshMaskOnlyValue = carriesFreshNoEchoValue(resolvedProps, updateSecrets);
|
|
32279
|
+
const desiredForSkipCheck = redactSecretsForState(markSameGenerationBag({ ...resolvedProps }), updateSecrets, desiredProps);
|
|
32280
|
+
const allowedSilentDrops = this.providerRegistry.getAllowedUnsupportedProperties?.();
|
|
32281
|
+
const desiredForSkipCheckAsWritten = currentResource.provisionedBy !== "cc-api" && allowedSilentDrops ? withoutAcceptedSilentDropProperties(resourceType, desiredForSkipCheck, allowedSilentDrops, currentResource.properties) : desiredForSkipCheck;
|
|
32282
|
+
const allowedForRecord = allowedSilentDrops ?? /* @__PURE__ */ new Set();
|
|
32283
|
+
const createOnlyEvidence = acceptedCreateOnlyDropsOf(currentResource);
|
|
32284
|
+
const currentPropsAsWritten = currentResource.provisionedBy === "cc-api" ? currentProps : withoutUnwrittenSilentDropProperties(resourceType, currentProps, desiredForSkipCheck, allowedForRecord, createOnlyEvidence);
|
|
32285
|
+
const applyAttributeOnlyUpdate = (attributeChanges) => {
|
|
32286
|
+
const attrSummary = attributeChanges.map((a) => `${a.attribute}: ${a.oldValue ?? "(unset)"} → ${a.newValue ?? "(unset)"}`).join(", ");
|
|
32287
|
+
this.logger.info(safeMsg` ↻ ${logicalId} (${resourceType}) attribute update: ${attrSummary}`);
|
|
32288
|
+
stateResources[logicalId] = {
|
|
32289
|
+
...currentResource,
|
|
32290
|
+
...this.extractTemplateAttributes(template, logicalId)
|
|
32291
|
+
};
|
|
32292
|
+
if (counts) counts.updated++;
|
|
32293
|
+
if (progress) progress.current++;
|
|
32294
|
+
const attrPrefix = progress ? `[${progress.current}/${progress.total}] ` : " ";
|
|
32295
|
+
renderer.removeTask(logicalId);
|
|
32296
|
+
this.logger.info(safeMsg`${attrPrefix}${formatResourceLine("updated", logicalId, resourceType, "updated (metadata)")}`);
|
|
32297
|
+
};
|
|
32298
|
+
if (!typeChanged && !suppliesFreshMaskOnlyValue && lostChild === void 0 && this.recreateDirectionFor(stackName, logicalId) === void 0 && keyOrderFreeJson(desiredForSkipCheckAsWritten) === keyOrderFreeJson(currentPropsAsWritten)) {
|
|
32299
|
+
if (change.attributeChanges && change.attributeChanges.length > 0) {
|
|
32300
|
+
applyAttributeOnlyUpdate(change.attributeChanges);
|
|
32301
|
+
return;
|
|
32302
|
+
}
|
|
32303
|
+
this.logger.debug(`Skipping ${logicalId}: no actual changes after intrinsic function resolution`);
|
|
32304
|
+
if (counts) counts.skipped++;
|
|
32305
|
+
return;
|
|
32306
|
+
}
|
|
32307
|
+
this.refuseRedactedAttributeReads(logicalId, resourceType, context);
|
|
32308
|
+
this.attemptedResolvedProps.set(logicalId, resolvedProps);
|
|
32309
|
+
const noEchoHeldPaths = /* @__PURE__ */ new Set();
|
|
32310
|
+
if (change.propertyChanges?.some((pc) => pc.requiresReplacement) === true) {
|
|
32311
|
+
let readback;
|
|
32312
|
+
const lowered = [];
|
|
32313
|
+
for (const pc of change.propertyChanges) {
|
|
32314
|
+
if (!pc.requiresReplacement) {
|
|
32315
|
+
lowered.push(pc);
|
|
32316
|
+
continue;
|
|
32317
|
+
}
|
|
32318
|
+
const freshLeaves = freshNoEchoLeafPositions(resolvedProps[pc.path], updateSecrets);
|
|
32319
|
+
if (!isReplacementCeiling(pc) && freshLeaves.length === 0) {
|
|
32320
|
+
lowered.push(pc);
|
|
32321
|
+
continue;
|
|
32322
|
+
}
|
|
32323
|
+
const moved = keyOrderFreeJson(desiredForSkipCheckAsWritten[pc.path]) !== keyOrderFreeJson(currentPropsAsWritten[pc.path]);
|
|
32324
|
+
const conditionalVerdict = moved && !typeChanged && isReplacementCeiling(pc) ? this.diffCalculator.conditionalReplacementVerdict?.(resourceType, pc.path, currentPropsAsWritten[pc.path], desiredForSkipCheckAsWritten[pc.path]) : void 0;
|
|
32325
|
+
if (moved && conditionalVerdict !== false) {
|
|
32326
|
+
lowered.push(pc);
|
|
32327
|
+
continue;
|
|
32328
|
+
}
|
|
32329
|
+
if (freshLeaves.length > 0) {
|
|
32330
|
+
if (typeChanged) {
|
|
32331
|
+
lowered.push(pc);
|
|
32332
|
+
continue;
|
|
32333
|
+
}
|
|
32334
|
+
readback ??= this.readReaderForFreshNoEchoCeiling(logicalId, currentResource, updateSecrets);
|
|
32335
|
+
const read = await readback;
|
|
32336
|
+
let verdict;
|
|
32337
|
+
if ("failure" in read) verdict = read.failure;
|
|
32338
|
+
else if (!Object.prototype.hasOwnProperty.call(read.live, pc.path)) verdict = "not-readable";
|
|
32339
|
+
else verdict = liveHoldsFreshLeaves(read.live[pc.path], freshLeaves) ? "held" : "differs";
|
|
32340
|
+
if (verdict !== "held") {
|
|
32341
|
+
this.logger.warn(safeMsg`${logicalId}.${pc.path} carries a NoEcho value that AWS could not confirm unchanged (${verdict}): replacement kept.`);
|
|
32342
|
+
lowered.push(pc);
|
|
32343
|
+
continue;
|
|
32344
|
+
}
|
|
32345
|
+
this.logger.debug(safeMsg`${logicalId}.${pc.path} carries a NoEcho value AWS already holds: not replaced.`);
|
|
32346
|
+
noEchoHeldPaths.add(pc.path);
|
|
32347
|
+
}
|
|
32348
|
+
lowered.push({
|
|
32349
|
+
...pc,
|
|
32350
|
+
requiresReplacement: false
|
|
32351
|
+
});
|
|
32352
|
+
}
|
|
32353
|
+
change.propertyChanges = lowered;
|
|
32354
|
+
}
|
|
32355
|
+
if (noEchoHeldPaths.size > 0 && !typeChanged && lostChild === void 0 && this.recreateDirectionFor(stackName, logicalId) === void 0 && keyOrderFreeJson(desiredForSkipCheckAsWritten) === keyOrderFreeJson(currentPropsAsWritten) && Object.entries(resolvedProps).every(([key, value]) => noEchoHeldPaths.has(key) || freshNoEchoLeafPositions(value, updateSecrets).length === 0)) {
|
|
32356
|
+
this.logger.debug(safeMsg`Skipping ${logicalId}: AWS already holds every NoEcho value it carries, and nothing else changed`);
|
|
32357
|
+
this.attemptedResolvedProps.delete(logicalId);
|
|
32358
|
+
if (change.attributeChanges && change.attributeChanges.length > 0) {
|
|
32359
|
+
applyAttributeOnlyUpdate(change.attributeChanges);
|
|
32360
|
+
return;
|
|
32361
|
+
}
|
|
32362
|
+
if (counts) counts.skipped++;
|
|
32363
|
+
return;
|
|
32364
|
+
}
|
|
32365
|
+
const propertyDrivenReplacement = typeChanged || change.propertyChanges?.some((pc) => pc.requiresReplacement);
|
|
32366
|
+
const recreateTargets = this.options.recreateTargets?.stackName === stackName ? this.options.recreateTargets : void 0;
|
|
32367
|
+
const recreateViaCcApi = recreateTargets?.viaCcApi.has(logicalId) ?? false;
|
|
32368
|
+
const recreateViaSdkProvider = recreateTargets?.viaSdkProvider.has(logicalId) ?? false;
|
|
32369
|
+
const recreateFlagged = recreateViaCcApi || recreateViaSdkProvider;
|
|
32370
|
+
const needsReplacement = propertyDrivenReplacement || recreateFlagged || lostWithParent !== void 0;
|
|
32371
|
+
if (propertyDrivenReplacement && !typeChanged && !recreateFlagged && lostWithParent === void 0 && this.options.replace !== true && currentResource.provisionedBy !== "cc-api") {
|
|
32372
|
+
const unwritten = unwrittenCreateOnlyReplacement(resourceType, currentProps, desiredForSkipCheck, allowedForRecord, createOnlyEvidence, (change.propertyChanges ?? []).filter((pc) => pc.requiresReplacement).map((pc) => pc.path));
|
|
32373
|
+
if (unwritten.length > 0) throw markRefusedBeforeApplying(markNonRetryable(new CdkdError(unwrittenCreateOnlyRefusal({
|
|
32374
|
+
logicalId,
|
|
32375
|
+
resourceType,
|
|
32376
|
+
unwritten,
|
|
32377
|
+
routeDriving: findActionableSilentDrops(resourceType, desiredForSkipCheck, allowedForRecord, currentProps).map(({ property }) => property),
|
|
32378
|
+
nested: this.options.parentStackInfo !== void 0,
|
|
32379
|
+
protectionEvidence: recordedProtectionEvidence(resourceType, currentProps, currentResource.observedProperties, this.stackRegion)
|
|
32380
|
+
}), "CREATE_ONLY_DROP_NEEDS_REPLACEMENT")));
|
|
32381
|
+
}
|
|
32382
|
+
const liveLabel = this.liveTaskLabels.get(logicalId);
|
|
32383
|
+
if (needsReplacement && liveLabel !== void 0 && !liveLabel.replacing) {
|
|
32384
|
+
const label = `Replacing ${logicalId} (${resourceType})${this.peekRoutingForLabel(change, currentResource, stackName, logicalId, true, this.recreateDirectionFor(stackName, logicalId)) === "cc-api" ? " [CC API]" : ""}`;
|
|
32385
|
+
this.liveTaskLabels.set(logicalId, {
|
|
32386
|
+
label,
|
|
32387
|
+
replacing: true,
|
|
32388
|
+
...liveLabel.warnSuffix !== void 0 && { warnSuffix: liveLabel.warnSuffix }
|
|
32389
|
+
});
|
|
32390
|
+
renderer.updateTaskLabel(logicalId, `${label}${liveLabel.warnSuffix ?? ""}`);
|
|
32391
|
+
} else if (!needsReplacement && liveLabel !== void 0 && liveLabel.replacing) {
|
|
32392
|
+
const label = `Updating ${logicalId} (${resourceType})${this.peekRoutingForLabel(change, currentResource, stackName, logicalId, false, this.recreateDirectionFor(stackName, logicalId)) === "cc-api" ? " [CC API]" : ""}`;
|
|
32393
|
+
this.liveTaskLabels.set(logicalId, {
|
|
32394
|
+
label,
|
|
32395
|
+
replacing: false,
|
|
32396
|
+
...liveLabel.warnSuffix !== void 0 && { warnSuffix: liveLabel.warnSuffix }
|
|
32397
|
+
});
|
|
32398
|
+
renderer.updateTaskLabel(logicalId, `${label}${liveLabel.warnSuffix ?? ""}`);
|
|
32399
|
+
}
|
|
32400
|
+
const dependencies = this.extractAllDependencies(template, logicalId);
|
|
32401
|
+
const updateReplacePolicy = template?.Resources?.[logicalId]?.UpdateReplacePolicy;
|
|
32402
|
+
const markRestored = (outcome) => {
|
|
32403
|
+
if (lostChild === void 0) return outcome;
|
|
32404
|
+
if (this.updatesThatSentNothing.has(logicalId)) {
|
|
32405
|
+
this.logger.warn(survivesParent(resourceType) ? safeMsg` ⚠ ${logicalId} lost its attachment to ${lostChild.parent}, which was re-created, but its update sent no change (it is recorded on Cloud Control, which patches record against template); it may no longer be attached to ${lostChild.parent}. Attach it there by hand.` : safeMsg` ⚠ ${logicalId} went with ${lostChild.parent}, which was re-created, but its update sent no change (it is recorded on Cloud Control, which patches record against template); its policy may be missing from ${lostChild.parent}. Re-run with --recreate-via-sdk-provider ${logicalId} to write it again.`);
|
|
32406
|
+
return outcome;
|
|
32407
|
+
}
|
|
32408
|
+
this.restoredLostChildren.add(logicalId);
|
|
32409
|
+
return outcome;
|
|
32410
|
+
};
|
|
32411
|
+
if (needsReplacement) return markRestored(await this.updateByReplacement({
|
|
32412
|
+
change,
|
|
32413
|
+
counts,
|
|
32414
|
+
currentProps,
|
|
32415
|
+
currentResource,
|
|
32416
|
+
dependencies,
|
|
32417
|
+
logicalId,
|
|
32418
|
+
oldResourceType,
|
|
32419
|
+
progress,
|
|
32420
|
+
propertyDrivenReplacement,
|
|
32421
|
+
recreateFlagged,
|
|
32422
|
+
recreateViaCcApi,
|
|
32423
|
+
recreateViaSdkProvider,
|
|
32424
|
+
renderer,
|
|
32425
|
+
resolvedProps,
|
|
32426
|
+
resourceType,
|
|
32427
|
+
stackName,
|
|
32428
|
+
stateResources,
|
|
32429
|
+
template,
|
|
32430
|
+
typeChanged,
|
|
32431
|
+
updateReplacePolicy,
|
|
32432
|
+
updateSecrets,
|
|
32433
|
+
lostWithParent
|
|
32434
|
+
}));
|
|
32435
|
+
return markRestored(await this.updateInPlace({
|
|
32436
|
+
conditions,
|
|
32437
|
+
counts,
|
|
32438
|
+
currentProps,
|
|
32439
|
+
currentPropsAsWritten,
|
|
32440
|
+
currentResource,
|
|
32441
|
+
dependencies,
|
|
32442
|
+
desiredForSkipCheckAsWritten,
|
|
32443
|
+
logicalId,
|
|
32444
|
+
noEchoHeldPaths,
|
|
32445
|
+
parameterValues,
|
|
32446
|
+
progress,
|
|
32447
|
+
renderer,
|
|
32448
|
+
resolvedProps,
|
|
32449
|
+
resourceType,
|
|
32450
|
+
stackName,
|
|
32451
|
+
stateResources,
|
|
32452
|
+
template,
|
|
32453
|
+
updateReplacePolicy,
|
|
32454
|
+
updateSecrets,
|
|
32455
|
+
reattach: lostChild?.mode === "reattach"
|
|
32456
|
+
}));
|
|
32457
|
+
}
|
|
32458
|
+
function unwrittenCreateOnlyRefusal(input) {
|
|
32459
|
+
const { logicalId, resourceType, unwritten, routeDriving, nested, protectionEvidence } = input;
|
|
32460
|
+
const one = unwritten.length === 1;
|
|
32461
|
+
const list = unwritten.join(", ");
|
|
32462
|
+
const keep = [.../* @__PURE__ */ new Set([...unwritten, ...routeDriving])].sort((a, b) => a.localeCompare(b)).map((property) => `${resourceType}:${property}`).join(",");
|
|
32463
|
+
const replaceFlags = nested ? "--replace (which creates the new resource before deleting the old one, so a resource holding a unique value other than its name, such as a CIDR block, collides)" : `--recreate-via-cc-api ${logicalId}, which deletes the old resource first (--replace also works, but creates the new one first, so a resource holding a unique value other than its name, such as a CIDR block, collides)`;
|
|
32464
|
+
const routed = [...routeDriving].sort((a, b) => a.localeCompare(b)).join(", ");
|
|
32465
|
+
return `${logicalId} (${resourceType}): ${list} ${one ? "is" : "are"} create-only, and the state record holds ${one ? "it" : "them"} although this type's SDK provider never writes ${one ? "it" : "them"}, so AWS does not. This deploy routes the resource through Cloud Control (--prefer-sdk-route does not cover ${routed}), and applying a create-only property means replacing the resource, which cdkd does not do on its own. This resource was not changed. To replace it and apply ${list}, re-run with ${replaceFlags}; a stateful resource also needs --force-stateful-recreation.` + (protectionEvidence !== void 0 ? ` ${recordedProtectionNote(protectionEvidence, nested ? "--replace" : `--recreate-via-cc-api ${logicalId} or --replace`)}` : "") + ` To keep dropping ${one ? "it" : "them"}, re-run with --prefer-sdk-route ${keep}.`;
|
|
32466
|
+
}
|
|
32467
|
+
|
|
32238
32468
|
//#endregion
|
|
32239
32469
|
//#region src/deployment/deploy-engine/update-replace.ts
|
|
32240
32470
|
async function updateByReplacement({ change, counts, currentProps, currentResource, dependencies, logicalId, oldResourceType, progress, propertyDrivenReplacement, recreateFlagged, recreateViaCcApi, recreateViaSdkProvider, renderer, resolvedProps, resourceType, stackName, stateResources, template, typeChanged, updateReplacePolicy, updateSecrets, lostWithParent }) {
|
|
@@ -32423,10 +32653,12 @@ async function updateByReplacement({ change, counts, currentProps, currentResour
|
|
|
32423
32653
|
}
|
|
32424
32654
|
this.registerNoEchoAttributes(logicalId, createResult, updateSecrets, resolvedProps);
|
|
32425
32655
|
if (equalIdIsSameResource && createResult.physicalId === currentResource.physicalId) this.recreatedUnderSameId.add(logicalId);
|
|
32656
|
+
const recordedReplacementProperties = this.propertiesToRecord(resolvedProps, createResult, resourceType, replaceDecision.provisionedBy);
|
|
32426
32657
|
stateResources[logicalId] = {
|
|
32427
32658
|
physicalId: createResult.physicalId,
|
|
32428
32659
|
resourceType,
|
|
32429
|
-
properties:
|
|
32660
|
+
properties: recordedReplacementProperties,
|
|
32661
|
+
...acceptedCreateOnlyDropsField(recordedReplacementProperties, resourceType, replaceDecision.provisionedBy, "new-resource"),
|
|
32430
32662
|
...createResult.attributes && { attributes: createResult.attributes },
|
|
32431
32663
|
...dependencies && dependencies.length > 0 && { dependencies },
|
|
32432
32664
|
...this.extractTemplateAttributes(template, logicalId),
|
|
@@ -32633,17 +32865,20 @@ async function updateInPlace({ conditions, counts, currentProps, currentPropsAsW
|
|
|
32633
32865
|
} else throw updateError;
|
|
32634
32866
|
}
|
|
32635
32867
|
if (result.wasReplaced) this.logger.info(`Resource ${logicalId} was replaced: ${currentResource.physicalId} -> ${result.physicalId}`);
|
|
32636
|
-
const
|
|
32868
|
+
const dischargedByReplacement = result.wasReplaced === true && result.physicalId !== currentResource.physicalId;
|
|
32869
|
+
const keepsParameterRefusal = !dischargedByReplacement && hasUnverifiableParameterRefusal(currentResource);
|
|
32637
32870
|
const carriedAttributes = result.attributes ?? (result.wasReplaced ? void 0 : currentResource.attributes);
|
|
32638
32871
|
this.registerNoEchoAttributes(logicalId, {
|
|
32639
32872
|
...carriedAttributes && { attributes: carriedAttributes },
|
|
32640
32873
|
...result.noEchoAttributes === true && { noEchoAttributes: true },
|
|
32641
32874
|
...result.noEchoAttributeNames && { noEchoAttributeNames: result.noEchoAttributeNames }
|
|
32642
32875
|
}, updateSecrets, resolvedProps);
|
|
32876
|
+
const recordedProperties = this.propertiesToRecord(resolvedProps, result, resourceType, resultProvisionedBy);
|
|
32643
32877
|
stateResources[logicalId] = {
|
|
32644
32878
|
physicalId: result.physicalId,
|
|
32645
32879
|
resourceType,
|
|
32646
|
-
properties:
|
|
32880
|
+
properties: recordedProperties,
|
|
32881
|
+
...acceptedCreateOnlyDropsField(recordedProperties, resourceType, resultProvisionedBy, dischargedByReplacement ? "new-resource" : "in-place", currentResource),
|
|
32647
32882
|
...carriedAttributes && { attributes: carriedAttributes },
|
|
32648
32883
|
...dependencies && dependencies.length > 0 && { dependencies },
|
|
32649
32884
|
...this.extractTemplateAttributes(template, logicalId),
|
|
@@ -32798,75 +33033,6 @@ async function withResourceDeadline(operation, opts) {
|
|
|
32798
33033
|
});
|
|
32799
33034
|
}
|
|
32800
33035
|
|
|
32801
|
-
//#endregion
|
|
32802
|
-
//#region src/deployment/prior-attempt-scope.ts
|
|
32803
|
-
const priorAttemptStore = new AsyncLocalStorage();
|
|
32804
|
-
function withPriorAttempts(lookup, fn) {
|
|
32805
|
-
return priorAttemptStore.run(lookup, fn);
|
|
32806
|
-
}
|
|
32807
|
-
function priorAttemptLookup(logicalId, attempts) {
|
|
32808
|
-
let landed = false;
|
|
32809
|
-
return {
|
|
32810
|
-
logicalId,
|
|
32811
|
-
attempts,
|
|
32812
|
-
notePossiblyLanded: () => {
|
|
32813
|
-
landed = true;
|
|
32814
|
-
},
|
|
32815
|
-
possiblyLanded: () => landed
|
|
32816
|
-
};
|
|
32817
|
-
}
|
|
32818
|
-
function getPriorAttempts(logicalId) {
|
|
32819
|
-
const bound = priorAttemptStore.getStore();
|
|
32820
|
-
return bound?.logicalId === logicalId ? bound : void 0;
|
|
32821
|
-
}
|
|
32822
|
-
function priorAttemptsInJournal(journal, logicalId, resourceType) {
|
|
32823
|
-
let bags = [];
|
|
32824
|
-
for (const segment of journal?.segments ?? []) {
|
|
32825
|
-
if (segment.operations.some((op) => op.logicalId === logicalId)) bags = [];
|
|
32826
|
-
for (const op of segment.failedOperations ?? []) {
|
|
32827
|
-
if (op.logicalId !== logicalId || op.resourceType !== resourceType) continue;
|
|
32828
|
-
if (op.changeType === "DELETE" || !isBag(op.attemptedProperties)) continue;
|
|
32829
|
-
if (recordedAsNewResource(op)) continue;
|
|
32830
|
-
bags.push(op.attemptedProperties);
|
|
32831
|
-
}
|
|
32832
|
-
if (segment.supersededLogicalIds?.includes(logicalId)) bags = [];
|
|
32833
|
-
}
|
|
32834
|
-
return bags;
|
|
32835
|
-
}
|
|
32836
|
-
function recordedAsNewResource(op) {
|
|
32837
|
-
if (typeof op.physicalId !== "string" || op.physicalId === "") return false;
|
|
32838
|
-
if (op.changeType === "CREATE") return true;
|
|
32839
|
-
const previous = op.previousState?.physicalId;
|
|
32840
|
-
return typeof previous === "string" && previous !== op.physicalId;
|
|
32841
|
-
}
|
|
32842
|
-
function isBag(value) {
|
|
32843
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
32844
|
-
}
|
|
32845
|
-
const REFUSED_BEFORE_APPLYING = Symbol.for("cdkd.refusedBeforeApplying");
|
|
32846
|
-
const MAX_CAUSE_DEPTH = 10;
|
|
32847
|
-
function markRefusedBeforeApplying(error) {
|
|
32848
|
-
if (!Object.isExtensible(error)) return error;
|
|
32849
|
-
Object.defineProperty(error, REFUSED_BEFORE_APPLYING, {
|
|
32850
|
-
value: true,
|
|
32851
|
-
enumerable: false,
|
|
32852
|
-
configurable: true,
|
|
32853
|
-
writable: false
|
|
32854
|
-
});
|
|
32855
|
-
return error;
|
|
32856
|
-
}
|
|
32857
|
-
function isRefusedBeforeApplying(error, logicalId) {
|
|
32858
|
-
let current = error;
|
|
32859
|
-
for (let depth = 0; depth < MAX_CAUSE_DEPTH && current != null; depth++) {
|
|
32860
|
-
if (typeof current === "object" || typeof current === "function") {
|
|
32861
|
-
const linkId = current.logicalId;
|
|
32862
|
-
if (typeof linkId === "string" && linkId !== logicalId) return false;
|
|
32863
|
-
if (current[REFUSED_BEFORE_APPLYING] === true) return true;
|
|
32864
|
-
}
|
|
32865
|
-
current = current.cause;
|
|
32866
|
-
}
|
|
32867
|
-
return false;
|
|
32868
|
-
}
|
|
32869
|
-
|
|
32870
33036
|
//#endregion
|
|
32871
33037
|
//#region src/deployment/deploy-engine/provision.ts
|
|
32872
33038
|
async function provisionResource(logicalId, change, stateResources, stackName, template, parameterValues, conditions, counts, progress) {
|
|
@@ -33245,14 +33411,17 @@ async function executeDeployment(template, currentState, changes, dag, execution
|
|
|
33245
33411
|
} catch (provisionError) {
|
|
33246
33412
|
this.interrupted = true;
|
|
33247
33413
|
this.interruptCause ??= "sibling-failure";
|
|
33414
|
+
const refused = isRefusedBeforeApplying(provisionError, logicalId);
|
|
33415
|
+
const physicalId = newResources[logicalId]?.physicalId ?? previousState?.physicalId;
|
|
33416
|
+
if (refused && change.changeType === "CREATE" && physicalId === void 0) throw provisionError;
|
|
33248
33417
|
failedOperations.push({
|
|
33249
33418
|
logicalId,
|
|
33250
33419
|
changeType: change.changeType,
|
|
33251
33420
|
resourceType: change.resourceType,
|
|
33252
33421
|
provisionedBy: newResources[logicalId]?.provisionedBy ?? previousState?.provisionedBy,
|
|
33253
33422
|
...previousState && { previousState },
|
|
33254
|
-
physicalId
|
|
33255
|
-
...!
|
|
33423
|
+
physicalId,
|
|
33424
|
+
...!refused && { attemptedProperties: this.attemptedResolvedProps.get(logicalId) }
|
|
33256
33425
|
});
|
|
33257
33426
|
throw provisionError;
|
|
33258
33427
|
}
|
|
@@ -33402,6 +33571,7 @@ async function executeDeployment(template, currentState, changes, dag, execution
|
|
|
33402
33571
|
this.logger.warn(`Failed to save partial state before rollback: ${saveError instanceof Error ? saveError.message : String(saveError)}`);
|
|
33403
33572
|
}
|
|
33404
33573
|
let autoRollbackClean = false;
|
|
33574
|
+
let autoRollbackJournaled = false;
|
|
33405
33575
|
let rollbackOrphans = [];
|
|
33406
33576
|
let rollbackSettledNested = /* @__PURE__ */ new Map();
|
|
33407
33577
|
if (error instanceof InterruptedError || isInterruptedWaitError(error) || this.interruptCause === "user") {
|
|
@@ -33414,9 +33584,16 @@ async function executeDeployment(template, currentState, changes, dag, execution
|
|
|
33414
33584
|
this.logger.warn("Deployment failed. --no-rollback is set, skipping rollback.");
|
|
33415
33585
|
this.logger.warn(safeMsg`Partial state has been saved. ${this.recoveryHint("Run 'cdkd deploy' to resume, 'cdkd rollback' to revert, or destroy to clean up.")}`);
|
|
33416
33586
|
} else {
|
|
33417
|
-
await this.writeRollbackJournalSegment(stackName, completedOperations, failedOperations, "auto-rollback-started", initialDeploy);
|
|
33587
|
+
autoRollbackJournaled = await this.writeRollbackJournalSegment(stackName, completedOperations, failedOperations, "auto-rollback-started", initialDeploy);
|
|
33418
33588
|
const rollbackResult = await this.performRollback(completedOperations, newResources, stackName, currentState);
|
|
33419
|
-
autoRollbackClean = rollbackResult.failures === 0;
|
|
33589
|
+
autoRollbackClean = autoRollbackJournaled && rollbackResult.failures === 0 && rollbackResult.skipped === 0;
|
|
33590
|
+
if (rollbackResult.failures === 0 && rollbackResult.skipped > 0) {
|
|
33591
|
+
this.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.` : ""));
|
|
33592
|
+
if (autoRollbackJournaled && this.options.parentStackInfo === void 0 && failedOperations.some((op) => op.changeType !== "DELETE")) this.logger.warn(safeMsg`The record of the operation that failed is kept too. Revert it with: ${pasteableCommand("cdkd rollback", [{
|
|
33593
|
+
value: stackName,
|
|
33594
|
+
hole: "stack"
|
|
33595
|
+
}, { literal: "--revert-failed" }]).command}`);
|
|
33596
|
+
}
|
|
33420
33597
|
rollbackOrphans = rollbackResult.orphaned;
|
|
33421
33598
|
rollbackSettledNested = rollbackResult.settledNested;
|
|
33422
33599
|
}
|
|
@@ -34218,37 +34395,6 @@ function preparePropertiesForCcApi(resourceType, resolvedProps, logicalId) {
|
|
|
34218
34395
|
return applyDefaultNameForFallback(logicalId, resourceType, resolvedProps);
|
|
34219
34396
|
}
|
|
34220
34397
|
|
|
34221
|
-
//#endregion
|
|
34222
|
-
//#region src/deployment/deploy-engine/record-shape.ts
|
|
34223
|
-
function auditResolvedAssetReferences(logicalId, resourceType, resolvedProps) {
|
|
34224
|
-
const redirect = this.options.assetRedirect;
|
|
34225
|
-
if (!redirect) return;
|
|
34226
|
-
const findings = findUnrewrittenAssetReferences(resolvedProps, redirect);
|
|
34227
|
-
if (findings.length === 0) return;
|
|
34228
|
-
const detail = findings.map((f) => ` - ${f.path}: still references '${f.source}'`).join("\n");
|
|
34229
|
-
throw new ProvisioningError(`Unrewritten asset reference on '${logicalId}' (${resourceType}): this region uses cdkd-owned asset storage, but the following resolved properties still point at the CDK bootstrap storage that 'cdk gc' may garbage-collect:\n${detail}\nThis is a template shape cdkd's asset-reference rewrite did not cover — deploying it would split-brain the stack (assets in cdkd storage, properties reading the CDK bucket). Please report this at https://github.com/go-to-k/cdkd/issues with the property shape. Workaround: deploy with --use-cdk-bootstrap-assets to pin the legacy destinations for this app.`, resourceType, logicalId);
|
|
34230
|
-
}
|
|
34231
|
-
function extractAllDependencies(template, logicalId) {
|
|
34232
|
-
const resource = template?.Resources?.[logicalId];
|
|
34233
|
-
if (!resource) return void 0;
|
|
34234
|
-
const parser = new TemplateParser();
|
|
34235
|
-
const parameterNames = new Set(Object.keys(template?.Parameters ?? {}));
|
|
34236
|
-
const deps = [...parser.extractDependencies(resource)].filter((dep) => !parameterNames.has(dep));
|
|
34237
|
-
return deps.length > 0 ? deps : void 0;
|
|
34238
|
-
}
|
|
34239
|
-
function propertiesToRecord(desiredProperties, result, resourceType, provisionedBy) {
|
|
34240
|
-
if (result.effectiveProperties) return provisionedBy === "sdk" ? withoutSilentDropProperties(resourceType, result.effectiveProperties) : result.effectiveProperties;
|
|
34241
|
-
const written = provisionedBy === "sdk" ? withoutSilentDropProperties(resourceType, desiredProperties) : desiredProperties;
|
|
34242
|
-
return markSameGenerationBag(written);
|
|
34243
|
-
}
|
|
34244
|
-
function extractTemplateAttributes(template, logicalId) {
|
|
34245
|
-
const resource = template?.Resources?.[logicalId];
|
|
34246
|
-
return {
|
|
34247
|
-
deletionPolicy: resource?.DeletionPolicy,
|
|
34248
|
-
updateReplacePolicy: resource?.UpdateReplacePolicy
|
|
34249
|
-
};
|
|
34250
|
-
}
|
|
34251
|
-
|
|
34252
34398
|
//#endregion
|
|
34253
34399
|
//#region src/analyzer/implicit-delete-deps.ts
|
|
34254
34400
|
const IMPLICIT_DELETE_DEPENDENCIES = {
|
|
@@ -34679,5 +34825,5 @@ DeployEngine.prototype.replacementNameOrigin = replacementNameOrigin;
|
|
|
34679
34825
|
DeployEngine.prototype.orphanedNameCollisionAdvice = orphanedNameCollisionAdvice;
|
|
34680
34826
|
|
|
34681
34827
|
//#endregion
|
|
34682
|
-
export { nestedChildStackName as $, shouldRetainResource as $a, markAuxiliaryFailure as $i, isUnboundTemplateParameter as $n, ssmResolvedValueType as $o, refuseMalformedOutputsForDestroy as $r, DBPROXY_TAGS_WHAT as $t, deleteTableWithIndexBusyRetry as A, carriesSecretMask as Aa, MULTI_REGION_RECREATE_BLOCKED_TYPES as Ai, DiffCalculator as An, partitionSensitiveEnv as Ao, malformedLocalResourcesWarning as Ar, extractDeploymentEventError as At, gray as B, isLockInfoExpired as Ba, coerceCfnInteger as Bi, isIamRoleArn as Bn, Synthesizer as Bo, malformedResourcePropertiesWarning as Br, collectDeclaredOutputNames as Bt, beginDeleteWait as C, scrubResourceRecord as Ca, findActionableSilentDrops as Ci, markWaitAbandoned as Cn, describeDockerFailure as Co, isReadableOrphanRecord as Cr, resolveAssemblyPath as Cs, isFinalSnapshotError as Ct, resolveDynamoDbDeleteBudgetMs as D, isUncertifiedBaselineMaskPosition as Da, hasNoCloudControlHandlers as Di, observeThenDisableInstanceApiTermination as Dn, getDockerCmd as Do, malformedExportSourceWarning as Dr, updatePartialReason as Dt, resolveDynamoDbDeleteBudgetClock as E, dynamicReferenceTokens as Ea, NO_CC_HANDLERS_REASON as Ei, isTerminationProtectionPropagationError as En, formatDockerLoginError as Eo, malformedExportNamesWarning as Er, updatePartialMessage as Et, isTruthyCfnBoolean as F, STATE_SOURCED_READBACK_RULES as Fa, coerceWarmThroughput as Fi, regionLessSecretName as Fn, warnFinchArgvExposure as Fo, malformedOrphansWarning as Fr, secretBearingStateKeyWarning as Ft, namesAnyDeclaredParameter as G, hasReadableExportSet as Ga, replayWarn as Gi, envCredentialsAreAssumedRole as Gn, resolveAutoAssetStorage as Go, refuseDivergentRecordRegionForDestroy as Gr, DEFAULT_RESOURCE_WARN_AFTER_MS as Gt, red as H, rebuildClientForBucketRegion as Ha, configIntegerRefusal as Hi, AWS_CREDENTIAL_ENV_KEYS as Hn, getDefaultStateBucketName as Ho, malformedScrubResourceEntriesRefusalMessage as Hr, isExportAliasCollision as Ht, formatResourceLine as I, TEMPLATE_SOURCED_RULES as Ia, isWarmThroughputDecrease as Ii, applyRoleArnIfSet as In, escapeRegExp$2 as Io, malformedOutputsRefusalMessage as Ir, secretSafeKeyDisplay as It, makeSiblingClaimReader as J, importableOutputKeys as Ja, requireConfigString as Ji, s3BucketDomainName as Jn, resolveStateBucketWithDefault as Jo, refuseMalformedOrphanRecordsForDestroy as Jr, earliestDefined as Jt, reachableDivergentParameters as K, hasReasonlessBaselineRefusal as Ka, requireConfigArray as Ki, isSettledInstanceState as Kn, resolveCaptureObservedState as Ko, refuseMalformedNestedChildOutputs as Kr, maskingRetryLogger as Kt, createReadOnlyAttributeHealerFactory as L, WHOLE_DYNAMIC_REFERENCE_PATTERN as La, toCfnInteger as Li, assertFlagRoleArn as Ln, stripControlChars as Lo, malformedOutputsWarning as Lr, exportNameSecretExposure as Lt, ECR_AUTO_DELETE_IMAGES_TAG as M, recordMaskOnlyValuesIn as Ma, isStatefulRecreateTargetSync as Mi, IntrinsicFunctionResolver as Mn, redactedDockerCause as Mo, malformedOrphanRecordsWarning as Mr, displayTextOrWithheld as Mt, S3_AUTO_DELETE_OBJECTS_TAG as N, STATE_SOURCED_BASELINE_RULES as Na, renderStatefulReason as Ni, classifyReplaySecretRegion as Nn, runDockerForeground as No, malformedOrphanRowsKeptWarning as Nr, exportAliasCollisionScrubWarning as Nt, DELETE_INDEX_WAIT_PROCEED_NOTE as O, pathCrossesDottedKey as Oa, findReplacedReadersOfRecreateTargets as Oi, reDisableInstanceApiTermination as On, isDockerClientEnvKey as Oo, malformedLocalOutputsWarning as Or, DeploymentEventsReader as Ot, hasCdkAutoDeleteTag as P, STATE_SOURCED_CROSS_GENERATION_RULES as Pa, WARM_THROUGHPUT_MEMBERS as Pi, producerRegionsFromState as Pn, runDockerStreaming as Po, malformedOrphansRefusalMessage as Pr, secretBearing as Pt, getNestedRevertRun as Q, orphansCarriedFrom as Qa, withRetry as Qi, coerceParameterTypedValue as Qn, warnDeprecatedNoPrefixCliFlag as Qo, refuseMalformedOutputs as Qr, acquireIdempotencyToken as Qt, bold as R, isSingleDynamicReferenceToken as Ra, toFiniteNumber as Ri, assertSendableRoleArn as Rn, AssetManifestLoader as Ro, malformedRenderedContainersWarning as Rr, isWholeDynamicReferenceValue as Rt, DYNAMODB_DELETE_MIN_RESOURCE_TIMEOUT_MS as S, redactSecretsForState as Sa, unreadableResourceEntries as Si, isWaitAbandonedError as Sn, describeDockerExecFailure as So, hasReadableResources as Sr, renderAssemblyPathEscape as Ss, effectiveDeletionPolicy as St, deleteBudgetKey as T, DYNAMIC_REFERENCE_TOKEN_SCAN as Ta, withoutSilentDropProperties as Ti, ec2InstanceProtectionSite as Tn, finchSecretArgvRefusal as To, malformedDriftResourcePropertiesWarning as Tr, resolveBucketRegion as Ts, unsupportedFinalSnapshotError as Tt, yellow as U, describeRegionValueKind as Ua, configStringRefusal as Ui, applyCallerIdentityCredentials as Un, getLegacyStateBucketName as Uo, malformedStateRefusalMessage as Ur, bindingSkippedOutputs as Ut, green as V, S3StateBackend as Va, configBooleanRefusal as Vi, sendableAssumeRoleCommand as Vn, synthesisStatusMessage as Vo, malformedResourcesWarning as Vr, collectPublishedOutputNames as Vt, computeParameterTaint as W, exportNamesCarriedFrom as Wa, readConfigString as Wi, callerEnvCredentials as Wn, resolveApp as Wo, previewableOrphanRecords as Wr, DEFAULT_RESOURCE_TIMEOUT_MS as Wt, NESTED_PENDING_PARENT_REASON as X, isReadableBag as Xa, templateResourceTypes as Xi, s3BucketRegionalDomainName as Xn, resolveUseCdkBootstrapAssets as Xo, refuseMalformedOrphansForDestroy as Xr, reserveStackCreateToken as Xt, planOrphanAdoption as Y, importableOutputs as Ya, prefetchCreateOnlyPropertyPaths as Yi, s3BucketDualStackDomainName as Yn, resolveStateBucketWithDefaultAndSource as Yo, refuseMalformedOrphans as Yr, ledgerForStack as Yt, dropSettledNestedJournals as Z, orphansAfterRollback as Za, describeTypeWithThrottleRetry as Zi, s3BucketWebsiteUrl as Zn, stateBucketExistenceConfirmed as Zo, refuseMalformedOrphansForOrphan as Zr, withCreateTokenLedger as Zt, PROTECTION_PROPERTY_BY_TYPE as _, createSecretMasker as _a, repairMalformedResourceEntriesForReadOnly as _i, unchangedBehindSecretReference as _n, validateContainerRepoName as _o, UNREADABLE_RESOURCES_MAP_ROW as _r, nullPrototypeRecord as _s, ATOMIC_FINAL_SNAPSHOT_TYPES as _t, conditionInputsFrom as a, liveMatchesUnresolvedTokenFrame as aa, refuseMalformedResourceEntriesForImportSave as ai, tagPlanWarning as an, createAssetRedirectResolver as ao, isNamelessDynamicReferenceError as ar, CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION as as, replayFailedOperations as at, readProtection as b, maskSecretsInText as ba, unpreviewableOrphanRecords as bi, deleteSkipReason as bn, resolveDockerContextDirectory as bo, hasReadableOrphans as br, describeFileReadFailure as bs, ccRoutedFinalSnapshotError as bt, isSecretBearingReferenceString as c, carryLogOnlyValues as ca, refuseMalformedResourcePropertiesForExport as ci, CC_BROKEN_REASON as cn, AssetModeResolver as co, cfnRefValueFromPhysicalId as cr, PARTITION_TABLE as cs, destroyStackRecordsView as ct, makeCanonicalizePropertiesFn as d, literalSplitDelimitersOf as da, refuseMalformedResourcesForDestroy as di, wouldReturnToSdkProvider as dn, ensureAssetStorage as do, parseWebACLArn as dr, AssemblyReader as ds, planFailedOps as dt, canonicalLambdaFunctionName as ea, refuseMalformedResourceAttributesForOrphan as ei, DBPROXY_TAG_OPTIONS as en, AssetPublisher as eo, parameterTypeMayLoseSecretIdentity as er, CFN_TEMPLATE_BODY_LIMIT as es, revertNestedChildFromJournal as et, getPriorAttempts as f, logOnlyValueCount as fa, refuseMalformedResourcesForExport as fi, isCustomResourceType as fn, getBootstrapMarkerKey as fo, withSharedDrainBudget as fr, StageLoadError as fs, planRollback as ft, recordedProtectionNote as g, shareLogOnlyValues as ga, repairMalformedOutputsForReadOnly as gi, ccProtectionRegistryTypes as gn, validateAssetBucketName as go, UNREADABLE_ORPHANS_CONTAINER_ROW as gr, hasPlainPrototype$1 as gs, inheritProducerRegions as gt, recordedProtectionEvidence as h, recordLogOnlyValue as ha, repairMalformedOrphansForReadOnly as hi, slowCcOperationTimeoutMs as hn, readBootstrapMarkerBody as ho, STATE_RESOURCES_MALFORMED as hr, hasOwnKey as hs, getCurrentProducerRegions as ht, conditionFingerprint as i, TemplateParser as ia, refuseMalformedResourceEntriesForImport as ii, tagMapAsList as in, buildAssetRedirectMap as io, carriesFetchableDynamicReference as ir, uploadCfnTemplate as is, withNestedStackContext as it, waitForIndexesSettled as j, recordMaskOnlyValue as ja, isStatefulRecreateTargetForReplace as ji, INTRINSIC_KEYS as jn, redactDockerArgvValues as jo, malformedOrphanRecordsRefusalMessage as jr, WITHHELD_NAME_DISPLAY as jt, INDEX_SETTLE_POLL_INTERVAL_MS as k, identityKeyFor as ka, shownType as ki, reEnableInstanceApiTermination as kn, isMalformedEnvKey as ko, malformedLocalResourceEntriesWarning as kr, DeploymentEventsStore as kt, keptWholeReasonText as l, createUnionSecretMasker as la, refuseMalformedResourcePropertiesForOrphan as li, ProviderRegistry as ln, BOOTSTRAP_MARKER_PREFIX as lo, isStalePlaceholderArnAttribute as lr, canonicalizeRegion as ls, getStackRecords as lt, withResourceDeadline as m, recordLogOnlyParameterValue as ma, repairMalformedOrphanRecordsForReadOnly as mi, CloudControlProvider as mn, parseBootstrapMarker as mo, STATE_REGION_DIVERGED as mr, defineOwnKey as ms, findNestedStackTypeChanges as mt, IMPLICIT_DELETE_DEPENDENCIES as n, sameLambdaFunctionAddress as na, refuseMalformedResourceEntriesForDeploy as ni, readTagList as nn, stringifyValue as no, isImpossibleEmptyStoredAttribute as nr, MIGRATE_TMP_PREFIX as ns, withNestedRevertRun as nt, parentSuppliedValues as o, inheritNestedStackParameterAssociations as oa, refuseMalformedResourceEntriesForOrphan as oi, definedAttributes as on, loadPublishableAssetManifest as oo, keepsSecretReferenceToken as or, decodeListingKey as os, replayRollback as ot, markRefusedBeforeApplying as p, printingCorpusOf as pa, refuseMalformedState as pi, getCurrentResourceSecrets as pn, isCrossRegionRedirect as po, JSON_LISTING_HOLE_VALUE as pr, processStackMessages as ps, resolveReplacementOldType as pt, resourcesNamingDeclaredParameter as q, hasUnverifiableParameterRefusal as qa, requireConfigObject as qi, s3BucketArn as qn, resolveSkipPrefix as qo, refuseMalformedOrphanRecords as qr, RollbackInlinePolicyWriters as qt, computeImplicitDeleteEdges as r, DagBuilder as ra, refuseMalformedResourceEntriesForDestroy as ri, refuseMalformedDesiredTags as rn, WorkGraph as ro, carriesDynamicReference as rr, findLargeInlineResources as rs, getCurrentNestedStackContext as rt, readRecordedConditionVerdicts as s, recordNestedStackParameterExpressions as sa, refuseMalformedResourcePropertiesForDrift as si, stringifyIfAssigned as sn, rewriteTemplateAssetReferences as so, AWS_NO_VALUE as sr, expectedOwnerParam as ss, awaitInFlightSibling as st, DeployEngine as t, lambdaFunctionNameForMask as ta, refuseMalformedResourceEntries as ti, planTagDiff as tn, isSensitiveAttributeName as to, getAccountInfo as tr, CFN_TEMPLATE_URL_LIMIT as ts, revertedNestedRowIds as tt, mergeNoChangeOutputs as u, hasMaskableValues as ua, refuseMalformedResourcesForDeploy as ui, ccBrokenReason as un, assertAssetBucketRegion as uo, refStateLookupFromResource as ur, derivePartitionAndUrlSuffix as us, withStackRecords as ut, isProtectionValueActive as v, errorCauseChain as va, repairMalformedResourcePropertiesForReadOnly as vi, UNSPECIFIED_SKIP_REASON as vn, buildDenyExternalAccessPolicy as vo, deployRefusesOrphanRowsReason as vr, ownValue as vs, PRE_DELETE_SNAPSHOT_TYPES as vt, compensateRemovedDeletionProtection as w, recoverMaskedOutput as wa, findSilentDropProperties as wi, disableInstanceApiTermination as wn, dockerSpawnEnvWithSensitive as wo, isReadableResourceEntry as wr, clearBucketRegionCache as ws, refusesFinalSnapshot as wt, DynamoDBGlobalTableProvider as x, markSameGenerationBag as xa, unreadableOrphanRecords as xi, withIndeterminateGuard as xn, describeDockerCapturedOutput as xo, hasReadableOutputs as xr, displayAssemblyPath as xs, createPreDeleteFinalSnapshot as xt, perType as y, maskSecretsInError as ya, repairMalformedResourcesForReadOnly as yi, deleteIndeterminateGuards as yn, buildDockerImage as yo, displayLogicalId as yr, absoluteAssemblyPathEscape as ys, buildFinalSnapshotIdentifier as yt, cyan as z, LockManager as za, coerceCfnBoolean as zi, explicitRoleArnOrThrow as zn, getDockerImageBySourceHash as zo, malformedResourceEntriesWarning as zr, noEchoParameterValueSeed as zt };
|
|
34683
|
-
//# sourceMappingURL=deploy-engine-
|
|
34828
|
+
export { nestedChildStackName as $, importableOutputs as $a, describeTypeWithThrottleRetry as $i, coerceParameterTypedValue as $n, resolveStateBucketWithDefaultAndSource as $o, refuseMalformedOutputs as $r, acquireIdempotencyToken as $t, ECR_AUTO_DELETE_IMAGES_TAG as A, pathCrossesDottedKey as Aa, findReplacedReadersOfRecreateTargets as Ai, reEnableInstanceApiTermination as An, formatDockerLoginError as Ao, malformedLocalResourceEntriesWarning as Ar, DeploymentEventsStore as At, gray as B, WHOLE_DYNAMIC_REFERENCE_PATTERN as Ba, toFiniteNumber as Bi, explicitRoleArnOrThrow as Bn, escapeRegExp$2 as Bo, malformedResourceEntriesWarning as Br, noEchoParameterValueSeed as Bt, deleteBudgetKey as C, markSameGenerationBag as Ca, unreadableResourceEntries as Ci, isWaitAbandonedError as Cn, buildDockerImage as Co, hasReadableResources as Cr, absoluteAssemblyPathEscape as Cs, effectiveDeletionPolicy as Ct, INDEX_SETTLE_POLL_INTERVAL_MS as D, DYNAMIC_REFERENCE_TOKEN_SCAN as Da, withoutSilentDropProperties as Di, isTerminationProtectionPropagationError as Dn, describeDockerFailure as Do, malformedExportNamesWarning as Dr, resolveAssemblyPath as Ds, updatePartialMessage as Dt, DELETE_INDEX_WAIT_PROCEED_NOTE as E, recoverMaskedOutput as Ea, unwrittenCreateOnlyReplacement as Ei, ec2InstanceProtectionSite as En, describeDockerExecFailure as Eo, malformedDriftResourcePropertiesWarning as Er, renderAssemblyPathEscape as Es, unsupportedFinalSnapshotError as Et, markRefusedBeforeApplying as F, recordNoEchoAttributeValues as Fa, renderStatefulReason as Fi, producerRegionsFromState as Fn, redactDockerArgvValues as Fo, malformedOrphansRefusalMessage as Fr, secretBearing as Ft, namesAnyDeclaredParameter as G, rebuildClientForBucketRegion as Ga, configStringRefusal as Gi, callerEnvCredentials as Gn, synthesisStatusMessage as Go, previewableOrphanRecords as Gr, DEFAULT_RESOURCE_TIMEOUT_MS as Gt, red as H, LockManager as Ha, coerceCfnInteger as Hi, sendableAssumeRoleCommand as Hn, AssetManifestLoader as Ho, malformedResourcesWarning as Hr, collectPublishedOutputNames as Ht, formatResourceLine as I, STATE_SOURCED_BASELINE_RULES as Ia, WARM_THROUGHPUT_MEMBERS as Ii, regionLessSecretName as In, redactedDockerCause as Io, malformedOrphansWarning as Ir, secretBearingStateKeyWarning as It, makeSiblingClaimReader as J, exportNamesCarriedFrom as Ja, requireConfigArray as Ji, s3BucketArn as Jn, resolveApp as Jo, refuseMalformedOrphanRecords as Jr, RollbackInlinePolicyWriters as Jt, reachableDivergentParameters as K, acceptedCreateOnlyDropsOf as Ka, readConfigString as Ki, envCredentialsAreAssumedRole as Kn, getDefaultStateBucketName as Ko, refuseDivergentRecordRegionForDestroy as Kr, DEFAULT_RESOURCE_WARN_AFTER_MS as Kt, createReadOnlyAttributeHealerFactory as L, STATE_SOURCED_CROSS_GENERATION_RULES as La, coerceWarmThroughput as Li, applyRoleArnIfSet as Ln, runDockerForeground as Lo, malformedOutputsRefusalMessage as Lr, secretSafeKeyDisplay as Lt, hasCdkAutoDeleteTag as M, carriesSecretMask as Ma, MULTI_REGION_RECREATE_BLOCKED_TYPES as Mi, INTRINSIC_KEYS as Mn, isDockerClientEnvKey as Mo, malformedOrphanRecordsRefusalMessage as Mr, WITHHELD_NAME_DISPLAY as Mt, isTruthyCfnBoolean as N, recordMaskOnlyValue as Na, isStatefulRecreateTargetForReplace as Ni, IntrinsicFunctionResolver as Nn, isMalformedEnvKey as No, malformedOrphanRecordsWarning as Nr, displayTextOrWithheld as Nt, deleteTableWithIndexBusyRetry as O, dynamicReferenceTokens as Oa, NO_CC_HANDLERS_REASON as Oi, observeThenDisableInstanceApiTermination as On, dockerSpawnEnvWithSensitive as Oo, malformedExportSourceWarning as Or, clearBucketRegionCache as Os, updatePartialReason as Ot, getPriorAttempts as P, recordMaskOnlyValuesIn as Pa, isStatefulRecreateTargetSync as Pi, classifyReplaySecretRegion as Pn, partitionSensitiveEnv as Po, malformedOrphanRowsKeptWarning as Pr, exportAliasCollisionScrubWarning as Pt, getNestedRevertRun as Q, importableOutputKeys as Qa, templateResourceTypes as Qi, s3BucketWebsiteUrl as Qn, resolveStateBucketWithDefault as Qo, refuseMalformedOrphansForOrphan as Qr, withCreateTokenLedger as Qt, bold as R, STATE_SOURCED_READBACK_RULES as Ra, isWarmThroughputDecrease as Ri, assertFlagRoleArn as Rn, runDockerStreaming as Ro, malformedOutputsWarning as Rr, exportNameSecretExposure as Rt, compensateRemovedDeletionProtection as S, maskSecretsInText as Sa, unreadableOrphanRecords as Si, withIndeterminateGuard as Sn, buildDenyExternalAccessPolicy as So, hasReadableOutputs as Sr, ownValue as Ss, createPreDeleteFinalSnapshot as St, resolveDynamoDbDeleteBudgetMs as T, scrubResourceRecord as Ta, findSilentDropProperties as Ti, disableInstanceApiTermination as Tn, describeDockerCapturedOutput as To, isReadableResourceEntry as Tr, displayAssemblyPath as Ts, refusesFinalSnapshot as Tt, yellow as U, isLockInfoExpired as Ua, configBooleanRefusal as Ui, AWS_CREDENTIAL_ENV_KEYS as Un, getDockerImageBySourceHash as Uo, malformedScrubResourceEntriesRefusalMessage as Ur, isExportAliasCollision as Ut, green as V, isSingleDynamicReferenceToken as Va, coerceCfnBoolean as Vi, isIamRoleArn as Vn, stripControlChars as Vo, malformedResourcePropertiesWarning as Vr, collectDeclaredOutputNames as Vt, computeParameterTaint as W, S3StateBackend as Wa, configIntegerRefusal as Wi, applyCallerIdentityCredentials as Wn, Synthesizer as Wo, malformedStateRefusalMessage as Wr, bindingSkippedOutputs as Wt, NESTED_PENDING_PARENT_REASON as X, hasReasonlessBaselineRefusal as Xa, requireConfigString as Xi, s3BucketDualStackDomainName as Xn, resolveCaptureObservedState as Xo, refuseMalformedOrphans as Xr, ledgerForStack as Xt, planOrphanAdoption as Y, hasReadableExportSet as Ya, requireConfigObject as Yi, s3BucketDomainName as Yn, resolveAutoAssetStorage as Yo, refuseMalformedOrphanRecordsForDestroy as Yr, earliestDefined as Yt, dropSettledNestedJournals as Z, hasUnverifiableParameterRefusal as Za, prefetchCreateOnlyPropertyPaths as Zi, s3BucketRegionalDomainName as Zn, resolveSkipPrefix as Zo, refuseMalformedOrphansForDestroy as Zr, reserveStackCreateToken as Zt, perType as _, recordLogOnlyValue as _a, repairMalformedOutputsForReadOnly as _i, ccProtectionRegistryTypes as _n, isCrossRegionRedirect as _o, UNREADABLE_ORPHANS_CONTAINER_ROW as _r, processStackMessages as _s, inheritProducerRegions as _t, conditionInputsFrom as a, DagBuilder as aa, refuseMalformedResourceEntriesForImport as ai, tagMapAsList as an, isSensitiveAttributeName as ao, carriesFetchableDynamicReference as ar, CFN_TEMPLATE_URL_LIMIT as as, replayFailedOperations as at, DYNAMODB_DELETE_MIN_RESOURCE_TIMEOUT_MS as b, errorCauseChain as ba, repairMalformedResourcesForReadOnly as bi, deleteIndeterminateGuards as bn, validateAssetBucketName as bo, displayLogicalId as br, hasPlainPrototype$1 as bs, buildFinalSnapshotIdentifier as bt, isSecretBearingReferenceString as c, inheritNestedStackParameterAssociations as ca, refuseMalformedResourcePropertiesForDrift as ci, stringifyIfAssigned as cn, buildAssetRedirectMap as co, AWS_NO_VALUE as cr, uploadCfnTemplate as cs, destroyStackRecordsView as ct, makeCanonicalizePropertiesFn as d, createUnionSecretMasker as da, refuseMalformedResourcesForDeploy as di, ccBrokenReason as dn, rewriteTemplateAssetReferences as do, refStateLookupFromResource as dr, expectedOwnerParam as ds, recordAfterRollbackUpdate as dt, withRetry as ea, refuseMalformedOutputsForDestroy as ei, DBPROXY_TAGS_WHAT as en, isReadableBag as eo, isUnboundTemplateParameter as er, resolveUseCdkBootstrapAssets as es, revertNestedChildFromJournal as et, withResourceDeadline as f, hasMaskableValues as fa, refuseMalformedResourcesForDestroy as fi, wouldReturnToSdkProvider as fn, AssetModeResolver as fo, parseWebACLArn as fr, PARTITION_TABLE as fs, planFailedOps as ft, isProtectionValueActive as g, recordLogOnlyParameterValue as ga, repairMalformedOrphansForReadOnly as gi, slowCcOperationTimeoutMs as gn, getBootstrapMarkerKey as go, STATE_RESOURCES_MALFORMED as gr, StageLoadError as gs, getCurrentProducerRegions as gt, PROTECTION_PROPERTY_BY_TYPE as h, printingCorpusOf as ha, repairMalformedOrphanRecordsForReadOnly as hi, CloudControlProvider as hn, ensureAssetStorage as ho, STATE_REGION_DIVERGED as hr, AssemblyReader as hs, findNestedStackTypeChanges as ht, conditionFingerprint as i, sameLambdaFunctionAddress as ia, refuseMalformedResourceEntriesForDestroy as ii, refuseMalformedDesiredTags as in, AssetPublisher as io, carriesDynamicReference as ir, CFN_TEMPLATE_BODY_LIMIT as is, withNestedStackContext as it, S3_AUTO_DELETE_OBJECTS_TAG as j, identityKeyFor as ja, shownType as ji, DiffCalculator as jn, getDockerCmd as jo, malformedLocalResourcesWarning as jr, extractDeploymentEventError as jt, waitForIndexesSettled as k, isUncertifiedBaselineMaskPosition as ka, hasNoCloudControlHandlers as ki, reDisableInstanceApiTermination as kn, finchSecretArgvRefusal as ko, malformedLocalOutputsWarning as kr, resolveBucketRegion as ks, DeploymentEventsReader as kt, keptWholeReasonText as l, recordNestedStackParameterExpressions as la, refuseMalformedResourcePropertiesForExport as li, CC_BROKEN_REASON as ln, createAssetRedirectResolver as lo, cfnRefValueFromPhysicalId as lr, CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION as ls, getStackRecords as lt, recordedProtectionNote as m, logOnlyValueCount as ma, refuseMalformedState as mi, getCurrentResourceSecrets as mn, assertAssetBucketRegion as mo, JSON_LISTING_HOLE_VALUE as mr, derivePartitionAndUrlSuffix as ms, resolveReplacementOldType as mt, IMPLICIT_DELETE_DEPENDENCIES as n, canonicalLambdaFunctionName as na, refuseMalformedResourceEntries as ni, planTagDiff as nn, orphansCarriedFrom as no, getAccountInfo as nr, warnDeprecatedNoPrefixCliFlag as ns, withNestedRevertRun as nt, parentSuppliedValues as o, TemplateParser as oa, refuseMalformedResourceEntriesForImportSave as oi, tagPlanWarning as on, stringifyValue as oo, isNamelessDynamicReferenceError as or, MIGRATE_TMP_PREFIX as os, replayRollback as ot, recordedProtectionEvidence as p, literalSplitDelimitersOf as pa, refuseMalformedResourcesForExport as pi, isCustomResourceType as pn, BOOTSTRAP_MARKER_PREFIX as po, withSharedDrainBudget as pr, canonicalizeRegion as ps, planRollback as pt, resourcesNamingDeclaredParameter as q, describeRegionValueKind as qa, replayWarn as qi, isSettledInstanceState as qn, getLegacyStateBucketName as qo, refuseMalformedNestedChildOutputs as qr, maskingRetryLogger as qt, computeImplicitDeleteEdges as r, lambdaFunctionNameForMask as ra, refuseMalformedResourceEntriesForDeploy as ri, readTagList as rn, shouldRetainResource as ro, isImpossibleEmptyStoredAttribute as rr, ssmResolvedValueType as rs, getCurrentNestedStackContext as rt, readRecordedConditionVerdicts as s, liveMatchesUnresolvedTokenFrame as sa, refuseMalformedResourceEntriesForOrphan as si, definedAttributes as sn, WorkGraph as so, keepsSecretReferenceToken as sr, findLargeInlineResources as ss, awaitInFlightSibling as st, DeployEngine as t, markAuxiliaryFailure as ta, refuseMalformedResourceAttributesForOrphan as ti, DBPROXY_TAG_OPTIONS as tn, orphansAfterRollback as to, parameterTypeMayLoseSecretIdentity as tr, stateBucketExistenceConfirmed as ts, revertedNestedRowIds as tt, mergeNoChangeOutputs as u, carryLogOnlyValues as ua, refuseMalformedResourcePropertiesForOrphan as ui, ProviderRegistry as un, loadPublishableAssetManifest as uo, isStalePlaceholderArnAttribute as ur, decodeListingKey as us, withStackRecords as ut, readProtection as v, shareLogOnlyValues as va, repairMalformedResourceEntriesForReadOnly as vi, unchangedBehindSecretReference as vn, parseBootstrapMarker as vo, UNREADABLE_RESOURCES_MAP_ROW as vr, defineOwnKey as vs, ATOMIC_FINAL_SNAPSHOT_TYPES as vt, resolveDynamoDbDeleteBudgetClock as w, redactSecretsForState as wa, findActionableSilentDrops as wi, markWaitAbandoned as wn, resolveDockerContextDirectory as wo, isReadableOrphanRecord as wr, describeFileReadFailure as ws, isFinalSnapshotError as wt, beginDeleteWait as x, maskSecretsInError as xa, unpreviewableOrphanRecords as xi, deleteSkipReason as xn, validateContainerRepoName as xo, hasReadableOrphans as xr, nullPrototypeRecord as xs, ccRoutedFinalSnapshotError as xt, DynamoDBGlobalTableProvider as y, createSecretMasker as ya, repairMalformedResourcePropertiesForReadOnly as yi, UNSPECIFIED_SKIP_REASON as yn, readBootstrapMarkerBody as yo, deployRefusesOrphanRowsReason as yr, hasOwnKey as ys, PRE_DELETE_SNAPSHOT_TYPES as yt, cyan as z, TEMPLATE_SOURCED_RULES as za, toCfnInteger as zi, assertSendableRoleArn as zn, warnFinchArgvExposure as zo, malformedRenderedContainersWarning as zr, isWholeDynamicReferenceValue as zt };
|
|
34829
|
+
//# sourceMappingURL=deploy-engine-BTOCDCWf.js.map
|