@go-to-k/cdkd 0.226.0 → 0.227.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +152 -137
- package/dist/cli.js.map +1 -1
- package/dist/{deploy-engine-DM557Qjg.js → deploy-engine-Bl_Ka0hj.js} +184 -11
- package/dist/deploy-engine-Bl_Ka0hj.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/deploy-engine-DM557Qjg.js.map +0 -1
|
@@ -21,6 +21,8 @@ import { homedir, tmpdir } from "node:os";
|
|
|
21
21
|
import { GetHostedZoneCommand, ListHostedZonesByNameCommand, Route53Client } from "@aws-sdk/client-route-53";
|
|
22
22
|
import { DescribeListenersCommand, DescribeLoadBalancersCommand, ElasticLoadBalancingV2Client } from "@aws-sdk/client-elastic-load-balancing-v2";
|
|
23
23
|
import { KMSClient, ListAliasesCommand } from "@aws-sdk/client-kms";
|
|
24
|
+
import { readFile } from "fs/promises";
|
|
25
|
+
import { join as join$1 } from "path";
|
|
24
26
|
import { DescribeImagesCommand as DescribeImagesCommand$1, ECRClient, GetAuthorizationTokenCommand } from "@aws-sdk/client-ecr";
|
|
25
27
|
import { hostname } from "os";
|
|
26
28
|
import graphlib from "graphlib";
|
|
@@ -2162,6 +2164,150 @@ function setsEqual(a, b) {
|
|
|
2162
2164
|
return true;
|
|
2163
2165
|
}
|
|
2164
2166
|
|
|
2167
|
+
//#endregion
|
|
2168
|
+
//#region src/assets/asset-manifest-loader.ts
|
|
2169
|
+
/**
|
|
2170
|
+
* Whether a file asset's `source.path` is a CloudFormation template asset
|
|
2171
|
+
* (the stack template `<Stack>.template.json` or a nested-stack template
|
|
2172
|
+
* `<Stack>.<Nested>.nested.template.json`). cdkd deploys templates itself and
|
|
2173
|
+
* never needs them in the bootstrap bucket, so they are the ONLY file assets
|
|
2174
|
+
* excluded from publishing.
|
|
2175
|
+
*
|
|
2176
|
+
* `.template.json` is the reliable discriminator: a plain `.json` exclusion is
|
|
2177
|
+
* WRONG because a legitimate user file asset can be a `.json` file (e.g. a Step
|
|
2178
|
+
* Functions `DefinitionS3Location` ASL document, or an app config) whose source
|
|
2179
|
+
* path is `asset.<hash>.json` — those MUST be published. Shared by both file-
|
|
2180
|
+
* asset-selection sites ({@link AssetManifestLoader.getFileAssets} and
|
|
2181
|
+
* `AssetPublisher.addAssetsToGraph`) so they cannot drift.
|
|
2182
|
+
*/
|
|
2183
|
+
function isCfnTemplateAssetPath(sourcePath) {
|
|
2184
|
+
return sourcePath.endsWith(".template.json");
|
|
2185
|
+
}
|
|
2186
|
+
/**
|
|
2187
|
+
* Asset manifest loader
|
|
2188
|
+
*
|
|
2189
|
+
* Loads and parses CDK asset manifests from the CDK output directory
|
|
2190
|
+
*/
|
|
2191
|
+
var AssetManifestLoader = class {
|
|
2192
|
+
logger = getLogger().child("AssetManifestLoader");
|
|
2193
|
+
/**
|
|
2194
|
+
* Load asset manifest from CDK output directory
|
|
2195
|
+
*
|
|
2196
|
+
* @param cdkOutputDir CDK output directory (e.g., "cdk.out")
|
|
2197
|
+
* @param stackName Stack name
|
|
2198
|
+
* @returns Asset manifest or null if not found
|
|
2199
|
+
*/
|
|
2200
|
+
async loadManifest(cdkOutputDir, stackName) {
|
|
2201
|
+
const manifestPath = join$1(cdkOutputDir, `${stackName}.assets.json`);
|
|
2202
|
+
try {
|
|
2203
|
+
this.logger.debug(`Loading asset manifest from: ${manifestPath}`);
|
|
2204
|
+
const content = await readFile(manifestPath, "utf-8");
|
|
2205
|
+
const manifest = JSON.parse(content);
|
|
2206
|
+
this.logger.debug(`Loaded asset manifest: ${Object.keys(manifest.files).length} file assets, ${Object.keys(manifest.dockerImages).length} docker image assets`);
|
|
2207
|
+
return manifest;
|
|
2208
|
+
} catch (error) {
|
|
2209
|
+
if (error.code === "ENOENT") {
|
|
2210
|
+
this.logger.debug(`Asset manifest not found: ${manifestPath}`);
|
|
2211
|
+
return null;
|
|
2212
|
+
}
|
|
2213
|
+
throw new Error(`Failed to load asset manifest from ${manifestPath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
2214
|
+
}
|
|
2215
|
+
}
|
|
2216
|
+
/**
|
|
2217
|
+
* Get file assets from manifest (excludes CloudFormation templates)
|
|
2218
|
+
*
|
|
2219
|
+
* @param manifest Asset manifest
|
|
2220
|
+
* @returns Map of asset hash to file asset
|
|
2221
|
+
*/
|
|
2222
|
+
getFileAssets(manifest) {
|
|
2223
|
+
const fileAssets = /* @__PURE__ */ new Map();
|
|
2224
|
+
for (const [assetHash, asset] of Object.entries(manifest.files)) {
|
|
2225
|
+
if (isCfnTemplateAssetPath(asset.source.path)) {
|
|
2226
|
+
this.logger.debug(`Skipping CloudFormation template asset: ${asset.displayName}`);
|
|
2227
|
+
continue;
|
|
2228
|
+
}
|
|
2229
|
+
fileAssets.set(assetHash, asset);
|
|
2230
|
+
}
|
|
2231
|
+
this.logger.debug(`Found ${fileAssets.size} file assets (excluding templates)`);
|
|
2232
|
+
return fileAssets;
|
|
2233
|
+
}
|
|
2234
|
+
/**
|
|
2235
|
+
* Get asset source path (absolute path)
|
|
2236
|
+
*
|
|
2237
|
+
* @param cdkOutputDir CDK output directory
|
|
2238
|
+
* @param asset File asset
|
|
2239
|
+
* @returns Absolute path to asset source
|
|
2240
|
+
*/
|
|
2241
|
+
getAssetSourcePath(cdkOutputDir, asset) {
|
|
2242
|
+
return join$1(cdkOutputDir, asset.source.path);
|
|
2243
|
+
}
|
|
2244
|
+
/**
|
|
2245
|
+
* Resolve asset destination values (replace ${AWS::AccountId}, ${AWS::Region}, etc.)
|
|
2246
|
+
*
|
|
2247
|
+
* @param value Value with placeholders
|
|
2248
|
+
* @param accountId AWS account ID
|
|
2249
|
+
* @param region AWS region
|
|
2250
|
+
* @param partition AWS partition (default: "aws")
|
|
2251
|
+
* @returns Resolved value
|
|
2252
|
+
*/
|
|
2253
|
+
resolveAssetDestinationValue(value, accountId, region, partition = "aws") {
|
|
2254
|
+
return value.replace(/\$\{AWS::AccountId\}/g, accountId).replace(/\$\{AWS::Region\}/g, region).replace(/\$\{AWS::Partition\}/g, partition);
|
|
2255
|
+
}
|
|
2256
|
+
};
|
|
2257
|
+
/**
|
|
2258
|
+
* Look up the docker-image asset that backs a Lambda's `Code.ImageUri`.
|
|
2259
|
+
*
|
|
2260
|
+
* The CDK template synthesizes `Code.ImageUri` as a `Fn::Sub` whose body
|
|
2261
|
+
* references the bootstrap ECR repo and ends in `:<hash>` — that hash is
|
|
2262
|
+
* the same key used in `manifest.dockerImages[<hash>]`. cdkd extracts the
|
|
2263
|
+
* hash by walking known image-URI shapes; on miss, when the manifest has
|
|
2264
|
+
* exactly one Docker image, we fall back to it (single-asset heuristic) so
|
|
2265
|
+
* locally-built non-bootstrapped images still work. This is documented as
|
|
2266
|
+
* a v1 limitation; immutable digest pins (`@sha256:<digest>`) hit the same
|
|
2267
|
+
* fallback path.
|
|
2268
|
+
*
|
|
2269
|
+
* Returns the `(hash, asset)` pair when matched, or `undefined` when both
|
|
2270
|
+
* the regex AND the single-asset fallback miss (typically: 0 docker assets,
|
|
2271
|
+
* or 2+ docker assets with no hash match — the caller should treat this as
|
|
2272
|
+
* "fall through to the ECR-pull path").
|
|
2273
|
+
*
|
|
2274
|
+
* Exported as a free function (not a method) so the local-invoke modules
|
|
2275
|
+
* can reuse it without depending on the `AssetManifestLoader` instance —
|
|
2276
|
+
* the manifest itself is a plain JSON shape.
|
|
2277
|
+
*/
|
|
2278
|
+
function getDockerImageBySourceHash(manifest, imageUri) {
|
|
2279
|
+
const dockerImages = manifest.dockerImages ?? {};
|
|
2280
|
+
const entries = Object.entries(dockerImages);
|
|
2281
|
+
if (entries.length === 0) return void 0;
|
|
2282
|
+
const hash = extractHashFromImageUri(imageUri);
|
|
2283
|
+
if (hash !== void 0) {
|
|
2284
|
+
const asset = dockerImages[hash];
|
|
2285
|
+
if (asset) return {
|
|
2286
|
+
hash,
|
|
2287
|
+
asset
|
|
2288
|
+
};
|
|
2289
|
+
}
|
|
2290
|
+
if (entries.length === 1) {
|
|
2291
|
+
const [singleHash, singleAsset] = entries[0];
|
|
2292
|
+
return {
|
|
2293
|
+
hash: singleHash,
|
|
2294
|
+
asset: singleAsset
|
|
2295
|
+
};
|
|
2296
|
+
}
|
|
2297
|
+
}
|
|
2298
|
+
/**
|
|
2299
|
+
* Extract the source hash from a Lambda `Code.ImageUri` string. CDK's
|
|
2300
|
+
* bootstrap layout ends every image URI in `:<hex-hash>`, and that hash
|
|
2301
|
+
* is the same key used in the asset manifest's `dockerImages` map.
|
|
2302
|
+
*
|
|
2303
|
+
* Returns `undefined` for shapes we can't parse (digest pins, missing tag,
|
|
2304
|
+
* etc.) — the caller falls back to the single-asset heuristic.
|
|
2305
|
+
*/
|
|
2306
|
+
function extractHashFromImageUri(imageUri) {
|
|
2307
|
+
if (imageUri.includes("@sha256:")) return void 0;
|
|
2308
|
+
return /:([a-f0-9]{8,})$/.exec(imageUri)?.[1];
|
|
2309
|
+
}
|
|
2310
|
+
|
|
2165
2311
|
//#endregion
|
|
2166
2312
|
//#region src/assets/file-asset-publisher.ts
|
|
2167
2313
|
/**
|
|
@@ -2870,7 +3016,7 @@ var AssetPublisher = class {
|
|
|
2870
3016
|
const cdkOutputDir = manifestPath.replace(/\/[^/]+$/, "");
|
|
2871
3017
|
const prefix = options.nodePrefix || "";
|
|
2872
3018
|
const nodeIds = [];
|
|
2873
|
-
const fileAssets = Object.entries(manifest.files || {}).filter(([, asset]) => !
|
|
3019
|
+
const fileAssets = Object.entries(manifest.files || {}).filter(([, asset]) => !isCfnTemplateAssetPath(asset.source.path));
|
|
2874
3020
|
for (const [hash, asset] of fileAssets) {
|
|
2875
3021
|
const nodeId = `asset-publish:${prefix}file:${hash}`;
|
|
2876
3022
|
graph.addNode({
|
|
@@ -4625,6 +4771,35 @@ var DagBuilder = class {
|
|
|
4625
4771
|
* https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html
|
|
4626
4772
|
*/
|
|
4627
4773
|
/**
|
|
4774
|
+
* Conditional-replacement predicate for `AWS::DynamoDB::Table.AttributeDefinitions`.
|
|
4775
|
+
*
|
|
4776
|
+
* Returns true only when an attribute present in BOTH the old and new definition
|
|
4777
|
+
* lists changed its `AttributeType` (e.g. `S` -> `N`). Adding a brand-new attribute
|
|
4778
|
+
* (to back a new GSI) or removing one (when a GSI is dropped) returns false — those
|
|
4779
|
+
* are in-place `UpdateTable` operations, matching CloudFormation's "No interruption"
|
|
4780
|
+
* update behavior for this property.
|
|
4781
|
+
*/
|
|
4782
|
+
function attributeTypeChangedForSharedAttribute(oldValue, newValue) {
|
|
4783
|
+
const toTypeMap = (value) => {
|
|
4784
|
+
const map = /* @__PURE__ */ new Map();
|
|
4785
|
+
if (Array.isArray(value)) {
|
|
4786
|
+
for (const def of value) if (def && typeof def === "object") {
|
|
4787
|
+
const name = def["AttributeName"];
|
|
4788
|
+
const type = def["AttributeType"];
|
|
4789
|
+
if (typeof name === "string" && typeof type === "string") map.set(name, type);
|
|
4790
|
+
}
|
|
4791
|
+
}
|
|
4792
|
+
return map;
|
|
4793
|
+
};
|
|
4794
|
+
const oldTypes = toTypeMap(oldValue);
|
|
4795
|
+
const newTypes = toTypeMap(newValue);
|
|
4796
|
+
for (const [name, oldType] of oldTypes) {
|
|
4797
|
+
const newType = newTypes.get(name);
|
|
4798
|
+
if (newType !== void 0 && newType !== oldType) return true;
|
|
4799
|
+
}
|
|
4800
|
+
return false;
|
|
4801
|
+
}
|
|
4802
|
+
/**
|
|
4628
4803
|
* Replacement rules registry
|
|
4629
4804
|
*
|
|
4630
4805
|
* Maps resource types to their replacement rules
|
|
@@ -4697,11 +4872,7 @@ var ReplacementRulesRegistry = class {
|
|
|
4697
4872
|
])
|
|
4698
4873
|
});
|
|
4699
4874
|
this.rules.set("AWS::DynamoDB::Table", {
|
|
4700
|
-
replacementProperties: new Set([
|
|
4701
|
-
"TableName",
|
|
4702
|
-
"KeySchema",
|
|
4703
|
-
"AttributeDefinitions"
|
|
4704
|
-
]),
|
|
4875
|
+
replacementProperties: new Set(["TableName", "KeySchema"]),
|
|
4705
4876
|
updateableProperties: new Set([
|
|
4706
4877
|
"BillingMode",
|
|
4707
4878
|
"ProvisionedThroughput",
|
|
@@ -4712,7 +4883,8 @@ var ReplacementRulesRegistry = class {
|
|
|
4712
4883
|
"Tags",
|
|
4713
4884
|
"TimeToLiveSpecification",
|
|
4714
4885
|
"PointInTimeRecoverySpecification"
|
|
4715
|
-
])
|
|
4886
|
+
]),
|
|
4887
|
+
conditionalReplacements: new Map([["AttributeDefinitions", attributeTypeChangedForSharedAttribute]])
|
|
4716
4888
|
});
|
|
4717
4889
|
this.rules.set("AWS::SQS::Queue", {
|
|
4718
4890
|
replacementProperties: new Set([
|
|
@@ -8810,7 +8982,7 @@ const PROPERTY_COVERAGE_BY_TYPE = new Map([
|
|
|
8810
8982
|
"TreatMissingData",
|
|
8811
8983
|
"Unit"
|
|
8812
8984
|
]),
|
|
8813
|
-
silentDrop: new Map([["EvaluationCriteria", "
|
|
8985
|
+
silentDrop: new Map([["EvaluationCriteria", "Absent from both the SDK PutMetricAlarm input and the aws-cdk-lib CfnAlarm L1 (a newer CFn-schema-only property ahead of SDK/CDK support); no wire path to forward it and no CDK app can emit it."], ["EvaluationInterval", "Absent from both the SDK PutMetricAlarm input and the aws-cdk-lib CfnAlarm L1 (a newer CFn-schema-only property ahead of SDK/CDK support); no wire path to forward it and no CDK app can emit it."]])
|
|
8814
8986
|
}],
|
|
8815
8987
|
["AWS::CodeBuild::Project", {
|
|
8816
8988
|
handled: new Set([
|
|
@@ -10276,6 +10448,7 @@ const PROPERTY_COVERAGE_BY_TYPE = new Map([
|
|
|
10276
10448
|
["AWS::StepFunctions::StateMachine", {
|
|
10277
10449
|
handled: new Set([
|
|
10278
10450
|
"Definition",
|
|
10451
|
+
"DefinitionS3Location",
|
|
10279
10452
|
"DefinitionString",
|
|
10280
10453
|
"DefinitionSubstitutions",
|
|
10281
10454
|
"EncryptionConfiguration",
|
|
@@ -10286,7 +10459,7 @@ const PROPERTY_COVERAGE_BY_TYPE = new Map([
|
|
|
10286
10459
|
"Tags",
|
|
10287
10460
|
"TracingConfiguration"
|
|
10288
10461
|
]),
|
|
10289
|
-
silentDrop: new Map(
|
|
10462
|
+
silentDrop: /* @__PURE__ */ new Map()
|
|
10290
10463
|
}],
|
|
10291
10464
|
["AWS::WAFv2::WebACL", {
|
|
10292
10465
|
handled: new Set([
|
|
@@ -13237,5 +13410,5 @@ var DeployEngine = class {
|
|
|
13237
13410
|
};
|
|
13238
13411
|
|
|
13239
13412
|
//#endregion
|
|
13240
|
-
export {
|
|
13241
|
-
//# sourceMappingURL=deploy-engine-
|
|
13413
|
+
export { findLargeInlineResources as $, shouldRetainResource as A, getDockerImageBySourceHash as B, applyRoleArnIfSet as C, LockManager as D, TemplateParser as E, formatDockerLoginError as F, resolveCaptureObservedState as G, getDefaultStateBucketName as H, getDockerCmd as I, resolveStateBucketWithDefaultAndSource as J, resolveSkipPrefix as K, runDockerForeground as L, stringifyValue as M, WorkGraph as N, S3StateBackend as O, buildDockerImage as P, MIGRATE_TMP_PREFIX as Q, runDockerStreaming as R, IntrinsicFunctionResolver as S, DagBuilder as T, getLegacyStateBucketName as U, Synthesizer as V, resolveApp as W, CFN_TEMPLATE_BODY_LIMIT as X, warnDeprecatedNoPrefixCliFlag as Y, CFN_TEMPLATE_URL_LIMIT as Z, IAMRoleProvider as _, withRetry as a, findActionableSilentDrops as b, computeImplicitDeleteEdges as c, bold as d, uploadCfnTemplate as et, cyan as f, yellow as g, red as h, withResourceDeadline as i, AssetPublisher as j, rebuildClientForBucketRegion as k, extractDeploymentEventError as l, green as m, DEFAULT_RESOURCE_WARN_AFTER_MS as n, clearBucketRegionCache as nt, isRetryableTransientError as o, gray as p, resolveStateBucketWithDefault as q, DeployEngine as r, resolveBucketRegion as rt, IMPLICIT_DELETE_DEPENDENCIES as s, DEFAULT_RESOURCE_TIMEOUT_MS as t, AssemblyReader as tt, formatResourceLine as u, collectInlinePolicyNamesManagedBySiblings as v, DiffCalculator as w, CloudControlProvider as x, ProviderRegistry as y, AssetManifestLoader as z };
|
|
13414
|
+
//# sourceMappingURL=deploy-engine-Bl_Ka0hj.js.map
|