@go-to-k/cdkd 0.290.35 → 0.290.37
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-BguZAQtF.js → asg-provider-CXLgFrPg.js} +2 -2
- package/dist/{asg-provider-BguZAQtF.js.map → asg-provider-CXLgFrPg.js.map} +1 -1
- package/dist/cli.js +2 -2
- package/dist/{deploy-engine-DhZtBBq0.js → deploy-engine-pVC4fG22.js} +362 -8
- package/dist/deploy-engine-pVC4fG22.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/{program-COiS7GZJ.js → program-CUOo1x11.js} +591 -282
- package/dist/{program-COiS7GZJ.js.map → program-CUOo1x11.js.map} +1 -1
- package/dist/{version-BIpCWEQx.js → version-COEQwjCP.js} +2 -2
- package/dist/{version-BIpCWEQx.js.map → version-COEQwjCP.js.map} +1 -1
- package/package.json +1 -1
- package/dist/deploy-engine-DhZtBBq0.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { n as isVersionOnlyInvocation, t as getCdkdVersion } from "./version-
|
|
2
|
+
import { n as isVersionOnlyInvocation, t as getCdkdVersion } from "./version-COEQwjCP.js";
|
|
3
3
|
|
|
4
4
|
//#region src/cli/pipe-close-handler.ts
|
|
5
5
|
/**
|
|
@@ -74,7 +74,7 @@ async function main() {
|
|
|
74
74
|
console.log(getCdkdVersion());
|
|
75
75
|
return;
|
|
76
76
|
}
|
|
77
|
-
const { buildProgram } = await import("./program-
|
|
77
|
+
const { buildProgram } = await import("./program-CUOo1x11.js");
|
|
78
78
|
const program = buildProgram();
|
|
79
79
|
const args = reorderArgs(process.argv);
|
|
80
80
|
await program.parseAsync(args);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { C as displayAwsMessage, D as truncateCodePoints, E as isPasteableIdent, S as UNRENDERABLE, T as displaySafe, d as applyDefaultNameForFallback, f as explicitNamePropertyFor, g as looksLikeCdkdGeneratedName, h as getCurrentStackName, m as generateResourceNameWithFallback, n as getLogger, p as generateResourceName, r as isStdoutReservedForPayload, s as getLiveRenderer, v as withStackName, w as displayIdent, x as STACK_REF_MAX_CODE_POINTS, y as withoutGeneratedFallbackName } from "./logger-BX4pJk0T.js";
|
|
2
2
|
import { a as setAssumedRoleCredentials, i as getPreAssumeEnvCredentials, n as awsClientDefaults, o as setPreAssumeEnvCredentials, r as getAssumedRoleCredentials, t as SECOND_ROLE_PUBLISH_REFUSAL } from "./aws-client-defaults-BoIxyCir.js";
|
|
3
|
-
import { t as getCdkdVersion } from "./version-
|
|
3
|
+
import { t as getCdkdVersion } from "./version-COEQwjCP.js";
|
|
4
4
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
5
5
|
import { createHash, randomUUID } from "node:crypto";
|
|
6
6
|
import { CreateBucketCommand, DeleteObjectCommand, DeleteObjectsCommand, GetBucketLocationCommand, GetBucketReplicationCommand, GetObjectCommand, HeadBucketCommand, HeadObjectCommand, ListObjectVersionsCommand, ListObjectsV2Command, NoSuchKey, PutBucketEncryptionCommand, PutBucketPolicyCommand, PutObjectCommand, PutPublicAccessBlockCommand, S3Client, S3ServiceException } from "@aws-sdk/client-s3";
|
|
@@ -9473,6 +9473,23 @@ const STATE_SCHEMA_VERSIONS_READABLE = [
|
|
|
9473
9473
|
10
|
|
9474
9474
|
];
|
|
9475
9475
|
/**
|
|
9476
|
+
* Whether `record` carries a baseline refusal no in-place UPDATE may clear.
|
|
9477
|
+
* Requires the marker AND the reason: a reason with no marker is not a state
|
|
9478
|
+
* any writer produces, and honouring it would invent a refusal.
|
|
9479
|
+
*/
|
|
9480
|
+
function hasUnverifiableParameterRefusal(record) {
|
|
9481
|
+
return record?.observedBaselineRefused === true && record.observedBaselineRefusalReason === "unverifiable-parameter";
|
|
9482
|
+
}
|
|
9483
|
+
/**
|
|
9484
|
+
* Whether `record` carries a marker with NO reason this binary knows — written
|
|
9485
|
+
* by an older cdkd, cause unknown. The one caller-side question is whether to read it
|
|
9486
|
+
* fail closed; see `observedBaselineRefusalReason`'s doc.
|
|
9487
|
+
*/
|
|
9488
|
+
function hasReasonlessBaselineRefusal(record) {
|
|
9489
|
+
const reason = record?.observedBaselineRefusalReason;
|
|
9490
|
+
return record?.observedBaselineRefused === true && reason !== "unverifiable-parameter" && reason !== "incomplete-resolution";
|
|
9491
|
+
}
|
|
9492
|
+
/**
|
|
9476
9493
|
* Returns true when a recorded `DeletionPolicy` should prevent cdkd from
|
|
9477
9494
|
* deleting the underlying AWS resource. `Retain` and `RetainExceptOnCreate`
|
|
9478
9495
|
* both keep the resource around; `Delete` / `Snapshot` / undefined all
|
|
@@ -33135,7 +33152,7 @@ var CloudControlProvider = class {
|
|
|
33135
33152
|
const indeterminateGuard = await this.confirmDeleteTargetIdentity(logicalId, resourceType, physicalId, context);
|
|
33136
33153
|
if (context?.removeProtection === true && resourceType === "AWS::AutoScaling::AutoScalingGroup") {
|
|
33137
33154
|
this.logger.debug(`Delegating protected AutoScalingGroup ${logicalId} delete to the SDK ASGProvider (Cloud Control cannot force-delete a protected ASG)`);
|
|
33138
|
-
const { ASGProvider } = await import("./asg-provider-
|
|
33155
|
+
const { ASGProvider } = await import("./asg-provider-CXLgFrPg.js").then((n) => n.n);
|
|
33139
33156
|
const asgProvider = new ASGProvider();
|
|
33140
33157
|
return withIndeterminateGuard(await asgProvider.delete(logicalId, physicalId, resourceType, _properties, context), indeterminateGuard);
|
|
33141
33158
|
}
|
|
@@ -40115,6 +40132,294 @@ async function createReplicationGroupFinalSnapshot(client, replicationGroupId, l
|
|
|
40115
40132
|
});
|
|
40116
40133
|
}
|
|
40117
40134
|
|
|
40135
|
+
//#endregion
|
|
40136
|
+
//#region src/analyzer/parameter-dependence.ts
|
|
40137
|
+
/**
|
|
40138
|
+
* The PARAMETER-DEPENDENCE WALK: which resources of a raw template depend on
|
|
40139
|
+
* which template parameters (issues
|
|
40140
|
+
* [#2854](https://github.com/go-to-k/cdkd/issues/2854),
|
|
40141
|
+
* [#3468](https://github.com/go-to-k/cdkd/issues/3468)).
|
|
40142
|
+
*
|
|
40143
|
+
* Pure template analysis with two consumers that must agree: `cdkd import`'s
|
|
40144
|
+
* ARM 4 (`src/cli/commands/import-deployed-parameters.ts` supplies the
|
|
40145
|
+
* divergent parameter set from `DescribeStacks`) and `cdkd deploy`'s reading of
|
|
40146
|
+
* a REASON-LESS `observedBaselineRefused` marker, which has no deployed values
|
|
40147
|
+
* at all and therefore treats every declared parameter as divergent
|
|
40148
|
+
* ({@link resourcesNamingDeclaredParameter}). It lives in this layer because
|
|
40149
|
+
* `src/deployment` may not import from `src/cli`.
|
|
40150
|
+
*
|
|
40151
|
+
* TAINT THROUGH ANOTHER RESOURCE'S ATTRIBUTES IS FOLLOWED within one stack: the
|
|
40152
|
+
* walk records the target of every `Fn::GetAtt` / `${A.Attr}`, and the refused
|
|
40153
|
+
* set is closed over those targets. A plain `Ref` of a resource is NOT
|
|
40154
|
+
* followed: it yields the physical id, and a secret used as a resource NAME is
|
|
40155
|
+
* already disclosed by the identifier itself.
|
|
40156
|
+
*/
|
|
40157
|
+
/**
|
|
40158
|
+
* Every intrinsic the dependence walk knows how to read. An `Fn::`-prefixed
|
|
40159
|
+
* key OUTSIDE this list is unclassifiable: it may name a parameter in a way
|
|
40160
|
+
* the generic recursion cannot see, so the walk fails closed on it.
|
|
40161
|
+
*/
|
|
40162
|
+
const KNOWN_INTRINSICS = /* @__PURE__ */ new Set([
|
|
40163
|
+
"Fn::GetAtt",
|
|
40164
|
+
"Fn::Join",
|
|
40165
|
+
"Fn::Sub",
|
|
40166
|
+
"Fn::Select",
|
|
40167
|
+
"Fn::Split",
|
|
40168
|
+
"Fn::If",
|
|
40169
|
+
"Fn::Equals",
|
|
40170
|
+
"Fn::And",
|
|
40171
|
+
"Fn::Or",
|
|
40172
|
+
"Fn::Not",
|
|
40173
|
+
"Fn::ImportValue",
|
|
40174
|
+
"Fn::GetStackOutput",
|
|
40175
|
+
"Fn::FindInMap",
|
|
40176
|
+
"Fn::Base64",
|
|
40177
|
+
"Fn::GetAZs",
|
|
40178
|
+
"Fn::Cidr"
|
|
40179
|
+
]);
|
|
40180
|
+
/** `${Name}` / `${Name.Attr}` in an `Fn::Sub` string; `${!Literal}` is an escape. */
|
|
40181
|
+
const SUB_VARIABLE = /\$\{([^!}][^}]*)\}/g;
|
|
40182
|
+
/**
|
|
40183
|
+
* Which names (parameters, but also resources and pseudo parameters — the
|
|
40184
|
+
* caller intersects with the divergent set) the RAW `Properties` of a resource
|
|
40185
|
+
* depend on, plus its resource-level `Condition`.
|
|
40186
|
+
*
|
|
40187
|
+
* Generic by design: instead of modelling each intrinsic's argument grammar it
|
|
40188
|
+
* recurses into EVERY value, so a `Ref` nested in an `Fn::Join` / `Fn::Select`
|
|
40189
|
+
* / `Fn::Split` operand, an `Fn::FindInMap` key, or an `Fn::Sub` variable-map
|
|
40190
|
+
* value is found without being named. Only the three forms that name something
|
|
40191
|
+
* by BARE STRING need their own arm: `Ref`, `Fn::Sub`'s template text, and a
|
|
40192
|
+
* condition name (`Fn::If`'s first argument, and `Condition` inside the
|
|
40193
|
+
* `Conditions` section), which is followed transitively through
|
|
40194
|
+
* `template.Conditions`.
|
|
40195
|
+
*
|
|
40196
|
+
* May throw `RangeError` on a bag deeper than the call stack; the caller wraps
|
|
40197
|
+
* it fail-closed, like the discard walk beside it.
|
|
40198
|
+
*/
|
|
40199
|
+
function collectParameterDependencies(properties, resourceCondition, template) {
|
|
40200
|
+
const names = /* @__PURE__ */ new Set();
|
|
40201
|
+
const attributeTargets = /* @__PURE__ */ new Set();
|
|
40202
|
+
const visitedConditions = /* @__PURE__ */ new Set();
|
|
40203
|
+
let unclassifiable = false;
|
|
40204
|
+
const conditions = template.Conditions !== null && typeof template.Conditions === "object" ? template.Conditions : {};
|
|
40205
|
+
const followCondition = (name) => {
|
|
40206
|
+
if (typeof name !== "string") {
|
|
40207
|
+
unclassifiable = true;
|
|
40208
|
+
return;
|
|
40209
|
+
}
|
|
40210
|
+
if (visitedConditions.has(name)) return;
|
|
40211
|
+
visitedConditions.add(name);
|
|
40212
|
+
if (!Object.hasOwn(conditions, name)) {
|
|
40213
|
+
unclassifiable = true;
|
|
40214
|
+
return;
|
|
40215
|
+
}
|
|
40216
|
+
walk(conditions[name], true);
|
|
40217
|
+
};
|
|
40218
|
+
const walk = (node, inConditions) => {
|
|
40219
|
+
if (node === null || typeof node !== "object") return;
|
|
40220
|
+
if (Array.isArray(node)) {
|
|
40221
|
+
for (const element of node) walk(element, inConditions);
|
|
40222
|
+
return;
|
|
40223
|
+
}
|
|
40224
|
+
for (const [key, value] of Object.entries(node)) {
|
|
40225
|
+
if (key === "Ref") {
|
|
40226
|
+
if (typeof value === "string") names.add(value);
|
|
40227
|
+
else unclassifiable = true;
|
|
40228
|
+
continue;
|
|
40229
|
+
}
|
|
40230
|
+
if (key === "Fn::Sub") {
|
|
40231
|
+
const text = Array.isArray(value) ? value[0] : value;
|
|
40232
|
+
if (typeof text !== "string" || Array.isArray(value) && value.length !== 2) unclassifiable = true;
|
|
40233
|
+
else for (const match of text.matchAll(SUB_VARIABLE)) {
|
|
40234
|
+
const variable = (match[1] ?? "").trim();
|
|
40235
|
+
names.add(variable);
|
|
40236
|
+
const dot = variable.indexOf(".");
|
|
40237
|
+
if (dot > 0) {
|
|
40238
|
+
names.add(variable.slice(0, dot));
|
|
40239
|
+
attributeTargets.add(variable.slice(0, dot));
|
|
40240
|
+
}
|
|
40241
|
+
}
|
|
40242
|
+
if (Array.isArray(value)) walk(value[1], inConditions);
|
|
40243
|
+
continue;
|
|
40244
|
+
}
|
|
40245
|
+
if (key === "Fn::GetAtt") {
|
|
40246
|
+
const target = Array.isArray(value) ? value[0] : value;
|
|
40247
|
+
if (typeof target === "string") {
|
|
40248
|
+
const dot = target.indexOf(".");
|
|
40249
|
+
const logicalId = Array.isArray(value) || dot <= 0 ? target : target.slice(0, dot);
|
|
40250
|
+
names.add(logicalId);
|
|
40251
|
+
attributeTargets.add(logicalId);
|
|
40252
|
+
} else unclassifiable = true;
|
|
40253
|
+
walk(value, inConditions);
|
|
40254
|
+
continue;
|
|
40255
|
+
}
|
|
40256
|
+
if (key === "Fn::If") {
|
|
40257
|
+
if (Array.isArray(value) && value.length === 3) {
|
|
40258
|
+
followCondition(value[0]);
|
|
40259
|
+
walk(value[1], inConditions);
|
|
40260
|
+
walk(value[2], inConditions);
|
|
40261
|
+
} else unclassifiable = true;
|
|
40262
|
+
continue;
|
|
40263
|
+
}
|
|
40264
|
+
if (key === "Condition" && inConditions) {
|
|
40265
|
+
followCondition(value);
|
|
40266
|
+
continue;
|
|
40267
|
+
}
|
|
40268
|
+
if (key.startsWith("Fn::") && !KNOWN_INTRINSICS.has(key)) unclassifiable = true;
|
|
40269
|
+
walk(value, inConditions);
|
|
40270
|
+
}
|
|
40271
|
+
};
|
|
40272
|
+
walk(properties, false);
|
|
40273
|
+
if (resourceCondition !== void 0) followCondition(resourceCondition);
|
|
40274
|
+
return {
|
|
40275
|
+
names,
|
|
40276
|
+
attributeTargets,
|
|
40277
|
+
unclassifiable
|
|
40278
|
+
};
|
|
40279
|
+
}
|
|
40280
|
+
/**
|
|
40281
|
+
* The divergent parameters that ANYTHING in the template names. A declared
|
|
40282
|
+
* parameter nothing names cannot have shaped a resource — and CDK's
|
|
40283
|
+
* `BootstrapVersion` is exactly that on every default-synthesized stack: SSM
|
|
40284
|
+
* typed, never bound by the resolver because nothing references it, hence
|
|
40285
|
+
* always "divergent". Left in, it would arm the unclassifiable-shape refusal on
|
|
40286
|
+
* stacks whose every real parameter is proven.
|
|
40287
|
+
*
|
|
40288
|
+
* "Names" is the UNION of this module's walk and `TemplateParser`'s reference
|
|
40289
|
+
* scan — the same scan the resolver uses to decide an SSM-typed parameter is
|
|
40290
|
+
* unreferenced — so the two cannot disagree about `BootstrapVersion`. An
|
|
40291
|
+
* unclassifiable shape does NOT keep the whole set here: CloudFormation names a
|
|
40292
|
+
* parameter only through `Ref`, `Fn::Sub` text or a condition, and the generic
|
|
40293
|
+
* recursion reads those inside any intrinsic, known or not. A walk that THROWS
|
|
40294
|
+
* keeps the whole set (fail closed).
|
|
40295
|
+
*/
|
|
40296
|
+
function reachableDivergentParameters(template, divergent, rawBags) {
|
|
40297
|
+
if (divergent.size === 0) return /* @__PURE__ */ new Set();
|
|
40298
|
+
try {
|
|
40299
|
+
const roots = [
|
|
40300
|
+
rawBags,
|
|
40301
|
+
template.Resources,
|
|
40302
|
+
template.Outputs,
|
|
40303
|
+
template.Conditions
|
|
40304
|
+
];
|
|
40305
|
+
const named = new Set(collectParameterDependencies(roots, void 0, template).names);
|
|
40306
|
+
const parser = new TemplateParser();
|
|
40307
|
+
for (const root of roots) {
|
|
40308
|
+
if (root === null || typeof root !== "object") continue;
|
|
40309
|
+
for (const name of parser.extractReferences(root)) named.add(name);
|
|
40310
|
+
}
|
|
40311
|
+
return new Set([...divergent].filter((name) => named.has(name)));
|
|
40312
|
+
} catch {
|
|
40313
|
+
return new Set(divergent);
|
|
40314
|
+
}
|
|
40315
|
+
}
|
|
40316
|
+
/** Whether any DECLARED parameter is named by anything in the template. */
|
|
40317
|
+
function namesAnyDeclaredParameter(template) {
|
|
40318
|
+
const declared = template.Parameters;
|
|
40319
|
+
if (declared === null || typeof declared !== "object") return false;
|
|
40320
|
+
const names = new Set(Object.keys(declared));
|
|
40321
|
+
return names.size > 0 && reachableDivergentParameters(template, names, []).size > 0;
|
|
40322
|
+
}
|
|
40323
|
+
/**
|
|
40324
|
+
* The per-stack ARM 4 verdict. Each resource is judged on its TEMPLATE
|
|
40325
|
+
* definition (`Properties` + `Condition`) AND on the raw bag the state record
|
|
40326
|
+
* carries, unioned: a record preserved by a selective merge holds a previous
|
|
40327
|
+
* run's RESOLVED literal (`Value: 'CHANGEME'`), which names no parameter, so
|
|
40328
|
+
* judging it on the state bag alone would leave nothing to carry to the
|
|
40329
|
+
* freshly imported resource that reads its attribute. Template resources that
|
|
40330
|
+
* are not in state at all are judged too, for the same reason.
|
|
40331
|
+
*
|
|
40332
|
+
* Seeds are direct dependents and unclassifiable bags (a bag that cannot be
|
|
40333
|
+
* read cannot be vouched for, and neither can what reads its attributes); the
|
|
40334
|
+
* refused set is then closed over ATTRIBUTE reads, to a fixpoint.
|
|
40335
|
+
*/
|
|
40336
|
+
function computeParameterTaint(template, stateBags, divergent) {
|
|
40337
|
+
const refused = /* @__PURE__ */ new Set();
|
|
40338
|
+
const unclassifiable = /* @__PURE__ */ new Set();
|
|
40339
|
+
const parametersHit = /* @__PURE__ */ new Set();
|
|
40340
|
+
if (divergent.size === 0) return {
|
|
40341
|
+
refused,
|
|
40342
|
+
unclassifiable,
|
|
40343
|
+
parametersHit
|
|
40344
|
+
};
|
|
40345
|
+
const templateResources = template.Resources !== null && typeof template.Resources === "object" ? template.Resources : {};
|
|
40346
|
+
const readers = /* @__PURE__ */ new Map();
|
|
40347
|
+
for (const logicalId of /* @__PURE__ */ new Set([...Object.keys(templateResources), ...stateBags.keys()])) {
|
|
40348
|
+
const definition = Object.hasOwn(templateResources, logicalId) ? templateResources[logicalId] : void 0;
|
|
40349
|
+
const record = definition !== null && typeof definition === "object" ? definition : {};
|
|
40350
|
+
try {
|
|
40351
|
+
const dependencies = collectParameterDependencies([record["Properties"], stateBags.get(logicalId)], record["Condition"], template);
|
|
40352
|
+
readers.set(logicalId, new Set(dependencies.attributeTargets));
|
|
40353
|
+
const hits = [...dependencies.names].filter((name) => divergent.has(name));
|
|
40354
|
+
for (const name of hits) parametersHit.add(name);
|
|
40355
|
+
if (hits.length > 0) refused.add(logicalId);
|
|
40356
|
+
else if (dependencies.unclassifiable) {
|
|
40357
|
+
refused.add(logicalId);
|
|
40358
|
+
unclassifiable.add(logicalId);
|
|
40359
|
+
}
|
|
40360
|
+
} catch {
|
|
40361
|
+
refused.add(logicalId);
|
|
40362
|
+
unclassifiable.add(logicalId);
|
|
40363
|
+
}
|
|
40364
|
+
}
|
|
40365
|
+
for (let grew = refused.size > 0; grew;) {
|
|
40366
|
+
grew = false;
|
|
40367
|
+
for (const [logicalId, targets] of readers) {
|
|
40368
|
+
if (refused.has(logicalId)) continue;
|
|
40369
|
+
if (![...targets].some((target) => refused.has(target))) continue;
|
|
40370
|
+
refused.add(logicalId);
|
|
40371
|
+
grew = true;
|
|
40372
|
+
}
|
|
40373
|
+
}
|
|
40374
|
+
return {
|
|
40375
|
+
refused,
|
|
40376
|
+
unclassifiable,
|
|
40377
|
+
parametersHit
|
|
40378
|
+
};
|
|
40379
|
+
}
|
|
40380
|
+
/**
|
|
40381
|
+
* The reading of a REASON-LESS `observedBaselineRefused` marker (issue
|
|
40382
|
+
* [#3468](https://github.com/go-to-k/cdkd/issues/3468)): which resources'
|
|
40383
|
+
* TEMPLATE definitions name a declared parameter, judged with NO deployed
|
|
40384
|
+
* values at hand — so every declared parameter anything names is divergent.
|
|
40385
|
+
* The answer is {@link computeParameterTaint}'s whole refused set: direct
|
|
40386
|
+
* dependents, unclassifiable bags, and attribute readers of either. Pseudo
|
|
40387
|
+
* parameters never count (the hit test intersects with DECLARED names) and
|
|
40388
|
+
* neither does a parameter nothing names, CDK's Rules-only `BootstrapVersion`
|
|
40389
|
+
* included.
|
|
40390
|
+
*
|
|
40391
|
+
* AN UNCLASSIFIABLE BAG COUNTS ONLY WHEN SOME DECLARED PARAMETER IS NAMED
|
|
40392
|
+
* SOMEWHERE in the template, exactly as in ARM 4, and deliberately: this set
|
|
40393
|
+
* has to cover what an older import's ARM 4 can have marked ON TEMPLATE
|
|
40394
|
+
* EVIDENCE (ARM 4 also read the state bags; a deploy's are resolved literals,
|
|
40395
|
+
* so they are not read here), and ARM 4 never ran on a template in which
|
|
40396
|
+
* nothing names a declared parameter. Counting the
|
|
40397
|
+
* bag regardless would make an old refusal of the other class sticky on every
|
|
40398
|
+
* CDK stack (each declares `BootstrapVersion`) and protect nothing.
|
|
40399
|
+
*
|
|
40400
|
+
* FAILS CLOSED, and never throws: a missing or unreadable template, a
|
|
40401
|
+
* `Resources` section that is not an object, or a walk that throws answers
|
|
40402
|
+
* `true` for every logical id, and says so in `failedClosed` — a cause CLASS,
|
|
40403
|
+
* never a template value or an error message. Absent from a readable
|
|
40404
|
+
* template's `Resources` answers `false` — that resource is being removed, and
|
|
40405
|
+
* a DELETE reads no baseline.
|
|
40406
|
+
*/
|
|
40407
|
+
function resourcesNamingDeclaredParameter(template) {
|
|
40408
|
+
const everything = (failedClosed) => Object.assign(() => true, { failedClosed });
|
|
40409
|
+
try {
|
|
40410
|
+
if (template === void 0 || template === null || typeof template !== "object") return everything("unreadable-template");
|
|
40411
|
+
const resources = template.Resources;
|
|
40412
|
+
if (resources === null || typeof resources !== "object" || Array.isArray(resources)) return everything("unreadable-template");
|
|
40413
|
+
const parameters = template.Parameters;
|
|
40414
|
+
if (parameters !== void 0 && (parameters === null || typeof parameters !== "object" || Array.isArray(parameters))) return everything("unreadable-template");
|
|
40415
|
+
const divergent = reachableDivergentParameters(template, new Set(Object.keys(parameters ?? {})), []);
|
|
40416
|
+
const refused = computeParameterTaint(template, /* @__PURE__ */ new Map(), divergent).refused;
|
|
40417
|
+
return Object.assign((logicalId) => refused.has(logicalId), { failedClosed: void 0 });
|
|
40418
|
+
} catch {
|
|
40419
|
+
return everything("walk-threw");
|
|
40420
|
+
}
|
|
40421
|
+
}
|
|
40422
|
+
|
|
40118
40423
|
//#endregion
|
|
40119
40424
|
//#region src/analyzer/skipped-outputs.ts
|
|
40120
40425
|
/**
|
|
@@ -44392,6 +44697,47 @@ var DeployEngine = class DeployEngine {
|
|
|
44392
44697
|
return Object.keys(siblings).length > 0 ? { siblings } : void 0;
|
|
44393
44698
|
}
|
|
44394
44699
|
/**
|
|
44700
|
+
* Issue [#3468](https://github.com/go-to-k/cdkd/issues/3468) — the
|
|
44701
|
+
* fail-closed reading of a REASON-LESS `observedBaselineRefused` marker.
|
|
44702
|
+
*
|
|
44703
|
+
* cdkd 0.290.35 wrote unverifiable-parameter refusals with no reason, so an
|
|
44704
|
+
* absent reason cannot be read as "an UPDATE may clear it". A reason-less
|
|
44705
|
+
* marker on a resource whose TEMPLATE definition names a declared parameter
|
|
44706
|
+
* is stamped `'unverifiable-parameter'` here, IN MEMORY, once, before the
|
|
44707
|
+
* diff: every later arm (the in-place rebuild, the metadata-only spread, the
|
|
44708
|
+
* NO_CHANGE carry, the auto-refresh) then sees the explicit form and needs
|
|
44709
|
+
* no rule of its own, and whatever this deploy saves holds it — the record
|
|
44710
|
+
* heals into the form later binaries read directly. Nothing is saved FOR the
|
|
44711
|
+
* stamp: a deploy that writes no state (`--dry-run`, no changes) re-derives
|
|
44712
|
+
* it next time.
|
|
44713
|
+
*
|
|
44714
|
+
* The template is the RAW one `deploy()` was handed (a nested child engine
|
|
44715
|
+
* gets its own), which is what the dependence walk needs. A template that
|
|
44716
|
+
* cannot be read, or a walk that throws, stamps every reason-less marker
|
|
44717
|
+
* (`resourcesNamingDeclaredParameter` fails closed). A record whose logical
|
|
44718
|
+
* id the template no longer defines is being DELETED and is left alone.
|
|
44719
|
+
*
|
|
44720
|
+
* The RECORD object is replaced, not mutated (a per-record alias taken
|
|
44721
|
+
* before this line keeps what was loaded); the container is updated in
|
|
44722
|
+
* place, which is what lets every later reader of it see the stamp.
|
|
44723
|
+
*/
|
|
44724
|
+
stampReasonlessParameterRefusals(stateResources, template) {
|
|
44725
|
+
let namesParameter;
|
|
44726
|
+
let stamped = 0;
|
|
44727
|
+
for (const [logicalId, resource] of Object.entries(stateResources)) {
|
|
44728
|
+
if (!hasReasonlessBaselineRefusal(resource)) continue;
|
|
44729
|
+
namesParameter ??= resourcesNamingDeclaredParameter(template);
|
|
44730
|
+
if (!namesParameter(logicalId)) continue;
|
|
44731
|
+
stateResources[logicalId] = {
|
|
44732
|
+
...resource,
|
|
44733
|
+
observedBaselineRefusalReason: "unverifiable-parameter"
|
|
44734
|
+
};
|
|
44735
|
+
stamped++;
|
|
44736
|
+
}
|
|
44737
|
+
if (namesParameter?.failedClosed !== void 0) this.logger.debug(`The template's parameter dependence could not be judged (${namesParameter.failedClosed}): every observed-baseline refusal recorded without a reason is treated as an unverifiable-parameter refusal (${stamped} stamped).`);
|
|
44738
|
+
if (stamped > 0) this.logger.debug(`${stamped} resource(s) carry an observed-baseline refusal recorded without a reason by an older cdkd, and their template definition reads a template parameter: treated as an unverifiable-parameter refusal (kept until the resource is replaced or re-imported against a CloudFormation stack that proves the parameter).`);
|
|
44739
|
+
}
|
|
44740
|
+
/**
|
|
44395
44741
|
* Kick off `provider.readCurrentState` for every resource in the
|
|
44396
44742
|
* loaded state that lacks `observedProperties` (e.g. state written
|
|
44397
44743
|
* by a pre-v3 binary, or a v3 record where a NO_CHANGE-skipped
|
|
@@ -44429,7 +44775,7 @@ var DeployEngine = class DeployEngine {
|
|
|
44429
44775
|
resource
|
|
44430
44776
|
});
|
|
44431
44777
|
}
|
|
44432
|
-
if (refused > 0) this.logger.debug(`observed-properties auto-refresh SKIPPED for ${refused} resource(s) whose baseline a 'cdkd import' run refused (issue #2944): their recorded properties cannot position the redaction, so capturing an AWS readback against them could persist a resolved secret in plaintext. A deploy that actually CHANGES one of them restores its baseline; a NO_CHANGE deploy does
|
|
44778
|
+
if (refused > 0) this.logger.debug(`observed-properties auto-refresh SKIPPED for ${refused} resource(s) whose baseline a 'cdkd import' run refused (issue #2944): their recorded properties cannot position the redaction, so capturing an AWS readback against them could persist a resolved secret in plaintext. A deploy that actually CHANGES one of them restores its baseline, unless the refusal is an unverifiable-parameter one (only a replacement or a proving re-import discharges that); a NO_CHANGE deploy never does.`);
|
|
44433
44779
|
if (candidates.length === 0) return;
|
|
44434
44780
|
const allSiblings = {};
|
|
44435
44781
|
for (const [lid, res] of Object.entries(stateResources)) allSiblings[lid] = {
|
|
@@ -44501,6 +44847,7 @@ var DeployEngine = class DeployEngine {
|
|
|
44501
44847
|
this.logger.info(failedOnly ? `A previous deploy of '${stackName}' failed and was automatically rolled back. The failed resource may be partially applied — run 'cdkd rollback ${stackName} --revert-failed' to revert it, or continue deploying to fix forward (a successful deploy clears this note).` : `A previous deploy of '${stackName}' failed or was interrupted. Run 'cdkd rollback ${stackName}' to revert it, or continue deploying to fix forward.`);
|
|
44502
44848
|
}
|
|
44503
44849
|
} catch {}
|
|
44850
|
+
this.stampReasonlessParameterRefusals(currentState.resources, template);
|
|
44504
44851
|
this.kickOffAutoRefreshObservedProperties(currentState.resources);
|
|
44505
44852
|
this.logger.debug(`Template has ${Object.keys(template.Resources || {}).length} resources`);
|
|
44506
44853
|
const outputsDigestSource = structuredClone({
|
|
@@ -44519,6 +44866,7 @@ var DeployEngine = class DeployEngine {
|
|
|
44519
44866
|
const effectiveTemplate = this.templateParser.filterResourcesByCondition(template, conditions);
|
|
44520
44867
|
const orphanCountBeforeAdoption = (currentState.orphans ?? []).length;
|
|
44521
44868
|
const orphanPlan = await this.adoptRollbackOrphans(currentState, effectiveTemplate);
|
|
44869
|
+
if (Object.keys(orphanPlan.adopted).length > 0) this.stampReasonlessParameterRefusals(currentState.resources, template);
|
|
44522
44870
|
const orphansChanged = Object.keys(orphanPlan.adopted).length > 0 || (currentState.orphans ?? []).length !== orphanCountBeforeAdoption;
|
|
44523
44871
|
const resourceTypes = new Set(Object.values(effectiveTemplate.Resources || {}).map((r) => r.Type).filter((type) => type !== "AWS::CDK::Metadata"));
|
|
44524
44872
|
this.providerRegistry.validateResourceTypes(resourceTypes);
|
|
@@ -45783,6 +46131,7 @@ var DeployEngine = class DeployEngine {
|
|
|
45783
46131
|
} else throw updateError;
|
|
45784
46132
|
}
|
|
45785
46133
|
if (result.wasReplaced) this.logger.info(`Resource ${logicalId} was replaced: ${currentResource.physicalId} -> ${result.physicalId}`);
|
|
46134
|
+
const keepsParameterRefusal = !(result.wasReplaced === true && result.physicalId !== currentResource.physicalId) && hasUnverifiableParameterRefusal(currentResource);
|
|
45786
46135
|
const carriedAttributes = result.attributes ?? (result.wasReplaced ? void 0 : currentResource.attributes);
|
|
45787
46136
|
this.registerNoEchoAttributes(logicalId, {
|
|
45788
46137
|
...carriedAttributes && { attributes: carriedAttributes },
|
|
@@ -45796,10 +46145,15 @@ var DeployEngine = class DeployEngine {
|
|
|
45796
46145
|
...carriedAttributes && { attributes: carriedAttributes },
|
|
45797
46146
|
...dependencies && dependencies.length > 0 && { dependencies },
|
|
45798
46147
|
...this.extractTemplateAttributes(template, logicalId),
|
|
45799
|
-
provisionedBy: resultProvisionedBy
|
|
46148
|
+
provisionedBy: resultProvisionedBy,
|
|
46149
|
+
...keepsParameterRefusal && {
|
|
46150
|
+
observedBaselineRefused: true,
|
|
46151
|
+
observedBaselineRefusalReason: "unverifiable-parameter"
|
|
46152
|
+
}
|
|
45800
46153
|
};
|
|
45801
|
-
|
|
45802
|
-
this.
|
|
46154
|
+
if (keepsParameterRefusal) this.logger.debug(`observedProperties capture SKIPPED for updated ${logicalId} (${resourceType}): 'cdkd import' refused its baseline because a template parameter was not provably deployed at its 'Default', and this deploy bound the same 'Default' — an in-place update cannot show that AWS no longer holds the deployed value. The refusal stands until the resource is replaced or re-imported against a CloudFormation stack that proves the parameter.`);
|
|
46155
|
+
const updateCaptureSiblings = keepsParameterRefusal ? void 0 : await this.buildObservedCaptureSiblings(resourceType, logicalId, result.physicalId, template, stateResources, stackName, parameterValues, conditions);
|
|
46156
|
+
if (!keepsParameterRefusal) this.kickOffObservedCapture(captureProvider, logicalId, result.physicalId, resourceType, resolvedProps, updateCaptureSiblings);
|
|
45803
46157
|
const updatePartial = updatePartialReason(result);
|
|
45804
46158
|
if (counts) {
|
|
45805
46159
|
if (updatePartial !== void 0) counts.updatePartial++;
|
|
@@ -46506,5 +46860,5 @@ var DeployEngine = class DeployEngine {
|
|
|
46506
46860
|
};
|
|
46507
46861
|
|
|
46508
46862
|
//#endregion
|
|
46509
|
-
export {
|
|
46510
|
-
//# sourceMappingURL=deploy-engine-
|
|
46863
|
+
export { yellow as $, NestedStackChildDirectDestroyError as $i, identityKeyFor as $n, getDockerCmd as $r, requireConfigObject as $t, createPreDeleteFinalSnapshot as A, PARTITION_TABLE as Ai, refuseMalformedNestedChildOutputs as An, stringifyValue as Ar, carriesDynamicReference as At, isStatefulRecreateTargetSync as B, setAwsClients as Bi, findSilentDropProperties as Bn, getBootstrapMarkerKey as Br, isSettledInstanceState as Bt, namesAnyDeclaredParameter as C, CFN_TEMPLATE_URL_LIMIT as Ci, malformedOutputsWarning as Cn, importableOutputKeys as Cr, slowCcOperationTimeoutMs as Ct, PRE_DELETE_SNAPSHOT_TYPES as D, CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION as Di, malformedStateRefusalMessage as Dn, orphansCarriedFrom as Dr, disableInstanceApiTermination as Dt, ATOMIC_FINAL_SNAPSHOT_TYPES as E, uploadCfnTemplate as Ei, malformedResourcesWarning as En, orphansAfterRollback as Er, deleteSkipReason as Et, extractDeploymentEventError as F, clearBucketRegionCache as Fi, refuseMalformedState as Fn, rewriteTemplateAssetReferences as Fr, isImpossibleEmptyStoredAttribute as Ft, toCfnInteger as G, DependencyError as Gi, STATE_SOURCED_BASELINE_RULES as Gn, validateContainerRepoName as Gr, coerceCfnBoolean as Gt, WARM_THROUGHPUT_MEMBERS as H, CdkdError as Hi, withRetry as Hn, parseBootstrapMarker as Hr, normalizeAwsTagsToCfn as Ht, makeSiblingClaimReader as I, resolveBucketRegion as Ii, repairMalformedOutputsForReadOnly as In, AssetModeResolver as Ir, isNamelessDynamicReferenceError as It, bold as J, IntrinsicResolutionRefusalError as Ji, TEMPLATE_SOURCED_RULES as Jn, describeDockerCapturedOutput as Jr, configIntegerRefusal as Jt, toFiniteNumber as K, DeployCancelledError as Ki, STATE_SOURCED_CROSS_GENERATION_RULES as Kn, buildDenyExternalAccessPolicy as Kr, coerceCfnInteger as Kt, planOrphanAdoption as L, AwsClients as Li, repairMalformedResourcePropertiesForReadOnly as Ln, BOOTSTRAP_MARKER_PREFIX as Lr, isUnboundTemplateParameter as Lt, refusesFinalSnapshot as M, derivePartitionAndUrlSuffix as Mi, refuseMalformedOutputsForDestroy as Mn, buildAssetRedirectMap as Mr, cfnRefValueFromPhysicalId as Mt, unsupportedFinalSnapshotError as N, AssemblyReader as Ni, refuseMalformedResourcePropertiesForOrphan as Nn, createAssetRedirectResolver as Nr, coerceParameterTypedValue as Nt, buildFinalSnapshotIdentifier as O, decodeListingKey as Oi, producerRecordKey as On, shouldRetainResource as Or, isTerminationProtectionPropagationError as Ot, makeCanonicalizePropertiesFn as P, processStackMessages as Pi, refuseMalformedResourcesForDestroy as Pn, loadPublishableAssetManifest as Pr, getAccountInfo as Pt, red as Q, MalformedProducerRecordRefusalError as Qi, errorCauseChain as Qn, formatDockerLoginError as Qr, requireConfigArray as Qt, MULTI_REGION_RECREATE_BLOCKED_TYPES as R, getAwsClients as Ri, repairMalformedResourcesForReadOnly as Rn, assertAssetBucketRegion as Rr, parameterTypeMayLoseSecretIdentity as Rt, computeParameterTaint as S, CFN_TEMPLATE_BODY_LIMIT as Si, malformedOutputsRefusalMessage as Sn, hasUnverifiableParameterRefusal as Sr, isWaitAbandonedError as St, resourcesNamingDeclaredParameter as T, findLargeInlineResources as Ti, malformedResourcePropertiesWarning as Tn, isReadableBag as Tr, deleteIndeterminateGuards as Tt, coerceWarmThroughput as U, ConfigError as Ui, DagBuilder as Un, readBootstrapMarkerBody as Ur, resolveExplicitPhysicalId as Ut, renderStatefulReason as V, AssetError as Vi, describeTypeWithThrottleRetry as Vn, isCrossRegionRedirect as Vr, WAFv2WebACLProvider as Vt, isWarmThroughputDecrease as W, CrossAccountSecretRefusalError as Wi, TemplateParser as Wn, validateAssetBucketName as Wr, assertRegionMatch as Wt, gray as X, LocalStartServiceError as Xi, createSecretMasker as Xn, describeDockerFailure as Xr, readConfigString as Xt, cyan as Y, LocalInvokeBuildError as Yi, carriesSecretMask as Yn, describeDockerExecFailure as Yr, configStringRefusal as Yt, green as Z, LockError as Zi, dynamicReferenceTokens as Zn, dockerSpawnEnvWithSensitive as Zr, replayWarn as Zt, bagHoldsSecretExpression as _, markRedactedCause as _a, resolveStateBucketWithDefaultAndSource as _i, hasReadableOutputs as _n, CUSTOM_RESOURCE_RESPONSE_PREFIX as _r, endCommandInterruptScope as _t, DeploymentEventsStore as a, StackTerminationProtectionError as aa, stripControlChars as ai, s3BucketDomainName as an, recoverMaskedOutput as ar, secretBearingStateKeyWarning as at, mergeNoChangeOutputs as b, safeStringify$1 as ba, warnDeprecatedNoPrefixCliFlag as bi, malformedExportSourceWarning as bn, hasReadableExportSet as br, startInterruptWatch as bt, replayFailedOperations as c, formatError as ca, Synthesizer as ci, s3BucketWebsiteUrl as cn, LockManager as cr, IAMRoleProvider as ct, updatePartialMessage as d, withErrorHandling as da, getLegacyStateBucketName as di, applyCallerIdentityCredentials as dn, UNREPRODUCIBLE_LOCK_CLAUSE as dr, ProviderRegistry as dt, PartialFailureError as ea, partitionSensitiveEnv as ei, requireConfigString as en, isSingleDynamicReferenceToken as er, collectDeclaredOutputNames as et, updatePartialReason as f, isMarkedNonRetryable as fa, resolveApp as fi, callerEnvCredentials as fn, buildForceUnlockCommand as fr, wouldReturnToSdkProvider as ft, computeImplicitDeleteEdges as g, markNonRetryable as ga, resolveStateBucketWithDefault as gi, STATE_RESOURCES_MALFORMED as gn, shellQuote as gr, beginCommandInterruptScope as gt, IMPLICIT_DELETE_DEPENDENCIES as h, isTransientServerError as ha, resolveSkipPrefix as hi, INTRINSIC_KEYS as hn, formatLockExpiry as hr, maskerOrIdentity as ht, DeploymentEventsReader as i, StackHasActiveImportsError as ia, escapeRegExp$1 as ii, s3BucketArn as in, recordMaskOnlyValue as ir, secretBearing as it, isFinalSnapshotError as j, canonicalizeRegion as ji, refuseMalformedOutputs as jn, WorkGraph as jr, carriesFetchableDynamicReference as jt, ccRoutedFinalSnapshotError as k, expectedOwnerParam as ki, refuseDivergentRecordRegionForDestroy as kn, AssetPublisher as kr, IntrinsicFunctionResolver as kt, replayRollback as l, isCdkdError as la, synthesisStatusMessage as li, applyRoleArnIfSet as ln, S3StateBackend as lr, collectInlinePolicyNamesManagedBySiblings as lt, maskingRetryLogger as m, isThrottlingError as ma, resolveCaptureObservedState as mi, DiffCalculator as mn, forceQuitRecoveryClause as mr, maskDeep as mt, DEFAULT_RESOURCE_WARN_AFTER_MS as n, ResourceTimeoutError as na, runDockerForeground as ni, producerRegionsFromState as nn, maskSecretsInError as nr, exportAliasCollisionScrubWarning as nt, planFailedOps as o, StateError as oa, AssetManifestLoader as oi, s3BucketDualStackDomainName as on, redactSecretsForState as or, secretSafeKeyDisplay as ot, withResourceDeadline as p, isRetryableTransientError as pa, resolveAutoAssetStorage as pi, envCredentialsAreAssumedRole as pn, buildLockContentionMessage as pr, createMaskedRetryLogger as pt, formatResourceLine as q, DynamicReferenceRegionAmbiguousError as qi, STATE_SOURCED_READBACK_RULES as qn, buildDockerImage as qr, configBooleanRefusal as qt, DeployEngine as r, ResourceUpdateNotSupportedError as ra, runDockerStreaming as ri, withSharedDrainBudget as rn, maskSecretsInText as rr, isExportAliasCollision as rt, planRollback as s, SynthesisError as sa, getDockerImageBySourceHash as si, s3BucketRegionalDomainName as sn, scrubResourceRecord as sr, getCurrentResourceSecrets as st, DEFAULT_RESOURCE_TIMEOUT_MS as t, ProvisioningError as ta, redactDockerArgvValues as ti, classifyReplaySecretRegion as tn, markSameGenerationBag as tr, collectPublishedOutputNames as tt, resolveReplacementOldType as u, normalizeAwsError as ua, getDefaultStateBucketName as ui, AWS_CREDENTIAL_ENV_KEYS as un, rebuildClientForBucketRegion as ur, clearOnUpdateRemoval as ut, isSecretBearingReferenceString as v, retryClassificationText as va, resolveUseCdkBootstrapAssets as vi, hasReadableResources as vn, DEFAULT_STATE_PREFIX as vr, interruptWatchListenerCount as vt, reachableDivergentParameters as w, MIGRATE_TMP_PREFIX as wi, malformedRenderedContainersWarning as wn, importableOutputs as wr, UNSPECIFIED_SKIP_REASON as wt, bindingSkippedOutputs as x, __exportAll as xa, ssmResolvedValueType as xi, malformedLocalOutputsWarning as xn, hasReasonlessBaselineRefusal as xr, CloudControlProvider as xt, keptWholeReasonText as y, describeAwsFailure as ya, stateBucketExistenceConfirmed as yi, malformedExportNamesWarning as yn, exportNamesCarriedFrom as yr, isInterruptedWaitError as yt, isStatefulRecreateTargetForReplace as z, resetAwsClients as zi, findActionableSilentDrops as zn, ensureAssetStorage as zr, refStateLookupFromResource as zt };
|
|
46864
|
+
//# sourceMappingURL=deploy-engine-pVC4fG22.js.map
|