Skip to content
cdkd

Importing by Resource Type

This page lists the value --resource expects for each resource type, and the types whose import behaves in a way worth knowing. Search it for your type, for example AWS::Glue::Table.

cdkd import MyStack --resource Uploads5E5E9B2F=acme-uploads

# quote a value that contains |
cdkd import MyStack --resource 'GetMethod4B5C6D7E=a1b2c3d4e5|xy9z8w|GET'

The value after = is the resource's physical id: the id cdkd stores for the resource, which cdkd state show and cdkd state resources print. It is not always the id CloudFormation shows. The tables below give the form for each type where it needs spelling out.

Which resource types can be imported says, for every type, whether cdkd finds it without a flag.

Types cdkd finds without a flag

cdkd looks these types up by the name in your template, so you normally pass nothing. When you do pass --resource for one, use this form:

Type --resource value
AWS::SSM::Parameter The parameter name only.
AWS::EC2::EIP An eipalloc-... allocation id, a public IP, or <publicIp>|<allocationId>.
AWS::EC2::InternetGateway The igw-... id.
AWS::EC2::RouteTable The rtb-... id.
AWS::EC2::NetworkAcl The acl-... id.
AWS::EC2::Instance The i-... id.
AWS::ECS::Service The service ARN, or <clusterArn>|<serviceName>.
AWS::Glue::Table <databaseName>|<tableName>, or the bare table name.
AWS::Pipes::Pipe The pipe name.
AWS::EMR::Cluster The cluster id j-XXXX.

Notes on single types:

  • AWS::EC2::EIP: whichever form you pass, cdkd stores <publicIp>|<allocationId>.
  • AWS::EC2::Instance: an instance that is terminated or shutting down is not adopted.
  • AWS::ECS::Service: cdkd stores the service ARN.
  • AWS::Pipes::Pipe and AWS::Budgets::Budget: the template's Name and Budget.BudgetName find them without a flag.
  • AWS::BedrockAgentCore::Browser and AWS::BedrockAgentCore::CodeInterpreter: these stand for the defaults AWS manages. cdkd finds them with GetBrowser and GetCodeInterpreter and needs no --resource.

AWS::SSM::Parameter

Pass the parameter name. cdkd refuses an ARN and a name:version or name:label selector, and the error names the value to pass instead.

The reason is that GetParameter accepts those forms while PutParameter and DeleteParameter reject them. A parameter adopted under an ARN would import cleanly and then break the next deploy and destroy.

AWS::Glue::Table

cdkd stores and displays a Glue table's id as <databaseName>|<tableName>. You can also pass the bare table name, which is the id CloudFormation records. cdkd then pairs it with the DatabaseName in your template.

Edge cases:

  • A name that itself contains |. A table or database name that contains | is adopted when it is paired with the template's own DatabaseName, either way round.
  • More than one possible reading. cdkd also tries a value with a | as a whole table name in the template's database. When more than one reading names an existing table, the import refuses instead of guessing.

AWS::Route53::HostedZone

cdkd finds the hosted zone by the Name in your template, using ListHostedZonesByName. The imported record holds the same Id and NameServers attributes a deploy records, so Fn::GetAtt <Zone>.NameServers and CDK's zone.hostedZoneNameServers resolve on an imported zone. A zone with no delegation set records an empty list.

Edge cases:

  • A public and a private zone share the name. The VPCs property in your template decides which one is meant. If the name is still ambiguous, the plan shows the row as failed and names --resource <logicalId>=<hostedZoneId>.
  • cdkd cannot read the name servers. When cdkd found the zone by name, reading the name servers costs one extra GetHostedZone call. If that call fails, the zone is still adopted with a warning, and attributes already in state are kept. With --resource there is no extra call, so a denied GetHostedZone fails that row.
  • The attributes are missing after an import. A plain cdkd deploy does not add them, because it does not update a zone that has not changed. Run the import again for that zone with --force, or change the zone in your template.

Types that need --resource

cdkd cannot look these types up, so you name each one. You pass nothing when CloudFormation can supply the id: under --migrate-from-cloudformation, or with --auto and a CloudFormation stack of the same name.

Resources with no name to look up

