@go-to-k/cdkd 0.252.0 → 0.252.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 +162 -41
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1888,7 +1888,7 @@ const FLUSH_INTERVAL_MS = 2e3;
|
|
|
1888
1888
|
const FLUSH_EVENT_THRESHOLD = 50;
|
|
1889
1889
|
/** Build-time cdkd version, with a dev fallback for non-built contexts. */
|
|
1890
1890
|
function getCdkdVersion() {
|
|
1891
|
-
return "0.252.
|
|
1891
|
+
return "0.252.2";
|
|
1892
1892
|
}
|
|
1893
1893
|
/**
|
|
1894
1894
|
* Generate a time-sortable unique run id, e.g.
|
|
@@ -24565,19 +24565,15 @@ var RDSDBProxyProvider = class {
|
|
|
24565
24565
|
return {
|
|
24566
24566
|
physicalId,
|
|
24567
24567
|
attributes: {
|
|
24568
|
-
DBProxyArn: proxy
|
|
24569
|
-
Endpoint: proxy
|
|
24570
|
-
VpcId: proxy
|
|
24568
|
+
...proxy?.DBProxyArn && { DBProxyArn: proxy.DBProxyArn },
|
|
24569
|
+
...proxy?.Endpoint && { Endpoint: proxy.Endpoint },
|
|
24570
|
+
...proxy?.VpcId && { VpcId: proxy.VpcId }
|
|
24571
24571
|
}
|
|
24572
24572
|
};
|
|
24573
24573
|
} catch {
|
|
24574
24574
|
return {
|
|
24575
24575
|
physicalId,
|
|
24576
|
-
attributes: {
|
|
24577
|
-
DBProxyArn: "",
|
|
24578
|
-
Endpoint: "",
|
|
24579
|
-
VpcId: ""
|
|
24580
|
-
}
|
|
24576
|
+
attributes: {}
|
|
24581
24577
|
};
|
|
24582
24578
|
}
|
|
24583
24579
|
}
|
|
@@ -24892,21 +24888,16 @@ var RDSDBProxyEndpointProvider = class {
|
|
|
24892
24888
|
return {
|
|
24893
24889
|
physicalId,
|
|
24894
24890
|
attributes: {
|
|
24895
|
-
Endpoint: ep
|
|
24896
|
-
DBProxyEndpointArn: ep
|
|
24897
|
-
IsDefault: ep
|
|
24898
|
-
VpcId: ep
|
|
24891
|
+
...ep?.Endpoint && { Endpoint: ep.Endpoint },
|
|
24892
|
+
...ep?.DBProxyEndpointArn && { DBProxyEndpointArn: ep.DBProxyEndpointArn },
|
|
24893
|
+
...ep && { IsDefault: ep.IsDefault ?? false },
|
|
24894
|
+
...ep?.VpcId && { VpcId: ep.VpcId }
|
|
24899
24895
|
}
|
|
24900
24896
|
};
|
|
24901
24897
|
} catch {
|
|
24902
24898
|
return {
|
|
24903
24899
|
physicalId,
|
|
24904
|
-
attributes: {
|
|
24905
|
-
Endpoint: "",
|
|
24906
|
-
DBProxyEndpointArn: "",
|
|
24907
|
-
IsDefault: false,
|
|
24908
|
-
VpcId: ""
|
|
24909
|
-
}
|
|
24900
|
+
attributes: {}
|
|
24910
24901
|
};
|
|
24911
24902
|
}
|
|
24912
24903
|
}
|
|
@@ -33774,13 +33765,14 @@ var SchedulerScheduleProvider = class {
|
|
|
33774
33765
|
const groupName = this.groupNameOf(properties);
|
|
33775
33766
|
this.logger.debug(`Creating Schedule ${logicalId}: ${name}${groupName ? ` (group: ${groupName})` : ""}`);
|
|
33776
33767
|
try {
|
|
33768
|
+
const response = await this.getClient().send(new CreateScheduleCommand({
|
|
33769
|
+
Name: name,
|
|
33770
|
+
...groupName && { GroupName: groupName },
|
|
33771
|
+
...this.toSdkFields(properties)
|
|
33772
|
+
}));
|
|
33777
33773
|
return {
|
|
33778
33774
|
physicalId: name,
|
|
33779
|
-
attributes: { Arn:
|
|
33780
|
-
Name: name,
|
|
33781
|
-
...groupName && { GroupName: groupName },
|
|
33782
|
-
...this.toSdkFields(properties)
|
|
33783
|
-
}))).ScheduleArn ?? "" }
|
|
33775
|
+
attributes: response.ScheduleArn ? { Arn: response.ScheduleArn } : {}
|
|
33784
33776
|
};
|
|
33785
33777
|
} catch (error) {
|
|
33786
33778
|
const cause = error instanceof Error ? error : void 0;
|
|
@@ -33798,10 +33790,11 @@ var SchedulerScheduleProvider = class {
|
|
|
33798
33790
|
...groupName && { GroupName: groupName },
|
|
33799
33791
|
...this.toSdkFields(properties)
|
|
33800
33792
|
};
|
|
33793
|
+
const response = await this.getClient().send(new UpdateScheduleCommand(input));
|
|
33801
33794
|
return {
|
|
33802
33795
|
physicalId,
|
|
33803
33796
|
wasReplaced: false,
|
|
33804
|
-
attributes: { Arn:
|
|
33797
|
+
attributes: response.ScheduleArn ? { Arn: response.ScheduleArn } : {}
|
|
33805
33798
|
};
|
|
33806
33799
|
} catch (error) {
|
|
33807
33800
|
if (error instanceof ResourceUpdateNotSupportedError) throw error;
|
|
@@ -33889,12 +33882,13 @@ var SchedulerScheduleProvider = class {
|
|
|
33889
33882
|
if (!explicit) return null;
|
|
33890
33883
|
const groupName = this.groupNameOf(input.properties);
|
|
33891
33884
|
try {
|
|
33885
|
+
const response = await this.getClient().send(new GetScheduleCommand({
|
|
33886
|
+
Name: explicit,
|
|
33887
|
+
...groupName && { GroupName: groupName }
|
|
33888
|
+
}));
|
|
33892
33889
|
return {
|
|
33893
33890
|
physicalId: explicit,
|
|
33894
|
-
attributes: { Arn:
|
|
33895
|
-
Name: explicit,
|
|
33896
|
-
...groupName && { GroupName: groupName }
|
|
33897
|
-
}))).Arn ?? "" }
|
|
33891
|
+
attributes: response.Arn ? { Arn: response.Arn } : {}
|
|
33898
33892
|
};
|
|
33899
33893
|
} catch (error) {
|
|
33900
33894
|
if (error instanceof ResourceNotFoundException$9) return null;
|
|
@@ -35555,6 +35549,38 @@ var FSxFileSystemProvider = class {
|
|
|
35555
35549
|
];
|
|
35556
35550
|
}
|
|
35557
35551
|
/**
|
|
35552
|
+
* Plain-string arrays FSx returns as unordered sets.
|
|
35553
|
+
*
|
|
35554
|
+
* - `WindowsConfiguration.Aliases` — DNS alias names (`files.example.com`).
|
|
35555
|
+
* Alternate names the file system answers to; the API documents no
|
|
35556
|
+
* ordering semantics and no name is privileged over another, so a
|
|
35557
|
+
* `DescribeFileSystems` reorder carries no meaning.
|
|
35558
|
+
*
|
|
35559
|
+
* This does not match the shared normalizer's AWS-id / ARN heuristic, so
|
|
35560
|
+
* without the declaration a reorder would surface as phantom drift. Declared
|
|
35561
|
+
* here rather than sorted in `readWindowsConfiguration` so the sort applies
|
|
35562
|
+
* to BOTH comparison sides — see
|
|
35563
|
+
* {@link ResourceProvider.getDriftUnorderedPaths}.
|
|
35564
|
+
*
|
|
35565
|
+
* Deliberately NOT declared:
|
|
35566
|
+
*
|
|
35567
|
+
* - `WindowsConfiguration.SelfManagedActiveDirectoryConfiguration.DnsIps` —
|
|
35568
|
+
* the API reference describes it only as "A list of IP addresses of DNS
|
|
35569
|
+
* servers or domain controllers in the self-managed AD directory"
|
|
35570
|
+
* (https://docs.aws.amazon.com/fsx/latest/APIReference/API_SelfManagedActiveDirectoryConfiguration.html),
|
|
35571
|
+
* with no statement that order is insignificant. DNS resolver lists are
|
|
35572
|
+
* conventionally preference-ordered (primary first), and if FSx honors
|
|
35573
|
+
* that when joining the domain, sorting would HIDE a real reorder. A
|
|
35574
|
+
* false positive is visible and correctable; silently hiding drift is
|
|
35575
|
+
* not. Same reasoning excludes ElastiCache `PreferredAvailabilityZones`.
|
|
35576
|
+
* - `OntapConfiguration.RouteTableIds` / `OpenZFSConfiguration.RouteTableIds`
|
|
35577
|
+
* — their `rtb-` elements already match the shared id heuristic.
|
|
35578
|
+
*/
|
|
35579
|
+
getDriftUnorderedPaths(resourceType) {
|
|
35580
|
+
if (resourceType !== "AWS::FSx::FileSystem") return [];
|
|
35581
|
+
return ["WindowsConfiguration.Aliases"];
|
|
35582
|
+
}
|
|
35583
|
+
/**
|
|
35558
35584
|
* Read the AWS-current file system configuration in CFn-property shape
|
|
35559
35585
|
* via `DescribeFileSystems`. Lustre data-repository fields (`ImportPath`
|
|
35560
35586
|
* / `ExportPath` / `AutoImportPolicy` / `ImportedFileChunkSize`) are
|
|
@@ -39947,7 +39973,7 @@ var DLMLifecyclePolicyProvider = class {
|
|
|
39947
39973
|
const response = await this.getClient().send(new GetLifecyclePolicyCommand$1({ PolicyId: input.knownPhysicalId }));
|
|
39948
39974
|
return response.Policy?.PolicyId ? {
|
|
39949
39975
|
physicalId: input.knownPhysicalId,
|
|
39950
|
-
attributes: { Arn: response.Policy.PolicyArn
|
|
39976
|
+
attributes: response.Policy.PolicyArn ? { Arn: response.Policy.PolicyArn } : {}
|
|
39951
39977
|
} : null;
|
|
39952
39978
|
} catch (err) {
|
|
39953
39979
|
if (err instanceof ResourceNotFoundException$12) return null;
|
|
@@ -44691,6 +44717,19 @@ function createDiffCommand() {
|
|
|
44691
44717
|
* on BOTH sides before the diff. These two passes were surfaced by dogfooding
|
|
44692
44718
|
* the sibling cdk-real-drift (cdkrd) tool, which hit the same false-positive
|
|
44693
44719
|
* classes against the same kind of AWS-snapshot baseline.
|
|
44720
|
+
*
|
|
44721
|
+
* Plain-string arrays are NOT canonicalized by the two heuristic passes above,
|
|
44722
|
+
* because a scalar list can be order-significant. But several CFn inputs are
|
|
44723
|
+
* semantically unordered sets of plain strings (FSx `WindowsConfiguration.Aliases`,
|
|
44724
|
+
* `...SelfManagedActiveDirectoryConfiguration.DnsIps`, ...), so
|
|
44725
|
+
* {@link canonicalizeUnorderedArraysAtPaths} sorts them at an explicit,
|
|
44726
|
+
* provider-declared path list only — an opt-in seam mirroring
|
|
44727
|
+
* `getDriftUnknownPaths` (see `ResourceProvider.getDriftUnorderedPaths`).
|
|
44728
|
+
* Doing it HERE rather than inside the provider's reverse-mapper is load-bearing:
|
|
44729
|
+
* the normalizer runs on BOTH comparison sides, so it stays correct for the
|
|
44730
|
+
* `properties`-fallback baseline (a resource deployed before observed-capture,
|
|
44731
|
+
* whose baseline is the user's TEMPLATE order). Sorting only the AWS read side
|
|
44732
|
+
* would manufacture drift on exactly that path.
|
|
44694
44733
|
*/
|
|
44695
44734
|
function canonicalizeTagListsDeep(v) {
|
|
44696
44735
|
if (Array.isArray(v)) {
|
|
@@ -44725,6 +44764,72 @@ function canonicalizeIdArraysDeep(v) {
|
|
|
44725
44764
|
}
|
|
44726
44765
|
return v;
|
|
44727
44766
|
}
|
|
44767
|
+
/**
|
|
44768
|
+
* Match a dotted property path against a provider-declared path list.
|
|
44769
|
+
*
|
|
44770
|
+
* An entry matches when the path is exactly equal to it, OR when the entry is
|
|
44771
|
+
* a prefix followed by `.`. Every entry is therefore a SUBTREE declaration:
|
|
44772
|
+
* `'VpcConfig'` matches `VpcConfig`, `VpcConfig.SubnetIds`, and anything
|
|
44773
|
+
* deeper. There is no leaf-only form.
|
|
44774
|
+
*
|
|
44775
|
+
* Shared by the two provider-declared path lists so their semantics cannot
|
|
44776
|
+
* drift apart: `getDriftUnknownPaths` (via `isIgnoredPath` in
|
|
44777
|
+
* `drift-calculator.ts`) and `getDriftUnorderedPaths` (via
|
|
44778
|
+
* {@link canonicalizeUnorderedArraysAtPaths} below).
|
|
44779
|
+
*/
|
|
44780
|
+
function matchesPathPrefix(path, entries) {
|
|
44781
|
+
for (const entry of entries) {
|
|
44782
|
+
if (path === entry) return true;
|
|
44783
|
+
if (path.startsWith(`${entry}.`)) return true;
|
|
44784
|
+
}
|
|
44785
|
+
return false;
|
|
44786
|
+
}
|
|
44787
|
+
/**
|
|
44788
|
+
* Sort plain-string arrays found at one of the provider-declared `paths`, and
|
|
44789
|
+
* ONLY there. Unlike the two heuristic passes above, this one is opt-in per
|
|
44790
|
+
* resource type via `ResourceProvider.getDriftUnorderedPaths` — a scalar list
|
|
44791
|
+
* is order-significant unless the provider says otherwise.
|
|
44792
|
+
*
|
|
44793
|
+
* Paths use dot-notation for nested keys and are matched by the shared
|
|
44794
|
+
* {@link matchesPathPrefix} rule, the same one `getDriftUnknownPaths` uses. So
|
|
44795
|
+
* `'WindowsConfiguration'` covers every plain-string array in that subtree, and
|
|
44796
|
+
* `'WindowsConfiguration.Aliases'` covers that path and everything beneath it
|
|
44797
|
+
* (every entry is a subtree declaration — there is no leaf-only form).
|
|
44798
|
+
*
|
|
44799
|
+
* One semantic DIVERGENCE from `getDriftUnknownPaths`, required for this pass
|
|
44800
|
+
* to work: `isIgnoredPath` never sees a path that crosses an array, because the
|
|
44801
|
+
* comparator's `diffAt` compares arrays wholesale via `deepEqual` and never
|
|
44802
|
+
* descends into elements. This walk DOES descend into array elements, giving
|
|
44803
|
+
* each element its parent's path (array indices never appear in paths). So
|
|
44804
|
+
* `'Items.Aliases'` is meaningful here — it reaches an `Aliases` array inside
|
|
44805
|
+
* each element of `Items` — while being inert as an ignore-path. The divergence
|
|
44806
|
+
* is strictly more permissive; nothing that matches for ignore-paths fails to
|
|
44807
|
+
* match here.
|
|
44808
|
+
*
|
|
44809
|
+
* Only arrays whose every element is a plain string are sorted, so a
|
|
44810
|
+
* mis-declared path can never reorder object or mixed-type elements. Nested
|
|
44811
|
+
* arrays are also left alone: an array element that is itself an array is not
|
|
44812
|
+
* descended into, so `{P: [['b','a']]}` never has its INNER list sorted by a
|
|
44813
|
+
* `'P'` declaration (no CFn shape in tree is an array-of-arrays, and sorting
|
|
44814
|
+
* one would contradict the plain-string-elements-only rule).
|
|
44815
|
+
*/
|
|
44816
|
+
function canonicalizeUnorderedArraysAtPaths(v, paths) {
|
|
44817
|
+
if (paths.length === 0) return v;
|
|
44818
|
+
return walkUnordered(v, "", paths);
|
|
44819
|
+
}
|
|
44820
|
+
function walkUnordered(v, path, paths) {
|
|
44821
|
+
if (Array.isArray(v)) {
|
|
44822
|
+
const mapped = v.map((el) => Array.isArray(el) ? el : walkUnordered(el, path, paths));
|
|
44823
|
+
if (mapped.length > 1 && matchesPathPrefix(path, paths) && mapped.every((el) => typeof el === "string")) return [...mapped].sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
|
|
44824
|
+
return mapped;
|
|
44825
|
+
}
|
|
44826
|
+
if (v && typeof v === "object") {
|
|
44827
|
+
const out = {};
|
|
44828
|
+
for (const [k, val] of Object.entries(v)) out[k] = walkUnordered(val, path === "" ? k : `${path}.${k}`, paths);
|
|
44829
|
+
return out;
|
|
44830
|
+
}
|
|
44831
|
+
return v;
|
|
44832
|
+
}
|
|
44728
44833
|
|
|
44729
44834
|
//#endregion
|
|
44730
44835
|
//#region src/analyzer/drift-calculator.ts
|
|
@@ -44784,25 +44889,35 @@ function canonicalizeIdArraysDeep(v) {
|
|
|
44784
44889
|
* it is exactly equal to the entry, or when the entry is a prefix followed
|
|
44785
44890
|
* by `.` — so `'Code'` excludes the whole `Code` subtree, and
|
|
44786
44891
|
* `'VpcConfig.SubnetIds'` excludes only that leaf.
|
|
44892
|
+
*
|
|
44893
|
+
* `options.unorderedPaths` is supplied by the provider (via
|
|
44894
|
+
* `getDriftUnorderedPaths`) for plain-string arrays that are semantically
|
|
44895
|
+
* UNORDERED sets — e.g. FSx `WindowsConfiguration.Aliases`. Those are sorted on
|
|
44896
|
+
* BOTH sides before comparison so an AWS-side reorder is not phantom drift.
|
|
44897
|
+
* Path matching uses the same prefix rule as `ignorePaths`.
|
|
44787
44898
|
*/
|
|
44788
44899
|
function calculateResourceDrift(stateProperties, awsProperties, options) {
|
|
44789
44900
|
const drifts = [];
|
|
44790
44901
|
const ignore = options?.ignorePaths ?? [];
|
|
44791
44902
|
const union = options?.unionWalkObjects ?? false;
|
|
44792
|
-
|
|
44793
|
-
|
|
44903
|
+
const unordered = options?.unorderedPaths ?? [];
|
|
44904
|
+
stateProperties = canonicalizeUnorderedArraysAtPaths(canonicalizeIdArraysDeep(canonicalizeTagListsDeep(stateProperties)), unordered);
|
|
44905
|
+
awsProperties = canonicalizeUnorderedArraysAtPaths(canonicalizeIdArraysDeep(canonicalizeTagListsDeep(awsProperties)), unordered);
|
|
44794
44906
|
for (const key of Object.keys(stateProperties)) {
|
|
44795
44907
|
if (isIgnoredPath(key, ignore)) continue;
|
|
44796
44908
|
diffAt(key, stateProperties[key], awsProperties[key], drifts, ignore, union);
|
|
44797
44909
|
}
|
|
44798
44910
|
return drifts;
|
|
44799
44911
|
}
|
|
44912
|
+
/**
|
|
44913
|
+
* Thin alias over the shared {@link matchesPathPrefix} rule, kept as a named
|
|
44914
|
+
* function because "ignored" is what the path list means at these call sites.
|
|
44915
|
+
* Sharing the implementation with `getDriftUnorderedPaths` is deliberate: both
|
|
44916
|
+
* lists are provider-declared and documented as reading the same way, so they
|
|
44917
|
+
* must not be able to drift apart.
|
|
44918
|
+
*/
|
|
44800
44919
|
function isIgnoredPath(path, ignorePaths) {
|
|
44801
|
-
|
|
44802
|
-
if (path === entry) return true;
|
|
44803
|
-
if (path.startsWith(`${entry}.`)) return true;
|
|
44804
|
-
}
|
|
44805
|
-
return false;
|
|
44920
|
+
return matchesPathPrefix(path, ignorePaths);
|
|
44806
44921
|
}
|
|
44807
44922
|
/**
|
|
44808
44923
|
* Recursive worker. Pushes drift entries into `out` rather than
|
|
@@ -45204,10 +45319,12 @@ async function runDriftForStack(stackName, region, stateBackend, providerRegistr
|
|
|
45204
45319
|
continue;
|
|
45205
45320
|
}
|
|
45206
45321
|
const ignorePaths = provider.getDriftUnknownPaths ? provider.getDriftUnknownPaths(resource.resourceType) : [];
|
|
45322
|
+
const unorderedPaths = provider.getDriftUnorderedPaths ? provider.getDriftUnorderedPaths(resource.resourceType) : [];
|
|
45207
45323
|
const useObserved = resource.observedProperties !== void 0;
|
|
45208
45324
|
const changes = calculateResourceDrift(useObserved ? resource.observedProperties : resource.properties ?? {}, aws, {
|
|
45209
45325
|
ignorePaths,
|
|
45210
|
-
unionWalkObjects: useObserved
|
|
45326
|
+
unionWalkObjects: useObserved,
|
|
45327
|
+
unorderedPaths
|
|
45211
45328
|
});
|
|
45212
45329
|
if (changes.length === 0) outcomes.push({
|
|
45213
45330
|
kind: "clean",
|
|
@@ -51901,7 +52018,8 @@ async function importOne(task) {
|
|
|
51901
52018
|
logicalId,
|
|
51902
52019
|
resourceType: resource.Type,
|
|
51903
52020
|
outcome: "imported",
|
|
51904
|
-
physicalId: result.physicalId
|
|
52021
|
+
physicalId: result.physicalId,
|
|
52022
|
+
...result.attributes !== void 0 && { attributes: result.attributes }
|
|
51905
52023
|
};
|
|
51906
52024
|
} catch (error) {
|
|
51907
52025
|
const msg = error instanceof Error ? error.message : String(error);
|
|
@@ -52044,11 +52162,14 @@ function buildStackState(stackName, region, rows, templateParser, template, exis
|
|
|
52044
52162
|
const tmplResource = template.Resources[row.logicalId];
|
|
52045
52163
|
if (!tmplResource) continue;
|
|
52046
52164
|
const deps = [...templateParser.extractDependencies(tmplResource)].filter((dep) => !parameterNames.has(dep));
|
|
52165
|
+
const prior = existingState?.resources[row.logicalId];
|
|
52166
|
+
const priorAttributes = prior && prior.physicalId === row.physicalId ? prior.attributes : void 0;
|
|
52167
|
+
const rowAttributes = row.attributes && Object.keys(row.attributes).length > 0 ? row.attributes : void 0;
|
|
52047
52168
|
resources[row.logicalId] = {
|
|
52048
52169
|
physicalId: row.physicalId,
|
|
52049
52170
|
resourceType: row.resourceType,
|
|
52050
52171
|
properties: tmplResource.Properties ?? {},
|
|
52051
|
-
attributes: {},
|
|
52172
|
+
attributes: rowAttributes ?? priorAttributes ?? {},
|
|
52052
52173
|
dependencies: deps,
|
|
52053
52174
|
provisionedBy: "sdk"
|
|
52054
52175
|
};
|
|
@@ -62017,7 +62138,7 @@ function reorderArgs(argv) {
|
|
|
62017
62138
|
async function main() {
|
|
62018
62139
|
installPipeCloseHandler();
|
|
62019
62140
|
const program = new Command();
|
|
62020
|
-
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.252.
|
|
62141
|
+
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.252.2");
|
|
62021
62142
|
program.addCommand(createBootstrapCommand());
|
|
62022
62143
|
program.addCommand(createSynthCommand());
|
|
62023
62144
|
program.addCommand(createListCommand());
|