@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
|
@@ -9,7 +9,7 @@ import { GetFunctionCommand, GetFunctionUrlConfigCommand, InvokeCommand, LambdaC
|
|
|
9
9
|
import { AssumeRoleCommand, GetCallerIdentityCommand, STSClient } from "@aws-sdk/client-sts";
|
|
10
10
|
import { CreateSnapshotCommand, DescribeAvailabilityZonesCommand, DescribeImagesCommand, DescribeInstancesCommand, DescribeLaunchTemplatesCommand, DescribeRouteTablesCommand, DescribeSecurityGroupsCommand, DescribeSnapshotsCommand, DescribeSubnetsCommand, DescribeVpcsCommand, DescribeVpnGatewaysCommand, EC2Client, ModifyInstanceAttributeCommand } from "@aws-sdk/client-ec2";
|
|
11
11
|
import { DescribeTableCommand, DynamoDBClient } from "@aws-sdk/client-dynamodb";
|
|
12
|
-
import { CloudFormationClient, CreateChangeSetCommand, DeleteStackCommand, DescribeChangeSetCommand, DescribeTypeCommand, GetTemplateCommand, waitUntilChangeSetCreateComplete } from "@aws-sdk/client-cloudformation";
|
|
12
|
+
import { CloudFormationClient, CreateChangeSetCommand, DeleteStackCommand, DescribeChangeSetCommand, DescribeStacksCommand, DescribeTypeCommand, GetTemplateCommand, ListExportsCommand, waitUntilChangeSetCreateComplete } from "@aws-sdk/client-cloudformation";
|
|
13
13
|
import { APIGatewayClient, GetRestApiCommand } from "@aws-sdk/client-api-gateway";
|
|
14
14
|
import { DescribeApiDestinationCommand, DescribeConnectionCommand, EventBridgeClient } from "@aws-sdk/client-eventbridge";
|
|
15
15
|
import { GetSecretValueCommand, SecretsManagerClient } from "@aws-sdk/client-secrets-manager";
|
|
@@ -10687,6 +10687,34 @@ var IntrinsicFunctionResolver = class {
|
|
|
10687
10687
|
logger = getLogger().child("IntrinsicFunctionResolver");
|
|
10688
10688
|
resolverRegion;
|
|
10689
10689
|
strictGetAtt;
|
|
10690
|
+
cfnFallback;
|
|
10691
|
+
/**
|
|
10692
|
+
* Per-region CloudFormation clients for the cross-stack fallback
|
|
10693
|
+
* lookups (issue #1697). Keyed by region because `Fn::GetStackOutput`
|
|
10694
|
+
* may target a region different from the consumer's deploy region.
|
|
10695
|
+
*/
|
|
10696
|
+
cfnClients = {};
|
|
10697
|
+
/**
|
|
10698
|
+
* Memoized full `ListExports` listing for the `Fn::ImportValue`
|
|
10699
|
+
* fallback (issue #1697 review). Without it, EVERY cdkd-miss import
|
|
10700
|
+
* re-paginates the whole region's export list — a deploy consuming N
|
|
10701
|
+
* values from CFn producers pays N full walks and exposes itself to
|
|
10702
|
+
* ListExports throttling. Resolver instances are per-deploy (the
|
|
10703
|
+
* engine constructs one per stack), so the cache lifetime matches the
|
|
10704
|
+
* exports-index philosophy: stable within a deploy, fresh across
|
|
10705
|
+
* deploys. FAILED fetches are not cached (the rejection handler
|
|
10706
|
+
* clears the slot) so a transient throttle does not poison the rest
|
|
10707
|
+
* of the deploy's lookups.
|
|
10708
|
+
*/
|
|
10709
|
+
cfnExportsPromise;
|
|
10710
|
+
/**
|
|
10711
|
+
* Memoized per-(region, stack) `DescribeStacks` outputs for the
|
|
10712
|
+
* `Fn::GetStackOutput` fallback (issue #1697 review) — a stack
|
|
10713
|
+
* referencing the same CFn producer N times pays one call. Successful
|
|
10714
|
+
* lookups (including the definitive "stack does not exist" miss) are
|
|
10715
|
+
* cached; lookup FAILURES are evicted so they are retried.
|
|
10716
|
+
*/
|
|
10717
|
+
cfnStackOutputsCache = /* @__PURE__ */ new Map();
|
|
10690
10718
|
/**
|
|
10691
10719
|
* Number of unknown-attribute resolutions that fell back to the physical
|
|
10692
10720
|
* ID (the warn path) since construction / the last
|
|
@@ -10709,6 +10737,7 @@ var IntrinsicFunctionResolver = class {
|
|
|
10709
10737
|
constructor(region, options) {
|
|
10710
10738
|
this.resolverRegion = region || process.env["AWS_REGION"] || "us-east-1";
|
|
10711
10739
|
this.strictGetAtt = options?.strictGetAtt ?? false;
|
|
10740
|
+
this.cfnFallback = options?.cfnFallback ?? true;
|
|
10712
10741
|
}
|
|
10713
10742
|
/** Unknown-attribute physicalId fallbacks recorded since the last reset. */
|
|
10714
10743
|
getPhysicalIdFallbackCount() {
|
|
@@ -11604,7 +11633,113 @@ var IntrinsicFunctionResolver = class {
|
|
|
11604
11633
|
continue;
|
|
11605
11634
|
}
|
|
11606
11635
|
}
|
|
11607
|
-
|
|
11636
|
+
if (this.cfnFallback) {
|
|
11637
|
+
const cfnExport = await this.lookupCfnExport(exportName);
|
|
11638
|
+
if (cfnExport) {
|
|
11639
|
+
this.logger.info(`Resolved Fn::ImportValue: ${exportName} = ${JSON.stringify(cfnExport.value)} (from CloudFormation exports${cfnExport.exportingStackId ? `; exporting stack: ${cfnExport.exportingStackId}` : ""}; weak reference — producer is not cdkd-managed)`);
|
|
11640
|
+
return cfnExport.value;
|
|
11641
|
+
}
|
|
11642
|
+
}
|
|
11643
|
+
throw new Error(`Fn::ImportValue: export '${exportName}' not found in any stack. Searched ${allStacks.length} cdkd state record(s)${this.cfnFallback ? " and CloudFormation exports" : ""}. Make sure the exporting stack has been deployed and the Output has an Export.Name property.`);
|
|
11644
|
+
}
|
|
11645
|
+
/**
|
|
11646
|
+
* CloudFormation `ListExports` fallback lookup for `Fn::ImportValue`
|
|
11647
|
+
* (issue #1697). Searches the consumer's deploy region (CFn exports are
|
|
11648
|
+
* region-scoped, same as cdkd's `Fn::ImportValue` semantics).
|
|
11649
|
+
*
|
|
11650
|
+
* Returns `undefined` both when the export does not exist AND when the
|
|
11651
|
+
* lookup itself failed (a warning is logged for the latter — e.g. the
|
|
11652
|
+
* caller's credentials lack `cloudformation:ListExports`), so the caller
|
|
11653
|
+
* surfaces its own not-found error either way. Graceful degradation is
|
|
11654
|
+
* deliberate: without this fallback the deploy would have failed with
|
|
11655
|
+
* the same not-found error anyway.
|
|
11656
|
+
*/
|
|
11657
|
+
async lookupCfnExport(exportName) {
|
|
11658
|
+
let listing = this.cfnExportsPromise;
|
|
11659
|
+
if (!listing) {
|
|
11660
|
+
listing = this.fetchAllCfnExports();
|
|
11661
|
+
this.cfnExportsPromise = listing;
|
|
11662
|
+
listing.catch(() => {
|
|
11663
|
+
if (this.cfnExportsPromise === listing) this.cfnExportsPromise = void 0;
|
|
11664
|
+
});
|
|
11665
|
+
}
|
|
11666
|
+
try {
|
|
11667
|
+
const exports = await listing;
|
|
11668
|
+
for (const exp of exports) if (exp.Name === exportName && exp.Value !== void 0) return {
|
|
11669
|
+
value: exp.Value,
|
|
11670
|
+
...exp.ExportingStackId && { exportingStackId: exp.ExportingStackId }
|
|
11671
|
+
};
|
|
11672
|
+
return;
|
|
11673
|
+
} catch (error) {
|
|
11674
|
+
this.logger.warn(`Fn::ImportValue: CloudFormation ListExports fallback failed for export '${exportName}' (region ${this.resolverRegion}): ${error instanceof Error ? error.message : String(error)}. Grant cloudformation:ListExports to resolve exports from CloudFormation-managed stacks, or pass --no-cfn-fallback to disable the fallback.`);
|
|
11675
|
+
return;
|
|
11676
|
+
}
|
|
11677
|
+
}
|
|
11678
|
+
/** Full paginated ListExports walk backing {@link lookupCfnExport}'s memo. */
|
|
11679
|
+
async fetchAllCfnExports() {
|
|
11680
|
+
const client = this.getCfnClient(this.resolverRegion);
|
|
11681
|
+
const exports = [];
|
|
11682
|
+
let nextToken;
|
|
11683
|
+
do {
|
|
11684
|
+
const res = await client.send(new ListExportsCommand({ NextToken: nextToken }));
|
|
11685
|
+
exports.push(...res.Exports ?? []);
|
|
11686
|
+
nextToken = res.NextToken;
|
|
11687
|
+
} while (nextToken);
|
|
11688
|
+
return exports;
|
|
11689
|
+
}
|
|
11690
|
+
/**
|
|
11691
|
+
* CloudFormation `DescribeStacks` fallback lookup for
|
|
11692
|
+
* `Fn::GetStackOutput` (issue #1697). Region-pinned because the
|
|
11693
|
+
* intrinsic may target a region different from the consumer's.
|
|
11694
|
+
*
|
|
11695
|
+
* Returns the stack's outputs map when the CFn stack exists;
|
|
11696
|
+
* `undefined` when it does not exist OR the lookup failed (a warning is
|
|
11697
|
+
* logged for non-not-found failures). Same graceful-degradation
|
|
11698
|
+
* contract as {@link lookupCfnExport}.
|
|
11699
|
+
*/
|
|
11700
|
+
async lookupCfnStackOutputs(stackName, region) {
|
|
11701
|
+
const cacheKey = `${region}\0${stackName}`;
|
|
11702
|
+
let fetch = this.cfnStackOutputsCache.get(cacheKey);
|
|
11703
|
+
if (!fetch) {
|
|
11704
|
+
fetch = this.fetchCfnStackOutputs(stackName, region);
|
|
11705
|
+
this.cfnStackOutputsCache.set(cacheKey, fetch);
|
|
11706
|
+
fetch.catch(() => {
|
|
11707
|
+
if (this.cfnStackOutputsCache.get(cacheKey) === fetch) this.cfnStackOutputsCache.delete(cacheKey);
|
|
11708
|
+
});
|
|
11709
|
+
}
|
|
11710
|
+
try {
|
|
11711
|
+
return await fetch;
|
|
11712
|
+
} catch (error) {
|
|
11713
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
11714
|
+
this.logger.warn(`Fn::GetStackOutput: CloudFormation DescribeStacks fallback failed for stack '${stackName}' (${region}): ${message}. Grant cloudformation:DescribeStacks to resolve outputs from CloudFormation-managed stacks, or pass --no-cfn-fallback to disable the fallback.`);
|
|
11715
|
+
return;
|
|
11716
|
+
}
|
|
11717
|
+
}
|
|
11718
|
+
/**
|
|
11719
|
+
* Single DescribeStacks read backing {@link lookupCfnStackOutputs}'s memo.
|
|
11720
|
+
* Resolves to the outputs map, `undefined` for the definitive
|
|
11721
|
+
* does-not-exist miss, and REJECTS on any other failure.
|
|
11722
|
+
*/
|
|
11723
|
+
async fetchCfnStackOutputs(stackName, region) {
|
|
11724
|
+
try {
|
|
11725
|
+
const stack = (await this.getCfnClient(region).send(new DescribeStacksCommand({ StackName: stackName }))).Stacks?.[0];
|
|
11726
|
+
if (!stack) return void 0;
|
|
11727
|
+
const outputs = {};
|
|
11728
|
+
for (const out of stack.Outputs ?? []) if (out.OutputKey && out.OutputValue !== void 0) outputs[out.OutputKey] = out.OutputValue;
|
|
11729
|
+
return outputs;
|
|
11730
|
+
} catch (error) {
|
|
11731
|
+
if (error instanceof Error && error.name === "ValidationError" && /does not exist/i.test(error.message)) return;
|
|
11732
|
+
throw error;
|
|
11733
|
+
}
|
|
11734
|
+
}
|
|
11735
|
+
/** Lazily-constructed per-region CloudFormation client (issue #1697). */
|
|
11736
|
+
getCfnClient(region) {
|
|
11737
|
+
let client = this.cfnClients[region];
|
|
11738
|
+
if (!client) {
|
|
11739
|
+
client = new CloudFormationClient({ region });
|
|
11740
|
+
this.cfnClients[region] = client;
|
|
11741
|
+
}
|
|
11742
|
+
return client;
|
|
11608
11743
|
}
|
|
11609
11744
|
/**
|
|
11610
11745
|
* Push a resolved `Fn::ImportValue` into the consumer's recorded-imports
|
|
@@ -11691,7 +11826,21 @@ var IntrinsicFunctionResolver = class {
|
|
|
11691
11826
|
if (!roleArn && context.stackName && context.stackName === stackName && region === this.resolverRegion) throw new Error(`Fn::GetStackOutput: cannot reference own stack '${stackName}' in the same region '${region}'`);
|
|
11692
11827
|
this.logger.debug(`Resolving Fn::GetStackOutput: StackName=${stackName}, Region=${region}, OutputName=${outputName}${roleArn ? `, RoleArn=${roleArn}` : ""}`);
|
|
11693
11828
|
const stateData = roleArn ? await this.getCrossAccountStackState(roleArn, stackName, region, context) : await this.getSameAccountStackState(stackName, region, context);
|
|
11694
|
-
if (!stateData)
|
|
11829
|
+
if (!stateData) {
|
|
11830
|
+
if (!roleArn && this.cfnFallback) {
|
|
11831
|
+
const cfnOutputs = await this.lookupCfnStackOutputs(stackName, region);
|
|
11832
|
+
if (cfnOutputs) {
|
|
11833
|
+
if (!(outputName in cfnOutputs)) {
|
|
11834
|
+
const available = Object.keys(cfnOutputs).join(", ") || "(none)";
|
|
11835
|
+
throw new Error(`Fn::GetStackOutput: output '${outputName}' not found in CloudFormation stack '${stackName}' (${region}). Available outputs: ${available}`);
|
|
11836
|
+
}
|
|
11837
|
+
const value = cfnOutputs[outputName];
|
|
11838
|
+
this.logger.info(`Resolved Fn::GetStackOutput: StackName=${stackName}, Region=${region}, OutputName=${outputName} -> ${JSON.stringify(value)} (from CloudFormation stack outputs; weak reference — producer is not cdkd-managed)`);
|
|
11839
|
+
return value;
|
|
11840
|
+
}
|
|
11841
|
+
}
|
|
11842
|
+
throw new Error(`Fn::GetStackOutput: stack '${stackName}' not found in region '${region}'${roleArn ? ` (cross-account via ${roleArn})` : ""}. ${!roleArn && this.cfnFallback ? "Searched cdkd state and CloudFormation stacks. Make sure the producer stack has been deployed (via cdkd or CloudFormation)." : `Make sure the producer stack has been deployed via cdkd.`}`);
|
|
11843
|
+
}
|
|
11695
11844
|
const outputs = stateData.state.outputs ?? {};
|
|
11696
11845
|
if (!(outputName in outputs)) {
|
|
11697
11846
|
const available = Object.keys(outputs).join(", ") || "(none)";
|
|
@@ -12915,7 +13064,7 @@ var CloudControlProvider = class {
|
|
|
12915
13064
|
if (context?.finalSnapshotIdentifier !== void 0) throw new ProvisioningError(`${logicalId} (${resourceType}) requires a final snapshot (DeletionPolicy: Snapshot), but the Cloud Control API delete route has no final-snapshot parameter. Re-run with --skip-final-snapshot after snapshotting manually, or retain the resource.`, resourceType, logicalId, physicalId);
|
|
12916
13065
|
if (context?.removeProtection === true && resourceType === "AWS::AutoScaling::AutoScalingGroup") {
|
|
12917
13066
|
this.logger.debug(`Delegating protected AutoScalingGroup ${logicalId} delete to the SDK ASGProvider (Cloud Control cannot force-delete a protected ASG)`);
|
|
12918
|
-
const { ASGProvider } = await import("./asg-provider-
|
|
13067
|
+
const { ASGProvider } = await import("./asg-provider-BSx4Vrth.js").then((n) => n.n);
|
|
12919
13068
|
await new ASGProvider().delete(logicalId, physicalId, resourceType, _properties, context);
|
|
12920
13069
|
return;
|
|
12921
13070
|
}
|
|
@@ -19791,7 +19940,7 @@ const FLUSH_INTERVAL_MS = 2e3;
|
|
|
19791
19940
|
const FLUSH_EVENT_THRESHOLD = 50;
|
|
19792
19941
|
/** Build-time cdkd version, with a dev fallback for non-built contexts. */
|
|
19793
19942
|
function getCdkdVersion() {
|
|
19794
|
-
return "0.
|
|
19943
|
+
return "0.281.0";
|
|
19795
19944
|
}
|
|
19796
19945
|
/**
|
|
19797
19946
|
* Generate a time-sortable unique run id, e.g.
|
|
@@ -20410,7 +20559,10 @@ var DeployEngine = class {
|
|
|
20410
20559
|
this.options = options;
|
|
20411
20560
|
this.stackRegion = stackRegion;
|
|
20412
20561
|
this.exportIndexStore = exportIndexStore;
|
|
20413
|
-
this.resolver = new IntrinsicFunctionResolver(stackRegion, {
|
|
20562
|
+
this.resolver = new IntrinsicFunctionResolver(stackRegion, {
|
|
20563
|
+
strictGetAtt: options.strictGetAtt ?? false,
|
|
20564
|
+
cfnFallback: options.cfnFallback ?? true
|
|
20565
|
+
});
|
|
20414
20566
|
this.options.concurrency = options.concurrency ?? 10;
|
|
20415
20567
|
this.options.dryRun = options.dryRun ?? false;
|
|
20416
20568
|
this.options.lockTimeout = options.lockTimeout ?? 300 * 1e3;
|
|
@@ -21957,4 +22109,4 @@ var DeployEngine = class {
|
|
|
21957
22109
|
|
|
21958
22110
|
//#endregion
|
|
21959
22111
|
export { requireConfigArray as $, expectedOwnerParam as $t, green as A, withErrorHandling as An, getDockerCmd as At, slowCcOperationTimeoutMs as B, resolveAutoAssetStorage as Bt, MULTI_REGION_RECREATE_BLOCKED_TYPES as C, StackHasActiveImportsError as Cn, ensureAssetStorage as Ct, bold as D, formatError as Dn, validateContainerRepoName as Dt, formatResourceLine as E, SynthesisError as En, validateAssetBucketName as Et, clearOnUpdateRemoval as F, Synthesizer as Ft, refStateLookupFromResource as G, resolveUseCdkBootstrapAssets as Gt, isTerminationProtectionPropagationError as H, resolveSkipPrefix as Ht, ProviderRegistry as I, synthesisStatusMessage as It, resolveExplicitPhysicalId as J, CFN_TEMPLATE_BODY_LIMIT as Jt, WAFv2WebACLProvider as K, stateBucketExistenceConfirmed as Kt, findActionableSilentDrops as L, getDefaultStateBucketName as Lt, yellow as M, runDockerStreaming as Mt, IAMRoleProvider as N, AssetManifestLoader as Nt, cyan as O, isCdkdError as On, buildDockerImage as Ot, collectInlinePolicyNamesManagedBySiblings as P, getDockerImageBySourceHash as Pt, replayWarn as Q, uploadCfnTemplate as Qt, findSilentDropProperties as R, getLegacyStateBucketName as Rt, extractDeploymentEventError as S, ResourceUpdateNotSupportedError as Sn, BOOTSTRAP_MARKER_PREFIX as St, renderStatefulReason as T, StateError as Tn, parseBootstrapMarker as Tt, IntrinsicFunctionResolver as U, resolveStateBucketWithDefault as Ut, disableInstanceApiTermination as V, resolveCaptureObservedState as Vt, cfnRefValueFromPhysicalId as W, resolveStateBucketWithDefaultAndSource as Wt, configStringRefusal as X, MIGRATE_TMP_PREFIX as Xt, assertRegionMatch as Y, CFN_TEMPLATE_URL_LIMIT as Yt, readConfigString as Z, findLargeInlineResources as Zt, createPreDeleteFinalSnapshot as _, MissingCdkCliError as _n, buildAssetRedirectMap as _t, DeploymentEventsStore as a, getAwsClients as an, withRetry as at, unsupportedFinalSnapshotError as b, ProvisioningError as bn, rewriteTemplateAssetReferences as bt, replayFailedOperations as c, AssetError as cn, DagBuilder as ct, IMPLICIT_DELETE_DEPENDENCIES as d, DependencyError as dn, S3StateBackend as dt, AssemblyReader as en, requireConfigObject as et, computeImplicitDeleteEdges as f, DeployCancelledError as fn, rebuildClientForBucketRegion as ft, ccRoutedFinalSnapshotError as g, LockError as gn, WorkGraph as gt, buildFinalSnapshotIdentifier as h, LocalStartServiceError as hn, stringifyValue as ht, DeploymentEventsReader as i, AwsClients as in, describeTypeWithThrottleRetry as it, red as j, __exportAll as jn, runDockerForeground as jt, gray as k, normalizeAwsError as kn, formatDockerLoginError as kt, replayRollback as l, CdkdError as ln, TemplateParser as lt, PRE_DELETE_SNAPSHOT_TYPES as m, LocalMigrateError as mn, AssetPublisher as mt, DEFAULT_RESOURCE_WARN_AFTER_MS as n, clearBucketRegionCache as nn, applyRoleArnIfSet as nt, planFailedOps as o, resetAwsClients as on, isRetryableTransientError as ot, ATOMIC_FINAL_SNAPSHOT_TYPES as p, LocalInvokeBuildError as pn, shouldRetainResource as pt, normalizeAwsTagsToCfn as q, warnDeprecatedNoPrefixCliFlag as qt, DeployEngine as r, resolveBucketRegion as rn, DiffCalculator as rt, planRollback as s, setAwsClients as sn, isThrottlingError as st, DEFAULT_RESOURCE_TIMEOUT_MS as t, processStackMessages as tn, requireConfigString as tt, withResourceDeadline as u, ConfigError as un, LockManager as ut, isFinalSnapshotError as v, NestedStackChildDirectDestroyError as vn, createAssetRedirectResolver as vt, isStatefulRecreateTargetSync as w, StackTerminationProtectionError as wn, getBootstrapMarkerKey as wt, makeCanonicalizePropertiesFn as x, ResourceTimeoutError as xn, AssetModeResolver as xt, refusesFinalSnapshot as y, PartialFailureError as yn, loadPublishableAssetManifest as yt, CloudControlProvider as z, resolveApp as zt };
|
|
21960
|
-
//# sourceMappingURL=deploy-engine-
|
|
22112
|
+
//# sourceMappingURL=deploy-engine-Bebl98bx.js.map
|