Type --resource value
AWS::IAM::Policy The physical id of the inline policy.
AWS::IAM::AccessKey The AKIA... access key id.
AWS::IAM::UserToGroupAddition The physical id.
AWS::CloudWatch::AnomalyDetector Any stable id.
AWS::Scheduler::Schedule The physical id.
AWS::CloudFormation::WaitConditionHandle Any id, or none.
AWS::ApiGateway::Account Any id.
AWS::CloudFront::OriginAccessControl The E... id.
  • AWS::IAM::AccessKey: cdkd verifies the id with GetAccessKeyLastUsed. An imported key has no stored SecretAccessKey, because IAM returns the secret only when the key is created. A template that reads Fn::GetAtt [<key>, SecretAccessKey] cannot resolve it for an imported key. Replace the key if the secret is needed.
  • AWS::CloudWatch::AnomalyDetector: cdkd records the id you give and derives its own id the next time the detector is replaced.
  • AWS::Scheduler::Schedule: the template's Name and GroupName also find the schedule without a flag.
  • AWS::CloudFormation::WaitConditionHandle: cdkd records the id as given, and uses a placeholder when you pass none. Under --migrate-from-cloudformation it records CloudFormation's pre-signed URL.
  • AWS::ApiGateway::Account: there is one per account and region and it has no id of its own, so cdkd records the id without an AWS call. A deploy records ApiGatewayAccount. cdkd destroy clears the region's CloudWatchRoleArn.
  • AWS::CloudFront::OriginAccessControl: cdkd verifies the id with GetOriginAccessControl.

Parts of a parent resource

Type --resource value
AWS::ApiGateway::Method <restApiId>|<resourceId>|<httpMethod>
AWS::AppSync::DataSource <apiId>|<name>
AWS::AppSync::Resolver <apiId>|<typeName>|<fieldName>
AWS::AppSync::ApiKey <apiId>|<apiKeyId>
AWS::S3Tables::Namespace <tableBucketARN>|<namespaceName>
AWS::S3Tables::Table <tableBucketARN>|<namespace>|<name>
AWS::Route53::RecordSet <hostedZoneId>|<name>|<type>
AWS::EC2::Route <routeTableId>|<destination>
AWS::EC2::NetworkAclEntry <networkAclId>|<ruleNumber>|<egress>
AWS::EC2::SecurityGroupIngress The sgr-... rule id.

These types take the plain physical id: AWS::ApiGateway::Authorizer, AWS::ApiGateway::Resource, AWS::ApiGateway::Deployment, AWS::ApiGateway::Stage, AWS::ApiGatewayV2::Stage, AWS::ApiGatewayV2::Integration, AWS::ApiGatewayV2::Route, AWS::ApiGatewayV2::Authorizer, AWS::AppSync::GraphQLSchema, AWS::ElasticLoadBalancingV2::Listener, AWS::EFS::MountTarget, AWS::RDS::DBProxyTargetGroup.

  • AWS::Route53::RecordSet: write <name> exactly as the template spells it. CDK emits a trailing dot.
  • AWS::EC2::Route: <destination> is the IPv4 CIDR, the IPv6 CIDR or the prefix-list id. CloudFormation's id has the same form.
  • AWS::S3Tables::Namespace and AWS::S3Tables::Table: only their parent, AWS::S3Tables::TableBucket, is found without a flag.

AWS::EC2::NetworkAclEntry

CloudFormation's id for an entry is a generated name that says nothing about the entry. When cdkd is given that id, it locates the entry from the NetworkAclId, RuleNumber and Egress in your template.

That needs the parent network ACL's id as well. Pass --resource for the ACL too, or add --auto so that a CloudFormation stack of the same name supplies it.

AWS::EC2::SecurityGroupIngress

Pass the sgr-... rule id. It is the id CloudFormation records for the type and the id the EC2 console shows. cdkd verifies it with DescribeSecurityGroupRules and declines the id of an egress rule.

cdkd stores <groupId>|<ipProtocol>|<fromPort>|<toPort> as the physical id, and the rule id as the Id attribute. You cannot pass that stored form to --resource, because the same four values can describe several rules.

