@go-to-k/cdkd 0.260.5 → 0.260.7
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 +158 -14
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1901,7 +1901,7 @@ const FLUSH_INTERVAL_MS = 2e3;
|
|
|
1901
1901
|
const FLUSH_EVENT_THRESHOLD = 50;
|
|
1902
1902
|
/** Build-time cdkd version, with a dev fallback for non-built contexts. */
|
|
1903
1903
|
function getCdkdVersion() {
|
|
1904
|
-
return "0.260.
|
|
1904
|
+
return "0.260.7";
|
|
1905
1905
|
}
|
|
1906
1906
|
/**
|
|
1907
1907
|
* Generate a time-sortable unique run id, e.g.
|
|
@@ -21875,6 +21875,22 @@ const DEPLOYMENT_CONFIG_PRESERVE_KEYS = /* @__PURE__ */ new Set(["HookDetails"])
|
|
|
21875
21875
|
*/
|
|
21876
21876
|
const DEPLOYMENT_CONFIG_PRESERVE_KEYS_CAMEL = /* @__PURE__ */ new Set(["hookDetails"]);
|
|
21877
21877
|
/**
|
|
21878
|
+
* Derive the cluster name from a long-format ECS Service ARN
|
|
21879
|
+
* (`arn:<partition>:ecs:<region>:<account>:service/<clusterName>/<serviceName>`)
|
|
21880
|
+
* so `DescribeServices` can be scoped to the right cluster (issue #1170).
|
|
21881
|
+
* Returns `undefined` for the legacy short-format ARN
|
|
21882
|
+
* (`.../service/<serviceName>`, which does not encode a cluster) or any input
|
|
21883
|
+
* that does not match the ARN shape — the caller then falls back to the default
|
|
21884
|
+
* cluster, matching what the short-format ARN implies.
|
|
21885
|
+
*/
|
|
21886
|
+
function clusterNameFromServiceArn(arn) {
|
|
21887
|
+
const resource = arn.split(":")[5];
|
|
21888
|
+
if (!resource) return void 0;
|
|
21889
|
+
const segments = resource.split("/");
|
|
21890
|
+
if (segments[0] !== "service") return void 0;
|
|
21891
|
+
return segments.length >= 3 ? segments[1] : void 0;
|
|
21892
|
+
}
|
|
21893
|
+
/**
|
|
21878
21894
|
* AWS ECS Provider
|
|
21879
21895
|
*
|
|
21880
21896
|
* Implements resource provisioning for ECS resources:
|
|
@@ -22277,7 +22293,10 @@ var ECSProvider = class {
|
|
|
22277
22293
|
}
|
|
22278
22294
|
}
|
|
22279
22295
|
async getServiceAttribute(physicalId, attributeName) {
|
|
22280
|
-
const service = (await this.getClient().send(new DescribeServicesCommand({
|
|
22296
|
+
const service = (await this.getClient().send(new DescribeServicesCommand({
|
|
22297
|
+
cluster: clusterNameFromServiceArn(physicalId),
|
|
22298
|
+
services: [physicalId]
|
|
22299
|
+
}))).services?.[0];
|
|
22281
22300
|
if (!service) return void 0;
|
|
22282
22301
|
switch (attributeName) {
|
|
22283
22302
|
case "ServiceArn": return service.serviceArn;
|
|
@@ -22676,6 +22695,123 @@ var ECSProvider = class {
|
|
|
22676
22695
|
return out;
|
|
22677
22696
|
}
|
|
22678
22697
|
/**
|
|
22698
|
+
* Reverse of `convertContainerDefinitions` for `readCurrentState` (issue
|
|
22699
|
+
* #1169). Emits CFn PascalCase so the drift baseline (state `properties`
|
|
22700
|
+
* PascalCase, or `observedProperties` captured via this same reader) compares
|
|
22701
|
+
* apples-to-apples instead of phantom-drifting on the whole array — the drift
|
|
22702
|
+
* comparator compares arrays wholesale via `deepEqual`, so the previous raw
|
|
22703
|
+
* SDK camelCase read (`result['ContainerDefinitions'] = td.containerDefinitions`)
|
|
22704
|
+
* never matched a PascalCase baseline.
|
|
22705
|
+
*
|
|
22706
|
+
* Two rules keep the read side matching a template that omits AWS's defaults:
|
|
22707
|
+
* 1. Only the fields `convertContainerDefinitions` can SET are emitted, so
|
|
22708
|
+
* the round-trip is symmetric — a field cdkd cannot set is never surfaced
|
|
22709
|
+
* as drift against a template that lacks it.
|
|
22710
|
+
* 2. AWS-defaulted-empty divergences are normalized away — `Cpu: 0`, empty
|
|
22711
|
+
* arrays (`PortMappings` / `Environment` / ...), and an empty
|
|
22712
|
+
* `LinuxParameters.Capabilities: {Add:[],Drop:[]}` are dropped so they
|
|
22713
|
+
* equal "absent" (what the template has). AWS returns these defaults on
|
|
22714
|
+
* EVERY read, so without this the `properties` fallback baseline
|
|
22715
|
+
* (pre-observedProperties state) would phantom-drift on every run; the
|
|
22716
|
+
* normalization trades that for a rare edge — a template that EXPLICITLY
|
|
22717
|
+
* sets one of these to its empty/zero default AND has no observed baseline
|
|
22718
|
+
* (CDK L2 never emits e.g. an explicit `Cpu: 0`). On the normal
|
|
22719
|
+
* `observedProperties` path both sides run through this reader, so the
|
|
22720
|
+
* snapshot is self-consistent regardless.
|
|
22721
|
+
*
|
|
22722
|
+
* Free-form maps (`DockerLabels`, `LogConfiguration.Options`) are copied
|
|
22723
|
+
* verbatim — their keys are user data (log-driver options / container labels),
|
|
22724
|
+
* NOT CFn property names, so they must not be case-flipped.
|
|
22725
|
+
*/
|
|
22726
|
+
containerDefinitionsToCfn(defs) {
|
|
22727
|
+
if (!defs) return [];
|
|
22728
|
+
return defs.map((c) => {
|
|
22729
|
+
const out = {};
|
|
22730
|
+
if (c.name !== void 0) out["Name"] = c.name;
|
|
22731
|
+
if (c.image !== void 0) out["Image"] = c.image;
|
|
22732
|
+
if (c.cpu !== void 0 && c.cpu !== 0) out["Cpu"] = c.cpu;
|
|
22733
|
+
if (c.memory !== void 0) out["Memory"] = c.memory;
|
|
22734
|
+
if (c.memoryReservation !== void 0) out["MemoryReservation"] = c.memoryReservation;
|
|
22735
|
+
if (c.essential !== void 0) out["Essential"] = c.essential;
|
|
22736
|
+
if (c.command && c.command.length > 0) out["Command"] = [...c.command];
|
|
22737
|
+
if (c.entryPoint && c.entryPoint.length > 0) out["EntryPoint"] = [...c.entryPoint];
|
|
22738
|
+
if (c.environment && c.environment.length > 0) out["Environment"] = c.environment.map((e) => ({
|
|
22739
|
+
Name: e.name,
|
|
22740
|
+
Value: e.value
|
|
22741
|
+
}));
|
|
22742
|
+
if (c.environmentFiles && c.environmentFiles.length > 0) out["EnvironmentFiles"] = c.environmentFiles.map((e) => ({
|
|
22743
|
+
Type: e.type,
|
|
22744
|
+
Value: e.value
|
|
22745
|
+
}));
|
|
22746
|
+
if (c.secrets && c.secrets.length > 0) out["Secrets"] = c.secrets.map((s) => ({
|
|
22747
|
+
Name: s.name,
|
|
22748
|
+
ValueFrom: s.valueFrom
|
|
22749
|
+
}));
|
|
22750
|
+
if (c.portMappings && c.portMappings.length > 0) out["PortMappings"] = camelToPascalCaseKeys(c.portMappings);
|
|
22751
|
+
if (c.mountPoints && c.mountPoints.length > 0) out["MountPoints"] = camelToPascalCaseKeys(c.mountPoints);
|
|
22752
|
+
if (c.volumesFrom && c.volumesFrom.length > 0) out["VolumesFrom"] = camelToPascalCaseKeys(c.volumesFrom);
|
|
22753
|
+
if (c.dependsOn && c.dependsOn.length > 0) out["DependsOn"] = camelToPascalCaseKeys(c.dependsOn);
|
|
22754
|
+
if (c.links && c.links.length > 0) out["Links"] = [...c.links];
|
|
22755
|
+
if (c.workingDirectory !== void 0) out["WorkingDirectory"] = c.workingDirectory;
|
|
22756
|
+
if (c.disableNetworking !== void 0) out["DisableNetworking"] = c.disableNetworking;
|
|
22757
|
+
if (c.privileged !== void 0) out["Privileged"] = c.privileged;
|
|
22758
|
+
if (c.readonlyRootFilesystem !== void 0) out["ReadonlyRootFilesystem"] = c.readonlyRootFilesystem;
|
|
22759
|
+
if (c.user !== void 0) out["User"] = c.user;
|
|
22760
|
+
if (c.ulimits && c.ulimits.length > 0) out["Ulimits"] = camelToPascalCaseKeys(c.ulimits);
|
|
22761
|
+
if (c.logConfiguration) out["LogConfiguration"] = this.logConfigurationToCfn(c.logConfiguration);
|
|
22762
|
+
if (c.healthCheck) out["HealthCheck"] = camelToPascalCaseKeys(c.healthCheck);
|
|
22763
|
+
if (c.linuxParameters) {
|
|
22764
|
+
const lp = this.linuxParametersToCfn(c.linuxParameters);
|
|
22765
|
+
if (Object.keys(lp).length > 0) out["LinuxParameters"] = lp;
|
|
22766
|
+
}
|
|
22767
|
+
if (c.dockerLabels && Object.keys(c.dockerLabels).length > 0) out["DockerLabels"] = { ...c.dockerLabels };
|
|
22768
|
+
if (c.startTimeout !== void 0) out["StartTimeout"] = c.startTimeout;
|
|
22769
|
+
if (c.stopTimeout !== void 0) out["StopTimeout"] = c.stopTimeout;
|
|
22770
|
+
if (c.interactive !== void 0) out["Interactive"] = c.interactive;
|
|
22771
|
+
if (c.pseudoTerminal !== void 0) out["PseudoTerminal"] = c.pseudoTerminal;
|
|
22772
|
+
return out;
|
|
22773
|
+
});
|
|
22774
|
+
}
|
|
22775
|
+
/**
|
|
22776
|
+
* Reverse of `convertLogConfiguration` for `containerDefinitionsToCfn`.
|
|
22777
|
+
* `LogDriver` flips; `Options` is a free-form log-driver option map copied
|
|
22778
|
+
* verbatim (its keys, e.g. `awslogs-group`, are NOT CFn property names);
|
|
22779
|
+
* `SecretOptions` is a `{Name, ValueFrom}[]` list. Emit-when-present so an
|
|
22780
|
+
* absent / empty sub-field does not phantom-drift.
|
|
22781
|
+
*/
|
|
22782
|
+
logConfigurationToCfn(lc) {
|
|
22783
|
+
const out = {};
|
|
22784
|
+
if (lc.logDriver !== void 0) out["LogDriver"] = lc.logDriver;
|
|
22785
|
+
if (lc.options && Object.keys(lc.options).length > 0) out["Options"] = { ...lc.options };
|
|
22786
|
+
if (lc.secretOptions && lc.secretOptions.length > 0) out["SecretOptions"] = lc.secretOptions.map((s) => ({
|
|
22787
|
+
Name: s.name,
|
|
22788
|
+
ValueFrom: s.valueFrom
|
|
22789
|
+
}));
|
|
22790
|
+
return out;
|
|
22791
|
+
}
|
|
22792
|
+
/**
|
|
22793
|
+
* Reverse of `convertLinuxParameters` for `containerDefinitionsToCfn`. The
|
|
22794
|
+
* SET side is a mechanical first-letter flip (`pascalToCamelCaseKeys`), so the
|
|
22795
|
+
* read side is the inverse `camelToPascalCaseKeys` — plus normalization of the
|
|
22796
|
+
* AWS-defaulted-empty `Capabilities` / `Devices` / `Tmpfs`: AWS returns
|
|
22797
|
+
* `capabilities: {add:[], drop:[]}` even when the template set neither, so the
|
|
22798
|
+
* empty `Add` / `Drop` (and an otherwise-empty `Capabilities`) and empty
|
|
22799
|
+
* `Devices` / `Tmpfs` arrays are dropped to equal a template that omits them.
|
|
22800
|
+
*/
|
|
22801
|
+
linuxParametersToCfn(lp) {
|
|
22802
|
+
const out = camelToPascalCaseKeys(lp);
|
|
22803
|
+
const caps = out["Capabilities"];
|
|
22804
|
+
if (caps) {
|
|
22805
|
+
const normalized = {};
|
|
22806
|
+
if (Array.isArray(caps["Add"]) && caps["Add"].length > 0) normalized["Add"] = caps["Add"];
|
|
22807
|
+
if (Array.isArray(caps["Drop"]) && caps["Drop"].length > 0) normalized["Drop"] = caps["Drop"];
|
|
22808
|
+
if (Object.keys(normalized).length > 0) out["Capabilities"] = normalized;
|
|
22809
|
+
else delete out["Capabilities"];
|
|
22810
|
+
}
|
|
22811
|
+
for (const key of ["Devices", "Tmpfs"]) if (Array.isArray(out[key]) && out[key].length === 0) delete out[key];
|
|
22812
|
+
return out;
|
|
22813
|
+
}
|
|
22814
|
+
/**
|
|
22679
22815
|
* Coerce a CFn boolean property to a real boolean at the wire boundary.
|
|
22680
22816
|
* CFn templates can carry booleans as the strings "true" / "false"
|
|
22681
22817
|
* (e.g. via Fn::Sub / parameter plumbing), so the SDK input must
|
|
@@ -22878,8 +23014,9 @@ var ECSProvider = class {
|
|
|
22878
23014
|
*
|
|
22879
23015
|
* Dispatches by resource type:
|
|
22880
23016
|
* - `AWS::ECS::Cluster` → `DescribeClusters`
|
|
22881
|
-
* - `AWS::ECS::Service` → `DescribeServices`. Service physicalIds
|
|
22882
|
-
* the
|
|
23017
|
+
* - `AWS::ECS::Service` → `DescribeServices`. Service physicalIds come in
|
|
23018
|
+
* two forms — the service ARN (what `createService` stores) and the
|
|
23019
|
+
* composite `<clusterArn>|<serviceName>` — and both are accepted (#1170).
|
|
22883
23020
|
* - `AWS::ECS::TaskDefinition` → `DescribeTaskDefinition`
|
|
22884
23021
|
*
|
|
22885
23022
|
* Each branch surfaces only the keys cdkd's `create()` accepts, mapping
|
|
@@ -22926,14 +23063,20 @@ var ECSProvider = class {
|
|
|
22926
23063
|
return result;
|
|
22927
23064
|
}
|
|
22928
23065
|
async readCurrentStateService(physicalId) {
|
|
23066
|
+
let cluster;
|
|
23067
|
+
let serviceName;
|
|
22929
23068
|
const sep = physicalId.indexOf("|");
|
|
22930
|
-
if (sep
|
|
22931
|
-
|
|
22932
|
-
|
|
23069
|
+
if (sep >= 0) {
|
|
23070
|
+
cluster = physicalId.substring(0, sep);
|
|
23071
|
+
serviceName = physicalId.substring(sep + 1);
|
|
23072
|
+
} else {
|
|
23073
|
+
serviceName = physicalId;
|
|
23074
|
+
cluster = clusterNameFromServiceArn(physicalId);
|
|
23075
|
+
}
|
|
22933
23076
|
let resp;
|
|
22934
23077
|
try {
|
|
22935
23078
|
resp = await this.getClient().send(new DescribeServicesCommand({
|
|
22936
|
-
cluster
|
|
23079
|
+
cluster,
|
|
22937
23080
|
services: [serviceName],
|
|
22938
23081
|
include: ["TAGS"]
|
|
22939
23082
|
}));
|
|
@@ -23001,7 +23144,7 @@ var ECSProvider = class {
|
|
|
23001
23144
|
if (td.ipcMode !== void 0) result["IpcMode"] = td.ipcMode;
|
|
23002
23145
|
if (td.ephemeralStorage?.sizeInGiB !== void 0) result["EphemeralStorage"] = { SizeInGiB: td.ephemeralStorage.sizeInGiB };
|
|
23003
23146
|
if (td.enableFaultInjection !== void 0) result["EnableFaultInjection"] = td.enableFaultInjection;
|
|
23004
|
-
result["ContainerDefinitions"] = td.containerDefinitions
|
|
23147
|
+
result["ContainerDefinitions"] = this.containerDefinitionsToCfn(td.containerDefinitions);
|
|
23005
23148
|
result["Tags"] = normalizeAwsTagsToCfn(resp.tags);
|
|
23006
23149
|
return result;
|
|
23007
23150
|
}
|
|
@@ -23012,10 +23155,11 @@ var ECSProvider = class {
|
|
|
23012
23155
|
* `AWS::ECS::TaskDefinition` — all explicit-override only (see the
|
|
23013
23156
|
* per-branch notes on why the `aws:cdk:path` tag walk was removed).
|
|
23014
23157
|
*
|
|
23015
|
-
*
|
|
23016
|
-
*
|
|
23017
|
-
*
|
|
23018
|
-
*
|
|
23158
|
+
* `createService` stores the service ARN as the Service physical id (and
|
|
23159
|
+
* the mutation ops pass it straight through as the `service` argument, with
|
|
23160
|
+
* the cluster read from the template `Cluster` property). The explicit
|
|
23161
|
+
* `--resource` override is honored verbatim, so a caller may also supply the
|
|
23162
|
+
* composite `<clusterArn>|<serviceName>` form that `readCurrentState` accepts.
|
|
23019
23163
|
*/
|
|
23020
23164
|
async import(input) {
|
|
23021
23165
|
switch (input.resourceType) {
|
|
@@ -61680,7 +61824,7 @@ function createMigrateCommand() {
|
|
|
61680
61824
|
*/
|
|
61681
61825
|
function buildProgram() {
|
|
61682
61826
|
const program = new Command();
|
|
61683
|
-
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.260.
|
|
61827
|
+
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.260.7");
|
|
61684
61828
|
program.addCommand(createBootstrapCommand());
|
|
61685
61829
|
program.addCommand(createSynthCommand());
|
|
61686
61830
|
program.addCommand(createListCommand());
|