@go-to-k/cdkd 0.280.46 → 0.281.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/README.md +57 -1
- package/dist/{asg-provider-DGHuyUA8.js → asg-provider-BSx4Vrth.js} +2 -2
- package/dist/{asg-provider-DGHuyUA8.js.map → asg-provider-BSx4Vrth.js.map} +1 -1
- package/dist/cli.js +280 -86
- package/dist/cli.js.map +1 -1
- package/dist/{deploy-engine-E_JV4UqE.js → deploy-engine-Bebl98bx.js} +159 -7
- package/dist/deploy-engine-Bebl98bx.js.map +1 -0
- package/dist/index.d.ts +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-E_JV4UqE.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { $ as requireConfigArray, $t as expectedOwnerParam, A as green, An as withErrorHandling, At as getDockerCmd, B as slowCcOperationTimeoutMs, Bt as resolveAutoAssetStorage, C as MULTI_REGION_RECREATE_BLOCKED_TYPES, Cn as StackHasActiveImportsError, Ct as ensureAssetStorage, D as bold, Dt as validateContainerRepoName, E as formatResourceLine, Et as validateAssetBucketName, F as clearOnUpdateRemoval, Ft as Synthesizer, G as refStateLookupFromResource, Gt as resolveUseCdkBootstrapAssets, H as isTerminationProtectionPropagationError, Ht as resolveSkipPrefix, I as ProviderRegistry, It as synthesisStatusMessage, J as resolveExplicitPhysicalId, Jt as CFN_TEMPLATE_BODY_LIMIT, K as WAFv2WebACLProvider, Kt as stateBucketExistenceConfirmed, L as findActionableSilentDrops, Lt as getDefaultStateBucketName, M as yellow, Mt as runDockerStreaming, N as IAMRoleProvider, Nt as AssetManifestLoader, O as cyan, Ot as buildDockerImage, P as collectInlinePolicyNamesManagedBySiblings, Pt as getDockerImageBySourceHash, Q as replayWarn, Qt as uploadCfnTemplate, R as findSilentDropProperties, Rt as getLegacyStateBucketName, S as extractDeploymentEventError, Sn as ResourceUpdateNotSupportedError, St as BOOTSTRAP_MARKER_PREFIX, T as renderStatefulReason, Tt as parseBootstrapMarker, U as IntrinsicFunctionResolver, Ut as resolveStateBucketWithDefault, V as disableInstanceApiTermination, Vt as resolveCaptureObservedState, W as cfnRefValueFromPhysicalId, Wt as resolveStateBucketWithDefaultAndSource, X as configStringRefusal, Xt as MIGRATE_TMP_PREFIX, Y as assertRegionMatch, Yt as CFN_TEMPLATE_URL_LIMIT, Z as readConfigString, Zt as findLargeInlineResources, _ as createPreDeleteFinalSnapshot, _n as MissingCdkCliError, _t as buildAssetRedirectMap, a as DeploymentEventsStore, an as getAwsClients, at as withRetry, b as unsupportedFinalSnapshotError, bn as ProvisioningError, bt as rewriteTemplateAssetReferences, c as replayFailedOperations, ct as DagBuilder, d as IMPLICIT_DELETE_DEPENDENCIES, dt as S3StateBackend, en as AssemblyReader, et as requireConfigObject, f as computeImplicitDeleteEdges, fn as DeployCancelledError, ft as rebuildClientForBucketRegion, g as ccRoutedFinalSnapshotError, gt as WorkGraph, h as buildFinalSnapshotIdentifier, hn as LocalStartServiceError, ht as stringifyValue, i as DeploymentEventsReader, in as AwsClients, it as describeTypeWithThrottleRetry, j as red, jt as runDockerForeground, k as gray, kn as normalizeAwsError, kt as formatDockerLoginError, l as replayRollback, ln as CdkdError, lt as TemplateParser, m as PRE_DELETE_SNAPSHOT_TYPES, mn as LocalMigrateError, mt as AssetPublisher, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nt as applyRoleArnIfSet, o as planFailedOps, on as resetAwsClients, ot as isRetryableTransientError, p as ATOMIC_FINAL_SNAPSHOT_TYPES, pn as LocalInvokeBuildError$1, pt as shouldRetainResource, q as normalizeAwsTagsToCfn, qt as warnDeprecatedNoPrefixCliFlag, r as DeployEngine, rn as resolveBucketRegion, rt as DiffCalculator, s as planRollback, sn as setAwsClients, st as isThrottlingError, t as DEFAULT_RESOURCE_TIMEOUT_MS, tn as processStackMessages, tt as requireConfigString, u as withResourceDeadline, ut as LockManager, v as isFinalSnapshotError, vn as NestedStackChildDirectDestroyError, vt as createAssetRedirectResolver, w as isStatefulRecreateTargetSync, wn as StackTerminationProtectionError, wt as getBootstrapMarkerKey, x as makeCanonicalizePropertiesFn, xn as ResourceTimeoutError, xt as AssetModeResolver, y as refusesFinalSnapshot, yn as PartialFailureError, yt as loadPublishableAssetManifest, z as CloudControlProvider, zt as resolveApp } from "./deploy-engine-
|
|
2
|
+
import { $ as requireConfigArray, $t as expectedOwnerParam, A as green, An as withErrorHandling, At as getDockerCmd, B as slowCcOperationTimeoutMs, Bt as resolveAutoAssetStorage, C as MULTI_REGION_RECREATE_BLOCKED_TYPES, Cn as StackHasActiveImportsError, Ct as ensureAssetStorage, D as bold, Dt as validateContainerRepoName, E as formatResourceLine, Et as validateAssetBucketName, F as clearOnUpdateRemoval, Ft as Synthesizer, G as refStateLookupFromResource, Gt as resolveUseCdkBootstrapAssets, H as isTerminationProtectionPropagationError, Ht as resolveSkipPrefix, I as ProviderRegistry, It as synthesisStatusMessage, J as resolveExplicitPhysicalId, Jt as CFN_TEMPLATE_BODY_LIMIT, K as WAFv2WebACLProvider, Kt as stateBucketExistenceConfirmed, L as findActionableSilentDrops, Lt as getDefaultStateBucketName, M as yellow, Mt as runDockerStreaming, N as IAMRoleProvider, Nt as AssetManifestLoader, O as cyan, Ot as buildDockerImage, P as collectInlinePolicyNamesManagedBySiblings, Pt as getDockerImageBySourceHash, Q as replayWarn, Qt as uploadCfnTemplate, R as findSilentDropProperties, Rt as getLegacyStateBucketName, S as extractDeploymentEventError, Sn as ResourceUpdateNotSupportedError, St as BOOTSTRAP_MARKER_PREFIX, T as renderStatefulReason, Tt as parseBootstrapMarker, U as IntrinsicFunctionResolver, Ut as resolveStateBucketWithDefault, V as disableInstanceApiTermination, Vt as resolveCaptureObservedState, W as cfnRefValueFromPhysicalId, Wt as resolveStateBucketWithDefaultAndSource, X as configStringRefusal, Xt as MIGRATE_TMP_PREFIX, Y as assertRegionMatch, Yt as CFN_TEMPLATE_URL_LIMIT, Z as readConfigString, Zt as findLargeInlineResources, _ as createPreDeleteFinalSnapshot, _n as MissingCdkCliError, _t as buildAssetRedirectMap, a as DeploymentEventsStore, an as getAwsClients, at as withRetry, b as unsupportedFinalSnapshotError, bn as ProvisioningError, bt as rewriteTemplateAssetReferences, c as replayFailedOperations, ct as DagBuilder, d as IMPLICIT_DELETE_DEPENDENCIES, dt as S3StateBackend, en as AssemblyReader, et as requireConfigObject, f as computeImplicitDeleteEdges, fn as DeployCancelledError, ft as rebuildClientForBucketRegion, g as ccRoutedFinalSnapshotError, gt as WorkGraph, h as buildFinalSnapshotIdentifier, hn as LocalStartServiceError, ht as stringifyValue, i as DeploymentEventsReader, in as AwsClients, it as describeTypeWithThrottleRetry, j as red, jt as runDockerForeground, k as gray, kn as normalizeAwsError, kt as formatDockerLoginError, l as replayRollback, ln as CdkdError, lt as TemplateParser, m as PRE_DELETE_SNAPSHOT_TYPES, mn as LocalMigrateError, mt as AssetPublisher, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nt as applyRoleArnIfSet, o as planFailedOps, on as resetAwsClients, ot as isRetryableTransientError, p as ATOMIC_FINAL_SNAPSHOT_TYPES, pn as LocalInvokeBuildError$1, pt as shouldRetainResource, q as normalizeAwsTagsToCfn, qt as warnDeprecatedNoPrefixCliFlag, r as DeployEngine, rn as resolveBucketRegion, rt as DiffCalculator, s as planRollback, sn as setAwsClients, st as isThrottlingError, t as DEFAULT_RESOURCE_TIMEOUT_MS, tn as processStackMessages, tt as requireConfigString, u as withResourceDeadline, ut as LockManager, v as isFinalSnapshotError, vn as NestedStackChildDirectDestroyError, vt as createAssetRedirectResolver, w as isStatefulRecreateTargetSync, wn as StackTerminationProtectionError, wt as getBootstrapMarkerKey, x as makeCanonicalizePropertiesFn, xn as ResourceTimeoutError, xt as AssetModeResolver, y as refusesFinalSnapshot, yn as PartialFailureError, yt as loadPublishableAssetManifest, z as CloudControlProvider, zt as resolveApp } from "./deploy-engine-Bebl98bx.js";
|
|
3
3
|
import { a as getLiveRenderer, c as PATTERN_B_RESOURCE_TYPES, d as generateResourceNameWithFallback, h as withStackName, i as runStackBuffered, m as withSkipPrefix, n as getLogger, o as PATTERN_B_NAME_OPTIONS, s as PATTERN_B_NAME_PROPERTIES, u as generateResourceName } from "./logger-zRrlbaQt.js";
|
|
4
|
-
import { t as ASGProvider } from "./asg-provider-
|
|
4
|
+
import { t as ASGProvider } from "./asg-provider-BSx4Vrth.js";
|
|
5
5
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
6
6
|
import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
7
7
|
import { CopyObjectCommand, CreateBucketCommand, DeleteBucketAnalyticsConfigurationCommand, DeleteBucketCommand, DeleteBucketCorsCommand, DeleteBucketEncryptionCommand, DeleteBucketIntelligentTieringConfigurationCommand, DeleteBucketInventoryConfigurationCommand, DeleteBucketLifecycleCommand, DeleteBucketMetricsConfigurationCommand, DeleteBucketOwnershipControlsCommand, DeleteBucketPolicyCommand, DeleteBucketReplicationCommand, DeleteBucketTaggingCommand, DeleteBucketWebsiteCommand, DeleteObjectsCommand, GetBucketAccelerateConfigurationCommand, GetBucketCorsCommand, GetBucketEncryptionCommand, GetBucketLifecycleConfigurationCommand, GetBucketLocationCommand, GetBucketLoggingCommand, GetBucketNotificationConfigurationCommand, GetBucketOwnershipControlsCommand, GetBucketPolicyCommand, GetBucketReplicationCommand, GetBucketTaggingCommand, GetBucketVersioningCommand, GetBucketWebsiteCommand, GetObjectCommand, GetObjectLockConfigurationCommand, GetPublicAccessBlockCommand, HeadBucketCommand, ListBucketAnalyticsConfigurationsCommand, ListBucketIntelligentTieringConfigurationsCommand, ListBucketInventoryConfigurationsCommand, ListBucketMetricsConfigurationsCommand, ListObjectVersionsCommand, ListObjectsV2Command, NoSuchBucket, PutBucketAccelerateConfigurationCommand, PutBucketAnalyticsConfigurationCommand, PutBucketCorsCommand, PutBucketEncryptionCommand, PutBucketIntelligentTieringConfigurationCommand, PutBucketInventoryConfigurationCommand, PutBucketLifecycleConfigurationCommand, PutBucketLoggingCommand, PutBucketMetricsConfigurationCommand, PutBucketNotificationConfigurationCommand, PutBucketOwnershipControlsCommand, PutBucketPolicyCommand, PutBucketReplicationCommand, PutBucketTaggingCommand, PutBucketVersioningCommand, PutBucketWebsiteCommand, PutObjectCommand, PutObjectLockConfigurationCommand, PutPublicAccessBlockCommand, S3Client, S3ServiceException } from "@aws-sdk/client-s3";
|
|
@@ -591,6 +591,22 @@ const useCdkBootstrapAssetsOption = new Option("--use-cdk-bootstrap-assets", "Pu
|
|
|
591
591
|
*/
|
|
592
592
|
const strictGetattOption = new Option("--strict-getatt", "Fail the deploy on ANY Fn::GetAtt that falls back to the physical ID because cdkd cannot construct the attribute (default: warn and use the physical ID, hard-failing only when the fallback is knowably wrong — an *Arn attribute with a non-ARN value or a *Url attribute with a non-http(s) value). Also fails the deploy when a stack Output cannot be resolved (default: warn and store no value).").default(false);
|
|
593
593
|
/**
|
|
594
|
+
* Issue #1697 — `--no-cfn-fallback` (deploy + diff). By default, a
|
|
595
|
+
* cross-stack reference (`Fn::ImportValue` / `Fn::GetStackOutput`) that is
|
|
596
|
+
* not found in cdkd state falls back to CloudFormation (`ListExports` /
|
|
597
|
+
* `DescribeStacks` outputs) so a cdkd-deployed consumer can reference a
|
|
598
|
+
* producer stack still managed by CloudFormation (`cdk deploy` / raw CFn).
|
|
599
|
+
* The fallback fires only after a cdkd-state miss (cdkd-first precedence),
|
|
600
|
+
* resolves as a WEAK reference (not recorded into `state.imports` /
|
|
601
|
+
* `state.outputReads`; no destroy-time protection on either side), and
|
|
602
|
+
* degrades gracefully when the caller lacks the CloudFormation read
|
|
603
|
+
* permissions (warning + the original not-found error). This flag disables
|
|
604
|
+
* the fallback entirely for users who want cdkd-state-only resolution —
|
|
605
|
+
* e.g. to keep IAM minimal or to keep an export-name typo failing fast
|
|
606
|
+
* instead of accidentally matching an unrelated CloudFormation export.
|
|
607
|
+
*/
|
|
608
|
+
const noCfnFallbackOption = new Option("--no-cfn-fallback", "Do not fall back to CloudFormation (ListExports / stack outputs) when an Fn::ImportValue / Fn::GetStackOutput reference is not found in cdkd state (default: fall back, so producers still managed by CloudFormation can be referenced)");
|
|
609
|
+
/**
|
|
594
610
|
* CDK annotation-message behavior flags (issue #1230, CDK CLI parity).
|
|
595
611
|
* Shared by `cdkd synth` and `cdkd deploy` — the two commands that fail on
|
|
596
612
|
* `Annotations.addError` (issue #1228). `--strict` additionally fails when
|
|
@@ -622,6 +638,7 @@ const deployOptions = [
|
|
|
622
638
|
replaceOption,
|
|
623
639
|
useCdkBootstrapAssetsOption,
|
|
624
640
|
strictGetattOption,
|
|
641
|
+
noCfnFallbackOption,
|
|
625
642
|
...resourceTimeoutOptions
|
|
626
643
|
];
|
|
627
644
|
/**
|
|
@@ -4875,6 +4892,20 @@ function s3BucketDestinationPath(dest, destinationPath) {
|
|
|
4875
4892
|
return isPlainObject$1(dest) && isFlattenedDestination(dest) ? destinationPath : `${destinationPath}.S3BucketDestination`;
|
|
4876
4893
|
}
|
|
4877
4894
|
/**
|
|
4895
|
+
* The structural path segments — relative to the enclosing `Destination` block —
|
|
4896
|
+
* of the bag `resolveS3BucketDestination` PICKED, so a substituted value can be
|
|
4897
|
+
* written back at the key the template actually declared (issue #1670).
|
|
4898
|
+
*
|
|
4899
|
+
* The value-side twin of {@link s3BucketDestinationPath}, which names the same
|
|
4900
|
+
* branch for MESSAGES. Derived from the picked bag's IDENTITY rather than by
|
|
4901
|
+
* re-running {@link isFlattenedDestination}: a third copy of that branch
|
|
4902
|
+
* condition is exactly what the predicate's own header warns about, and identity
|
|
4903
|
+
* cannot drift from the resolver at all.
|
|
4904
|
+
*/
|
|
4905
|
+
function s3BucketDestinationSegments(declared, picked) {
|
|
4906
|
+
return picked === declared ? [] : ["S3BucketDestination"];
|
|
4907
|
+
}
|
|
4908
|
+
/**
|
|
4878
4909
|
* Name a malformed value in a refusal message, the way `config-shape.ts`'s
|
|
4879
4910
|
* private `describe` does for the string-reading guards. Kept local rather than
|
|
4880
4911
|
* exported from there because `resolveS3BucketDestination` is S3-specific
|
|
@@ -5129,6 +5160,35 @@ var S3BucketProvider = class S3BucketProvider {
|
|
|
5129
5160
|
return true;
|
|
5130
5161
|
}
|
|
5131
5162
|
/**
|
|
5163
|
+
* A string read whose replay downgrade is a warn-and-SUBSTITUTE, reporting
|
|
5164
|
+
* the substitution so the caller can record what was SENT (issue #1670).
|
|
5165
|
+
*
|
|
5166
|
+
* The third shape beside {@link skipOnUnusableConfigString}'s SKIP and the
|
|
5167
|
+
* plain strict read, for the sites where the fallback IS the right value to
|
|
5168
|
+
* send. The deploy then succeeds with the default on the wire, so recording
|
|
5169
|
+
* the declared value describes a configuration AWS does not hold, and
|
|
5170
|
+
* `readCurrentState` reads all of these back — the permanent phantom drift
|
|
5171
|
+
* `.claude/rules/providers.md` records for the #1633 warn-and-default arm.
|
|
5172
|
+
* That file also carries the full rationale, including why these sites take
|
|
5173
|
+
* NO `canonicalizeDesiredProperties` twin; do not re-derive it here.
|
|
5174
|
+
*
|
|
5175
|
+
* Three details are load-bearing:
|
|
5176
|
+
*
|
|
5177
|
+
* - `onSubstituted` receives the value this call RETURNS, not the `fallback`
|
|
5178
|
+
* argument, so "what is recorded" and "what is sent" stay one expression.
|
|
5179
|
+
* - `options` is forwarded to BOTH the probe and the read, so a site that
|
|
5180
|
+
* ever needs `coerceNumber` cannot make the two disagree.
|
|
5181
|
+
* - Without `options.onUnusable` there is no probe: the read still THROWS,
|
|
5182
|
+
* and recording a value the provider merely failed to send is what the
|
|
5183
|
+
* "already ANNOUNCED" condition on `effectiveProperties` forbids.
|
|
5184
|
+
*/
|
|
5185
|
+
readSubstitutedConfigString(container, key, fallback, containerPath, options, onSubstituted) {
|
|
5186
|
+
const refused = options.onUnusable !== void 0 && configStringRefusal(container, key, fallback, containerPath, options) !== void 0;
|
|
5187
|
+
const value = readConfigString(container, key, fallback, containerPath, options);
|
|
5188
|
+
if (refused) onSubstituted(value);
|
|
5189
|
+
return value;
|
|
5190
|
+
}
|
|
5191
|
+
/**
|
|
5132
5192
|
* Apply lifecycle configuration
|
|
5133
5193
|
*
|
|
5134
5194
|
* CFn property: LifecycleConfiguration.Rules[]
|
|
@@ -5457,8 +5517,11 @@ var S3BucketProvider = class S3BucketProvider {
|
|
|
5457
5517
|
* CFn property: MetricsConfigurations[] (array of configurations)
|
|
5458
5518
|
* SDK: PutBucketMetricsConfiguration (one per configuration, keyed by Id)
|
|
5459
5519
|
*
|
|
5460
|
-
* @returns
|
|
5461
|
-
*
|
|
5520
|
+
* @returns what happened to each item, as {@link PerItemApplyOutcome} — the
|
|
5521
|
+
* per-item unit of `effectiveProperties` (issue #1612). This applier has no
|
|
5522
|
+
* warn-and-SUBSTITUTE read, so its `substituted` map is always empty; the
|
|
5523
|
+
* shape is shared with its three siblings so the two call-site recorders
|
|
5524
|
+
* stay uniform and a future substitution here cannot go unrecorded.
|
|
5462
5525
|
*/
|
|
5463
5526
|
async applyMetricsConfigurations(bucketName, configs, onUnusable) {
|
|
5464
5527
|
const skipped = [];
|
|
@@ -5490,7 +5553,10 @@ var S3BucketProvider = class S3BucketProvider {
|
|
|
5490
5553
|
}));
|
|
5491
5554
|
}
|
|
5492
5555
|
this.logger.debug(`Applied ${configs.length - skipped.length} metrics configuration(s) to bucket ${bucketName}`);
|
|
5493
|
-
return
|
|
5556
|
+
return {
|
|
5557
|
+
skipped,
|
|
5558
|
+
substituted: /* @__PURE__ */ new Map()
|
|
5559
|
+
};
|
|
5494
5560
|
}
|
|
5495
5561
|
/**
|
|
5496
5562
|
* Pick the `S3BucketDestination` bag out of an analytics / inventory
|
|
@@ -5547,15 +5613,24 @@ var S3BucketProvider = class S3BucketProvider {
|
|
|
5547
5613
|
* CFn property: AnalyticsConfigurations[] (array of configurations)
|
|
5548
5614
|
* SDK: PutBucketAnalyticsConfiguration (one per configuration, keyed by Id)
|
|
5549
5615
|
*
|
|
5550
|
-
* @returns
|
|
5551
|
-
*
|
|
5616
|
+
* @returns what happened to each item, as {@link PerItemApplyOutcome} — the
|
|
5617
|
+
* per-item unit of `effectiveProperties` (issues #1612 / #1670). Both arms
|
|
5618
|
+
* are reachable here: a container / destination guard SKIPS the item, while
|
|
5619
|
+
* the `OutputSchemaVersion` and destination `Format` reads warn and SEND a
|
|
5620
|
+
* substituted default, so the item is recorded as SENT rather than as
|
|
5621
|
+
* declared.
|
|
5552
5622
|
*/
|
|
5553
5623
|
async applyAnalyticsConfigurations(bucketName, configs, onUnusable) {
|
|
5554
5624
|
const skipped = [];
|
|
5625
|
+
const substituted = /* @__PURE__ */ new Map();
|
|
5555
5626
|
let index = -1;
|
|
5556
5627
|
for (const config of configs) {
|
|
5557
5628
|
index += 1;
|
|
5558
5629
|
const id = config["Id"];
|
|
5630
|
+
let sentItem;
|
|
5631
|
+
const recordSubstitution = (path, sent) => {
|
|
5632
|
+
sentItem = S3BucketProvider.withDeepValue(sentItem ?? config, path, sent);
|
|
5633
|
+
};
|
|
5559
5634
|
const rawStorageClassAnalysis = config["StorageClassAnalysis"];
|
|
5560
5635
|
if (rawStorageClassAnalysis != null && requireConfigObject(rawStorageClassAnalysis, "AWS::S3::Bucket AnalyticsConfigurations[].StorageClassAnalysis", { ...onUnusable ? { onUnusable } : {} }) === void 0) {
|
|
5561
5636
|
skipped.push(index);
|
|
@@ -5594,12 +5669,23 @@ var S3BucketProvider = class S3BucketProvider {
|
|
|
5594
5669
|
continue;
|
|
5595
5670
|
}
|
|
5596
5671
|
const destPath = s3BucketDestinationPath(rawDest, analyticsDestPath);
|
|
5672
|
+
const destSegments = s3Dest ? s3BucketDestinationSegments(rawDest, s3Dest) : [];
|
|
5597
5673
|
analyticsConfig.StorageClassAnalysis = { DataExport: {
|
|
5598
|
-
OutputSchemaVersion:
|
|
5674
|
+
OutputSchemaVersion: this.readSubstitutedConfigString(dataExport, "OutputSchemaVersion", "V_1", "AWS::S3::Bucket AnalyticsConfigurations[].StorageClassAnalysis.DataExport", { ...onUnusable ? { onUnusable } : {} }, (sent) => recordSubstitution([
|
|
5675
|
+
"StorageClassAnalysis",
|
|
5676
|
+
"DataExport",
|
|
5677
|
+
"OutputSchemaVersion"
|
|
5678
|
+
], sent)),
|
|
5599
5679
|
Destination: s3Dest ? { S3BucketDestination: {
|
|
5600
5680
|
Bucket: s3Dest["BucketArn"] ?? s3Dest["Bucket"],
|
|
5601
5681
|
BucketAccountId: s3Dest["BucketAccountId"],
|
|
5602
|
-
Format:
|
|
5682
|
+
Format: this.readSubstitutedConfigString(s3Dest, "Format", "CSV", destPath, { ...onUnusable ? { onUnusable } : {} }, (sent) => recordSubstitution([
|
|
5683
|
+
"StorageClassAnalysis",
|
|
5684
|
+
"DataExport",
|
|
5685
|
+
"Destination",
|
|
5686
|
+
...destSegments,
|
|
5687
|
+
"Format"
|
|
5688
|
+
], sent)),
|
|
5603
5689
|
Prefix: s3Dest["Prefix"]
|
|
5604
5690
|
} } : void 0
|
|
5605
5691
|
} };
|
|
@@ -5609,9 +5695,13 @@ var S3BucketProvider = class S3BucketProvider {
|
|
|
5609
5695
|
Id: id,
|
|
5610
5696
|
AnalyticsConfiguration: analyticsConfig
|
|
5611
5697
|
}));
|
|
5698
|
+
if (sentItem !== void 0) substituted.set(index, sentItem);
|
|
5612
5699
|
}
|
|
5613
5700
|
this.logger.debug(`Applied ${configs.length - skipped.length} analytics configuration(s) to bucket ${bucketName}`);
|
|
5614
|
-
return
|
|
5701
|
+
return {
|
|
5702
|
+
skipped,
|
|
5703
|
+
substituted
|
|
5704
|
+
};
|
|
5615
5705
|
}
|
|
5616
5706
|
/**
|
|
5617
5707
|
* Apply intelligent tiering configurations
|
|
@@ -5619,8 +5709,11 @@ var S3BucketProvider = class S3BucketProvider {
|
|
|
5619
5709
|
* CFn property: IntelligentTieringConfigurations[]
|
|
5620
5710
|
* SDK: PutBucketIntelligentTieringConfiguration (one per configuration, keyed by Id)
|
|
5621
5711
|
*
|
|
5622
|
-
* @returns
|
|
5623
|
-
*
|
|
5712
|
+
* @returns what happened to each item, as {@link PerItemApplyOutcome} — the
|
|
5713
|
+
* per-item unit of `effectiveProperties` (issue #1612). Its per-item
|
|
5714
|
+
* `Status` read takes the SKIP downgrade rather than a substitution (issue
|
|
5715
|
+
* #1595 — defaulting to `Enabled` would start archiving objects), so the
|
|
5716
|
+
* `substituted` map is always empty here.
|
|
5624
5717
|
*/
|
|
5625
5718
|
async applyIntelligentTieringConfigurations(bucketName, configs, onUnusable) {
|
|
5626
5719
|
const skipped = [];
|
|
@@ -5661,7 +5754,10 @@ var S3BucketProvider = class S3BucketProvider {
|
|
|
5661
5754
|
}));
|
|
5662
5755
|
}
|
|
5663
5756
|
this.logger.debug(`Applied ${configs.length - skipped.length} intelligent tiering configuration(s) to bucket ${bucketName}`);
|
|
5664
|
-
return
|
|
5757
|
+
return {
|
|
5758
|
+
skipped,
|
|
5759
|
+
substituted: /* @__PURE__ */ new Map()
|
|
5760
|
+
};
|
|
5665
5761
|
}
|
|
5666
5762
|
/**
|
|
5667
5763
|
* Apply inventory configurations
|
|
@@ -5669,11 +5765,15 @@ var S3BucketProvider = class S3BucketProvider {
|
|
|
5669
5765
|
* CFn property: InventoryConfigurations[]
|
|
5670
5766
|
* SDK: PutBucketInventoryConfiguration (one per configuration, keyed by Id)
|
|
5671
5767
|
*
|
|
5672
|
-
* @returns
|
|
5673
|
-
*
|
|
5768
|
+
* @returns what happened to each item, as {@link PerItemApplyOutcome} — the
|
|
5769
|
+
* per-item unit of `effectiveProperties` (issues #1612 / #1670). Both arms
|
|
5770
|
+
* are reachable here: `IncludedObjectVersions` / the schedule frequency pair
|
|
5771
|
+
* / the destination guard SKIP the item, while the destination `Format` read
|
|
5772
|
+
* warns and SENDS a substituted default.
|
|
5674
5773
|
*/
|
|
5675
5774
|
async applyInventoryConfigurations(bucketName, configs, onUnusable) {
|
|
5676
5775
|
const skipped = [];
|
|
5776
|
+
const substituted = /* @__PURE__ */ new Map();
|
|
5677
5777
|
let index = -1;
|
|
5678
5778
|
for (const config of configs) {
|
|
5679
5779
|
index += 1;
|
|
@@ -5690,6 +5790,11 @@ var S3BucketProvider = class S3BucketProvider {
|
|
|
5690
5790
|
continue;
|
|
5691
5791
|
}
|
|
5692
5792
|
const destPath = s3BucketDestinationPath(rawDest, inventoryDestPath);
|
|
5793
|
+
const destSegments = s3Dest ? s3BucketDestinationSegments(rawDest, s3Dest) : [];
|
|
5794
|
+
let sentItem;
|
|
5795
|
+
const recordSubstitution = (path, sent) => {
|
|
5796
|
+
sentItem = S3BucketProvider.withDeepValue(sentItem ?? config, path, sent);
|
|
5797
|
+
};
|
|
5693
5798
|
const scheduleFrequencyRefusal = onUnusable ? configStringRefusal(config, "ScheduleFrequency", "Weekly", "AWS::S3::Bucket InventoryConfigurations[]") : void 0;
|
|
5694
5799
|
if (scheduleFrequencyRefusal !== void 0 && config["Schedule"] == null) {
|
|
5695
5800
|
onUnusable?.(`${scheduleFrequencyRefusal}. Skipping this inventory configuration: there is no Schedule.Frequency to fall back to, and defaulting to Weekly would silently re-cadence a live inventory report; the same value is REFUSED on a template-path create`);
|
|
@@ -5703,6 +5808,7 @@ var S3BucketProvider = class S3BucketProvider {
|
|
|
5703
5808
|
continue;
|
|
5704
5809
|
}
|
|
5705
5810
|
const frequency = useScheduleFrequency ? requireConfigString(config["ScheduleFrequency"], "Weekly", "AWS::S3::Bucket InventoryConfigurations[].ScheduleFrequency") : readConfigString(config["Schedule"], "Frequency", "Weekly", "AWS::S3::Bucket InventoryConfigurations[].Schedule");
|
|
5811
|
+
if (scheduleFrequencyRefusal !== void 0) recordSubstitution(["ScheduleFrequency"], frequency);
|
|
5706
5812
|
const inventoryConfig = {
|
|
5707
5813
|
Id: id,
|
|
5708
5814
|
IsEnabled: config["Enabled"] ?? true,
|
|
@@ -5711,7 +5817,11 @@ var S3BucketProvider = class S3BucketProvider {
|
|
|
5711
5817
|
Destination: { S3BucketDestination: s3Dest ? {
|
|
5712
5818
|
Bucket: s3Dest["BucketArn"] ?? s3Dest["Bucket"],
|
|
5713
5819
|
AccountId: s3Dest["BucketAccountId"],
|
|
5714
|
-
Format:
|
|
5820
|
+
Format: this.readSubstitutedConfigString(s3Dest, "Format", "CSV", destPath, { ...onUnusable ? { onUnusable } : {} }, (sent) => recordSubstitution([
|
|
5821
|
+
"Destination",
|
|
5822
|
+
...destSegments,
|
|
5823
|
+
"Format"
|
|
5824
|
+
], sent)),
|
|
5715
5825
|
Prefix: s3Dest["Prefix"]
|
|
5716
5826
|
} : void 0 },
|
|
5717
5827
|
OptionalFields: config["OptionalFields"],
|
|
@@ -5722,9 +5832,13 @@ var S3BucketProvider = class S3BucketProvider {
|
|
|
5722
5832
|
Id: id,
|
|
5723
5833
|
InventoryConfiguration: inventoryConfig
|
|
5724
5834
|
}));
|
|
5835
|
+
if (sentItem !== void 0) substituted.set(index, sentItem);
|
|
5725
5836
|
}
|
|
5726
5837
|
this.logger.debug(`Applied ${configs.length - skipped.length} inventory configuration(s) to bucket ${bucketName}`);
|
|
5727
|
-
return
|
|
5838
|
+
return {
|
|
5839
|
+
skipped,
|
|
5840
|
+
substituted
|
|
5841
|
+
};
|
|
5728
5842
|
}
|
|
5729
5843
|
/**
|
|
5730
5844
|
* Apply replication configuration
|
|
@@ -5958,24 +6072,26 @@ var S3BucketProvider = class S3BucketProvider {
|
|
|
5958
6072
|
return config;
|
|
5959
6073
|
}
|
|
5960
6074
|
/**
|
|
5961
|
-
* Turn a set of
|
|
5962
|
-
*
|
|
6075
|
+
* Turn a set of per-property overrides into the `effectiveProperties` bag the
|
|
6076
|
+
* deploy engine records in place of the desired one (issues #1612 / #1670).
|
|
5963
6077
|
*
|
|
5964
|
-
* A warn-and-
|
|
5965
|
-
*
|
|
5966
|
-
*
|
|
5967
|
-
*
|
|
5968
|
-
*
|
|
5969
|
-
*
|
|
5970
|
-
*
|
|
6078
|
+
* A warn-and-SKIP arm makes the deploy SUCCEED while a declared configuration
|
|
6079
|
+
* never reaches AWS, and a warn-and-SUBSTITUTE read makes it succeed while a
|
|
6080
|
+
* DIFFERENT value than the declared one reaches AWS. Either way, recording
|
|
6081
|
+
* the desired bag verbatim writes something AWS does not hold:
|
|
6082
|
+
* `readCurrentState` can never match it, every later `cdkd drift` re-reports
|
|
6083
|
+
* the difference, and `drift --revert` re-issues the same call — the
|
|
6084
|
+
* permanent phantom drift `.claude/rules/providers.md` records for the EC2
|
|
6085
|
+
* Route warn arm (#1591), reached here through a skip or a substitution
|
|
6086
|
+
* instead of a narrowing.
|
|
5971
6087
|
*
|
|
5972
6088
|
* A `undefined` override value means the key is ABSENT from the effective
|
|
5973
6089
|
* bag, which is why this walks the map rather than spreading it: spreading
|
|
5974
6090
|
* would leave an explicit `undefined` that `JSON.stringify` drops on one
|
|
5975
6091
|
* side of the next diff but not the other.
|
|
5976
6092
|
*
|
|
5977
|
-
* @returns the complete replacement bag, or `undefined` when nothing
|
|
5978
|
-
*
|
|
6093
|
+
* @returns the complete replacement bag, or `undefined` when there is nothing
|
|
6094
|
+
* to override — the engine then records the desired properties unchanged.
|
|
5979
6095
|
*/
|
|
5980
6096
|
static applyEffectiveOverrides(properties, overrides) {
|
|
5981
6097
|
if (overrides.size === 0) return void 0;
|
|
@@ -5999,14 +6115,22 @@ var S3BucketProvider = class S3BucketProvider {
|
|
|
5999
6115
|
* items would manufacture a fresh phantom drift while removing the one this
|
|
6000
6116
|
* exists to fix.
|
|
6001
6117
|
*
|
|
6118
|
+
* An item that WAS applied but with a value a warn-and-SUBSTITUTE read
|
|
6119
|
+
* replaced is the third arm (issue #1670): it keeps its position and its
|
|
6120
|
+
* declared shape, and only the substituted field differs — `sentItem` is the
|
|
6121
|
+
* item AS SENT, which is what AWS holds and therefore what state must
|
|
6122
|
+
* describe.
|
|
6123
|
+
*
|
|
6002
6124
|
* @param previous the previously-recorded array, or `undefined` on the
|
|
6003
6125
|
* replay-CREATE path, where nothing was ever applied and there is no
|
|
6004
6126
|
* previous item to substitute.
|
|
6127
|
+
* @param sentItemOf the item as SENT for an APPLIED item whose declared value
|
|
6128
|
+
* was substituted, or `undefined` when declared == sent (the ordinary case).
|
|
6005
6129
|
* @returns the effective array, or `undefined` when the key should be ABSENT
|
|
6006
6130
|
* from the effective bag (nothing survived AND the previous side declared
|
|
6007
6131
|
* nothing, so the property was never applied at all).
|
|
6008
6132
|
*/
|
|
6009
|
-
static buildEffectiveItemArray(desired, previous, isSkipped) {
|
|
6133
|
+
static buildEffectiveItemArray(desired, previous, isSkipped, sentItemOf) {
|
|
6010
6134
|
const previousById = /* @__PURE__ */ new Map();
|
|
6011
6135
|
for (const item of previous ?? []) {
|
|
6012
6136
|
const id = configItemId(item);
|
|
@@ -6015,7 +6139,7 @@ var S3BucketProvider = class S3BucketProvider {
|
|
|
6015
6139
|
const effective = [];
|
|
6016
6140
|
desired.forEach((item, index) => {
|
|
6017
6141
|
if (!isSkipped(item, index)) {
|
|
6018
|
-
effective.push(item);
|
|
6142
|
+
effective.push(sentItemOf?.(item, index) ?? item);
|
|
6019
6143
|
return;
|
|
6020
6144
|
}
|
|
6021
6145
|
const id = configItemId(item);
|
|
@@ -6026,6 +6150,34 @@ var S3BucketProvider = class S3BucketProvider {
|
|
|
6026
6150
|
return effective;
|
|
6027
6151
|
}
|
|
6028
6152
|
/**
|
|
6153
|
+
* A COPY of `container` with `path` set to `value` (issue #1670).
|
|
6154
|
+
*
|
|
6155
|
+
* Copying rather than mutating is load-bearing, not hygiene: the container is
|
|
6156
|
+
* an item of the caller's DESIRED property bag, which `DiffCalculator` and the
|
|
6157
|
+
* engine still read afterwards — writing the substituted value into it would
|
|
6158
|
+
* silently rewrite the template side of the next comparison, which is exactly
|
|
6159
|
+
* the `canonicalizeDesiredProperties` behavior this fix must NOT have. Only
|
|
6160
|
+
* the objects ALONG the path are cloned; every sibling subtree is shared,
|
|
6161
|
+
* which is safe because nothing here mutates them.
|
|
6162
|
+
*
|
|
6163
|
+
* A non-object intermediate is rebuilt as an EMPTY block, which is not a
|
|
6164
|
+
* defensive shrug but the accurate record: it is what `readConfigString`
|
|
6165
|
+
* itself did on the way in — its container arm says "Treating the block as
|
|
6166
|
+
* empty, so <path>.<key> takes its default" — so `{}` plus the substituted
|
|
6167
|
+
* leaf IS what was sent. No call site can reach it today (every intermediate
|
|
6168
|
+
* has already been validated by `requireConfigObject` /
|
|
6169
|
+
* `resolveS3BucketDestination`, which SKIP the item on a malformed one).
|
|
6170
|
+
*/
|
|
6171
|
+
static withDeepValue(container, path, value) {
|
|
6172
|
+
const [head, ...rest] = path;
|
|
6173
|
+
if (head === void 0) return container;
|
|
6174
|
+
const child = container[head];
|
|
6175
|
+
return {
|
|
6176
|
+
...container,
|
|
6177
|
+
[head]: rest.length === 0 ? value : S3BucketProvider.withDeepValue(isPlainObject$1(child) ? child : {}, rest, value)
|
|
6178
|
+
};
|
|
6179
|
+
}
|
|
6180
|
+
/**
|
|
6029
6181
|
* Diff CFn-shape sub-config values between previous and new state.
|
|
6030
6182
|
*
|
|
6031
6183
|
* Four transitions:
|
|
@@ -6100,18 +6252,42 @@ var S3BucketProvider = class S3BucketProvider {
|
|
|
6100
6252
|
const retainPrevious = (key) => {
|
|
6101
6253
|
overrides.set(key, previousProperties[key]);
|
|
6102
6254
|
};
|
|
6103
|
-
/**
|
|
6104
|
-
|
|
6105
|
-
|
|
6255
|
+
/**
|
|
6256
|
+
* Per-property accumulator for one of the four `Id`-keyed appliers.
|
|
6257
|
+
*
|
|
6258
|
+
* Keyed by `Id` rather than by index because on THIS path the diff loop
|
|
6259
|
+
* hands the applier exactly one item per call (so every outcome index is
|
|
6260
|
+
* 0) and the id is all the loop knows about it.
|
|
6261
|
+
*/
|
|
6262
|
+
const itemOutcomes = () => {
|
|
6263
|
+
const skipped = /* @__PURE__ */ new Set();
|
|
6264
|
+
const sentItems = /* @__PURE__ */ new Map();
|
|
6265
|
+
return {
|
|
6266
|
+
skipped,
|
|
6267
|
+
sentItems,
|
|
6268
|
+
record: (id, outcome) => {
|
|
6269
|
+
if (outcome.skipped.length > 0) skipped.add(id);
|
|
6270
|
+
const sent = outcome.substituted.get(0);
|
|
6271
|
+
if (sent !== void 0) sentItems.set(id, sent);
|
|
6272
|
+
}
|
|
6273
|
+
};
|
|
6274
|
+
};
|
|
6275
|
+
/** Record a PER-ITEM skip / substitution set against the desired / previous arrays. */
|
|
6276
|
+
const retainPreviousItems = (key, collected) => {
|
|
6277
|
+
const { skipped: skippedIds, sentItems } = collected;
|
|
6278
|
+
if (skippedIds.size === 0 && sentItems.size === 0) return;
|
|
6106
6279
|
const desired = properties[key];
|
|
6107
6280
|
if (!Array.isArray(desired)) {
|
|
6108
|
-
this.logger.debug(`Bucket ${bucketName}: ${skippedIds.size} skipped ${key} item(s) could not be recorded — the desired value is not an array`);
|
|
6281
|
+
this.logger.debug(`Bucket ${bucketName}: ${skippedIds.size + sentItems.size} skipped or substituted ${key} item(s) could not be recorded — the desired value is not an array`);
|
|
6109
6282
|
return;
|
|
6110
6283
|
}
|
|
6111
6284
|
const previous = previousProperties[key];
|
|
6112
6285
|
overrides.set(key, S3BucketProvider.buildEffectiveItemArray(desired, Array.isArray(previous) ? previous : void 0, (item) => {
|
|
6113
6286
|
const id = configItemId(item);
|
|
6114
6287
|
return id !== void 0 && skippedIds.has(id);
|
|
6288
|
+
}, (item) => {
|
|
6289
|
+
const id = configItemId(item);
|
|
6290
|
+
return id !== void 0 ? sentItems.get(id) : void 0;
|
|
6115
6291
|
}));
|
|
6116
6292
|
};
|
|
6117
6293
|
const previousVersioning = previousProperties["VersioningConfiguration"];
|
|
@@ -6172,9 +6348,10 @@ var S3BucketProvider = class S3BucketProvider {
|
|
|
6172
6348
|
this.logger.debug(`Cleared object lock rule on bucket ${bucketName}`);
|
|
6173
6349
|
});
|
|
6174
6350
|
await this.diffSubConfig(bucketName, previousProperties["AccelerateConfiguration"], properties["AccelerateConfiguration"], async (cfg) => this.applyAccelerateConfiguration(bucketName, cfg), async () => this.applyAccelerateConfiguration(bucketName, { AccelerationStatus: "Suspended" }));
|
|
6175
|
-
const
|
|
6351
|
+
const metricsOutcomes = itemOutcomes();
|
|
6176
6352
|
await this.diffArrayConfigById(bucketName, previousProperties["MetricsConfigurations"], properties["MetricsConfigurations"], async (id, cfg) => {
|
|
6177
|
-
|
|
6353
|
+
const outcome = await this.applyMetricsConfigurations(bucketName, [cfg], (m) => this.logger.warn(m));
|
|
6354
|
+
metricsOutcomes.record(String(id), outcome);
|
|
6178
6355
|
}, async (id) => {
|
|
6179
6356
|
await this.s3Client.send(new DeleteBucketMetricsConfigurationCommand({
|
|
6180
6357
|
Bucket: bucketName,
|
|
@@ -6182,10 +6359,11 @@ var S3BucketProvider = class S3BucketProvider {
|
|
|
6182
6359
|
}));
|
|
6183
6360
|
this.logger.debug(`Deleted metrics configuration ${id} on bucket ${bucketName}`);
|
|
6184
6361
|
});
|
|
6185
|
-
retainPreviousItems("MetricsConfigurations",
|
|
6186
|
-
const
|
|
6362
|
+
retainPreviousItems("MetricsConfigurations", metricsOutcomes);
|
|
6363
|
+
const analyticsOutcomes = itemOutcomes();
|
|
6187
6364
|
await this.diffArrayConfigById(bucketName, previousProperties["AnalyticsConfigurations"], properties["AnalyticsConfigurations"], async (id, cfg) => {
|
|
6188
|
-
|
|
6365
|
+
const outcome = await this.applyAnalyticsConfigurations(bucketName, [cfg], (m) => this.logger.warn(m));
|
|
6366
|
+
analyticsOutcomes.record(String(id), outcome);
|
|
6189
6367
|
}, async (id) => {
|
|
6190
6368
|
await this.s3Client.send(new DeleteBucketAnalyticsConfigurationCommand({
|
|
6191
6369
|
Bucket: bucketName,
|
|
@@ -6193,10 +6371,11 @@ var S3BucketProvider = class S3BucketProvider {
|
|
|
6193
6371
|
}));
|
|
6194
6372
|
this.logger.debug(`Deleted analytics configuration ${id} on bucket ${bucketName}`);
|
|
6195
6373
|
});
|
|
6196
|
-
retainPreviousItems("AnalyticsConfigurations",
|
|
6197
|
-
const
|
|
6374
|
+
retainPreviousItems("AnalyticsConfigurations", analyticsOutcomes);
|
|
6375
|
+
const intelligentTieringOutcomes = itemOutcomes();
|
|
6198
6376
|
await this.diffArrayConfigById(bucketName, previousProperties["IntelligentTieringConfigurations"], properties["IntelligentTieringConfigurations"], async (id, cfg) => {
|
|
6199
|
-
|
|
6377
|
+
const outcome = await this.applyIntelligentTieringConfigurations(bucketName, [cfg], (m) => this.logger.warn(m));
|
|
6378
|
+
intelligentTieringOutcomes.record(String(id), outcome);
|
|
6200
6379
|
}, async (id) => {
|
|
6201
6380
|
await this.s3Client.send(new DeleteBucketIntelligentTieringConfigurationCommand({
|
|
6202
6381
|
Bucket: bucketName,
|
|
@@ -6204,10 +6383,11 @@ var S3BucketProvider = class S3BucketProvider {
|
|
|
6204
6383
|
}));
|
|
6205
6384
|
this.logger.debug(`Deleted intelligent tiering configuration ${id} on bucket ${bucketName}`);
|
|
6206
6385
|
});
|
|
6207
|
-
retainPreviousItems("IntelligentTieringConfigurations",
|
|
6208
|
-
const
|
|
6386
|
+
retainPreviousItems("IntelligentTieringConfigurations", intelligentTieringOutcomes);
|
|
6387
|
+
const inventoryOutcomes = itemOutcomes();
|
|
6209
6388
|
await this.diffArrayConfigById(bucketName, previousProperties["InventoryConfigurations"], properties["InventoryConfigurations"], async (id, cfg) => {
|
|
6210
|
-
|
|
6389
|
+
const outcome = await this.applyInventoryConfigurations(bucketName, [cfg], (m) => this.logger.warn(m));
|
|
6390
|
+
inventoryOutcomes.record(String(id), outcome);
|
|
6211
6391
|
}, async (id) => {
|
|
6212
6392
|
await this.s3Client.send(new DeleteBucketInventoryConfigurationCommand({
|
|
6213
6393
|
Bucket: bucketName,
|
|
@@ -6215,7 +6395,7 @@ var S3BucketProvider = class S3BucketProvider {
|
|
|
6215
6395
|
}));
|
|
6216
6396
|
this.logger.debug(`Deleted inventory configuration ${id} on bucket ${bucketName}`);
|
|
6217
6397
|
});
|
|
6218
|
-
retainPreviousItems("InventoryConfigurations",
|
|
6398
|
+
retainPreviousItems("InventoryConfigurations", inventoryOutcomes);
|
|
6219
6399
|
if (versioningChanged && desiredVersioningStatus === "Suspended") {
|
|
6220
6400
|
const hasObjectLock = (p) => {
|
|
6221
6401
|
if (p["ObjectLockEnabled"] === true || p["ObjectLockEnabled"] === "true") return true;
|
|
@@ -6232,20 +6412,29 @@ var S3BucketProvider = class S3BucketProvider {
|
|
|
6232
6412
|
* Apply ALL sub-configs unconditionally on initial create. Used by
|
|
6233
6413
|
* `create()` so the bucket starts out matching the template.
|
|
6234
6414
|
*
|
|
6235
|
-
* @returns the per-property overrides for `effectiveProperties` (
|
|
6236
|
-
* #1612). Every
|
|
6237
|
-
* rollback executor's reverse-replacement arm), where the bucket
|
|
6238
|
-
* new and nothing was applied — so
|
|
6239
|
-
* retaining a previous value, because there is no previous value to
|
|
6240
|
-
* The per-item arrays keep the items that DID apply
|
|
6415
|
+
* @returns the per-property overrides for `effectiveProperties` (issues
|
|
6416
|
+
* #1612 / #1670). Every downgrade reachable here is on the REPLAY-create
|
|
6417
|
+
* path (the rollback executor's reverse-replacement arm), where the bucket
|
|
6418
|
+
* is brand new and nothing was applied — so a SKIP drops the key rather
|
|
6419
|
+
* than retaining a previous value, because there is no previous value to
|
|
6420
|
+
* keep. The per-item arrays keep the items that DID apply, including an
|
|
6421
|
+
* item applied with a SUBSTITUTED value, recorded as it was sent.
|
|
6241
6422
|
*/
|
|
6242
6423
|
async applyAllSubConfigsForCreate(bucketName, properties, context) {
|
|
6243
6424
|
const overrides = /* @__PURE__ */ new Map();
|
|
6244
|
-
/**
|
|
6245
|
-
|
|
6246
|
-
|
|
6247
|
-
|
|
6248
|
-
|
|
6425
|
+
/**
|
|
6426
|
+
* Record a per-ITEM applier outcome.
|
|
6427
|
+
*
|
|
6428
|
+
* A SKIPPED item is DROPPED — there is no previously-applied item to
|
|
6429
|
+
* substitute on a fresh bucket. An item applied with a SUBSTITUTED value
|
|
6430
|
+
* (issue #1670) is kept in place as SENT, which is a decision the create
|
|
6431
|
+
* path makes for the same reason the update path does: the Put SUCCEEDED,
|
|
6432
|
+
* so AWS holds the substituted value and state must say so.
|
|
6433
|
+
*/
|
|
6434
|
+
const recordItemOutcome = (key, configs, outcome) => {
|
|
6435
|
+
if (outcome.skipped.length === 0 && outcome.substituted.size === 0) return;
|
|
6436
|
+
const skipped = new Set(outcome.skipped);
|
|
6437
|
+
overrides.set(key, S3BucketProvider.buildEffectiveItemArray(configs, void 0, (_item, index) => skipped.has(index), (_item, index) => outcome.substituted.get(index)));
|
|
6249
6438
|
};
|
|
6250
6439
|
const replayOnUnusable = replayWarn(this.logger, context).onUnusable;
|
|
6251
6440
|
const notifConfig = properties["NotificationConfiguration"];
|
|
@@ -6269,13 +6458,13 @@ var S3BucketProvider = class S3BucketProvider {
|
|
|
6269
6458
|
const accelerateConfig = properties["AccelerateConfiguration"];
|
|
6270
6459
|
if (accelerateConfig) await this.applyAccelerateConfiguration(bucketName, accelerateConfig);
|
|
6271
6460
|
const metricsConfigs = properties["MetricsConfigurations"];
|
|
6272
|
-
if (metricsConfigs && Array.isArray(metricsConfigs) && metricsConfigs.length > 0)
|
|
6461
|
+
if (metricsConfigs && Array.isArray(metricsConfigs) && metricsConfigs.length > 0) recordItemOutcome("MetricsConfigurations", metricsConfigs, await this.applyMetricsConfigurations(bucketName, metricsConfigs, replayOnUnusable));
|
|
6273
6462
|
const analyticsConfigs = properties["AnalyticsConfigurations"];
|
|
6274
|
-
if (analyticsConfigs && Array.isArray(analyticsConfigs) && analyticsConfigs.length > 0)
|
|
6463
|
+
if (analyticsConfigs && Array.isArray(analyticsConfigs) && analyticsConfigs.length > 0) recordItemOutcome("AnalyticsConfigurations", analyticsConfigs, await this.applyAnalyticsConfigurations(bucketName, analyticsConfigs, replayOnUnusable));
|
|
6275
6464
|
const itConfigs = properties["IntelligentTieringConfigurations"];
|
|
6276
|
-
if (itConfigs && Array.isArray(itConfigs) && itConfigs.length > 0)
|
|
6465
|
+
if (itConfigs && Array.isArray(itConfigs) && itConfigs.length > 0) recordItemOutcome("IntelligentTieringConfigurations", itConfigs, await this.applyIntelligentTieringConfigurations(bucketName, itConfigs, replayOnUnusable));
|
|
6277
6466
|
const inventoryConfigs = properties["InventoryConfigurations"];
|
|
6278
|
-
if (inventoryConfigs && Array.isArray(inventoryConfigs) && inventoryConfigs.length > 0)
|
|
6467
|
+
if (inventoryConfigs && Array.isArray(inventoryConfigs) && inventoryConfigs.length > 0) recordItemOutcome("InventoryConfigurations", inventoryConfigs, await this.applyInventoryConfigurations(bucketName, inventoryConfigs, replayOnUnusable));
|
|
6279
6468
|
const replConfig = properties["ReplicationConfiguration"];
|
|
6280
6469
|
if (replConfig) {
|
|
6281
6470
|
if (!await this.applyReplicationConfiguration(bucketName, replConfig, replayOnUnusable)) overrides.set("ReplicationConfiguration", void 0);
|
|
@@ -6866,15 +7055,17 @@ var S3BucketProvider = class S3BucketProvider {
|
|
|
6866
7055
|
if (sca?.["DataExport"]) {
|
|
6867
7056
|
const dataExport = sca["DataExport"];
|
|
6868
7057
|
const s3Dest = dataExport["Destination"]?.["S3BucketDestination"];
|
|
6869
|
-
|
|
6870
|
-
|
|
6871
|
-
|
|
6872
|
-
|
|
6873
|
-
|
|
6874
|
-
|
|
6875
|
-
|
|
6876
|
-
|
|
6877
|
-
|
|
7058
|
+
const dataExportCfn = {};
|
|
7059
|
+
if (dataExport["OutputSchemaVersion"] !== void 0) dataExportCfn["OutputSchemaVersion"] = dataExport["OutputSchemaVersion"];
|
|
7060
|
+
if (s3Dest) {
|
|
7061
|
+
const cfnDest = {};
|
|
7062
|
+
if (s3Dest["Bucket"] !== void 0) cfnDest["BucketArn"] = s3Dest["Bucket"];
|
|
7063
|
+
if (s3Dest["BucketAccountId"] !== void 0) cfnDest["BucketAccountId"] = s3Dest["BucketAccountId"];
|
|
7064
|
+
if (s3Dest["Format"] !== void 0) cfnDest["Format"] = s3Dest["Format"];
|
|
7065
|
+
if (s3Dest["Prefix"] !== void 0) cfnDest["Prefix"] = s3Dest["Prefix"];
|
|
7066
|
+
dataExportCfn["Destination"] = cfnDest;
|
|
7067
|
+
}
|
|
7068
|
+
out["StorageClassAnalysis"] = { DataExport: dataExportCfn };
|
|
6878
7069
|
}
|
|
6879
7070
|
return out;
|
|
6880
7071
|
}
|
|
@@ -51641,6 +51832,7 @@ async function deployCommand(stacks, options) {
|
|
|
51641
51832
|
...options.skipFinalSnapshot && { skipFinalSnapshot: true },
|
|
51642
51833
|
finalSnapshotClients: stackAwsClients,
|
|
51643
51834
|
...options.strictGetatt && { strictGetAtt: true },
|
|
51835
|
+
...options.cfnFallback === false && { cfnFallback: false },
|
|
51644
51836
|
captureObservedState: resolveCaptureObservedState(options.captureObservedState),
|
|
51645
51837
|
...options.resourceWarnAfter?.globalMs !== void 0 && { resourceWarnAfterMs: options.resourceWarnAfter.globalMs },
|
|
51646
51838
|
...options.resourceTimeout?.globalMs !== void 0 && { resourceTimeoutMs: options.resourceTimeout.globalMs },
|
|
@@ -52702,8 +52894,8 @@ async function loadStateOrEmpty(stackName, region, stateBackend) {
|
|
|
52702
52894
|
* Pure with respect to AWS state mutation — only reads state (the resolver
|
|
52703
52895
|
* may read producer state for `Fn::ImportValue` / `Fn::GetStackOutput`).
|
|
52704
52896
|
*/
|
|
52705
|
-
async function computeStackDiff(currentState, template, region, stackName, stateBackend, diffCalculator, parameters, canonicalizeProperties) {
|
|
52706
|
-
const intrinsicResolver = new IntrinsicFunctionResolver(region);
|
|
52897
|
+
async function computeStackDiff(currentState, template, region, stackName, stateBackend, diffCalculator, parameters, canonicalizeProperties, cfnFallback) {
|
|
52898
|
+
const intrinsicResolver = new IntrinsicFunctionResolver(region, { cfnFallback: cfnFallback ?? true });
|
|
52707
52899
|
let mergedParameters = parameters;
|
|
52708
52900
|
let parametersBound = false;
|
|
52709
52901
|
try {
|
|
@@ -52765,10 +52957,10 @@ async function computeStackDiff(currentState, template, region, stackName, state
|
|
|
52765
52957
|
* unresolvable case), while resolvable parameters (the freshly-deployed tree)
|
|
52766
52958
|
* get exact scalar values.
|
|
52767
52959
|
*/
|
|
52768
|
-
async function resolveChildStackParameters(parentStackRow, parentTemplate, parentState, region, parentStackName, stateBackend, parentParameters) {
|
|
52960
|
+
async function resolveChildStackParameters(parentStackRow, parentTemplate, parentState, region, parentStackName, stateBackend, parentParameters, cfnFallback) {
|
|
52769
52961
|
const rawParams = parentStackRow.Properties?.["Parameters"];
|
|
52770
52962
|
if (!rawParams || typeof rawParams !== "object" || Array.isArray(rawParams)) return {};
|
|
52771
|
-
const resolver = new IntrinsicFunctionResolver(region);
|
|
52963
|
+
const resolver = new IntrinsicFunctionResolver(region, { cfnFallback: cfnFallback ?? true });
|
|
52772
52964
|
const resolved = {};
|
|
52773
52965
|
for (const [name, value] of Object.entries(rawParams)) try {
|
|
52774
52966
|
resolved[name] = await resolver.resolve(value, {
|
|
@@ -52803,13 +52995,13 @@ async function resolveChildStackParameters(parentStackRow, parentTemplate, paren
|
|
|
52803
52995
|
* fail at deploy time.
|
|
52804
52996
|
*/
|
|
52805
52997
|
async function buildDiffTree(args) {
|
|
52806
|
-
const { stackName, displayName, region, template, nestedTemplates, recursive, stateBackend, diffCalculator, parameters, canonicalizeProperties, assetRedirect } = args;
|
|
52998
|
+
const { stackName, displayName, region, template, nestedTemplates, recursive, stateBackend, diffCalculator, parameters, canonicalizeProperties, assetRedirect, cfnFallback } = args;
|
|
52807
52999
|
const state = await loadStateOrEmpty(stackName, region, stateBackend);
|
|
52808
53000
|
const node = {
|
|
52809
53001
|
stackName,
|
|
52810
53002
|
displayName,
|
|
52811
53003
|
region,
|
|
52812
|
-
changes: await computeStackDiff(state, template, region, stackName, stateBackend, diffCalculator, parameters, canonicalizeProperties),
|
|
53004
|
+
changes: await computeStackDiff(state, template, region, stackName, stateBackend, diffCalculator, parameters, canonicalizeProperties, cfnFallback),
|
|
52813
53005
|
ccApiRoutes: collectCcApiRoutes(template, state),
|
|
52814
53006
|
children: []
|
|
52815
53007
|
};
|
|
@@ -52824,7 +53016,7 @@ async function buildDiffTree(args) {
|
|
|
52824
53016
|
const childTemplate = readNestedTemplate(childTemplatePath);
|
|
52825
53017
|
if (assetRedirect) rewriteTemplateAssetReferences(childTemplate, assetRedirect);
|
|
52826
53018
|
const grandchildTemplates = indexNestedChildTemplates(childTemplate, childTemplatePath);
|
|
52827
|
-
const childParameters = await resolveChildStackParameters(resource, template, state, region, stackName, stateBackend, parameters);
|
|
53019
|
+
const childParameters = await resolveChildStackParameters(resource, template, state, region, stackName, stateBackend, parameters, cfnFallback);
|
|
52828
53020
|
node.children.push(await buildDiffTree({
|
|
52829
53021
|
stackName: childStackName,
|
|
52830
53022
|
displayName: childStackName,
|
|
@@ -52836,7 +53028,8 @@ async function buildDiffTree(args) {
|
|
|
52836
53028
|
diffCalculator,
|
|
52837
53029
|
parameters: childParameters,
|
|
52838
53030
|
...canonicalizeProperties && { canonicalizeProperties },
|
|
52839
|
-
...assetRedirect && { assetRedirect }
|
|
53031
|
+
...assetRedirect && { assetRedirect },
|
|
53032
|
+
...cfnFallback !== void 0 && { cfnFallback }
|
|
52840
53033
|
}));
|
|
52841
53034
|
}
|
|
52842
53035
|
for (const [logicalId, resource] of Object.entries(state.resources)) {
|
|
@@ -53223,7 +53416,8 @@ async function diffCommand(stacks, options) {
|
|
|
53223
53416
|
stateBackend,
|
|
53224
53417
|
diffCalculator,
|
|
53225
53418
|
canonicalizeProperties,
|
|
53226
|
-
...assetRedirect && { assetRedirect }
|
|
53419
|
+
...assetRedirect && { assetRedirect },
|
|
53420
|
+
...options.cfnFallback === false && { cfnFallback: false }
|
|
53227
53421
|
}));
|
|
53228
53422
|
}
|
|
53229
53423
|
if (options.json) process.stdout.write(`${JSON.stringify(trees.map(diffTreeToJson), null, 2)}\n`);
|
|
@@ -53243,7 +53437,7 @@ async function diffCommand(stacks, options) {
|
|
|
53243
53437
|
* Create diff command
|
|
53244
53438
|
*/
|
|
53245
53439
|
function createDiffCommand() {
|
|
53246
|
-
const cmd = new Command("diff").description("Show difference between current state and desired state").argument("[stacks...]", "Stack name(s) to diff. Accepts physical CloudFormation names (e.g. 'MyStage-Api') or CDK display paths (e.g. 'MyStage/Api'). Supports wildcards (e.g. 'MyStage/*').").option("--all", "Diff all stacks", false).option("--recursive", "Recurse into each AWS::CloudFormation::Stack row and diff every nested-stack child against its own deployed state (DFS order). Default is non-recursive, matching cdk diff.", false).option("--fail", "Exit with code 1 when any change is detected (matches cdk diff --fail). With --recursive, considers the whole nested-stack tree.", false).option("--json", "Output the diff as JSON (nested tree shape when combined with --recursive)", false).addOption(useCdkBootstrapAssetsOption).action(withErrorHandling(diffCommand));
|
|
53440
|
+
const cmd = new Command("diff").description("Show difference between current state and desired state").argument("[stacks...]", "Stack name(s) to diff. Accepts physical CloudFormation names (e.g. 'MyStage-Api') or CDK display paths (e.g. 'MyStage/Api'). Supports wildcards (e.g. 'MyStage/*').").option("--all", "Diff all stacks", false).option("--recursive", "Recurse into each AWS::CloudFormation::Stack row and diff every nested-stack child against its own deployed state (DFS order). Default is non-recursive, matching cdk diff.", false).option("--fail", "Exit with code 1 when any change is detected (matches cdk diff --fail). With --recursive, considers the whole nested-stack tree.", false).option("--json", "Output the diff as JSON (nested tree shape when combined with --recursive)", false).addOption(useCdkBootstrapAssetsOption).addOption(noCfnFallbackOption).action(withErrorHandling(diffCommand));
|
|
53247
53441
|
[
|
|
53248
53442
|
...commonOptions,
|
|
53249
53443
|
...appOptions,
|
|
@@ -56335,8 +56529,8 @@ async function exportCommand(stackArg, options) {
|
|
|
56335
56529
|
const crossRefs = scanCrossStackReferences(allSynthStacks, resolvedStackName);
|
|
56336
56530
|
if (crossRefs.length > 0) {
|
|
56337
56531
|
const lines = crossRefs.map((r) => ` ${r.consumerStackName} → ${resolvedStackName}.${r.outputName} at ${r.location}`);
|
|
56338
|
-
if (options.strictCrossStack) throw new Error(`Refusing to export: ${crossRefs.length} cross-stack reference(s) to ${resolvedStackName} found in sibling stacks. After migration, those references
|
|
56339
|
-
logger.warn(`${crossRefs.length} cross-stack reference(s) to '${resolvedStackName}' from sibling stacks.
|
|
56532
|
+
if (options.strictCrossStack) throw new Error(`Refusing to export: ${crossRefs.length} cross-stack reference(s) to ${resolvedStackName} found in sibling stacks. After migration, those references depend on the CloudFormation fallback (the migrated stack's outputs live in CFn; cdkd resolves them via DescribeStacks after the cdkd-state miss), and consumers deployed with --no-cfn-fallback break. Migrate consumers first, or remove the references, or drop --strict-cross-stack to proceed with a warning:\n` + lines.join("\n"));
|
|
56533
|
+
logger.warn(`${crossRefs.length} cross-stack reference(s) to '${resolvedStackName}' from sibling stacks. After the migration those consumers resolve this stack's outputs via the CloudFormation fallback (weak reference; the outputs now live in CFn) — they break only when deployed with --no-cfn-fallback. Migrate consumers from the leaves up if you rely on cdkd-state-only resolution.`);
|
|
56340
56534
|
for (const line of lines) logger.warn(line);
|
|
56341
56535
|
}
|
|
56342
56536
|
}
|
|
@@ -56420,8 +56614,8 @@ async function exportCommand(stackArg, options) {
|
|
|
56420
56614
|
const crossRefs = scanCrossStackReferences(allSynthStacks, resolvedStackName);
|
|
56421
56615
|
if (crossRefs.length > 0) {
|
|
56422
56616
|
const lines = crossRefs.map((r) => ` ${r.consumerStackName} → ${resolvedStackName}.${r.outputName} at ${r.location}`);
|
|
56423
|
-
if (options.strictCrossStack) throw new Error(`Refusing to export: ${crossRefs.length} cross-stack reference(s) to ${resolvedStackName} found in sibling stacks. After migration, those references
|
|
56424
|
-
logger.warn(`${crossRefs.length} cross-stack reference(s) to '${resolvedStackName}' from sibling stacks.
|
|
56617
|
+
if (options.strictCrossStack) throw new Error(`Refusing to export: ${crossRefs.length} cross-stack reference(s) to ${resolvedStackName} found in sibling stacks. After migration, those references depend on the CloudFormation fallback (the migrated stack's outputs live in CFn; cdkd resolves them via DescribeStacks after the cdkd-state miss), and consumers deployed with --no-cfn-fallback break. Migrate consumers first, or remove the references, or drop --strict-cross-stack to proceed with a warning:\n` + lines.join("\n"));
|
|
56618
|
+
logger.warn(`${crossRefs.length} cross-stack reference(s) to '${resolvedStackName}' from sibling stacks. After the migration those consumers resolve this stack's outputs via the CloudFormation fallback (weak reference; the outputs now live in CFn) — they break only when deployed with --no-cfn-fallback. Migrate consumers from the leaves up if you rely on cdkd-state-only resolution.`);
|
|
56425
56619
|
for (const line of lines) logger.warn(line);
|
|
56426
56620
|
}
|
|
56427
56621
|
}
|
|
@@ -58329,7 +58523,7 @@ async function confirmPrompt$3(prompt) {
|
|
|
58329
58523
|
}
|
|
58330
58524
|
}
|
|
58331
58525
|
function createExportCommand() {
|
|
58332
|
-
const cmd = new Command("export").description("Hand a cdkd-managed stack over to CloudFormation via CFn IMPORT (changeset). AWS resources are unchanged; cdkd state for the stack is deleted on success. Mirror of `cdkd import` (AWS → cdkd) in the reverse direction (cdkd → CFn). Accepts JSON and YAML templates (YAML via a CFn-aware codec that preserves !Ref / !GetAtt / !Sub shorthand). Aborts if any resource is not CFn-importable.").argument("[stack]", "Stack name to export (auto-detected for single-stack apps)").option("--cfn-stack-name <name>", "Name of the destination CloudFormation stack for the root stack. Defaults to the cdkd stack name (or the cdkd2cfnStackName mapping when the name contains '~'). For per-nested-child overrides, use --cfn-child-stack-name.").option("--cfn-child-stack-name <pair...>", "Per-nested-child CFn stack-name override. Repeatable. Format: '<cdkdName>=<cfnName>' (e.g. --cfn-child-stack-name 'MyApp~Database=my-app-db'). The cdkd stack name for a nested child is '<parent>~<childLogicalId>' (v6 state-key form). Without an override the CFn name is derived by replacing '~' with '-'. Only consulted when the exported stack tree contains nested children; ignored for flat stacks.").option("--template <path>", "Path to a pre-rendered CloudFormation template (JSON or YAML — format auto-detected). Skips synth.").option("--stack-region <region>", "Region of the cdkd state record to operate on. Required when the same stack name has state in multiple regions.").option("--dry-run", "Print the import plan without creating a changeset.", false).option("--accept-transient-context", "Allow CLI -c key=value overrides at export time even though they are not persisted to cdk.json / cdk.context.json (default: refuse). When set, the user is responsible for passing the same -c flags to every future cdk deploy.", false).option("--include-non-importable", "Run a 2-phase migration when the stack contains non-importable resources (Custom::*). Phase 1 imports the importable resources; phase 2 CFn-CREATEs the non-importable ones, which re-invokes each Custom Resource's onCreate handler. Make sure onCreate is idempotent before enabling.", false).option("--parameter <key=value...>", "CFn template Parameter override, repeatable. Required when the synthesized template has Parameters without Default values; otherwise overrides the template's default value. Format: --parameter Key=Value.").option("--strict-cross-stack", "Refuse to export when sibling cdkd stacks in the same CDK app reference the exporting stack via Fn::GetStackOutput. Without the flag, cdkd warns
|
|
58526
|
+
const cmd = new Command("export").description("Hand a cdkd-managed stack over to CloudFormation via CFn IMPORT (changeset). AWS resources are unchanged; cdkd state for the stack is deleted on success. Mirror of `cdkd import` (AWS → cdkd) in the reverse direction (cdkd → CFn). Accepts JSON and YAML templates (YAML via a CFn-aware codec that preserves !Ref / !GetAtt / !Sub shorthand). Aborts if any resource is not CFn-importable.").argument("[stack]", "Stack name to export (auto-detected for single-stack apps)").option("--cfn-stack-name <name>", "Name of the destination CloudFormation stack for the root stack. Defaults to the cdkd stack name (or the cdkd2cfnStackName mapping when the name contains '~'). For per-nested-child overrides, use --cfn-child-stack-name.").option("--cfn-child-stack-name <pair...>", "Per-nested-child CFn stack-name override. Repeatable. Format: '<cdkdName>=<cfnName>' (e.g. --cfn-child-stack-name 'MyApp~Database=my-app-db'). The cdkd stack name for a nested child is '<parent>~<childLogicalId>' (v6 state-key form). Without an override the CFn name is derived by replacing '~' with '-'. Only consulted when the exported stack tree contains nested children; ignored for flat stacks.").option("--template <path>", "Path to a pre-rendered CloudFormation template (JSON or YAML — format auto-detected). Skips synth.").option("--stack-region <region>", "Region of the cdkd state record to operate on. Required when the same stack name has state in multiple regions.").option("--dry-run", "Print the import plan without creating a changeset.", false).option("--accept-transient-context", "Allow CLI -c key=value overrides at export time even though they are not persisted to cdk.json / cdk.context.json (default: refuse). When set, the user is responsible for passing the same -c flags to every future cdk deploy.", false).option("--include-non-importable", "Run a 2-phase migration when the stack contains non-importable resources (Custom::*). Phase 1 imports the importable resources; phase 2 CFn-CREATEs the non-importable ones, which re-invokes each Custom Resource's onCreate handler. Make sure onCreate is idempotent before enabling.", false).option("--parameter <key=value...>", "CFn template Parameter override, repeatable. Required when the synthesized template has Parameters without Default values; otherwise overrides the template's default value. Format: --parameter Key=Value.").option("--strict-cross-stack", "Refuse to export when sibling cdkd stacks in the same CDK app reference the exporting stack via Fn::GetStackOutput. Without the flag, cdkd warns and proceeds — the consumers keep resolving via the CloudFormation fallback (weak reference) unless they deploy with --no-cfn-fallback.", false).option("--no-recreate-import-unsupported", "Block instead of auto-handling resource types AWS does NOT support in IMPORT changesets (currently only AWS::ApiGatewayV2::Stage, emitted by CDK HttpApi). Default behavior: cdkd skips these from phase 1, deletes the AWS-side resource between phases, and lets CFn re-CREATE in phase 2 (brief unavailability window). With this flag, the export aborts with a clear error instead.").action(withErrorHandling(exportCommand));
|
|
58333
58527
|
[
|
|
58334
58528
|
...commonOptions,
|
|
58335
58529
|
...appOptions,
|
|
@@ -72155,7 +72349,7 @@ function createMigrateCommand() {
|
|
|
72155
72349
|
*/
|
|
72156
72350
|
function buildProgram() {
|
|
72157
72351
|
const program = new Command();
|
|
72158
|
-
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.
|
|
72352
|
+
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.281.0");
|
|
72159
72353
|
program.hook("preAction", (_thisCommand, actionCommand) => {
|
|
72160
72354
|
const { profile } = actionCommand.optsWithGlobals();
|
|
72161
72355
|
if (profile !== void 0) process.env["AWS_PROFILE"] = profile;
|