Type --resource value
AWS::Lambda::Permission The bare statement id.
AWS::Lambda::EventInvokeConfig <functionName>|<qualifier>
AWS::EC2::SubnetRouteTableAssociation The rtbassoc-... association id.
AWS::EC2::SubnetNetworkAclAssociation The aclassoc-... association id.
AWS::EC2::VPCGatewayAttachment <internetGatewayId>|<vpcId>, or CloudFormation's IGW|<vpcId>.
AWS::BedrockAgentCore::Runtime The runtime ARN.
AWS::BedrockAgentCore::Evaluator The evaluator ARN or bare id.
AWS::Lambda::MicrovmImage The image ARN.

These types take the plain physical id: AWS::SNS::Subscription, AWS::SNS::TopicPolicy, AWS::SQS::QueuePolicy, AWS::S3::BucketPolicy, AWS::Lambda::EventSourceMapping, AWS::Lambda::Url, AWS::CloudFormation::CustomResource, AWS::CloudFront::CloudFrontOriginAccessIdentity.

  • AWS::Lambda::Permission: cdkd also reads the older <functionArn>|<statementId> form.
  • AWS::Lambda::EventInvokeConfig: a bare function name means the qualifier $LATEST.
  • AWS::EC2::VPCGatewayAttachment: only internet gateway attachments are adopted; a VPN gateway attachment is not. Given IGW|<vpcId>, cdkd takes the gateway from the template's InternetGatewayId, or else from the one gateway attached to that VPC.
  • AWS::BedrockAgentCore::Evaluator: cdkd turns a bare id into the ARN with GetEvaluator.
  • AWS::Lambda::MicrovmImage: a bare name is rejected.

Cloud Control API fallback

cdkd has its own import code for the types above. Any other type can still be imported when the AWS Cloud Control API supports it, as long as you name the resource with --resource:

cdkd import MyStack --resource 'VpcIpv6Cidr=vpc-cidr-assoc-0abc123|vpc-0def456'

cdkd does not look such a resource up for you, because that would cost one ListResources call per type.

The state record of a resource imported this way says provisionedBy: cc-api, as it would after a deploy. Later deploys, drift checks and destroys therefore keep using Cloud Control for it.

Ids made of several fields

Cloud Control identifies some types by several fields joined with |. The example above is an AWS::EC2::VPCCidrBlock, whose id is <Id>|<VpcId>. cdkd records that joined value as the physical id.

CloudFormation's physical id for such a resource is often one field only: the bare vpc-cidr-assoc-... for a VPCCidrBlock. When cdkd receives that shorter id, from --migrate-from-cloudformation or from a bare --resource value, it fills in the other fields from your template. A Ref to another imported resource counts as a value it can use.

This needs the cloudformation:DescribeType permission. When the template does not give exactly the missing fields as plain values, the import of that resource fails and names the full value to pass, for example --resource 'VpcIpv6Cidr=<Id>|<VpcId>'.

What cdkd records for Fn::GetAtt

A state record has an attributes map, which is where Fn::GetAtt reads from. Cloud Control returns every property of the resource, but cdkd keeps in attributes only the ones the type's schema declares as read-only. Those are the ones CloudFormation allows Fn::GetAtt to read.

cdkd records every other property as the mask ***. A later Fn::GetAtt on a masked property is refused by name, so it cannot resolve to a wrong value.

Reading the schema needs cloudformation:DescribeType: one call per resource type, cached for the run. Without the permission, cdkd masks every property and warns. An Fn::GetAtt on that resource then fails until a deploy next creates or updates the resource. The direct fix is to grant the permission and run cdkd import again.

The record is still sensitive:

  • A credential that is itself a read-only attribute is recorded in the clear. The schema does not mark which attributes are secret.
  • The mask applies to attributes only. The copy of the resource that cdkd keeps for drift detection holds every property; see A value your template never references.
  • The next deploy that creates or updates the resource writes every property back into attributes.

What importing the same resource a second time does to masked values is in Import internals.

CDK Stages are not nested stacks

Each stack inside a CDK Stage is a separate top-level stack. Import it by passing its display path or physical name as the stack argument. A real nested stack (AWS::CloudFormation::Stack) can be imported only with --migrate-from-cloudformation.

Last updated: