@go-to-k/cdkd 0.94.3 → 0.94.6
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 +3 -0
- package/dist/cli.js +76 -12
- package/dist/cli.js.map +3 -3
- package/dist/go-to-k-cdkd-0.94.6.tgz +0 -0
- package/package.json +1 -1
- package/dist/go-to-k-cdkd-0.94.3.tgz +0 -0
package/README.md
CHANGED
|
@@ -8,6 +8,8 @@ Drop-in CDK CLI for existing CDK apps — faster deploys via AWS SDK instead of
|
|
|
8
8
|
|
|
9
9
|

|
|
10
10
|
|
|
11
|
+
**cdkd complements the AWS CDK CLI rather than replacing it.** Use cdkd in dev/test for rapid iteration and SAM-style local execution; use the AWS CDK CLI in production for full CloudFormation tooling. Bidirectional migration is supported — [import an existing CloudFormation stack](#importing-existing-resources) into cdkd for iteration, or [export back to CloudFormation](#exporting-a-stack-back-to-cloudformation) when ready for production.
|
|
12
|
+
|
|
11
13
|
> **⚠️ WARNING: NOT PRODUCTION READY**
|
|
12
14
|
>
|
|
13
15
|
> An experimental project exploring direct SDK provisioning as an alternative to the AWS CDK CLI — **NOT a replacement** and **NOT suitable for production use**. Features are incomplete, APIs may change without notice, and bugs may affect your AWS infrastructure. Use at your own risk in development / testing environments only.
|
|
@@ -25,6 +27,7 @@ Drop-in CDK CLI for existing CDK apps — faster deploys via AWS SDK instead of
|
|
|
25
27
|
- **`--no-wait` for async resources**: Skip the multi-minute wait on CloudFront / RDS / ElastiCache / NAT Gateway and return as soon as the create call returns (CloudFormation always blocks)
|
|
26
28
|
- **VPC route DependsOn relaxation (on by default)**: Drop CDK-injected defensive `DependsOn` edges from VPC Lambdas onto private-subnet routes so `CloudFront::Distribution` and `Lambda::Url` start their ~3-min propagation in parallel with NAT Gateway stabilization (~50% faster on VPC + Lambda + CloudFront stacks). Pass `--no-aggressive-vpc-parallel` to opt out.
|
|
27
29
|
- **Local execution without deploying** (`cdkd local invoke` / `cdkd local start-api` / `cdkd local run-task`): run any Lambda — stand up every API Gateway route as a local HTTP server — or start every container in an `AWS::ECS::TaskDefinition` on a per-task docker network with the AWS-published metadata-endpoints sidecar. SAM-compatible mental model but reuses cdkd's synthesis / asset / route-discovery (no `template.yaml` round-trip). All AWS Lambda runtimes (Node.js / Python / Ruby / Java / .NET / `provided.*`) and one server per discovered API (HTTP API v2 / REST v1 / Function URL) with their own port / authorizers / CORS configs. `local run-task` is Phase 1 (single task, DependsOn ordering, IAM task-role via AssumeRole) — ECS Services / ALB routing / Service Connect are Phase 2 / Phase 3 follow-ups. `cdkd local run-task --from-state` substitutes intrinsic-valued container `Environment[].Value` (`Ref` / `Fn::GetAtt` / `Fn::Sub` / `Fn::Join`) and `Secrets[].ValueFrom` against the deployed cdkd state — `table.tableName` / `ecs.Secret.fromSecretsManager(secret)` / `ecs.Secret.fromSsmParameter(param)` Just Work locally instead of silently dropping.
|
|
30
|
+
- **Bidirectional CloudFormation migration**: `cdkd import` adopts AWS-deployed resources (including `cdk deploy`-managed CloudFormation stacks via `--migrate-from-cloudformation`) into cdkd state without re-creating them; `cdkd export` hands a cdkd-managed stack back to CloudFormation when you're ready to move to production. See [Importing existing resources](#importing-existing-resources) and [Exporting a stack back to CloudFormation](#exporting-a-stack-back-to-cloudformation).
|
|
28
31
|
|
|
29
32
|
> **Note**: Resource types not covered by either SDK Providers or Cloud Control API cannot be deployed with cdkd. If you encounter an unsupported resource type, deployment will fail with a clear error message.
|
|
30
33
|
|
package/dist/cli.js
CHANGED
|
@@ -80145,7 +80145,17 @@ function readStringProperty(properties, key, resourceType) {
|
|
|
80145
80145
|
return v;
|
|
80146
80146
|
}
|
|
80147
80147
|
var IMPORT_UNSUPPORTED_RECREATABLE_TYPES = /* @__PURE__ */ new Set([
|
|
80148
|
-
|
|
80148
|
+
// AWS::ApiGatewayV2::Stage — `handlers: []`. HttpApi auto-emits `$default`.
|
|
80149
|
+
"AWS::ApiGatewayV2::Stage",
|
|
80150
|
+
// AWS::IAM::Policy — `handlers: ['create', 'delete', 'update']` (no `read`/
|
|
80151
|
+
// `list`). Inline policies attached to roles / users / groups don't have a
|
|
80152
|
+
// first-class AWS resource id, so CFn IMPORT can't look them up. cdkd's
|
|
80153
|
+
// own IAMPolicyProvider issues `iam:PutRolePolicy` / `PutUserPolicy` /
|
|
80154
|
+
// `PutGroupPolicy` per attachment target; CFn phase-2 CREATE uses the
|
|
80155
|
+
// exact same APIs, so pre-delete + phase-2-CREATE round-trips cleanly.
|
|
80156
|
+
// CDK auto-emits this type for L2 grants (ECS Task Execution Role
|
|
80157
|
+
// ECR pull policy, Lambda execution role inline policies, etc.).
|
|
80158
|
+
"AWS::IAM::Policy"
|
|
80149
80159
|
]);
|
|
80150
80160
|
var PRE_DELETE_HANDLERS = {
|
|
80151
80161
|
"AWS::ApiGatewayV2::Stage": async (entry) => {
|
|
@@ -80165,6 +80175,55 @@ var PRE_DELETE_HANDLERS = {
|
|
|
80165
80175
|
}
|
|
80166
80176
|
throw err;
|
|
80167
80177
|
}
|
|
80178
|
+
},
|
|
80179
|
+
"AWS::IAM::Policy": async (entry) => {
|
|
80180
|
+
const {
|
|
80181
|
+
IAMClient: IAMClient6,
|
|
80182
|
+
DeleteRolePolicyCommand: DeleteRolePolicyCommand3,
|
|
80183
|
+
DeleteUserPolicyCommand: DeleteUserPolicyCommand3,
|
|
80184
|
+
DeleteGroupPolicyCommand: DeleteGroupPolicyCommand3,
|
|
80185
|
+
NoSuchEntityException: NoSuchEntityException5
|
|
80186
|
+
} = await import("@aws-sdk/client-iam");
|
|
80187
|
+
const policyName = entry.physicalId.includes(":") ? entry.physicalId.split(":")[0] : entry.physicalId;
|
|
80188
|
+
if (!policyName) {
|
|
80189
|
+
throw new Error(
|
|
80190
|
+
`cdkd state's physicalId for ${entry.logicalId} (${entry.resourceType}) is empty / invalid`
|
|
80191
|
+
);
|
|
80192
|
+
}
|
|
80193
|
+
const roles = entry.properties["Roles"];
|
|
80194
|
+
const users = entry.properties["Users"];
|
|
80195
|
+
const groups = entry.properties["Groups"];
|
|
80196
|
+
const hasAttachment = (roles?.length ?? 0) + (users?.length ?? 0) + (groups?.length ?? 0) > 0;
|
|
80197
|
+
if (!hasAttachment) {
|
|
80198
|
+
throw new Error(
|
|
80199
|
+
`cdkd state's properties for ${entry.logicalId} (${entry.resourceType}) has no Roles/Users/Groups attachment recorded \u2014 cannot pre-delete the inline policy. State may be from a pre-v0.74 cdkd binary; re-run \`cdkd state refresh-observed\` before export.`
|
|
80200
|
+
);
|
|
80201
|
+
}
|
|
80202
|
+
const client = new IAMClient6({});
|
|
80203
|
+
const deleteSafely = async (op) => {
|
|
80204
|
+
try {
|
|
80205
|
+
await op();
|
|
80206
|
+
} catch (err) {
|
|
80207
|
+
if (err instanceof NoSuchEntityException5)
|
|
80208
|
+
return;
|
|
80209
|
+
throw err;
|
|
80210
|
+
}
|
|
80211
|
+
};
|
|
80212
|
+
for (const roleName of roles ?? []) {
|
|
80213
|
+
await deleteSafely(
|
|
80214
|
+
() => client.send(new DeleteRolePolicyCommand3({ RoleName: roleName, PolicyName: policyName }))
|
|
80215
|
+
);
|
|
80216
|
+
}
|
|
80217
|
+
for (const userName of users ?? []) {
|
|
80218
|
+
await deleteSafely(
|
|
80219
|
+
() => client.send(new DeleteUserPolicyCommand3({ UserName: userName, PolicyName: policyName }))
|
|
80220
|
+
);
|
|
80221
|
+
}
|
|
80222
|
+
for (const groupName of groups ?? []) {
|
|
80223
|
+
await deleteSafely(
|
|
80224
|
+
() => client.send(new DeleteGroupPolicyCommand3({ GroupName: groupName, PolicyName: policyName }))
|
|
80225
|
+
);
|
|
80226
|
+
}
|
|
80168
80227
|
}
|
|
80169
80228
|
};
|
|
80170
80229
|
async function exportCommand(stackArg, options) {
|
|
@@ -80297,15 +80356,6 @@ async function exportCommand(stackArg, options) {
|
|
|
80297
80356
|
`${blocked.length} resource(s) block migration. Either destroy them first (cdkd destroy / cdkd state destroy cherry-picked), or remove them from the CDK app and re-synthesize.`
|
|
80298
80357
|
);
|
|
80299
80358
|
}
|
|
80300
|
-
if (phase2Creates.length > 0 && !options.includeNonImportable) {
|
|
80301
|
-
logger.error("The following resources cannot be imported into CloudFormation:");
|
|
80302
|
-
for (const p of phase2Creates) {
|
|
80303
|
-
logger.error(` - ${p.logicalId} (${p.resourceType}): CFn cannot import this type`);
|
|
80304
|
-
}
|
|
80305
|
-
throw new Error(
|
|
80306
|
-
`${phase2Creates.length} non-importable resource(s) detected (Custom::*). Pass --include-non-importable to run a 2-phase migration: phase 1 imports the importable resources; phase 2 CFn-CREATEs the non-importable ones (re-invoking each Custom Resource's backing Lambda onCreate handler \u2014 make sure those are idempotent). Or destroy these resources first.`
|
|
80307
|
-
);
|
|
80308
|
-
}
|
|
80309
80359
|
if (phase1Imports.length === 0 && phase2Creates.length === 0 && recreateBeforePhase2.length === 0) {
|
|
80310
80360
|
logger.warn("No resources to migrate \u2014 cdkd state is empty.");
|
|
80311
80361
|
return;
|
|
@@ -80331,14 +80381,28 @@ async function exportCommand(stackArg, options) {
|
|
|
80331
80381
|
logger.info(` ${r.logicalId} (${r.resourceType}) \u2014 physicalId: ${r.physicalId}`);
|
|
80332
80382
|
}
|
|
80333
80383
|
logger.info(
|
|
80334
|
-
" Brief unavailability window (~10s for Stage; HttpApi endpoint URL is unchanged because it embeds ApiId, not StageName). Pass --no-recreate-import-unsupported to block instead."
|
|
80384
|
+
" Brief unavailability window per type (~10s for Stage; HttpApi endpoint URL is unchanged because it embeds ApiId, not StageName. IAM::Policy: the inline policy attachment is dropped from each Role/User/Group between phases \u2014 any in-flight AWS API call that depends on the granted permission will fail until CFn re-CREATEs in phase 2). Pass --no-recreate-import-unsupported to block instead."
|
|
80335
80385
|
);
|
|
80336
80386
|
logger.info("");
|
|
80337
80387
|
}
|
|
80338
80388
|
if (options.dryRun) {
|
|
80389
|
+
if (phase2Creates.length > 0 && !options.includeNonImportable) {
|
|
80390
|
+
logger.warn(
|
|
80391
|
+
`${phase2Creates.length} non-importable resource(s) detected (Custom::*). A real run (without --dry-run) would require --include-non-importable to run a 2-phase migration: phase 1 imports the importable resources; phase 2 CFn-CREATEs the non-importable ones (re-invoking each Custom Resource's backing Lambda onCreate handler \u2014 make sure those are idempotent).`
|
|
80392
|
+
);
|
|
80393
|
+
}
|
|
80339
80394
|
logger.info("--dry-run: no CloudFormation changeset will be created.");
|
|
80340
80395
|
return;
|
|
80341
80396
|
}
|
|
80397
|
+
if (phase2Creates.length > 0 && !options.includeNonImportable) {
|
|
80398
|
+
logger.error("The following resources cannot be imported into CloudFormation:");
|
|
80399
|
+
for (const p of phase2Creates) {
|
|
80400
|
+
logger.error(` - ${p.logicalId} (${p.resourceType}): CFn cannot import this type`);
|
|
80401
|
+
}
|
|
80402
|
+
throw new Error(
|
|
80403
|
+
`${phase2Creates.length} non-importable resource(s) detected (Custom::*). Pass --include-non-importable to run a 2-phase migration: phase 1 imports the importable resources; phase 2 CFn-CREATEs the non-importable ones (re-invoking each Custom Resource's backing Lambda onCreate handler \u2014 make sure those are idempotent). Or destroy these resources first.`
|
|
80404
|
+
);
|
|
80405
|
+
}
|
|
80342
80406
|
if (!options.yes) {
|
|
80343
80407
|
const phase2Note = phase2Creates.length > 0 ? ` Phase 2 will then CREATE ${phase2Creates.length} non-importable resource(s) (invoking each Custom Resource's onCreate handler).` : "";
|
|
80344
80408
|
const recreateNote = recreateBeforePhase2.length > 0 ? ` cdkd will also DELETE ${recreateBeforePhase2.length} AWS resource(s) between phases so CFn can re-CREATE them in phase 2 (brief unavailability window \u2014 see plan above for the affected resources).` : "";
|
|
@@ -81176,7 +81240,7 @@ function reorderArgs(argv) {
|
|
|
81176
81240
|
}
|
|
81177
81241
|
async function main() {
|
|
81178
81242
|
const program = new Command18();
|
|
81179
|
-
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.94.
|
|
81243
|
+
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.94.6");
|
|
81180
81244
|
program.addCommand(createBootstrapCommand());
|
|
81181
81245
|
program.addCommand(createSynthCommand());
|
|
81182
81246
|
program.addCommand(createListCommand());
|