Name check before a create
Before cdkd creates certain resources under a name it generated, it asks AWS
whether a resource already holds that name. If one does, and nothing this
stack has recorded names it, the deploy refuses to create the resource and
stops with the error code GENERATED_NAME_HELD.
The check is one of the two that keep
one stack name to one deployment.
It works whatever state backend the other deployment uses: another
--state-prefix, another --state-bucket, or another account's bucket.
Why a taken name is dangerous
For most resource types, a create call fails when the name is taken. For the types below it does not fail. The call hands back the existing resource, or overwrites it:
| Resource type | Looked up with |
|---|---|
AWS::SQS::Queue |
sqs:GetQueueUrl |
AWS::SNS::Topic |
sns:GetTopicAttributes |
AWS::Logs::LogGroup |
logs:DescribeLogGroups |
AWS::CloudWatch::Alarm |
cloudwatch:DescribeAlarms |
AWS::Events::Rule |
events:DescribeRule |
AWS::S3::Bucket |
s3:ListBucket on that bucket |
AWS::ECS::Cluster |
ecs:DescribeClusters |
AWS::ElasticLoadBalancingV2::LoadBalancer |
elasticloadbalancing:DescribeLoadBalancers |
AWS::ElasticLoadBalancingV2::TargetGroup |
elasticloadbalancing:DescribeTargetGroups |
AWS::StepFunctions::StateMachine |
states:DescribeStateMachine |
Without the check, a deploy that met another deployment's queue under its own generated name would record that queue as its own. A later destroy or rollback would then delete it.
Only these types are checked. Every other type's create fails on a taken name, and a create through Cloud Control refuses an existing name.
A name your template declares is not looked up. Declaring a name is choosing it.
When a taken name is allowed
The create goes ahead when this stack's own records show that the existing resource belongs to it. cdkd looks in these places:
- The state record. The resource is in the stack's record, under any logical ID, or among the resources a rollback left in AWS.
- The rollback journal. A failed deploy of this stack created the resource and recorded its physical ID.
- The create-token ledger (
create-tokens.json). The deploy writes the names it is about to create before it sends the creates. A re-run after a crash finds the name there and takes the resource back. retained.json. The stack let go of the resource but kept it in AWS (RemovalPolicy.RETAIN), in a destroy or in a deploy that removed it from the template. The next deploy under the same prefix that creates it again takes it back.- The stack's history, only when the stack has no
retained.jsonbecause an older cdkd destroyed it last. cdkd reads earlier versions of the record and the deployment events for a resource that was kept.
For a type that reports a creation time, the time must also fit. A resource created after this stack let go of the name belongs to someone else.
The internals page states each of these rules in full.
What a refusal looks like
The message names the resource that holds the name, the likely cause, and the command that adopts the resource:
MyQueue would be created with the cdkd-generated name ..., which an existing
resource (...) already holds, and nothing this stack records names that
resource ...
That one resource is not created. Resources the same deploy created earlier are rolled back, as after any failure.
What to do depends on whose resource it is:
Another deployment owns it. Deploy this stack under that deployment's state backend only, or give this stack another name.
It is this stack's own. Adopt it with the command the message prints, then run the deploy again:
cdkd import MyStack --resource MyQueue=<physicalId>
After cdkd state orphan
cdkd state orphan removes the record and empties retained.json, so nothing
this stack records names its resources any more. A redeploy under the same
prefix that would create one of them again is refused, and cdkd import
adopts it.
This is deliberate. Orphaning is how you hand a record over, and cdkd does not take the resources back on its own.
Permissions
The lookups need the read action in the table above for each type the stack creates.
A lookup that AWS refuses with 403 prints a warning, and the create goes ahead as it did before the check existed. Any other lookup failure refuses that create.
Two more actions on the state bucket are optional: s3:ListBucketVersions and
s3:GetObjectVersion. cdkd uses them to read earlier versions of a record
after an upgrade. Without them, that source allows nothing.
What the check costs
A redeploy that creates nothing looks nothing up. Updates, no-change deploys and destroys make no lookup either.
On a first deploy, cdkd starts every lookup at once as soon as the plan is known, and each create waits only for its own answer. A first deploy pays about one round trip, whatever its size.
Every lookup is an exact read by name. cdkd never uses a listing such as
ListQueues, because a listing can omit a resource created a minute earlier.
A queue or a bucket can still read as present for up to a minute after it was deleted. When one holds the name, cdkd reads it again every 10 seconds for about 65 seconds before it refuses the create.
What the check does not see
- Two first deploys of the same stack name at the same moment. A resource created between the lookup and the create is missed. In one bucket the stack registry serializes the two deploys. In two buckets the gap remains for as long as the deploy runs.
- A kept resource that no record names any more. For example, an older
cdkd kept it and its history has since rotated away. Re-adding it is
refused, and
cdkd importadopts it. - A re-created resource of a type with no creation time. An S3 bucket, SNS topic, CloudWatch alarm, EventBridge rule, ECS cluster or ELBv2 target group that this stack kept, that was then deleted outside cdkd and created again by another deployment, is allowed by its name alone.
- A bucket of the same name in another region counts as holding the name.
Related
- The state store: why a stack name is one deployment
- Stack registry: the second check, on stacks in one bucket
- Lock and state errors: the troubleshooting entry for this refusal
- Importing Existing Resources: adopting a resource into a stack