@go-to-k/cdkd 0.29.0 → 0.30.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 +55 -596
- package/dist/cli.js +103 -29
- package/dist/cli.js.map +3 -3
- package/dist/go-to-k-cdkd-0.30.0.tgz +0 -0
- package/package.json +1 -1
- package/dist/go-to-k-cdkd-0.29.0.tgz +0 -0
package/README.md
CHANGED
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
- **Diff calculation**: Self-implemented resource/property-level diff between desired template and current state
|
|
25
25
|
- **S3-based state management**: No DynamoDB required, uses S3 conditional writes for locking
|
|
26
26
|
- **DAG-based parallelization**: Analyze `Ref`/`Fn::GetAtt` dependencies and execute in parallel
|
|
27
|
+
- **`--no-wait` for async resources**: Skip the multi-minute wait on CloudFront / RDS / ElastiCache and return as soon as the create call returns (CloudFormation always blocks)
|
|
27
28
|
|
|
28
29
|
> **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.
|
|
29
30
|
|
|
@@ -90,58 +91,9 @@ Reproduce with `./tests/benchmark/run-benchmark.sh all`. See [tests/benchmark/RE
|
|
|
90
91
|
└────────┘ └────────┘
|
|
91
92
|
```
|
|
92
93
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
1. CLI Layer
|
|
97
|
-
├── Resolve --app (CLI > CDKD_APP env > cdk.json "app")
|
|
98
|
-
├── Resolve --state-bucket (CLI > env > cdk.json > auto: cdkd-state-{accountId}, with legacy fallback to cdkd-state-{accountId}-{region})
|
|
99
|
-
└── Initialize AWS clients
|
|
100
|
-
|
|
101
|
-
2. Synthesis (self-implemented, no CDK CLI dependency)
|
|
102
|
-
├── Short-circuit: if --app is an existing directory, treat it as a
|
|
103
|
-
│ pre-synthesized cloud assembly and skip the steps below
|
|
104
|
-
├── Load context (merge order, later wins):
|
|
105
|
-
│ ├── CDK defaults (path-metadata, asset-metadata, version-reporting, bundling-stacks)
|
|
106
|
-
│ ├── ~/.cdk.json "context" field (user defaults)
|
|
107
|
-
│ ├── cdk.json "context" field (project settings)
|
|
108
|
-
│ ├── cdk.context.json (cached lookups, reloaded each iteration)
|
|
109
|
-
│ └── CLI -c key=value (highest priority)
|
|
110
|
-
├── Execute CDK app as subprocess
|
|
111
|
-
│ ├── child_process.spawn(app command)
|
|
112
|
-
│ ├── Pass env: CDK_OUTDIR, CDK_CONTEXT_JSON, CDK_DEFAULT_REGION/ACCOUNT
|
|
113
|
-
│ └── App writes Cloud Assembly to cdk.out/
|
|
114
|
-
├── Parse cdk.out/manifest.json
|
|
115
|
-
│ ├── Extract stacks (type: aws:cloudformation:stack)
|
|
116
|
-
│ ├── Extract asset manifests (type: cdk:asset-manifest)
|
|
117
|
-
│ └── Extract stack dependencies
|
|
118
|
-
└── Context provider loop (if missing context detected):
|
|
119
|
-
├── Resolve via AWS SDK (all CDK context provider types supported)
|
|
120
|
-
├── Save to cdk.context.json
|
|
121
|
-
└── Re-execute CDK app with updated context
|
|
122
|
-
|
|
123
|
-
3. Asset Publishing + Deployment (WorkGraph DAG)
|
|
124
|
-
├── Each asset is a node, each stack deploy is a node
|
|
125
|
-
│ ├── asset-publish nodes: 8 concurrent (file S3 uploads + Docker build+push)
|
|
126
|
-
│ ├── stack nodes: 4 concurrent deployments
|
|
127
|
-
│ ├── Dependencies: asset-publish → stack (all assets complete before deploy)
|
|
128
|
-
│ └── Inter-stack: stack A → stack B (CDK dependency order)
|
|
129
|
-
├── Region resolved from asset manifest destination (stack's target region)
|
|
130
|
-
├── Skip if already exists (HeadObject for S3, DescribeImages for ECR)
|
|
131
|
-
├── Per-stack deploy flow:
|
|
132
|
-
│ ├── Acquire S3 lock (optimistic locking)
|
|
133
|
-
│ ├── Load current state from S3
|
|
134
|
-
│ ├── Build DAG from template (Ref/Fn::GetAtt/DependsOn)
|
|
135
|
-
│ ├── Calculate diff (CREATE/UPDATE/DELETE)
|
|
136
|
-
│ ├── Resolve intrinsic functions (Ref, Fn::Sub, Fn::Join, etc.)
|
|
137
|
-
│ ├── Execute via event-driven DAG dispatch (a resource starts as
|
|
138
|
-
│ │ soon as ALL of its own deps complete; no level barrier):
|
|
139
|
-
│ │ ├── SDK Providers (direct API calls, preferred)
|
|
140
|
-
│ │ └── Cloud Control API (fallback, async polling)
|
|
141
|
-
│ ├── Save state after each successful resource (partial state save)
|
|
142
|
-
│ └── Release lock
|
|
143
|
-
└── synth does NOT publish assets or deploy (deploy only)
|
|
144
|
-
```
|
|
94
|
+
For a step-by-step walkthrough of the full `cdkd deploy` pipeline (CLI
|
|
95
|
+
parsing → synthesis → asset publishing → per-stack deploy), see
|
|
96
|
+
[docs/architecture.md](docs/architecture.md#5-end-to-end-pipeline-walkthrough-cdkd-deploy).
|
|
145
97
|
|
|
146
98
|
## Supported Features
|
|
147
99
|
|
|
@@ -181,101 +133,16 @@ Reproduce with `./tests/benchmark/run-benchmark.sh all`. See [tests/benchmark/RE
|
|
|
181
133
|
|
|
182
134
|
### Resource Provisioning
|
|
183
135
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
| **Messaging** | AWS::SQS::Queue | SDK Provider | ✅ |
|
|
195
|
-
| **Messaging** | AWS::SQS::QueuePolicy | SDK Provider | ✅ |
|
|
196
|
-
| **Messaging** | AWS::SNS::Topic | SDK Provider | ✅ |
|
|
197
|
-
| **Messaging** | AWS::SNS::Subscription | SDK Provider | ✅ |
|
|
198
|
-
| **Messaging** | AWS::SNS::TopicPolicy | SDK Provider | ✅ |
|
|
199
|
-
| **Compute** | AWS::Lambda::Function | SDK Provider | ✅ |
|
|
200
|
-
| **Compute** | AWS::Lambda::Permission | SDK Provider | ✅ |
|
|
201
|
-
| **Compute** | AWS::Lambda::Url | SDK Provider | ✅ |
|
|
202
|
-
| **Compute** | AWS::Lambda::EventSourceMapping | SDK Provider | ✅ |
|
|
203
|
-
| **Compute** | AWS::Lambda::LayerVersion | SDK Provider | ✅ |
|
|
204
|
-
| **Database** | AWS::DynamoDB::Table | SDK Provider | ✅ |
|
|
205
|
-
| **Monitoring** | AWS::Logs::LogGroup | SDK Provider | ✅ |
|
|
206
|
-
| **Monitoring** | AWS::CloudWatch::Alarm | SDK Provider | ✅ |
|
|
207
|
-
| **Secrets** | AWS::SecretsManager::Secret | SDK Provider | ✅ |
|
|
208
|
-
| **Config** | AWS::SSM::Parameter | SDK Provider | ✅ |
|
|
209
|
-
| **Events** | AWS::Events::Rule | SDK Provider | ✅ |
|
|
210
|
-
| **Events** | AWS::Events::EventBus | SDK Provider | ✅ |
|
|
211
|
-
| **Networking** | AWS::EC2::VPC | SDK Provider | ✅ |
|
|
212
|
-
| **Networking** | AWS::EC2::Subnet | SDK Provider | ✅ |
|
|
213
|
-
| **Networking** | AWS::EC2::InternetGateway | SDK Provider | ✅ |
|
|
214
|
-
| **Networking** | AWS::EC2::VPCGatewayAttachment | SDK Provider | ✅ |
|
|
215
|
-
| **Networking** | AWS::EC2::RouteTable | SDK Provider | ✅ |
|
|
216
|
-
| **Networking** | AWS::EC2::Route | SDK Provider | ✅ |
|
|
217
|
-
| **Networking** | AWS::EC2::SubnetRouteTableAssociation | SDK Provider | ✅ |
|
|
218
|
-
| **Networking** | AWS::EC2::SecurityGroup | SDK Provider | ✅ |
|
|
219
|
-
| **Networking** | AWS::EC2::SecurityGroupIngress | SDK Provider | ✅ |
|
|
220
|
-
| **Networking** | AWS::EC2::NetworkAcl | SDK Provider | ✅ |
|
|
221
|
-
| **Networking** | AWS::EC2::NetworkAclEntry | SDK Provider | ✅ |
|
|
222
|
-
| **Networking** | AWS::EC2::SubnetNetworkAclAssociation | SDK Provider | ✅ |
|
|
223
|
-
| **Compute** | AWS::EC2::Instance | SDK Provider | ✅ |
|
|
224
|
-
| **API Gateway** | AWS::ApiGateway::Account | SDK Provider | ✅ |
|
|
225
|
-
| **API Gateway** | AWS::ApiGateway::Resource | SDK Provider | ✅ |
|
|
226
|
-
| **API Gateway** | AWS::ApiGateway::Deployment | SDK Provider | ✅ |
|
|
227
|
-
| **API Gateway** | AWS::ApiGateway::Stage | SDK Provider | ✅ |
|
|
228
|
-
| **API Gateway** | AWS::ApiGateway::Method | SDK Provider | ✅ |
|
|
229
|
-
| **API Gateway** | AWS::ApiGateway::Authorizer | SDK Provider | ✅ |
|
|
230
|
-
| **API Gateway** | AWS::ApiGatewayV2::Api | SDK Provider | ✅ |
|
|
231
|
-
| **API Gateway** | AWS::ApiGatewayV2::Stage | SDK Provider | ✅ |
|
|
232
|
-
| **API Gateway** | AWS::ApiGatewayV2::Integration | SDK Provider | ✅ |
|
|
233
|
-
| **API Gateway** | AWS::ApiGatewayV2::Route | SDK Provider | ✅ |
|
|
234
|
-
| **API Gateway** | AWS::ApiGatewayV2::Authorizer | SDK Provider | ✅ |
|
|
235
|
-
| **CDN** | AWS::CloudFront::CloudFrontOriginAccessIdentity | SDK Provider | ✅ |
|
|
236
|
-
| **CDN** | AWS::CloudFront::Distribution | SDK Provider | ✅ |
|
|
237
|
-
| **Orchestration** | AWS::StepFunctions::StateMachine | SDK Provider | ✅ |
|
|
238
|
-
| **Container** | AWS::ECS::Cluster | SDK Provider | ✅ |
|
|
239
|
-
| **Container** | AWS::ECS::TaskDefinition | SDK Provider | ✅ |
|
|
240
|
-
| **Container** | AWS::ECS::Service | SDK Provider | ✅ |
|
|
241
|
-
| **Load Balancing** | AWS::ElasticLoadBalancingV2::LoadBalancer | SDK Provider | ✅ |
|
|
242
|
-
| **Load Balancing** | AWS::ElasticLoadBalancingV2::TargetGroup | SDK Provider | ✅ |
|
|
243
|
-
| **Load Balancing** | AWS::ElasticLoadBalancingV2::Listener | SDK Provider | ✅ |
|
|
244
|
-
| **Database** | AWS::RDS::DBSubnetGroup | SDK Provider | ✅ |
|
|
245
|
-
| **Database** | AWS::RDS::DBCluster | SDK Provider | ✅ |
|
|
246
|
-
| **Database** | AWS::RDS::DBInstance | SDK Provider | ✅ |
|
|
247
|
-
| **DNS** | AWS::Route53::HostedZone | SDK Provider | ✅ |
|
|
248
|
-
| **DNS** | AWS::Route53::RecordSet | SDK Provider | ✅ |
|
|
249
|
-
| **Security** | AWS::WAFv2::WebACL | SDK Provider | ✅ |
|
|
250
|
-
| **Auth** | AWS::Cognito::UserPool | SDK Provider | ✅ |
|
|
251
|
-
| **Cache** | AWS::ElastiCache::CacheCluster | SDK Provider | ✅ |
|
|
252
|
-
| **Cache** | AWS::ElastiCache::SubnetGroup | SDK Provider | ✅ |
|
|
253
|
-
| **Discovery** | AWS::ServiceDiscovery::PrivateDnsNamespace | SDK Provider | ✅ |
|
|
254
|
-
| **Discovery** | AWS::ServiceDiscovery::Service | SDK Provider | ✅ |
|
|
255
|
-
| **GraphQL** | AWS::AppSync::GraphQLApi | SDK Provider | ✅ |
|
|
256
|
-
| **GraphQL** | AWS::AppSync::GraphQLSchema | SDK Provider | ✅ |
|
|
257
|
-
| **GraphQL** | AWS::AppSync::DataSource | SDK Provider | ✅ |
|
|
258
|
-
| **GraphQL** | AWS::AppSync::Resolver | SDK Provider | ✅ |
|
|
259
|
-
| **GraphQL** | AWS::AppSync::ApiKey | SDK Provider | ✅ |
|
|
260
|
-
| **Analytics** | AWS::Glue::Database | SDK Provider | ✅ |
|
|
261
|
-
| **Analytics** | AWS::Glue::Table | SDK Provider | ✅ |
|
|
262
|
-
| **Encryption** | AWS::KMS::Key | SDK Provider | ✅ |
|
|
263
|
-
| **Encryption** | AWS::KMS::Alias | SDK Provider | ✅ |
|
|
264
|
-
| **Streaming** | AWS::Kinesis::Stream | SDK Provider | ✅ |
|
|
265
|
-
| **Streaming** | AWS::KinesisFirehose::DeliveryStream | SDK Provider | ✅ |
|
|
266
|
-
| **Storage** | AWS::EFS::FileSystem | SDK Provider | ✅ |
|
|
267
|
-
| **Storage** | AWS::EFS::MountTarget | SDK Provider | ✅ |
|
|
268
|
-
| **Storage** | AWS::EFS::AccessPoint | SDK Provider | ✅ |
|
|
269
|
-
| **Storage** | AWS::S3Express::DirectoryBucket | SDK Provider | ✅ |
|
|
270
|
-
| **Storage** | AWS::S3Tables::TableBucket | SDK Provider | ✅ |
|
|
271
|
-
| **Storage** | AWS::S3Tables::Namespace | SDK Provider | ✅ |
|
|
272
|
-
| **Storage** | AWS::S3Tables::Table | SDK Provider | ✅ |
|
|
273
|
-
| **Storage** | AWS::S3Vectors::VectorBucket | SDK Provider | ✅ |
|
|
274
|
-
| **Audit** | AWS::CloudTrail::Trail | SDK Provider | ✅ |
|
|
275
|
-
| **CI/CD** | AWS::CodeBuild::Project | SDK Provider | ✅ |
|
|
276
|
-
| **AI/ML** | AWS::BedrockAgentCore::Runtime | SDK Provider | ✅ |
|
|
277
|
-
| **Custom** | Custom::* (Lambda/SNS-backed) | SDK Provider | ✅ |
|
|
278
|
-
| **Other** | All other resource types | Cloud Control | ✅ |
|
|
136
|
+
cdkd ships **90+ dedicated SDK Providers** (direct AWS SDK calls, no
|
|
137
|
+
polling overhead) covering the most-used services — IAM, Lambda, S3,
|
|
138
|
+
DynamoDB, EC2, RDS, ECS, API Gateway, CloudFront, Step Functions, EFS,
|
|
139
|
+
KMS, Cognito, AppSync, and more. **Any other CloudFormation resource
|
|
140
|
+
type** is handled via the Cloud Control API fallback (async polling).
|
|
141
|
+
Resource types not supported by either path fail at deploy time with a
|
|
142
|
+
clear error.
|
|
143
|
+
|
|
144
|
+
See **[docs/supported-resources.md](docs/supported-resources.md)** for
|
|
145
|
+
the full per-type table.
|
|
279
146
|
|
|
280
147
|
### Other Features
|
|
281
148
|
|
|
@@ -431,8 +298,8 @@ cdkd destroy --all --force
|
|
|
431
298
|
cdkd force-unlock MyStack
|
|
432
299
|
|
|
433
300
|
# Adopt already-deployed AWS resources into cdkd state.
|
|
434
|
-
# See
|
|
435
|
-
#
|
|
301
|
+
# See docs/import.md for the full guide (auto / selective / hybrid modes,
|
|
302
|
+
# --resource overrides, --resource-mapping CDK CLI compatibility).
|
|
436
303
|
cdkd import MyStack --dry-run
|
|
437
304
|
cdkd import MyStack --yes
|
|
438
305
|
|
|
@@ -503,76 +370,30 @@ cdkd state destroy MyStack --region us-east-1
|
|
|
503
370
|
> `cdkd destroy` (synth-driven, deletes AWS resources + state) and
|
|
504
371
|
> `cdkd state destroy` (state-driven, same effect) round out the matrix.
|
|
505
372
|
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
| Option | Default | Description |
|
|
509
|
-
| --- | --- | --- |
|
|
510
|
-
| `--concurrency` | 10 | Maximum concurrent resource operations per stack |
|
|
511
|
-
| `--stack-concurrency` | 4 | Maximum concurrent stack deployments |
|
|
512
|
-
| `--asset-publish-concurrency` | 8 | Maximum concurrent asset publish operations (S3 + ECR push) |
|
|
513
|
-
| `--image-build-concurrency` | 4 | Maximum concurrent Docker image builds |
|
|
514
|
-
|
|
515
|
-
## `--no-wait`
|
|
373
|
+
## `--no-wait`: skip async-resource waits
|
|
516
374
|
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
375
|
+
CloudFront Distributions, RDS Clusters/Instances, and ElastiCache
|
|
376
|
+
typically take 3–15 minutes for AWS to fully propagate. By default
|
|
377
|
+
cdkd waits for them to reach a ready state — the same behavior as
|
|
378
|
+
CloudFormation. Pass `--no-wait` to return as soon as the create call
|
|
379
|
+
returns:
|
|
520
380
|
|
|
521
381
|
```bash
|
|
522
382
|
cdkd deploy --no-wait
|
|
523
383
|
```
|
|
524
384
|
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
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.
|
|
530
|
-
|
|
531
|
-
| Option | Default | Description |
|
|
532
|
-
| --- | --- | --- |
|
|
533
|
-
| `--resource-warn-after <duration_or_type=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). Repeatable. |
|
|
534
|
-
| `--resource-timeout <duration_or_type=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. Repeatable. |
|
|
535
|
-
|
|
536
|
-
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.
|
|
537
|
-
|
|
538
|
-
Both flags accept either form on each invocation:
|
|
539
|
-
|
|
540
|
-
- **Bare duration** (`30m`) sets the global default. The last bare value wins.
|
|
541
|
-
- **`TYPE=DURATION`** (`AWS::CloudFront::Distribution=1h`) adds a per-resource-type override that supersedes the global default for that type only.
|
|
542
|
-
|
|
543
|
-
`TYPE` must look like `AWS::Service::Resource`; malformed types are rejected at parse time. `warn < timeout` is enforced both globally and per-type — so `--resource-warn-after AWS::X=10m --resource-timeout AWS::X=5m` is a parse-time error.
|
|
544
|
-
|
|
545
|
-
```bash
|
|
546
|
-
# Surface "still running" warnings sooner on a fast-feedback dev loop
|
|
547
|
-
cdkd deploy --resource-warn-after 90s --resource-timeout 10m
|
|
548
|
-
|
|
549
|
-
# Keep the global default tight, raise it only for resources known to take longer
|
|
550
|
-
cdkd deploy \
|
|
551
|
-
--resource-timeout 30m \
|
|
552
|
-
--resource-timeout AWS::CloudFront::Distribution=1h \
|
|
553
|
-
--resource-timeout AWS::RDS::DBCluster=1h30m
|
|
554
|
-
|
|
555
|
-
# Force Custom Resources to abort earlier than their 1h self-reported polling cap
|
|
556
|
-
cdkd deploy --resource-timeout AWS::CloudFormation::CustomResource=5m
|
|
557
|
-
```
|
|
558
|
-
|
|
559
|
-
### Why the default is 30m, not 1h
|
|
560
|
-
|
|
561
|
-
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 non-CR resource hold the whole stack for an hour even though no other resource type ever needs more than a few minutes. The 30m global default catches stuck operations faster.
|
|
385
|
+
The resource is fully functional once AWS finishes the async
|
|
386
|
+
deployment in the background. CloudFormation has no equivalent — once
|
|
387
|
+
you submit a stack, you wait for everything.
|
|
562
388
|
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
The error message on timeout names the resource, type, region, elapsed time, and operation, and reminds you that long-running resources self-report their needed budget — when you see CR time out, the cause is genuinely the handler, not too-tight a default:
|
|
566
|
-
|
|
567
|
-
```text
|
|
568
|
-
Resource MyBucket (AWS::S3::Bucket) in us-east-1 timed out after 30m during CREATE (elapsed 30m).
|
|
569
|
-
This may indicate a stuck Cloud Control polling loop, hung Custom Resource, or
|
|
570
|
-
slow ENI provisioning. Re-run with --resource-timeout AWS::S3::Bucket=<DURATION>
|
|
571
|
-
to bump the budget for this resource type only, or --verbose to see the
|
|
572
|
-
underlying provider activity.
|
|
573
|
-
```
|
|
389
|
+
## Other CLI flags
|
|
574
390
|
|
|
575
|
-
|
|
391
|
+
For concurrency knobs (`--concurrency`, `--stack-concurrency`,
|
|
392
|
+
`--asset-publish-concurrency`, `--image-build-concurrency`) and
|
|
393
|
+
per-resource timeout flags (`--resource-warn-after`,
|
|
394
|
+
`--resource-timeout` — including the per-resource-type override syntax
|
|
395
|
+
and the rationale for the 30m default), see
|
|
396
|
+
**[docs/cli-reference.md](docs/cli-reference.md)**.
|
|
576
397
|
|
|
577
398
|
## Example
|
|
578
399
|
|
|
@@ -602,397 +423,48 @@ LambdaStack
|
|
|
602
423
|
|
|
603
424
|
Resources are dispatched as soon as their own dependencies complete (event-driven DAG). ServiceRole and Table run in parallel; DefaultPolicy starts the moment ServiceRole is done — without waiting for Table — and Handler starts the moment DefaultPolicy is done.
|
|
604
425
|
|
|
605
|
-
## Architecture
|
|
606
|
-
|
|
607
|
-
Built on modern AWS tooling:
|
|
608
|
-
|
|
609
|
-
- **Synthesis orchestration** - Executes CDK app as subprocess (synthesis itself is done by aws-cdk-lib), parses Cloud Assembly (manifest.json) directly, context provider loop (missing context → SDK lookup → re-synthesize)
|
|
610
|
-
- **Self-implemented asset publisher** - S3 file upload with ZIP packaging (via `archiver`) and ECR Docker image publishing
|
|
611
|
-
- **AWS SDK v3** - Direct resource provisioning
|
|
612
|
-
- **Cloud Control API** - Fallback resource management for types without SDK Providers
|
|
613
|
-
- **S3 Conditional Writes** - State locking via `If-None-Match`/`If-Match`
|
|
614
|
-
|
|
615
426
|
## Importing existing resources
|
|
616
427
|
|
|
617
|
-
`cdkd import` adopts AWS resources that are already deployed (
|
|
618
|
-
`cdk deploy`, manual creation, or another tool) into cdkd state
|
|
619
|
-
next `cdkd deploy` updates them in-place instead of
|
|
620
|
-
duplicates.
|
|
621
|
-
|
|
622
|
-
It reads the CDK app to find logical IDs, resource types, and
|
|
623
|
-
dependencies, then matches each logical ID to a real AWS resource in
|
|
624
|
-
one of three modes:
|
|
625
|
-
|
|
626
|
-
All examples below assume cdkd reads the CDK app command from `cdk.json`
|
|
627
|
-
(the typical case). Pass `--app "<command>"` only if you're running cdkd
|
|
628
|
-
outside the CDK project directory or want to override `cdk.json`.
|
|
629
|
-
|
|
630
|
-
### Mode 1: auto (default — no flags)
|
|
428
|
+
`cdkd import` adopts AWS resources that are already deployed (via
|
|
429
|
+
`cdk deploy`, manual creation, or another tool) into cdkd state so the
|
|
430
|
+
next `cdkd deploy` updates them in-place instead of CREATEing duplicates.
|
|
631
431
|
|
|
632
432
|
```bash
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
Imports **every** resource in the synthesized template by tag. cdkd
|
|
637
|
-
looks up each resource using its `aws:cdk:path` tag (which CDK
|
|
638
|
-
automatically writes), so resources deployed by `cdk deploy` are found
|
|
639
|
-
without any manual work. Useful for **adopting a whole stack** that was
|
|
640
|
-
previously deployed by `cdk deploy`. This is cdkd's value-add over
|
|
641
|
-
`cdk import` — CDK CLI does not have a tag-based bulk-import mode.
|
|
642
|
-
|
|
643
|
-
### Mode 2: selective (CDK CLI parity — when explicit overrides are given)
|
|
644
|
-
|
|
645
|
-
```bash
|
|
646
|
-
# Import ONLY MyBucket; the other resources in the template are left alone.
|
|
647
|
-
cdkd import MyStack --resource MyBucket=my-bucket-name
|
|
648
|
-
|
|
649
|
-
# Several resources at once (--resource is repeatable).
|
|
650
|
-
cdkd import MyStack \
|
|
651
|
-
--resource MyBucket=my-bucket-name \
|
|
652
|
-
--resource MyFn=my-function-name
|
|
653
|
-
|
|
654
|
-
# CDK CLI compat: read overrides from a JSON file.
|
|
655
|
-
cdkd import MyStack --resource-mapping mapping.json
|
|
656
|
-
# mapping.json: { "MyBucket": "my-bucket-name", "MyFn": "my-function-name" }
|
|
657
|
-
|
|
658
|
-
# CDK CLI compat: inline JSON (handy for non-TTY CI scripts).
|
|
659
|
-
cdkd import MyStack --resource-mapping-inline '{"MyBucket":"my-bucket-name"}'
|
|
660
|
-
|
|
661
|
-
# Capture cdkd's resolved logicalId→physicalId mapping for re-use.
|
|
662
|
-
# Combine with --auto (or no flags) to record the tag-based lookups.
|
|
663
|
-
cdkd import MyStack --record-resource-mapping ./mapping.json
|
|
664
|
-
# mapping.json after the run: { "MyBucket": "my-bucket-name", ... }
|
|
665
|
-
# Replay non-interactively in CI:
|
|
666
|
-
cdkd import MyStack --resource-mapping ./mapping.json --yes
|
|
667
|
-
```
|
|
668
|
-
|
|
669
|
-
When at least one `--resource` flag (or a `--resource-mapping` /
|
|
670
|
-
`--resource-mapping-inline` payload) is supplied, **only the listed
|
|
671
|
-
resources are imported**. Every other resource in the template is
|
|
672
|
-
reported as `out of scope` and left out of state — the next `cdkd
|
|
673
|
-
deploy` will treat them as new and CREATE them. This matches the
|
|
674
|
-
semantics of `cdk import --resource-mapping` /
|
|
675
|
-
`--resource-mapping-inline`. cdkd validates that every override key is
|
|
676
|
-
a real logical ID in the template; a typo aborts the run rather than
|
|
677
|
-
silently importing nothing. `--resource-mapping` and
|
|
678
|
-
`--resource-mapping-inline` are mutually exclusive — pick one source.
|
|
679
|
-
|
|
680
|
-
Use selective mode when you want to **adopt a few specific resources**
|
|
681
|
-
out of a larger stack — for example, you have one S3 bucket that was
|
|
682
|
-
created manually that you want cdkd to manage, while the rest of the
|
|
683
|
-
stack will be deployed fresh.
|
|
684
|
-
|
|
685
|
-
**Selective mode is non-destructive.** When state already exists for
|
|
686
|
-
the stack, listed resources are **merged** into it: unlisted entries
|
|
687
|
-
already in state are preserved (no `--force` needed). `--force` is
|
|
688
|
-
only required when a listed override would overwrite a resource
|
|
689
|
-
already in state — that's the one case where the merge is destructive.
|
|
690
|
-
This is the right command for "I have a deployed stack and want to
|
|
691
|
-
adopt one more resource into it":
|
|
433
|
+
# Adopt a whole stack previously deployed by cdk deploy (tag-based auto-lookup).
|
|
434
|
+
cdkd import MyStack --yes
|
|
692
435
|
|
|
693
|
-
|
|
694
|
-
# Existing state has Queue + Topic; add Bucket without affecting them.
|
|
436
|
+
# Adopt only specific resources (CDK CLI parity).
|
|
695
437
|
cdkd import MyStack --resource MyBucket=my-bucket-name
|
|
696
|
-
# Resulting state: Queue + Topic (preserved) + Bucket (newly imported).
|
|
697
|
-
```
|
|
698
438
|
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
```bash
|
|
702
|
-
cdkd import MyStack \
|
|
703
|
-
--resource MyBucket=my-bucket-name \
|
|
704
|
-
--auto
|
|
705
|
-
```
|
|
706
|
-
|
|
707
|
-
Listed resources use the explicit physical ID you supplied; **every
|
|
708
|
-
other resource still goes through tag-based auto-import**. Useful when
|
|
709
|
-
you have one resource whose tag-based lookup is unreliable (e.g. you
|
|
710
|
-
deleted and re-created it without the tag) but you want cdkd to find
|
|
711
|
-
the rest by tag automatically.
|
|
712
|
-
|
|
713
|
-
### Common flags
|
|
714
|
-
|
|
715
|
-
| Flag | Purpose |
|
|
716
|
-
| --- | --- |
|
|
717
|
-
| `--dry-run` | Preview what would be imported. State is NOT written. |
|
|
718
|
-
| `--yes` | Skip the confirmation prompt before writing state (and the CloudFormation retirement prompt under `--migrate-from-cloudformation`). |
|
|
719
|
-
| `--force` | Confirm a destructive write to existing state — see below. |
|
|
720
|
-
| `--migrate-from-cloudformation [name]` | After cdkd state is written, retire the source CloudFormation stack: inject `DeletionPolicy: Retain` + `UpdateReplacePolicy: Retain` on every resource via `UpdateStack`, then `DeleteStack`. AWS resources are NOT deleted. See [Migrating from `cdk deploy` (CloudFormation) to cdkd](#migrating-from-cdk-deploy-cloudformation-to-cdkd) below. |
|
|
721
|
-
|
|
722
|
-
`--force` is only needed when the import would lose data:
|
|
723
|
-
|
|
724
|
-
- **Auto / whole-stack mode + existing state**: required. The resource
|
|
725
|
-
map is rebuilt from the template, so any state entry not re-imported
|
|
726
|
-
is dropped.
|
|
727
|
-
- **Selective mode + listed override already in state**: required.
|
|
728
|
-
The listed entry is overwritten with the new physical id.
|
|
729
|
-
- **Selective mode without a conflict (pure merge)**: not required.
|
|
730
|
-
Unlisted state entries are preserved automatically.
|
|
731
|
-
- **No existing state (first-time import)**: not required.
|
|
732
|
-
|
|
733
|
-
### Migrating from `cdk deploy` (CloudFormation) to cdkd
|
|
734
|
-
|
|
735
|
-
If a stack was previously deployed via `cdk deploy` (and is therefore
|
|
736
|
-
managed by CloudFormation), `cdkd import --migrate-from-cloudformation` adopts
|
|
737
|
-
the resources into cdkd state AND retires the source CloudFormation
|
|
738
|
-
stack in one go:
|
|
739
|
-
|
|
740
|
-
```bash
|
|
439
|
+
# Migrate off CloudFormation in one shot — adopt + retire the source CFn stack.
|
|
741
440
|
cdkd import MyStack --migrate-from-cloudformation --yes
|
|
742
441
|
```
|
|
743
442
|
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
here: upstream `cdk deploy` doesn't propagate the `aws:cdk:path` template
|
|
749
|
-
metadata as a real AWS tag, and AWS reserves the `aws:` tag prefix so
|
|
750
|
-
neither cdkd nor a CFn `UpdateStack` can add it on the way through.)
|
|
751
|
-
|
|
752
|
-
The flow:
|
|
753
|
-
|
|
754
|
-
1. `DescribeStackResources` — ask CloudFormation for every
|
|
755
|
-
`(LogicalResourceId, PhysicalResourceId)` pair in the source stack.
|
|
756
|
-
These are merged into the import overrides; user-supplied
|
|
757
|
-
`--resource <id>=<physical>` flags take precedence over CFn's view.
|
|
758
|
-
2. `cdkd import` runs and adopts every resource into cdkd state via
|
|
759
|
-
each provider's `import()` method, using the CFn-resolved physical
|
|
760
|
-
ids as direct lookups.
|
|
761
|
-
3. `cdkd` writes state.
|
|
762
|
-
4. `DescribeStacks` + `GetTemplate` + `UpdateStack` to inject
|
|
763
|
-
`DeletionPolicy: Retain` and `UpdateReplacePolicy: Retain` on every
|
|
764
|
-
resource — a metadata-only update.
|
|
765
|
-
5. `DeleteStack` — every resource is now `Retain`, so CloudFormation
|
|
766
|
-
walks the stack and skips every resource. The stack record disappears;
|
|
767
|
-
the underlying AWS resources are left intact and are now solely
|
|
768
|
-
managed by cdkd.
|
|
769
|
-
|
|
770
|
-
Steps 1–5 all run inside the same lock so a concurrent `cdkd deploy`
|
|
771
|
-
cannot race the in-flight migration.
|
|
772
|
-
|
|
773
|
-
By default the CloudFormation stack name is taken from the cdkd stack
|
|
774
|
-
name (the typical case — CDK uses the synthesized stack name as the CFn
|
|
775
|
-
stack name). Pass an explicit value when the names differ:
|
|
776
|
-
|
|
777
|
-
```bash
|
|
778
|
-
cdkd import MyStack --migrate-from-cloudformation LegacyCfnStackName --yes
|
|
779
|
-
```
|
|
780
|
-
|
|
781
|
-
Limitations:
|
|
782
|
-
|
|
783
|
-
- **JSON-only.** The Retain-policy injection in step 4 targets the CDK-
|
|
784
|
-
generated JSON template. Hand-written YAML CFn stacks fail with a
|
|
785
|
-
clear error; retire them manually.
|
|
786
|
-
- **51,200-byte template limit.** The modified template is submitted
|
|
787
|
-
inline via `TemplateBody`. Stacks whose modified template exceeds
|
|
788
|
-
this limit fail in step 4 with a clear error pointing to the manual
|
|
789
|
-
3-step procedure (S3-backed `TemplateURL` fallback is a planned
|
|
790
|
-
follow-up). cdkd state has already been written at that point, so
|
|
791
|
-
re-runs and manual cleanup are both supported.
|
|
792
|
-
- **Not compatible with `--dry-run`.** The post-state-write
|
|
793
|
-
`UpdateStack` + `DeleteStack` are real side-effects and cannot be
|
|
794
|
-
faithfully simulated. Use plain `cdkd import --dry-run` to preview
|
|
795
|
-
per-resource import outcomes.
|
|
796
|
-
- **Partial imports leave unmanaged resources.** If a resource cannot
|
|
797
|
-
be imported (no provider, AWS not-found, etc.), `DeleteStack` skips
|
|
798
|
-
it (Retain) and cdkd never wrote it into state — so the resource
|
|
799
|
-
exists in AWS but unmanaged by both CloudFormation and cdkd. cdkd
|
|
800
|
-
warns loudly when this happens; either re-import the missing
|
|
801
|
-
resources first or accept the orphaning intentionally.
|
|
802
|
-
|
|
803
|
-
### After import
|
|
804
|
-
|
|
805
|
-
Run `cdkd diff` to see how the imported state lines up with the
|
|
806
|
-
template. If the resource's actual properties differ from the template,
|
|
807
|
-
the next `cdkd deploy` will UPDATE them to match. If you imported only
|
|
808
|
-
some resources (selective mode), the remaining template resources
|
|
809
|
-
appear as `to create` in the diff.
|
|
810
|
-
|
|
811
|
-
### Provider support
|
|
812
|
-
|
|
813
|
-
Tag-based auto-lookup is implemented for the most-used resource types
|
|
814
|
-
(S3 Bucket, Lambda Function, IAM Role, SNS Topic, SQS Queue, DynamoDB
|
|
815
|
-
Table, Logs LogGroup, EventBridge EventBus, KMS Key/Alias, Secrets
|
|
816
|
-
Manager Secret, SSM Parameter, EC2 VPC/Subnet/SecurityGroup, RDS,
|
|
817
|
-
ECS Cluster/Service/TaskDefinition, CloudFront Distribution, Cognito
|
|
818
|
-
User Pool — the full list is in [CLAUDE.md](CLAUDE.md)). For resource
|
|
819
|
-
types without auto-lookup support (ApiGateway sub-resources, niche
|
|
820
|
-
services, anything in Cloud Control API), use the explicit
|
|
821
|
-
`--resource <id>=<physicalId>` override mode — selective mode handles
|
|
822
|
-
exactly this case. Resource types whose provider does not implement
|
|
823
|
-
import are reported as `unsupported` and skipped.
|
|
824
|
-
|
|
825
|
-
### `cdkd import` vs upstream `cdk import`
|
|
826
|
-
|
|
827
|
-
cdkd's `import` command mirrors the surface of upstream
|
|
828
|
-
[`cdk import`](https://docs.aws.amazon.com/cdk/v2/guide/ref-cli-cmd-import.html)
|
|
829
|
-
where it can, but the underlying mechanism is fundamentally different
|
|
830
|
-
and a handful of upstream-only flags are not implemented. Use this
|
|
831
|
-
table to predict behavior when migrating from `cdk import`.
|
|
832
|
-
|
|
833
|
-
| Topic | `cdk import` (upstream) | `cdkd import` |
|
|
834
|
-
| --- | --- | --- |
|
|
835
|
-
| Mechanism | CloudFormation `CreateChangeSet` with `ResourcesToImport` — atomic, all-or-nothing. | Per-resource SDK calls (e.g. `s3:HeadBucket`, `lambda:GetFunction`, IAM `ListRoleTags`). **Not atomic.** |
|
|
836
|
-
| 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). |
|
|
837
|
-
| 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). |
|
|
838
|
-
| Selective mode (`--resource <id>=<physical>` repeatable) | Not supported (upstream uses interactive prompts or a mapping file). | Supported as cdkd's CLI-friendly equivalent. |
|
|
839
|
-
| `--resource-mapping-inline '<json>'` | Supported (use in non-TTY environments). | Supported. Same shape as `--resource-mapping <file>` but supplied as a string — useful for non-TTY CI scripts that do not want a separate file. Mutually exclusive with `--resource-mapping`. |
|
|
840
|
-
| `--record-resource-mapping <file>` | Supported (writes the mapping the user typed at the prompt to a file for re-use). | Supported. Writes the resolved `{logicalId: physicalId}` map (covers explicit overrides AND cdkd's tag-based auto-lookup) to the file before the confirmation prompt. The file is produced even if the user says "no" or under `--dry-run`, so the resolved data is never thrown away. |
|
|
841
|
-
| 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. |
|
|
842
|
-
| 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. |
|
|
843
|
-
| 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`. |
|
|
844
|
-
| 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. |
|
|
845
|
-
| 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. |
|
|
846
|
-
| Bootstrap requirement | Bootstrap v12+ (deploy role needs to read the encrypted staging bucket). | cdkd's own state bucket; no CDK bootstrap version requirement. |
|
|
847
|
-
| 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. |
|
|
848
|
-
| Confirmation prompt before writing state | n/a (CloudFormation operates atomically). | Yes — cdkd asks before writing the state file. Skip with `--yes`. |
|
|
849
|
-
| `--force` | "Continue even if the diff includes updates or deletions" — about diff strictness. | "Confirm a destructive write to existing state" — required for auto/whole-stack rebuild and for overwriting a listed entry already in state; not required for a pure selective merge. **Same flag name, different meaning.** |
|
|
850
|
-
| `--dry-run` | Implied by `--no-execute` (creates the changeset without executing). | Native: shows the import plan and exits without writing state. |
|
|
851
|
-
|
|
852
|
-
#### Practical implications when migrating from `cdk import`
|
|
853
|
-
|
|
854
|
-
- If you script around `--resource-mapping <file>`: behavior matches.
|
|
855
|
-
The file format (`{"LogicalId": "physical-id"}`) is the same.
|
|
856
|
-
- If you script around `--resource-mapping-inline`: behavior matches.
|
|
857
|
-
The JSON shape is the same as `--resource-mapping <file>`.
|
|
858
|
-
- If you script around `--record-resource-mapping <file>`: behavior
|
|
859
|
-
matches. cdkd writes the resolved `{logicalId: physicalId}` map to
|
|
860
|
-
the file before the confirmation prompt — and even if the user says
|
|
861
|
-
"no" or under `--dry-run` — so you can capture cdkd's tag-based
|
|
862
|
-
auto-lookup result and replay it via `--resource-mapping` in CI.
|
|
863
|
-
- If your workflow relies on the interactive prompt: rewrite as
|
|
864
|
-
`--resource-mapping <file>`. cdkd will not prompt.
|
|
865
|
-
- If you rely on atomic rollback: cdkd cannot offer that — its
|
|
866
|
-
per-resource model writes state only after the full pass completes
|
|
867
|
-
(and after confirmation), so a partial run is bounded, but if a
|
|
868
|
-
later resource fails after several earlier ones already returned
|
|
869
|
-
successfully and you confirm the write, those earlier ones are
|
|
870
|
-
in cdkd state. Use `cdkd state orphan <stack>` to back out.
|
|
871
|
-
- If you import nested stacks: neither tool supports this. Convert
|
|
872
|
-
to top-level CDK stacks first.
|
|
443
|
+
See **[docs/import.md](docs/import.md)** for the full guide: three import
|
|
444
|
+
modes (auto / selective / hybrid), `--resource-mapping` CDK CLI
|
|
445
|
+
compatibility, CloudFormation migration flow, provider coverage, and the
|
|
446
|
+
parity matrix vs upstream `cdk import`.
|
|
873
447
|
|
|
874
448
|
## State Management
|
|
875
449
|
|
|
876
|
-
State is stored in S3
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
```
|
|
880
|
-
s3://{state-bucket}/
|
|
881
|
-
└── {prefix}/ # Default: "cdkd" (configurable via --state-prefix)
|
|
882
|
-
├── MyStack/
|
|
883
|
-
│ └── us-east-1/
|
|
884
|
-
│ ├── state.json # Resource state (version: 2)
|
|
885
|
-
│ └── lock.json # Exclusive deploy lock
|
|
886
|
-
└── AnotherStack/
|
|
887
|
-
├── us-east-1/
|
|
888
|
-
│ ├── state.json
|
|
889
|
-
│ └── lock.json
|
|
890
|
-
└── us-west-2/ # same stackName, different region
|
|
891
|
-
├── state.json
|
|
892
|
-
└── lock.json
|
|
893
|
-
```
|
|
894
|
-
|
|
895
|
-
> **Caveat: same `stackName` in multiple regions becomes visible after
|
|
896
|
-
> `env.region` changes.** Before this layout shipped, changing a stack's
|
|
897
|
-
> `env.region` between deploys silently overwrote the prior region's state
|
|
898
|
-
> and `cdkd destroy` ran against the wrong region. cdkd now treats the two
|
|
899
|
-
> regions as independent. Use `cdkd state list` to see both, and
|
|
900
|
-
> `cdkd state orphan <stack> --stack-region <region>` to prune one without
|
|
901
|
-
> touching the other.
|
|
902
|
-
>
|
|
903
|
-
> **Legacy key-layout migration (within the same bucket):** state files
|
|
904
|
-
> written by cdkd before this layout (`version: 1`, flat
|
|
905
|
-
> `cdkd/{stackName}/state.json`) are still readable. The next cdkd write
|
|
906
|
-
> auto-migrates to the new region-prefixed key
|
|
907
|
-
> (`cdkd/{stackName}/{region}/state.json`) and removes the legacy file —
|
|
908
|
-
> no manual action required. An older cdkd binary reading a `version: 2`
|
|
909
|
-
> file fails with a clear "upgrade cdkd" error rather than silently
|
|
910
|
-
> mishandling it.
|
|
911
|
-
>
|
|
912
|
-
> Note: this only covers the **key layout inside an existing state
|
|
913
|
-
> bucket**. The separate **bucket-name migration** (legacy
|
|
914
|
-
> `cdkd-state-{accountId}-{region}` → new `cdkd-state-{accountId}`)
|
|
915
|
-
> is described below and does NOT auto-migrate.
|
|
916
|
-
|
|
917
|
-
### Bucket migration
|
|
918
|
-
|
|
919
|
-
The default state-bucket name changed in v0.11.0 from the region-suffixed
|
|
920
|
-
`cdkd-state-{accountId}-{region}` to the region-free
|
|
921
|
-
`cdkd-state-{accountId}`. The bucket name is region-free because S3 names
|
|
922
|
-
are globally unique, so teammates with different profile regions all
|
|
923
|
-
converge on the same bucket; the bucket's actual region is auto-detected
|
|
924
|
-
via `GetBucketLocation`.
|
|
925
|
-
|
|
926
|
-
Existing users keep working without doing anything: when only the legacy
|
|
927
|
-
bucket exists, cdkd transparently falls back to it and emits a
|
|
928
|
-
deprecation warning. To stop the warning (and consolidate state into the
|
|
929
|
-
new bucket) run:
|
|
930
|
-
|
|
931
|
-
```bash
|
|
932
|
-
# Per-region: copies all objects from cdkd-state-{accountId}-{region}
|
|
933
|
-
# into cdkd-state-{accountId}. Source bucket is kept by default.
|
|
934
|
-
cdkd state migrate --region us-east-1
|
|
935
|
-
|
|
936
|
-
# Optional: delete the legacy bucket once the copy is verified.
|
|
937
|
-
cdkd state migrate --region us-east-1 --remove-legacy
|
|
938
|
-
```
|
|
939
|
-
|
|
940
|
-
This migration is **account-wide / per-region**, not per-stack — running
|
|
941
|
-
it once per region clears the legacy bucket for that region in one shot.
|
|
942
|
-
For multi-region accounts, run it once per region (each invocation copies
|
|
943
|
-
into the same destination bucket).
|
|
944
|
-
|
|
945
|
-
`cdkd state migrate` refuses to run while any stack has an active
|
|
946
|
-
`lock.json` (an in-flight `cdkd deploy` / `destroy` would race the copy),
|
|
947
|
-
verifies object-count parity between source and destination before any
|
|
948
|
-
source cleanup, and only deletes the legacy bucket when
|
|
949
|
-
`--remove-legacy` is passed.
|
|
950
|
-
|
|
951
|
-
See the [Configuration](#configuration) table below for the full
|
|
952
|
-
precedence rules of the `--state-bucket` flag and its env-var / cdk.json
|
|
953
|
-
fallbacks.
|
|
954
|
-
|
|
955
|
-
### Configuration
|
|
450
|
+
State is stored in S3 with optimistic locking via S3 Conditional Writes
|
|
451
|
+
(no DynamoDB required). Keys are scoped by `(stackName, region)` so the
|
|
452
|
+
same stack deployed to two regions has two independent state files.
|
|
956
453
|
|
|
957
454
|
| Setting | CLI | cdk.json | Env var | Default |
|
|
958
455
|
|---------|-----|----------|---------|---------|
|
|
959
|
-
| Bucket | `--state-bucket` | `context.cdkd.stateBucket` | `CDKD_STATE_BUCKET` | `cdkd-state-{accountId}` (legacy `cdkd-state-{accountId}-{region}` is still read with a deprecation warning) |
|
|
456
|
+
| Bucket | `--state-bucket` | `context.cdkd.stateBucket` | `CDKD_STATE_BUCKET` | `cdkd-state-{accountId}` (legacy `cdkd-state-{accountId}-{region}` is still read with a deprecation warning — run `cdkd state migrate` to consolidate) |
|
|
960
457
|
| Prefix | `--state-prefix` | - | - | `cdkd` |
|
|
961
458
|
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
```bash
|
|
967
|
-
# App A
|
|
968
|
-
cdkd deploy --state-prefix app-a
|
|
969
|
-
|
|
970
|
-
# App B
|
|
971
|
-
cdkd deploy --state-prefix app-b
|
|
972
|
-
```
|
|
973
|
-
|
|
974
|
-
> **Note**: `cdkd destroy --all` only targets stacks from the current CDK app (determined by synthesis), not all stacks in the bucket.
|
|
459
|
+
The state bucket is shared across all CDK apps in the same account by
|
|
460
|
+
default. To isolate apps, pass different `--state-prefix` values.
|
|
461
|
+
`cdkd destroy --all` only targets stacks from the current CDK app
|
|
462
|
+
(determined by synthesis), not all stacks in the bucket.
|
|
975
463
|
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
version: 2,
|
|
981
|
-
stackName: "MyStack",
|
|
982
|
-
region: "us-east-1",
|
|
983
|
-
resources: {
|
|
984
|
-
"MyFunction": {
|
|
985
|
-
physicalId: "arn:aws:lambda:...",
|
|
986
|
-
resourceType: "AWS::Lambda::Function",
|
|
987
|
-
properties: { ... },
|
|
988
|
-
attributes: { Arn: "...", ... }, // For Fn::GetAtt
|
|
989
|
-
dependencies: ["MyBucket"] // For proper deletion order
|
|
990
|
-
}
|
|
991
|
-
},
|
|
992
|
-
outputs: { ... },
|
|
993
|
-
lastModified: 1234567890
|
|
994
|
-
}
|
|
995
|
-
```
|
|
464
|
+
See **[docs/state-management.md](docs/state-management.md)** for the full
|
|
465
|
+
spec: S3 key layout, optimistic-locking mechanism (ETag-based), state
|
|
466
|
+
schema, legacy `version: 1` migration, bucket-name migration via
|
|
467
|
+
`cdkd state migrate`, and troubleshooting.
|
|
996
468
|
|
|
997
469
|
## Stack Outputs
|
|
998
470
|
|
|
@@ -1022,19 +494,6 @@ After deployment, outputs are resolved and saved to the S3 state file:
|
|
|
1022
494
|
- cdkd: Outputs saved in S3 state file (e.g., `s3://bucket/cdkd/MyStack/us-east-1/state.json`)
|
|
1023
495
|
- Both resolve intrinsic functions (Ref, Fn::GetAtt, etc.) to actual values
|
|
1024
496
|
|
|
1025
|
-
## Testing
|
|
1026
|
-
|
|
1027
|
-
- Unit tests covering all layers
|
|
1028
|
-
- Integration examples verified with real AWS deployments (see `tests/integration/`)
|
|
1029
|
-
- E2E test script for automated deploy/diff/update/destroy cycles
|
|
1030
|
-
|
|
1031
|
-
```bash
|
|
1032
|
-
pnpm test # Run unit tests
|
|
1033
|
-
pnpm run test:coverage # With coverage report
|
|
1034
|
-
```
|
|
1035
|
-
|
|
1036
|
-
See [docs/testing.md](docs/testing.md) for integration and E2E testing instructions.
|
|
1037
|
-
|
|
1038
497
|
## License
|
|
1039
498
|
|
|
1040
499
|
Apache 2.0
|