@go-to-k/cdkd 0.23.2 → 0.25.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 CHANGED
@@ -502,6 +502,40 @@ cdkd deploy --no-wait
502
502
 
503
503
  This can significantly speed up deployments with CloudFront (which takes 3-15 minutes to deploy to edge locations). The resource is fully functional once AWS finishes the async deployment.
504
504
 
505
+ ## Per-resource timeout
506
+
507
+ Both `cdkd deploy` and `cdkd destroy` (including `cdkd state destroy`) enforce a wall-clock deadline on every individual CREATE / UPDATE / DELETE so a stuck Cloud Control polling loop, hung Custom Resource handler, or slow ENI release cannot block the run forever.
508
+
509
+ | Option | Default | Description |
510
+ | --- | --- | --- |
511
+ | `--resource-warn-after <duration>` | `5m` | Warn when a single resource operation has been running longer than this. The live progress line is suffixed with `[taking longer than expected, Nm+]` and a `WARN` log line is emitted (printed above the live area in TTY mode, plain stderr otherwise). |
512
+ | `--resource-timeout <duration>` | `30m` | Abort a single resource operation that exceeds this. The deploy / destroy fails with `ResourceTimeoutError` (wrapped in `ProvisioningError`) and the existing rollback / state-preservation path runs. |
513
+
514
+ Durations are written as `<number>s`, `<number>m`, or `<number>h` (e.g. `30s`, `90s`, `5m`, `1.5h`). Zero, negative, missing-unit, and unknown-unit values are rejected at parse time.
515
+
516
+ ```bash
517
+ # Bump the per-resource budget to one hour (matches the Custom Resource provider's polling cap)
518
+ cdkd deploy --resource-timeout 1h
519
+
520
+ # Surface "still running" warnings sooner on a fast-feedback dev loop
521
+ cdkd deploy --resource-warn-after 90s --resource-timeout 10m
522
+ ```
523
+
524
+ ### Why the default is 30m, not 1h
525
+
526
+ cdkd's Custom Resource provider polls async handlers (`isCompleteHandler` pattern) for up to one hour before giving up. Setting the per-resource timeout to 1h by default would make a single hung Custom Resource hold the whole stack for an hour even though no other resource type ever needs more than a few minutes. A shorter default (`30m`) catches stuck operations faster, and stacks that legitimately rely on long-running Custom Resources opt into the higher budget explicitly with `--resource-timeout 1h`.
527
+
528
+ The error message on timeout names the resource, type, region, elapsed time, and operation, and reminds you to re-run with `--resource-timeout 1h` (or higher) for genuinely-long resources:
529
+
530
+ ```text
531
+ Resource MyBucket (AWS::S3::Bucket) in us-east-1 timed out after 30m during CREATE (elapsed 30m).
532
+ This may indicate a stuck Cloud Control polling loop, hung Custom Resource, or
533
+ slow ENI provisioning. Re-run with --resource-timeout 1h if the resource genuinely
534
+ needs more time, or --verbose to see the underlying provider activity.
535
+ ```
536
+
537
+ Note: `--resource-warn-after` must be less than `--resource-timeout`. Reversed values are rejected at parse time.
538
+
505
539
  ## Example
506
540
 
507
541
  ```typescript
@@ -582,15 +616,21 @@ cdkd import MyStack \
582
616
  # CDK CLI compat: read overrides from a JSON file.
583
617
  cdkd import MyStack --resource-mapping mapping.json
584
618
  # mapping.json: { "MyBucket": "my-bucket-name", "MyFn": "my-function-name" }
619
+
620
+ # CDK CLI compat: inline JSON (handy for non-TTY CI scripts).
621
+ cdkd import MyStack --resource-mapping-inline '{"MyBucket":"my-bucket-name"}'
585
622
  ```
586
623
 
587
- When at least one `--resource` flag (or a `--resource-mapping` file) is
588
- supplied, **only the listed resources are imported**. Every other
589
- resource in the template is reported as `out of scope` and left out of
590
- state the next `cdkd deploy` will treat them as new and CREATE them.
591
- This matches the semantics of `cdk import --resource-mapping`. cdkd
592
- validates that every override key is a real logical ID in the
593
- template; a typo aborts the run rather than silently importing nothing.
624
+ When at least one `--resource` flag (or a `--resource-mapping` /
625
+ `--resource-mapping-inline` payload) is supplied, **only the listed
626
+ resources are imported**. Every other resource in the template is
627
+ reported as `out of scope` and left out of state the next `cdkd
628
+ deploy` will treat them as new and CREATE them. This matches the
629
+ semantics of `cdk import --resource-mapping` /
630
+ `--resource-mapping-inline`. cdkd validates that every override key is
631
+ a real logical ID in the template; a typo aborts the run rather than
632
+ silently importing nothing. `--resource-mapping` and
633
+ `--resource-mapping-inline` are mutually exclusive — pick one source.
594
634
 
595
635
  Use selective mode when you want to **adopt a few specific resources**
596
636
  out of a larger stack — for example, you have one S3 bucket that was
@@ -641,6 +681,50 @@ services, anything in Cloud Control API), use the explicit
641
681
  exactly this case. Resource types whose provider does not implement
642
682
  import are reported as `unsupported` and skipped.
643
683
 
