-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve experience for renaming L1s #207
Comments
Contrary to CloudFormation, which is a flat list of resources, CDK stacks form a tree. We need a way to assign unique and stable Logical IDs that won't cause conflicts. From the When you synthesize a stack into an AWS CloudFormation template, the CDK assigns a logical ID, which must be unique within the template, to each resource in the stack. Each resource in the construct tree has a unique path that represents its location within the tree. The logical ID of a resource is formed by concatenating the names of all of the constructs in the resource’s path, and appending an eight-character MD5 hash of the path. This final component is necessary since AWS CloudFormation logical IDs cannot include the delimiting slash character (/), so simply concatenating the component values does not work. For example, concatenating the components of the path /a/b/c produces abc, which is the same as concatenating the components of the path /ab/c. Since logical IDs can only use alphanumeric characters and also restricted in length, we are unable to simply use a delimited path as the logical ID. Instead IDs are allocated by concatenating a human-friendly rendition from the path (concatenation, de-duplicate, trim) with a short MD5 hash of the delimited path:
Low-level CloudFormation Resources that are direct children of the This scheme ensures that:
The AWS CDK applies some heuristics to improve the human-friendliness of the prefix:
Renaming Logical IDsThe :py:meth: class MyStack extends Stack {
constructor(parent: App, name: string, props: StackProps) {
super(parent, name);
// note that `renameLogical` must be called /before/ defining the construct.
// a good practice would be to always put these at the top of your stack initializer.
this.renameLogical('MyTableCD117FA1', 'MyTable');
this.renameLogical('MyQueueAB4432A3', 'MyAwesomeQueue');
new Table(this, 'MyTable');
new Queue(this, 'MyQueue');
}
} |
Thanks for all the information.
I'm trying to make sure that I understand this distinction. Can you give an example of where objects in a CDK application form a tree structure? I assume this means a class that you instantiate by providing a Even in this case, where the CDK models structures as a tree, the serialization of that tree resolves to a flat
🤔 I don't understand how the runtime values section of the documentation relates here. Actually I fundamentally don't understand what the purpose of the runtime values example is. This section, right? |
Yes. We have designed the programming model of the CDK to encourage modularity of cloud apps. The ability to encapsulate a set of resources behind an abstraction is one of the main motivations for building the CDK. Any class that extends
Throwing errors for conflicting IDs will quickly become very frustrating. A simple example would be instantiating a construct a few times within the stack. Already there, every instance will have duplicated IDs. These types of problems compound when consuming reusable construct libraries which you don't even control.
😨 Just a mistake in our docs. Thanks for calling this out. PR #209 should fix this. |
@rclark let me know if you need further information or if it's okay to close this for now. |
Well.. my problem with this is that we have a lot existing stacks and if I want to use this tool, I need to program it in such way that it generates the stacks which are similar to our existing stacks and I need to keep the original LogicalIDs unchanged otherwise all of our current resources will be removed and recreated. We defined our own DSL and we wrote an internal tool to parse that DSL to CloudFormation stacks and deploy them. This tool can really reduce our workload because we don't need to write CloudFormation handlebars to parse our DSL anymore - instead we can do it in programmatic way. However, we'd like to keep our resource logical IDs unchanged because of what I mentioned above. Could you please kindly give any suggestions on this? Thanks |
If you create a So, for example, if your template looks like this: Resources:
MyTopicHaha:
Type: AWS::SNS::Topic
Properties:
DisplayName: display-name-for-my-topic You can define a stack with a import cdk = require('@aws-cdk/cdk');
import sns = require('@aws-cdk/aws-sns');
export class MyStack extends cdk.Stack {
constructor(parent: cdk.App, name: string, props?: cdk.StackProps) {
super(parent, name, props);
new sns.CfnTopic(this, 'MyTopicHaha', {
displayName: 'display-name-for-my-topic'
});
}
} You can also use Let me know if that helps. |
@eladb With your first approach I think that makes sense and that'll work, though I'll have to work with the "raw" CFN models. For your second approach, const bucket = new s3.Bucket(this, "MyFirstBucket",...);
this.renameLogical(bucket.getLogicalId(), 'MyFirstBucket'); Do you know if this is possible or I'm just simply asking for something impractical here? Thank you |
You could get the logical ID of an internal resource this way: const bucketLogicalId = (bucket.findChild('Resource') as cdk.Resource).logicalId; |
@eladb Thank you. this.renameLogical(bucket.findChild('Resource') as cdk.Resource).logicalId, 'MyFirstBucket');
const bucket = new s3.Bucket(this, "MyFirstBucket",...); However, as you easily see, this won't work because bucket wasn't even created when I call So it seems there's just no way so far to use |
Obviously that’s a good point. In the meantime, you could synthesize first to determine the generated ID and then use “rename” but that’s a very broken experience. Let us give this a bit of thought. Reopening for now. |
@eladb this is a functionality a lot of poeple are asking for, but I still wasn't able to find a straight and documented solution |
Hey - With the current release of the CDK, given a import s3 = require('@aws-cdk/aws-s3');
import cdk = require('@aws-cdk/core');
const app = new cdk.App();
const stack = new cdk.Stack(app, 'Test');
const bucket = new s3.Bucket(stack, 'MyBucket');
(bucket.node.defaultChild! as cdk.CfnResource).overrideLogicalId('Bazinga'); Synthesizes to: Resources:
Bazinga: # Wheeeeee!
Type: AWS::S3::Bucket
UpdateReplacePolicy: Retain
DeletionPolicy: Retain
Metadata:
aws:cdk:path: Test/MyBucket/Resource |
@RomainMuller |
Is this feature working only on a subset of resources? Autoscaling Group L2 construct, for instance, does not have default_child property set to underlying Cfn Construct. |
This is causing me a lot of problems with nested stacks If there anyway to turn off the dynamic naming, maybe a boolean |
Perhaps you can use |
Using a L2 construct (I think that's how you refer to them) to define a resource doesn't allow me to explicitly define the resource's logical name.
==>
Reasons that I'd like to be able to set the logical name precisely:
if I need to look at my template to debug anything, or if I have workflows that involve inspecting templates in API responses or the console UI, it can be easier to deal with if I can explicitly set my resource's logical name
if I have to resort to L1 constructs from '@aws-cdk/resources', the pattern is changed -- while the
name
argument looks the same, I end up without a suffixed logical resource name==>
The text was updated successfully, but these errors were encountered: