Import internals
Detail behind Importing Existing Resources and its sub-pages
(Import options and the import plan,
Importing by resource type and
After an import) that you need only when debugging an
import or changing cdkd import itself.
Nested-stack migration
--migrate-from-cloudformation walks a CloudFormation stack that contains
AWS::CloudFormation::Stack children recursively.
- Reading ids. For every nested-stack row, cdkd calls
DescribeStackResources(<child ARN>)to enumerate the child's resources, and so on to arbitrary depth. Children at every level are fetched in parallel. - Writing state. After the root state is written, cdkd writes one
v6-keyed state file per nested child at
cdkd/<parent>~<childLogicalId>/<region>/state.json, withparentStack/parentLogicalId/parentRegionpopulated. Grandchildren getcdkd/<parent>~<child>~<grand>/<region>/state.json. Per-child locks are acquired before the write and released in reverse on success or failure. - The parent's row. The root parent's state entry for each nested-stack
row carries the synthesized cdkd-local ARN
(
arn:cdkd-local:<region>:<account>:nested-stack/<parent>/<logicalId>), not the real AWS child stack ARN. This matches what acdkd deploywrites for a nested stack, so an import followed by a deploy shows no phantom property change. - Retain injection. For every nested-stack row in the parent template,
cdkd fetches the child's template with
GetTemplate, injects Retain on every non-nested-stack resource at every depth, uploads the modified child template to the cdkd state bucket, and rewrites the parent'sProperties.TemplateURLto point at it. The parent-sideDeleteStackcascades into each child: every leaf resource is retained, and the child stack record is deleted as a side effect.
The synthesized template and the AWS shape are validated up front. A nested-stack row in the template with no matching AWS child, or the reverse, is an error before any state write and names the logical id.
Template format and size
The Retain injection parses the source template through cdkd's
CloudFormation-aware codec, which preserves every shorthand intrinsic (!Ref,
!Sub, !GetAtt, !Join) across the parse, inject and re-serialize round
trip. The update submits the template in the same format as the source: a
YAML-authored stack stays YAML, with a .yaml key suffix and an
application/x-yaml content type when uploaded.
Templates up to the 51,200-byte inline TemplateBody limit are submitted
directly. Larger templates are uploaded to the state bucket under
cdkd-migrate-tmp/<stack>/<timestamp>.json and submitted with TemplateURL;
the object is deleted right after UpdateStack. Templates over the 1 MB
TemplateURL limit cannot be submitted. The same limit applies independently
to every uploaded nested-child template.
Stacks imported with cdkd 0.290.35
cdkd 0.290.35 recorded a baseline refusal without its reason. cdkd 0.290.35
and 0.290.36 both clear a marker that has no reason. If a stack imported with
0.290.35 has since had one of these resources updated by either version, or
re-imported by either after the CloudFormation stack was gone, the marker is
already gone and the deployed parameter value may be in that resource's
observedProperties in state.json, and in older S3 object versions of
state.json, which stay after the current one is fixed. No cdkd version can
detect this afterwards: the record looks like any other. If that can apply to
you, in this order:
- Rotate the secret.
- Fix the current
state.json. When the value comes from a{{resolve:...}}reference, write that reference in the template in place of the parameter and deploy, so the next baseline is recorded as the reference. Otherwise no cdkd command removes a recorded baseline in place, and theobservedPropertiesentry has to be removed fromstate.jsonby hand. - Last, delete the noncurrent object versions under the stack's state prefix. The deploy in step 2 saves state more than once, and each save turns the previous object, still holding the old value, into a new noncurrent version, so a purge done earlier has to be done again.
cdkd state refresh-observed is not a remedy: it reads the value from AWS
again. cdkd scrub finds a value only through a reference the
template spells, so it finds nothing while the parameter is bound to its
placeholder.
A refusal marker with no reason
Stacks imported with cdkd 0.290.35 carry baseline refusals without the reason. No other refusal recorded one at the time either, so a marker with no reason does not say which kind it is. cdkd reads it cautiously.
When the resource's definition in the template being deployed (or re-imported)
reads a template parameter, directly, through a condition, or through an
attribute of a resource that does, the refusal is treated as an
unverifiable-parameter one. The same holds when cdkd cannot tell: the
template cannot be read, or the definition uses an intrinsic function cdkd
does not know in a template where something reads a declared parameter. In
all of those cases cdkd deploy records the reason on its next state write.
The cost is that an older refusal of the other kind on such a resource also
stays until the resource is replaced or re-imported against a proving
CloudFormation stack. A marker with no reason on a resource that provably
reads no parameter is cleared by an update. Every refusal now records a reason
(incomplete-resolution for the other kind), so the cautious reading applies
only to those older records.
Known gap: if you replace the parameter reference with its literal value
before the first deploy or re-import with a fixed cdkd that writes state (a
--dry-run or a deploy with no changes does not), the template no longer
shows the dependence and the marker clears.
This protects future deploys only; see Stacks imported with cdkd 0.290.35 for a value that may already be recorded.
Re-importing a Cloud Control resource
A re-import of a resource already in state (same physical id) never replaces
an unmasked attribute value that record holds with the mask: it keeps the
recorded value and says so, naming each key, since that value is what the last
deploy recorded and may be stale. Certified attributes still take the freshly
read value. When a re-import produces no value for a key the record already
masks (GetResource returned no readable model, the key is masked again, or
the import omits it), the mask is kept rather than dropped, and the import
warns, naming each key that stays masked.
Records that say sdk for a Cloud Control resource
An earlier cdkd version recorded every imported resource provisionedBy: sdk,
including each one it read through Cloud Control. Such a record still routes
through Cloud Control, and --recreate-via-cc-api refuses a type with no SDK
provider whatever its record says, so it needs no action.
To correct one anyway, first check with cdkd diff that the resource has no
pending change (the re-import records the current template's properties, so a
pending one would read as already applied). Then re-import it by its recorded
physical id, quoted since a composite id contains |:
cdkd import MyStack --resource '<logicalId>=<physicalId>' --force