684
+ ### `cdkd import` vs upstream `cdk import`
685
+
686
+ cdkd's `import` command mirrors the surface of upstream
687
+ [`cdk import`](https://docs.aws.amazon.com/cdk/v2/guide/ref-cli-cmd-import.html)
688
+ where it can, but the underlying mechanism is fundamentally different
689
+ and a handful of upstream-only flags are not implemented. Use this
690
+ table to predict behavior when migrating from `cdk import`.
691
+
692
+ | Topic | `cdk import` (upstream) | `cdkd import` |
693
+ | --- | --- | --- |
694
+ | Mechanism | CloudFormation `CreateChangeSet` with `ResourcesToImport` — atomic, all-or-nothing. | Per-resource SDK calls (e.g. `s3:HeadBucket`, `lambda:GetFunction`, IAM `ListRoleTags`). **Not atomic.** |
695
+ | Failure mode | Failed import rolls the changeset back; the stack is left unchanged. | Per-resource: `imported` / `skipped-not-found` / `skipped-no-impl` / `skipped-out-of-scope` / `failed` rows are summarized. State is written for whatever succeeded — but only after a confirmation prompt (or `--yes`), so a partial run is opt-in. To roll a partial import back, use `cdkd state orphan <stack>` (drops the state record only). |
696
+ | Selective mode (`--resource-mapping <file>`) | Supported. Listed resources are imported; unlisted resources cause the changeset to fail. | Supported. Listed resources are imported; unlisted resources are reported as `out of scope` and left out of state (next `cdkd deploy` will CREATE them). |
697
+ | Selective mode (`--resource <id>=<physical>` repeatable) | Not supported (upstream uses interactive prompts or a mapping file). | Supported as cdkd's CLI-friendly equivalent. |
698
+ | `--resource-mapping-inline '<json>'` | Supported (use in non-TTY environments). | **Not supported.** Use `--resource <id>=<physical>` (repeatable) or `--resource-mapping <file>` instead. |
699
+ | `--record-resource-mapping <file>` | Supported (writes the mapping the user typed at the prompt to a file for re-use). | **Not supported.** cdkd has no interactive prompt to record. |
700
+ | Interactive prompt for missing IDs | Default in TTY — prompts for every resource not covered by a mapping file. | **Not supported.** cdkd is non-interactive: missing logical IDs are looked up by `aws:cdk:path` tag in `auto` / `hybrid` modes, or skipped as `out of scope` in selective mode. The only prompt is the final "write state?" confirmation, which `--yes` skips. |
701
+ | Typo'd logical ID | Aborts with a clear error before any AWS calls. | Aborts with a clear error before any AWS calls — checked against the synthesized template. |
702
+ | Whole-stack tag-based import | **Not supported.** | **cdkd-specific.** With no flags, cdkd looks every resource up by its `aws:cdk:path` tag — the typical case for adopting a stack previously deployed by `cdk deploy`. |
703
+ | Hybrid mode (overrides + tag fallback) | **Not supported.** | **cdkd-specific.** `--auto` together with `--resource` lets listed resources use the explicit physical id while everything else still goes through tag lookup. |
704
+ | Nested stacks (`AWS::CloudFormation::Stack`) | Explicitly unsupported. | Also unsupported in practice — cdkd does not deploy nested CloudFormation stacks at all (no `AWS::CloudFormation::Stack` provider). The `Stack` resource itself would be reported as `unsupported`. CDK Stages (separate top-level stacks) are fine: pass the stack's display path or physical name as the positional argument. |
705
+ | Bootstrap requirement | Bootstrap v12+ (deploy role needs to read the encrypted staging bucket). | cdkd's own state bucket; no CDK bootstrap version requirement. |
706
+ | Resource-type coverage | Whatever [CloudFormation supports for import](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resource-import-supported-resources.html). | The set of cdkd providers that implement `import()` (see [CLAUDE.md](CLAUDE.md) for the current list). For any other CC-API-supported type, use `--resource <id>=<physical>` to drive the Cloud Control API fallback. The two lists overlap heavily but are not identical. |
707
+ | Confirmation prompt before writing state | n/a (CloudFormation operates atomically). | Yes — cdkd asks before writing the state file. Skip with `--yes`. |
708
+ | `--force` | "Continue even if the diff includes updates or deletions" — about diff strictness. | "Overwrite an existing state record" — about state safety. **Same flag name, different meaning.** |
709
+ | `--dry-run` | Implied by `--no-execute` (creates the changeset without executing). | Native: shows the import plan and exits without writing state. |
710
+
711
+ #### Practical implications when migrating from `cdk import`
712
+
713
+ - If you script around `--resource-mapping <file>`: behavior matches.
714
+ The file format (`{"LogicalId": "physical-id"}`) is the same.
715
+ - If you script around `--resource-mapping-inline`: rewrite as
716
+ repeated `--resource <id>=<physical>` flags, or write a temp file.
717
+ - If your workflow relies on the interactive prompt: rewrite as
718
+ `--resource-mapping <file>`. cdkd will not prompt.
719
+ - If you rely on atomic rollback: cdkd cannot offer that — its
720
+ per-resource model writes state only after the full pass completes
721
+ (and after confirmation), so a partial run is bounded, but if a
722
+ later resource fails after several earlier ones already returned
723
+ successfully and you confirm the write, those earlier ones are
724
+ in cdkd state. Use `cdkd state orphan <stack>` to back out.
725
+ - If you import nested stacks: neither tool supports this. Convert
726
+ to top-level CDK stacks first.
727
+
644
728
  ## State Management
645
729
 
646
730
  State is stored in S3. Keys are scoped by `(stackName, region)` so the same