@go-to-k/cdkd 0.207.0 → 0.207.2
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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { a as setAwsClients, i as resetAwsClients, r as getAwsClients, t as AwsClients } from "./aws-clients-DWUnLza1.js";
|
|
3
|
-
import { $ as
|
|
3
|
+
import { $ as findLargeInlineResources, A as LockManager, At as getLiveRenderer, B as runDockerStreaming, C as CloudControlProvider, D as DiffCalculator, Dt as getLogger, E as applyRoleArnIfSet, F as WorkGraph, Ft as withSkipPrefix, G as resolveCaptureObservedState, H as getDefaultStateBucketName, I as buildDockerImage, It as withStackName, J as resolveStateBucketWithDefaultAndSource, K as resolveSkipPrefix, L as formatDockerLoginError, M as shouldRetainResource, Mt as PATTERN_B_RESOURCE_TYPES, N as AssetPublisher, Nt as generateResourceName, O as DagBuilder, P as stringifyValue, Pt as generateResourceNameWithFallback, Q as MIGRATE_TMP_PREFIX, R as getDockerCmd, S as findActionableSilentDrops, T as IntrinsicFunctionResolver, Tt as withErrorHandling, U as getLegacyStateBucketName, V as Synthesizer, W as resolveApp, X as CFN_TEMPLATE_BODY_LIMIT, Y as warnDeprecatedNoPrefixCliFlag, Z as CFN_TEMPLATE_URL_LIMIT, _ as CDK_PATH_TAG, _t as ResourceUpdateNotSupportedError, a as withRetry, at as CdkdError, b as resolveExplicitPhysicalId, c as formatResourceLine, ct as LocalInvokeBuildError$1, d as gray, et as uploadCfnTemplate, f as green, ft as MissingCdkCliError, g as collectInlinePolicyNamesManagedBySiblings, gt as ResourceTimeoutError, h as IAMRoleProvider, ht as ProvisioningError, i as withResourceDeadline, j as S3StateBackend, jt as PATTERN_B_NAME_PROPERTIES, k as TemplateParser, kt as runStackBuffered, l as bold, lt as LocalMigrateError, m as yellow, mt as PartialFailureError, n as DEFAULT_RESOURCE_WARN_AFTER_MS, o as isRetryableTransientError, p as red, pt as NestedStackChildDirectDestroyError, q as resolveStateBucketWithDefault, r as DeployEngine, rt as resolveBucketRegion, s as IMPLICIT_DELETE_DEPENDENCIES, t as DEFAULT_RESOURCE_TIMEOUT_MS, tt as AssemblyReader, u as cyan, ut as LocalStartServiceError, v as matchesCdkPath, vt as StackHasActiveImportsError, w as assertRegionMatch, wt as normalizeAwsError, x as ProviderRegistry, y as normalizeAwsTagsToCfn, yt as StackTerminationProtectionError, z as runDockerForeground } from "./deploy-engine-DQzo06ax.js";
|
|
4
4
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
5
5
|
import { randomBytes, randomUUID } from "node:crypto";
|
|
6
6
|
import { CopyObjectCommand, CreateBucketCommand, DeleteBucketAnalyticsConfigurationCommand, DeleteBucketCommand, DeleteBucketCorsCommand, DeleteBucketIntelligentTieringConfigurationCommand, DeleteBucketInventoryConfigurationCommand, DeleteBucketLifecycleCommand, DeleteBucketMetricsConfigurationCommand, DeleteBucketPolicyCommand, DeleteBucketReplicationCommand, DeleteBucketTaggingCommand, DeleteBucketWebsiteCommand, DeleteObjectsCommand, GetBucketAccelerateConfigurationCommand, GetBucketCorsCommand, GetBucketEncryptionCommand, GetBucketLifecycleConfigurationCommand, GetBucketLocationCommand, GetBucketLoggingCommand, GetBucketNotificationConfigurationCommand, GetBucketPolicyCommand, GetBucketReplicationCommand, GetBucketTaggingCommand, GetBucketVersioningCommand, GetBucketWebsiteCommand, GetObjectCommand, GetObjectLockConfigurationCommand, GetPublicAccessBlockCommand, HeadBucketCommand, ListBucketAnalyticsConfigurationsCommand, ListBucketIntelligentTieringConfigurationsCommand, ListBucketInventoryConfigurationsCommand, ListBucketMetricsConfigurationsCommand, ListBucketsCommand, ListDirectoryBucketsCommand, 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";
|
|
@@ -1857,6 +1857,95 @@ var ExportIndexStore = class {
|
|
|
1857
1857
|
}
|
|
1858
1858
|
};
|
|
1859
1859
|
|
|
1860
|
+
//#endregion
|
|
1861
|
+
//#region src/analyzer/cross-stack-deps.ts
|
|
1862
|
+
/**
|
|
1863
|
+
* Infer cross-stack ordering edges that CDK's manifest dependency graph
|
|
1864
|
+
* (`stack.dependencyNames`, surfaced from `addDependency`) does NOT capture.
|
|
1865
|
+
*
|
|
1866
|
+
* Two stacks can be linked by a RAW cross-stack reference —
|
|
1867
|
+
* `cdk.Fn.importValue('<exportName>')` (→ `Fn::ImportValue`) or
|
|
1868
|
+
* `Fn::GetStackOutput` — WITHOUT an explicit `addDependency`. CDK only emits a
|
|
1869
|
+
* manifest dependency when the reference goes through its own
|
|
1870
|
+
* `exportValue` / strong-reference machinery; a hand-written
|
|
1871
|
+
* `Fn.importValue` of a literal export name produces no manifest edge. Under
|
|
1872
|
+
* concurrent `--all` deploys that lets the consumer race ahead of the
|
|
1873
|
+
* producer and fail (`export not found` / `stack not found`); on `--all`
|
|
1874
|
+
* destroy it lets the producer be deleted while a consumer still imports it.
|
|
1875
|
+
*
|
|
1876
|
+
* This helper closes that gap by scanning the synthesized templates directly
|
|
1877
|
+
* (NOT the runtime S3 export index, which is empty on a fresh multi-stack
|
|
1878
|
+
* deploy). It returns, per consumer stackName, the set of OTHER stackNames in
|
|
1879
|
+
* the SAME input set that it depends on (consumer → producer edges).
|
|
1880
|
+
*
|
|
1881
|
+
* Rules (mirroring deploy.ts's existing `if (stackMap.has(depName))` guard):
|
|
1882
|
+
* - Edges are only added between stacks BOTH present in the input set. A
|
|
1883
|
+
* producer outside the set = no edge — its export resolves at runtime from
|
|
1884
|
+
* already-deployed state, which is correct.
|
|
1885
|
+
* - `Fn::ImportValue` with a literal-string export name matches against the
|
|
1886
|
+
* `Export.Name` of every OTHER stack's outputs. An import whose export name
|
|
1887
|
+
* no stack in the set produces (external / pre-existing export) is ignored.
|
|
1888
|
+
* - `Fn::GetStackOutput`'s `StackName` argument names the producer stack
|
|
1889
|
+
* DIRECTLY (the intrinsic arg is an object `{ StackName, OutputName,
|
|
1890
|
+
* Region?, RoleArn? }` — see
|
|
1891
|
+
* `src/deployment/intrinsic-function-resolver.ts`). If that stack is in the
|
|
1892
|
+
* set, add the edge.
|
|
1893
|
+
* - Non-literal `Fn::ImportValue` / `Fn::GetStackOutput` args (intrinsic
|
|
1894
|
+
* nesting, etc.) are skipped without crashing — they cannot be statically
|
|
1895
|
+
* resolved to a producer stack name here.
|
|
1896
|
+
*
|
|
1897
|
+
* @param stacks the stacks being deployed / destroyed together (the `--all`
|
|
1898
|
+
* set, or the auto-include-dependency-expanded target set).
|
|
1899
|
+
* @returns Map<consumerStackName, Set<producerStackName>>. Consumers with no
|
|
1900
|
+
* inferred cross-stack producer get an empty set entry.
|
|
1901
|
+
*/
|
|
1902
|
+
function inferCrossStackStackDeps(stacks) {
|
|
1903
|
+
const exportOwner = /* @__PURE__ */ new Map();
|
|
1904
|
+
for (const stack of stacks) {
|
|
1905
|
+
const outputs = stack.template.Outputs;
|
|
1906
|
+
if (!outputs) continue;
|
|
1907
|
+
for (const output of Object.values(outputs)) {
|
|
1908
|
+
const name = output?.Export?.Name;
|
|
1909
|
+
if (typeof name === "string" && name !== "") {
|
|
1910
|
+
if (!exportOwner.has(name)) exportOwner.set(name, stack.stackName);
|
|
1911
|
+
}
|
|
1912
|
+
}
|
|
1913
|
+
}
|
|
1914
|
+
const stackNames = new Set(stacks.map((s) => s.stackName));
|
|
1915
|
+
const result = /* @__PURE__ */ new Map();
|
|
1916
|
+
for (const stack of stacks) {
|
|
1917
|
+
const producers = /* @__PURE__ */ new Set();
|
|
1918
|
+
collectCrossStackRefs(stack.template, (kind, value) => {
|
|
1919
|
+
let producer;
|
|
1920
|
+
if (kind === "ImportValue") {
|
|
1921
|
+
if (typeof value === "string") producer = exportOwner.get(value);
|
|
1922
|
+
} else if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
1923
|
+
const sn = value["StackName"];
|
|
1924
|
+
if (typeof sn === "string") producer = sn;
|
|
1925
|
+
}
|
|
1926
|
+
if (producer && producer !== stack.stackName && stackNames.has(producer)) producers.add(producer);
|
|
1927
|
+
});
|
|
1928
|
+
result.set(stack.stackName, producers);
|
|
1929
|
+
}
|
|
1930
|
+
return result;
|
|
1931
|
+
}
|
|
1932
|
+
/**
|
|
1933
|
+
* Recursively walk a template node, invoking `onRef` for every
|
|
1934
|
+
* `Fn::ImportValue` / `Fn::GetStackOutput` intrinsic encountered. The
|
|
1935
|
+
* callback receives the discriminator and the raw (unresolved) argument.
|
|
1936
|
+
*/
|
|
1937
|
+
function collectCrossStackRefs(node, onRef) {
|
|
1938
|
+
if (!node || typeof node !== "object") return;
|
|
1939
|
+
if (Array.isArray(node)) {
|
|
1940
|
+
for (const item of node) collectCrossStackRefs(item, onRef);
|
|
1941
|
+
return;
|
|
1942
|
+
}
|
|
1943
|
+
const obj = node;
|
|
1944
|
+
if ("Fn::ImportValue" in obj) onRef("ImportValue", obj["Fn::ImportValue"]);
|
|
1945
|
+
if ("Fn::GetStackOutput" in obj) onRef("GetStackOutput", obj["Fn::GetStackOutput"]);
|
|
1946
|
+
for (const value of Object.values(obj)) collectCrossStackRefs(value, onRef);
|
|
1947
|
+
}
|
|
1948
|
+
|
|
1860
1949
|
//#endregion
|
|
1861
1950
|
//#region src/provisioning/providers/iam-policy-provider.ts
|
|
1862
1951
|
/**
|
|
@@ -33930,7 +34019,7 @@ async function runDestroyForStack(stackName, state, ctx) {
|
|
|
33930
34019
|
} catch (retryError) {
|
|
33931
34020
|
lastDeleteError = retryError;
|
|
33932
34021
|
const msg = retryError instanceof Error ? retryError.message : String(retryError);
|
|
33933
|
-
if (!(
|
|
34022
|
+
if (!(isRetryableTransientError(retryError, msg) || msg.includes("Too Many Requests")) || attempt >= maxAttempts) break;
|
|
33934
34023
|
const delay = 5e3 * Math.pow(2, attempt);
|
|
33935
34024
|
logger.debug(` ⏳ Retrying delete ${logicalId} in ${delay / 1e3}s (attempt ${attempt + 1}/${maxAttempts})`);
|
|
33936
34025
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
@@ -34961,13 +35050,19 @@ async function deployCommand(stacks, options) {
|
|
|
34961
35050
|
else if (allStacks.length === 1) targetStacks = allStacks;
|
|
34962
35051
|
else throw new Error(`Multiple stacks found: ${allStacks.map(describeStack).join(", ")}. Specify stack name(s) or use --all`);
|
|
34963
35052
|
if (targetStacks.length === 0) throw new Error(stackPatterns.length > 0 ? `No stacks matching ${stackPatterns.join(", ")} found in assembly. Available: ${allStacks.map(describeStack).join(", ")}` : "No stacks found in assembly");
|
|
35053
|
+
const inferredCrossStackDeps = inferCrossStackStackDeps(allStacks);
|
|
35054
|
+
const effectiveStackDeps = (stackName, deps) => {
|
|
35055
|
+
const union = new Set(deps);
|
|
35056
|
+
for (const producer of inferredCrossStackDeps.get(stackName) ?? []) union.add(producer);
|
|
35057
|
+
return union;
|
|
35058
|
+
};
|
|
34964
35059
|
if (!options.exclusively) {
|
|
34965
35060
|
const targetNames = new Set(targetStacks.map((s) => s.stackName));
|
|
34966
35061
|
const allStackMap = new Map(allStacks.map((s) => [s.stackName, s]));
|
|
34967
35062
|
const addDependencies = (stackName) => {
|
|
34968
35063
|
const stack = allStackMap.get(stackName);
|
|
34969
35064
|
if (!stack) return;
|
|
34970
|
-
for (const depName of stack.dependencyNames) if (!targetNames.has(depName)) {
|
|
35065
|
+
for (const depName of effectiveStackDeps(stackName, stack.dependencyNames)) if (!targetNames.has(depName)) {
|
|
34971
35066
|
const depStack = allStackMap.get(depName);
|
|
34972
35067
|
if (depStack) {
|
|
34973
35068
|
targetNames.add(depName);
|
|
@@ -35012,7 +35107,7 @@ async function deployCommand(stacks, options) {
|
|
|
35012
35107
|
} catch (error) {
|
|
35013
35108
|
if (error.code !== "ENOENT") throw error;
|
|
35014
35109
|
}
|
|
35015
|
-
for (const depName of stack.dependencyNames) if (stackMap.has(depName)) stackDeps.add(`stack:${depName}`);
|
|
35110
|
+
for (const depName of effectiveStackDeps(stack.stackName, stack.dependencyNames)) if (stackMap.has(depName)) stackDeps.add(`stack:${depName}`);
|
|
35016
35111
|
workGraph.addNode({
|
|
35017
35112
|
id: stackNodeId,
|
|
35018
35113
|
type: "stack",
|
|
@@ -37369,6 +37464,39 @@ function createDriftCommand() {
|
|
|
37369
37464
|
//#endregion
|
|
37370
37465
|
//#region src/cli/commands/destroy.ts
|
|
37371
37466
|
/**
|
|
37467
|
+
* Topologically order `stackNames` so that every consumer is destroyed BEFORE
|
|
37468
|
+
* its producers. `consumerToProducers` maps consumer → set of producer stack
|
|
37469
|
+
* names (the deploy-direction edges from `inferCrossStackStackDeps`); destroy
|
|
37470
|
+
* is the reverse, so a stack must appear before all of its producers.
|
|
37471
|
+
*
|
|
37472
|
+
* Kahn-style with a deterministic tie-break: among nodes currently free to be
|
|
37473
|
+
* emitted (no remaining unemitted consumer pointing at them), pick the one
|
|
37474
|
+
* earliest in the original `stackNames` order so the output is stable and the
|
|
37475
|
+
* original order is preserved whenever there are no cross-stack edges. A cycle
|
|
37476
|
+
* (should not happen for valid templates) degrades gracefully — any leftover
|
|
37477
|
+
* nodes are appended in original order rather than dropped.
|
|
37478
|
+
*/
|
|
37479
|
+
function orderConsumersBeforeProducers(stackNames, consumerToProducers) {
|
|
37480
|
+
const pendingConsumers = /* @__PURE__ */ new Map();
|
|
37481
|
+
for (const name of stackNames) pendingConsumers.set(name, /* @__PURE__ */ new Set());
|
|
37482
|
+
for (const [consumer, producers] of consumerToProducers) for (const producer of producers) pendingConsumers.get(producer)?.add(consumer);
|
|
37483
|
+
const emitted = /* @__PURE__ */ new Set();
|
|
37484
|
+
const ordered = [];
|
|
37485
|
+
while (ordered.length < stackNames.length) {
|
|
37486
|
+
const next = stackNames.find((name) => !emitted.has(name) && [...pendingConsumers.get(name) ?? []].every((c) => emitted.has(c)));
|
|
37487
|
+
if (!next) {
|
|
37488
|
+
for (const name of stackNames) if (!emitted.has(name)) {
|
|
37489
|
+
emitted.add(name);
|
|
37490
|
+
ordered.push(name);
|
|
37491
|
+
}
|
|
37492
|
+
break;
|
|
37493
|
+
}
|
|
37494
|
+
emitted.add(next);
|
|
37495
|
+
ordered.push(next);
|
|
37496
|
+
}
|
|
37497
|
+
return ordered;
|
|
37498
|
+
}
|
|
37499
|
+
/**
|
|
37372
37500
|
* Destroy command implementation
|
|
37373
37501
|
*/
|
|
37374
37502
|
async function destroyCommand(stackArgs, options) {
|
|
@@ -37414,21 +37542,27 @@ async function destroyCommand(stackArgs, options) {
|
|
|
37414
37542
|
if (options.allowUnsupportedTypes?.length) providerRegistry.allowUnsupportedTypes(options.allowUnsupportedTypes);
|
|
37415
37543
|
const appCmd = options.app || resolveApp();
|
|
37416
37544
|
let appStacks = [];
|
|
37545
|
+
let synthScanStacks = [];
|
|
37417
37546
|
if (appCmd) try {
|
|
37418
37547
|
const synthesizer = new Synthesizer();
|
|
37419
37548
|
const context = parseContextOptions(options.context);
|
|
37420
|
-
|
|
37549
|
+
const result = await synthesizer.synthesize({
|
|
37421
37550
|
app: appCmd,
|
|
37422
37551
|
output: options.output || "cdk.out",
|
|
37423
37552
|
...Object.keys(context).length > 0 && { context },
|
|
37424
37553
|
stateBucket,
|
|
37425
37554
|
...options.profile && { macroExpandS3ClientOpts: { profile: options.profile } }
|
|
37426
|
-
})
|
|
37555
|
+
});
|
|
37556
|
+
appStacks = result.stacks.map((s) => ({
|
|
37427
37557
|
stackName: s.stackName,
|
|
37428
37558
|
displayName: s.displayName,
|
|
37429
37559
|
...s.region && { region: s.region },
|
|
37430
37560
|
...s.terminationProtection !== void 0 && { terminationProtection: s.terminationProtection }
|
|
37431
37561
|
}));
|
|
37562
|
+
synthScanStacks = result.stacks.map((s) => ({
|
|
37563
|
+
stackName: s.stackName,
|
|
37564
|
+
template: s.template
|
|
37565
|
+
}));
|
|
37432
37566
|
} catch {
|
|
37433
37567
|
logger.debug("Could not synthesize app, falling back to state-based stack list");
|
|
37434
37568
|
}
|
|
@@ -37475,6 +37609,11 @@ async function destroyCommand(stackArgs, options) {
|
|
|
37475
37609
|
logger.info("No matching stacks found in state");
|
|
37476
37610
|
return;
|
|
37477
37611
|
}
|
|
37612
|
+
if (synthScanStacks.length > 0 && stackNames.length > 1) {
|
|
37613
|
+
const inSet = new Set(stackNames);
|
|
37614
|
+
const inferred = inferCrossStackStackDeps(synthScanStacks.filter((s) => inSet.has(s.stackName)));
|
|
37615
|
+
stackNames = orderConsumersBeforeProducers(stackNames, inferred);
|
|
37616
|
+
}
|
|
37478
37617
|
logger.info(`Found ${stackNames.length} stack(s) to destroy: ${stackNames.join(", ")}`);
|
|
37479
37618
|
const accountId = "unknown";
|
|
37480
37619
|
const stateRefsByName = /* @__PURE__ */ new Map();
|
|
@@ -52557,7 +52696,7 @@ function reorderArgs(argv) {
|
|
|
52557
52696
|
*/
|
|
52558
52697
|
async function main() {
|
|
52559
52698
|
const program = new Command();
|
|
52560
|
-
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.207.
|
|
52699
|
+
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.207.2");
|
|
52561
52700
|
program.addCommand(createBootstrapCommand());
|
|
52562
52701
|
program.addCommand(createSynthCommand());
|
|
52563
52702
|
program.addCommand(createListCommand());
|