@go-to-k/cdkd 0.229.7 → 0.230.0
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 +22 -127
- package/dist/cli.js.map +1 -1
- package/dist/{deploy-engine-BIYc-qWo.js → deploy-engine-_N5kVjZN.js} +159 -4
- package/dist/deploy-engine-_N5kVjZN.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/package.json +1 -1
- package/dist/deploy-engine-BIYc-qWo.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { A as withErrorHandling, B as generateResourceName, C as StackHasActiveImportsError, F as getLiveRenderer, H as withSkipPrefix, I as PATTERN_B_NAME_OPTIONS, L as PATTERN_B_NAME_PROPERTIES, M as getLogger, P as runStackBuffered, R as PATTERN_B_RESOURCE_TYPES, S as ResourceUpdateNotSupportedError, U as withStackName, V as generateResourceNameWithFallback, _ as MissingCdkCliError, a as assertRegionMatch, b as ProvisioningError, f as LocalInvokeBuildError$1, i as resolveExplicitPhysicalId, k as normalizeAwsError, l as CdkdError, m as LocalStartServiceError, n as matchesCdkPath, o as disableInstanceApiTermination, p as LocalMigrateError, r as normalizeAwsTagsToCfn, s as isTerminationProtectionPropagationError, t as CDK_PATH_TAG, v as NestedStackChildDirectDestroyError, w as StackTerminationProtectionError, x as ResourceTimeoutError, y as PartialFailureError } from "./import-helpers-DayvBD4T.js";
|
|
3
3
|
import { a as setAwsClients, i as resetAwsClients, r as getAwsClients, t as AwsClients } from "./aws-clients-pjPwZz1r.js";
|
|
4
|
-
import { $ as
|
|
4
|
+
import { $ as CFN_TEMPLATE_BODY_LIMIT, A as LockManager, B as runDockerForeground, C as findActionableSilentDrops, D as DiffCalculator, E as applyRoleArnIfSet, F as stringifyValue, G as getDefaultStateBucketName, H as AssetManifestLoader, I as WorkGraph, J as resolveCaptureObservedState, K as getLegacyStateBucketName, L as buildDockerImage, M as rebuildClientForBucketRegion, N as shouldRetainResource, O as DagBuilder, P as AssetPublisher, Q as warnDeprecatedNoPrefixCliFlag, R as formatDockerLoginError, S as ProviderRegistry, T as IntrinsicFunctionResolver, U as getDockerImageBySourceHash, V as runDockerStreaming, W as Synthesizer, X as resolveStateBucketWithDefault, Y as resolveSkipPrefix, Z as resolveStateBucketWithDefaultAndSource, _ as green, a as withRetry, b as IAMRoleProvider, c as computeImplicitDeleteEdges, d as isStatefulRecreateTargetSync, et as CFN_TEMPLATE_URL_LIMIT, f as renderStatefulReason, g as gray, h as cyan, i as withResourceDeadline, it as AssemblyReader, j as S3StateBackend, k as TemplateParser, l as extractDeploymentEventError, m as bold, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nt as findLargeInlineResources, o as isRetryableTransientError, ot as resolveBucketRegion, p as formatResourceLine, q as resolveApp, r as DeployEngine, rt as uploadCfnTemplate, s as IMPLICIT_DELETE_DEPENDENCIES, t as DEFAULT_RESOURCE_TIMEOUT_MS, tt as MIGRATE_TMP_PREFIX, u as MULTI_REGION_RECREATE_BLOCKED_TYPES, v as red, w as CloudControlProvider, x as collectInlinePolicyNamesManagedBySiblings, y as yellow, z as getDockerCmd } from "./deploy-engine-_N5kVjZN.js";
|
|
5
5
|
import { t as ASGProvider } from "./asg-provider-Dgj3loIG.js";
|
|
6
6
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
7
7
|
import { randomBytes, randomUUID } from "node:crypto";
|
|
@@ -491,6 +491,7 @@ const recreateViaSdkProviderOption = new Option("--recreate-via-sdk-provider <lo
|
|
|
491
491
|
* into a footgun; pretending to scope it per-resource is misleading).
|
|
492
492
|
*/
|
|
493
493
|
const forceStatefulRecreationOption = new Option("--force-stateful-recreation", "Bypass the stateful-resource guard for --recreate-via-cc-api targets. Required when ANY named target is a stateful type (RDS / DynamoDB / EFS / S3 with data / Logs with retention / Cognito / Secrets / SSM / Glue / ECR / CloudFront / Kinesis / OpenSearch). Destroy + recreate loses ALL data in the resource — no automatic data migration. Triple-opt-in for CI use: --recreate-via-cc-api <id> --force-stateful-recreation --yes.").default(false);
|
|
494
|
+
const replaceOption = new Option("--replace", "Replace (DELETE + CREATE) a resource whose in-place update is rejected because an immutable property changed and AWS exposes no update API for it (e.g. Lambda LayerVersion content, EFS AccessPoint, ECS TaskDefinition, ApiGatewayV2 immutable fields). Without this flag such a change fails the deploy. Stateful types (RDS / DynamoDB / EFS / S3 with data / Logs with retention / etc.) ALSO require --force-stateful-recreation since the replacement is a data-losing DELETE + CREATE.").default(false);
|
|
494
495
|
const deployOptions = [
|
|
495
496
|
new Option("--concurrency <number>", "Maximum concurrent resource operations").default(10).argParser((value) => parseInt(value, 10)),
|
|
496
497
|
new Option("--stack-concurrency <number>", "Maximum concurrent stack deployments").default(4).argParser((value) => parseInt(value, 10)),
|
|
@@ -509,6 +510,7 @@ const deployOptions = [
|
|
|
509
510
|
recreateViaCcApiOption,
|
|
510
511
|
recreateViaSdkProviderOption,
|
|
511
512
|
forceStatefulRecreationOption,
|
|
513
|
+
replaceOption,
|
|
512
514
|
...resourceTimeoutOptions
|
|
513
515
|
];
|
|
514
516
|
/**
|
|
@@ -983,119 +985,6 @@ function createListCommand() {
|
|
|
983
985
|
return cmd;
|
|
984
986
|
}
|
|
985
987
|
|
|
986
|
-
//#endregion
|
|
987
|
-
//#region src/provisioning/stateful-types.ts
|
|
988
|
-
/**
|
|
989
|
-
* Stateful-resource guard list (issue [#615]).
|
|
990
|
-
*
|
|
991
|
-
* `--recreate-via-cc-api <LogicalId>` destroys + recreates the named
|
|
992
|
-
* resource in one deploy so a previously-silent-dropped top-level CFn
|
|
993
|
-
* property reaches AWS via Cloud Control API. For most types this is
|
|
994
|
-
* safe — destroying + recreating an IAM Role or a Lambda Function
|
|
995
|
-
* loses no user data — but for **data-bearing** types the destroy
|
|
996
|
-
* cycle loses everything in the resource: rows in a DynamoDB table,
|
|
997
|
-
* objects in an S3 bucket, log lines in a LogGroup, images in an ECR
|
|
998
|
-
* repository, etc.
|
|
999
|
-
*
|
|
1000
|
-
* To avoid an accidental data-loss footgun, cdkd refuses to recreate
|
|
1001
|
-
* any resource whose type is in {@link STATEFUL_TYPES} unless the user
|
|
1002
|
-
* ALSO passes `--force-stateful-recreation`. The two-flag protection
|
|
1003
|
-
* mirrors `--remove-protection`'s pattern (see
|
|
1004
|
-
* `src/cli/commands/destroy-runner.ts`).
|
|
1005
|
-
*
|
|
1006
|
-
* The list is hand-curated and intentionally **conservative**: every
|
|
1007
|
-
* type here carries user data that the AWS service does NOT
|
|
1008
|
-
* automatically migrate to the replacement resource. Types that the
|
|
1009
|
-
* AWS service treats as ephemeral (e.g. Lambda Function, IAM Role)
|
|
1010
|
-
* are NOT in this list — recreate is cheap.
|
|
1011
|
-
*
|
|
1012
|
-
* Two entries are **conditionally stateful** — they only count when
|
|
1013
|
-
* the resource actually contains data:
|
|
1014
|
-
*
|
|
1015
|
-
* - `AWS::S3::Bucket`: empty buckets are safe to recreate. The
|
|
1016
|
-
* deploy engine probes `s3:ListObjectsV2` at plan time and only
|
|
1017
|
-
* refuses when the bucket has at least one object.
|
|
1018
|
-
* - `AWS::Logs::LogGroup`: a log group with `RetentionInDays`
|
|
1019
|
-
* undefined or zero is functionally ephemeral. The deploy engine
|
|
1020
|
-
* refuses only when `RetentionInDays > 0`.
|
|
1021
|
-
*
|
|
1022
|
-
* Both conditional checks live in {@link isStatefulRecreateTarget};
|
|
1023
|
-
* the bare {@link STATEFUL_TYPES} set is the type-only first-cut.
|
|
1024
|
-
*/
|
|
1025
|
-
const STATEFUL_TYPES = new Set([
|
|
1026
|
-
"AWS::RDS::DBInstance",
|
|
1027
|
-
"AWS::RDS::DBCluster",
|
|
1028
|
-
"AWS::DocDB::DBInstance",
|
|
1029
|
-
"AWS::DocDB::DBCluster",
|
|
1030
|
-
"AWS::Neptune::DBInstance",
|
|
1031
|
-
"AWS::Neptune::DBCluster",
|
|
1032
|
-
"AWS::DynamoDB::Table",
|
|
1033
|
-
"AWS::DynamoDB::GlobalTable",
|
|
1034
|
-
"AWS::EFS::FileSystem",
|
|
1035
|
-
"AWS::S3::Bucket",
|
|
1036
|
-
"AWS::ECR::Repository",
|
|
1037
|
-
"AWS::Kinesis::Stream",
|
|
1038
|
-
"AWS::Elasticsearch::Domain",
|
|
1039
|
-
"AWS::OpenSearchService::Domain",
|
|
1040
|
-
"AWS::Cognito::UserPool",
|
|
1041
|
-
"AWS::SecretsManager::Secret",
|
|
1042
|
-
"AWS::SSM::Parameter",
|
|
1043
|
-
"AWS::Glue::Database",
|
|
1044
|
-
"AWS::Glue::Table",
|
|
1045
|
-
"AWS::Logs::LogGroup",
|
|
1046
|
-
"AWS::CloudFront::Distribution"
|
|
1047
|
-
]);
|
|
1048
|
-
/**
|
|
1049
|
-
* Multi-region resource types — `--recreate-via-cc-api` refuses these
|
|
1050
|
-
* outright in v1 regardless of `--force-stateful-recreation`. Design
|
|
1051
|
-
* doc §8 calls these "out of scope": the destroy + recreate cycle
|
|
1052
|
-
* across replica regions is more involved than a single-region
|
|
1053
|
-
* destroy-and-create (replica regions, automated backups, eventual
|
|
1054
|
-
* consistency across the replication mesh, etc.).
|
|
1055
|
-
*
|
|
1056
|
-
* Distinct from {@link STATEFUL_TYPES} — STATEFUL_TYPES gates on data
|
|
1057
|
-
* loss (bypassable with `--force-stateful-recreation`); this set is
|
|
1058
|
-
* an out-of-scope refusal (no bypass).
|
|
1059
|
-
*/
|
|
1060
|
-
const MULTI_REGION_RECREATE_BLOCKED_TYPES = new Set(["AWS::DynamoDB::GlobalTable"]);
|
|
1061
|
-
/**
|
|
1062
|
-
* Cheap, synchronous read of the resource's recorded properties only.
|
|
1063
|
-
* For `AWS::S3::Bucket` this returns `null` — the live `ListObjectsV2`
|
|
1064
|
-
* probe to distinguish empty buckets (safe to recreate) from
|
|
1065
|
-
* non-empty (data loss) lives in
|
|
1066
|
-
* `src/deployment/recreate-targets.ts#probeStatefulRecreateTargetsAsync`
|
|
1067
|
-
* (issue [#648]) and runs after this sync first-cut. Sync callers can
|
|
1068
|
-
* still treat `null` as "not stateful" — the deploy command does both
|
|
1069
|
-
* passes back-to-back; only callers that explicitly opt out of the
|
|
1070
|
-
* async probe need to assume conservative "stateful" semantics.
|
|
1071
|
-
*
|
|
1072
|
-
* Returns the {@link StatefulReason} when the type is stateful (or
|
|
1073
|
-
* `null` for non-stateful types).
|
|
1074
|
-
*/
|
|
1075
|
-
function isStatefulRecreateTargetSync(resourceType, recordedProperties) {
|
|
1076
|
-
if (!STATEFUL_TYPES.has(resourceType)) return null;
|
|
1077
|
-
if (resourceType === "AWS::Logs::LogGroup") {
|
|
1078
|
-
const retention = recordedProperties?.["RetentionInDays"];
|
|
1079
|
-
if (typeof retention === "number" && retention > 0) return "has-retention";
|
|
1080
|
-
return null;
|
|
1081
|
-
}
|
|
1082
|
-
if (resourceType === "AWS::S3::Bucket") return null;
|
|
1083
|
-
return "always";
|
|
1084
|
-
}
|
|
1085
|
-
/**
|
|
1086
|
-
* Human-readable rendering of {@link StatefulReason} for error
|
|
1087
|
-
* messages. Used by the pre-flight guard's "X resources require
|
|
1088
|
-
* --force-stateful-recreation" listing.
|
|
1089
|
-
*/
|
|
1090
|
-
function renderStatefulReason(reason) {
|
|
1091
|
-
switch (reason) {
|
|
1092
|
-
case "always": return "destroy loses all data in the resource";
|
|
1093
|
-
case "has-objects": return "S3 bucket is non-empty";
|
|
1094
|
-
case "has-retention": return "log group retains data (RetentionInDays > 0)";
|
|
1095
|
-
case null: return "(not stateful)";
|
|
1096
|
-
}
|
|
1097
|
-
}
|
|
1098
|
-
|
|
1099
988
|
//#endregion
|
|
1100
989
|
//#region src/deployment/recreate-targets.ts
|
|
1101
990
|
/**
|
|
@@ -1556,7 +1445,7 @@ const FLUSH_INTERVAL_MS = 2e3;
|
|
|
1556
1445
|
const FLUSH_EVENT_THRESHOLD = 50;
|
|
1557
1446
|
/** Build-time cdkd version, with a dev fallback for non-built contexts. */
|
|
1558
1447
|
function getCdkdVersion() {
|
|
1559
|
-
return "0.
|
|
1448
|
+
return "0.230.0";
|
|
1560
1449
|
}
|
|
1561
1450
|
/**
|
|
1562
1451
|
* Generate a time-sortable unique run id, e.g.
|
|
@@ -9629,12 +9518,15 @@ var LambdaLayerVersionProvider = class {
|
|
|
9629
9518
|
* which is never what `--revert` should do.
|
|
9630
9519
|
* - On the deploy path, content / runtime / arch changes flow
|
|
9631
9520
|
* through CDK's hash-based logical naming, which produces a fresh
|
|
9632
|
-
* logical ID and a CREATE+DELETE in cdkd's diff
|
|
9633
|
-
*
|
|
9634
|
-
*
|
|
9521
|
+
* logical ID and a CREATE+DELETE in cdkd's diff. For a hand-authored
|
|
9522
|
+
* template that edits the SAME logical id in place, the replacement
|
|
9523
|
+
* rule for `AWS::Lambda::LayerVersion` (every property is
|
|
9524
|
+
* "Update requires: Replacement") drives a DELETE+CREATE before
|
|
9525
|
+
* `update()` is ever reached, so this method is a defensive fallback
|
|
9526
|
+
* that should not fire in normal use.
|
|
9635
9527
|
*/
|
|
9636
9528
|
async update(logicalId, _physicalId, resourceType, _properties, _previousProperties) {
|
|
9637
|
-
return Promise.reject(new ResourceUpdateNotSupportedError(resourceType, logicalId, "AWS Lambda LayerVersion is immutable on AWS — there is no UpdateLayerVersion API; every change requires PublishLayerVersion (a new version with a new LayerVersionArn).
|
|
9529
|
+
return Promise.reject(new ResourceUpdateNotSupportedError(resourceType, logicalId, "AWS Lambda LayerVersion is immutable on AWS — there is no UpdateLayerVersion API; every change requires PublishLayerVersion (a new version with a new LayerVersionArn). cdkd normally classifies any LayerVersion property change as a replacement (DELETE + CREATE), so reaching this path is unexpected; re-run the deploy or change the resource definition to publish a new version."));
|
|
9638
9530
|
}
|
|
9639
9531
|
/**
|
|
9640
9532
|
* Delete a Lambda layer version
|
|
@@ -29210,7 +29102,7 @@ var GlueSecurityConfigurationProvider = class {
|
|
|
29210
29102
|
/**
|
|
29211
29103
|
* Read AWS-current SecurityConfiguration shape via
|
|
29212
29104
|
* `GetSecurityConfiguration`. Always emits the three CFn-modeled
|
|
29213
|
-
* sub-configs (`
|
|
29105
|
+
* sub-configs (`S3Encryptions: []`, `CloudWatchEncryption: {}`,
|
|
29214
29106
|
* `JobBookmarksEncryption: {}`) per PR #145 even when AWS reports
|
|
29215
29107
|
* nothing — closes the "console-side encryption enable on a previously
|
|
29216
29108
|
* default config" detection gap on the v3 baseline.
|
|
@@ -29273,13 +29165,14 @@ function sleep$1(ms) {
|
|
|
29273
29165
|
/**
|
|
29274
29166
|
* Build the SDK `EncryptionConfiguration` from the CFn-shape input
|
|
29275
29167
|
* (`AWS::Glue::SecurityConfiguration.EncryptionConfiguration`). Each
|
|
29276
|
-
* sub-config (`
|
|
29277
|
-
* `JobBookmarksEncryption`)
|
|
29278
|
-
*
|
|
29168
|
+
* sub-config (`S3Encryptions[]` / `CloudWatchEncryption` /
|
|
29169
|
+
* `JobBookmarksEncryption`) maps to the SDK member names — `CloudWatchEncryption`
|
|
29170
|
+
* / `JobBookmarksEncryption` match verbatim, but the CFn `S3Encryptions` (plural)
|
|
29171
|
+
* list maps to the SDK `S3Encryption` (singular) field.
|
|
29279
29172
|
*/
|
|
29280
29173
|
function buildEncryptionConfiguration(input) {
|
|
29281
29174
|
const result = {};
|
|
29282
|
-
if (Array.isArray(input["
|
|
29175
|
+
if (Array.isArray(input["S3Encryptions"])) result.S3Encryption = input["S3Encryptions"].map((entry) => {
|
|
29283
29176
|
const e = entry;
|
|
29284
29177
|
const item = {};
|
|
29285
29178
|
if (typeof e["S3EncryptionMode"] === "string") item.S3EncryptionMode = e["S3EncryptionMode"];
|
|
@@ -29305,7 +29198,7 @@ function buildEncryptionConfiguration(input) {
|
|
|
29305
29198
|
/**
|
|
29306
29199
|
* Reverse-map AWS's `EncryptionConfiguration` SDK shape into the CFn
|
|
29307
29200
|
* shape with always-emit placeholders (PR #145):
|
|
29308
|
-
* - `
|
|
29201
|
+
* - `S3Encryptions[]` → `?? []` (so console-side ADD is detectable)
|
|
29309
29202
|
* - `CloudWatchEncryption` → `?? {}`
|
|
29310
29203
|
* - `JobBookmarksEncryption` → `?? {}`
|
|
29311
29204
|
* - `DataQualityEncryption` → silently dropped (not in CFn schema)
|
|
@@ -29313,7 +29206,7 @@ function buildEncryptionConfiguration(input) {
|
|
|
29313
29206
|
function mapEncryptionConfigurationToCfn(cfg) {
|
|
29314
29207
|
const c = cfg ?? {};
|
|
29315
29208
|
return {
|
|
29316
|
-
|
|
29209
|
+
S3Encryptions: (c.S3Encryption ?? []).map((entry) => {
|
|
29317
29210
|
const out = {};
|
|
29318
29211
|
if (entry.S3EncryptionMode !== void 0) out["S3EncryptionMode"] = entry.S3EncryptionMode;
|
|
29319
29212
|
if (entry.KmsKeyArn !== void 0) out["KmsKeyArn"] = entry.KmsKeyArn;
|
|
@@ -37069,6 +36962,8 @@ async function deployCommand(stacks, options) {
|
|
|
37069
36962
|
...eventRecorder && { eventRecorder },
|
|
37070
36963
|
...recreateViaCcApiTargets && recreateViaCcApiTargets.size > 0 && { recreateViaCcApiTargets },
|
|
37071
36964
|
...recreateViaSdkProviderTargets && recreateViaSdkProviderTargets.size > 0 && { recreateViaSdkProviderTargets },
|
|
36965
|
+
...options.replace && { replace: true },
|
|
36966
|
+
...options.forceStatefulRecreation && { forceStatefulRecreation: true },
|
|
37072
36967
|
captureObservedState: resolveCaptureObservedState(options.captureObservedState),
|
|
37073
36968
|
...options.resourceWarnAfter?.globalMs !== void 0 && { resourceWarnAfterMs: options.resourceWarnAfter.globalMs },
|
|
37074
36969
|
...options.resourceTimeout?.globalMs !== void 0 && { resourceTimeoutMs: options.resourceTimeout.globalMs },
|
|
@@ -55067,7 +54962,7 @@ function reorderArgs(argv) {
|
|
|
55067
54962
|
async function main() {
|
|
55068
54963
|
installPipeCloseHandler();
|
|
55069
54964
|
const program = new Command();
|
|
55070
|
-
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.
|
|
54965
|
+
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.230.0");
|
|
55071
54966
|
program.addCommand(createBootstrapCommand());
|
|
55072
54967
|
program.addCommand(createSynthCommand());
|
|
55073
54968
|
program.addCommand(createListCommand());
|