-
Notifications
You must be signed in to change notification settings - Fork 222
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
feat(concepts): "scope" instead of "parent" #1
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,12 @@ | ||
-------- | ||
|
||
This documentation is for the developer preview release of the AWS CDK\. Do not use this version of the AWS CDK in production\. Subsequent releases of the AWS CDK will likely include breaking changes\. | ||
This documentation is for the developer preview release of the AWS CDK\. Do not use this version of the AWS CDK in production\. Subsequent releases of the AWS CDK will likely include breaking changes\. | ||
|
||
-------- | ||
|
||
# AWS CDK Concepts<a name="concepts"></a> | ||
|
||
This topic describes some of the concepts \(the why and how\) behind the AWS CDK\. It also discusses the advantages of a AWS Construct Library over a low\-level CloudFormation Resource\. | ||
This topic describes some of the concepts \(the why and how\) behind the AWS CDK\. It also discusses the advantages of the AWS Construct Library over a low\-level CloudFormation Resource\. | ||
|
||
AWS CDK apps are represented as a hierarchal structure we call the *construct tree*\. Every node in the tree is a [Construct](https://awslabs.github.io/aws-cdk/refs/_aws-cdk_cdk.html#construct) object\. The root of an AWS CDK app is typically an [App](https://awslabs.github.io/aws-cdk/refs/_aws-cdk_cdk.html#app) construct\. Apps contain one or more [Stack](https://awslabs.github.io/aws-cdk/refs/_aws-cdk_cdk.html#@aws-cdk/cdk.Stack) constructs, which are deployable units of your app\. | ||
AWS CDK apps are composed of building blocks called [constructs](https://awslabs.github.io/aws-cdk/refs/_aws-cdk_cdk.html#construct), which are composed together to form [Stacks](https://awslabs.github.io/aws-cdk/refs/_aws-cdk_cdk.html#@aws-cdk/cdk.Stack) and [Apps](https://awslabs.github.io/aws-cdk/refs/_aws-cdk_cdk.html#app). | ||
|
||
This composition of constructs gives you the flexibility to architect your app, such as having a stack deployed in multiple regions\. Stacks represent a collection of AWS resources, either directly or indirectly through a child construct that itself represents an AWS resource, such as an Amazon SQS queue, an Amazon SNS topic, a Lambda function, or a DynamoDB table\. | ||
|
||
This composition of constructs also means you can easily create sharable constructs, and make changes to any construct and have those changes available to consumers as shared class libraries\. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,104 +1,100 @@ | ||
-------- | ||
|
||
This documentation is for the developer preview release of the AWS CDK\. Do not use this version of the AWS CDK in production\. Subsequent releases of the AWS CDK will likely include breaking changes\. | ||
This documentation is for the developer preview release of the AWS CDK\. Do not use this version of the AWS CDK in production\. Subsequent releases of the AWS CDK will likely include breaking changes\. | ||
|
||
-------- | ||
|
||
# Constructs<a name="constructs"></a> | ||
|
||
Constructs are the building blocks of AWS CDK applications\. Constructs can have child constructs, which in turn can have child constructs, forming a hierarchical tree structure\. | ||
Constructs can be viewed as "cloud components". They can represent architectures of any complexity. They can represent a single resource, such as an Amazon S3 Bucket or an Amazon SNS Topic, reusable components such as a static website, a part of a specific application and up to complex multi-stack applications that span multiple accounts and region. Everything in the AWS CDK is a construct. | ||
|
||
The AWS CDK includes two different levels of constructs: | ||
This composition of constructs also means you can easily create sharable constructs, and make changes to any construct and have those changes available to consumers as shared class libraries\. | ||
|
||
CloudFormation Resource | ||
These constructs are low\-level constructs that provide a direct, one\-to\-one, mapping to an AWS CloudFormation resource, as listed in the AWS CloudFormation topic [ AWS Resource Types Reference](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html)\. | ||
All CloudFormation Resource members are found in the `@aws-cdk/resources` package\. | ||
## The AWS Construct Library | ||
|
||
AWS Construct Library | ||
These constructs have been handwritten by AWS and come with convenient defaults and additional knowledge about the inner workings of the AWS resources they represent\. In general, you will be able to express your intent without worrying about the details too much, and the correct resources will automatically be defined for you\. | ||
AWS Construct Library members are found in the `@aws-cdk/aws-NAMESPACE` packages, where NAMESPACE is the short name for the associated service, such as SQS for the AWS Construct Library for the Amazon SQS service\. See the [Reference](https://awslabs.github.io/aws-cdk/reference.html#reference) section for descriptions of the AWS CDK packages and constructs\. | ||
The AWS CDK is shipped with a rich class library of constructs called the **AWS Construct Library**. This library consists of constructs that represent all the resources available on AWS. | ||
|
||
Each module in the AWS Construct Library includes two types of constructs for each resource: low-level and high-level. | ||
|
||
The low-level resources are automatically generated from the [AWS CloudFormation Resource Types Reference](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html). Low-level constructs are named `CfnXyz` (where "Xyz" represents the name of the resource) and provide direct, one-to-one access to how a resource is synthesized in the CloudFormation template produced by your CDK app. Using low-level resources require explicit configuration of all resource properties, IAM policies and requires deep understanding of the details. | ||
|
||
High-level resources are hand-written by AWS and offer a rich, intent-based API for using AWS services. They offer the same functionality as the low-level resources but encode much of the details, boilerplate and glue-logic required in order to use AWS. High-level resources offer convenient defaults and additional knowledge about the inner workings of the AWS resources they represent\. In general, you will be able to express your intent without worrying about the details too much, and the correct resources and configuration will automatically be defined for you\. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thought-provoking example such as granting access/enabling encryption etc. ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let me noodle this. |
||
|
||
Similarly to the AWS SDKs and AWS CloudFormation, the AWS Construct Library is organized into modules, one for each AWS service. For example, the `@aws-cdk/aws-ec2` module includes resources for EC2 instances, Auto Scaling Groups and VPCs, the aws-sns module includes resources such as Topic and Subscription, and so forth. See the [Reference](https://awslabs.github.io/aws-cdk/reference.html#reference) section for descriptions of the AWS CDK packages and constructs\. | ||
|
||
AWS Construct Library members are found in the `@aws-cdk/aws-NAMESPACE` packages, where NAMESPACE is the short name for the associated service, such as SQS for the AWS Construct Library for the Amazon SQS service\. | ||
|
||
## Construct Structure<a name="constructs_structure"></a> | ||
|
||
The construct tree structure is a powerful design pattern for composing high\-level abstractions\. For example, you can define a `StorageLayer` construct that represents your application's storage layer and include all the AWS resources, such as DynamoDB tables and Amazon S3 buckets, needed to implement your storage layer in this construct\. When your higher\-level code uses this construct, it only needs to instantiate the `StorageLayer` construct\. | ||
Constructs are represented as normal classes in your code and are defined by instantiating an object of that class. | ||
|
||
When you initialize a construct, add the construct to the construct tree by specifying the parent construct as the first initializer parameter, an identifier for the construct as the second parameter, and a set of properties for the final parameter, as shown in the following example\. | ||
When constructs are initialized, they are always defined within the _**scope**_ of another construct and they always have an _**id**_ which must be unique within the same scope. | ||
|
||
``` | ||
new SomeConstruct(parent, name[, props]); | ||
For example, here's how you would define an SNS Topic in your stack with default configuration: | ||
|
||
```ts | ||
new sns.Topic(this, 'MyTopic'); | ||
``` | ||
|
||
In almost all cases, you should pass the keyword `this` for the `parent` argument, because you will generally initialize new constructs in the context of the parent construct\. Any descriptive string will do for the `name` argument, and an in\-line object for the set of properties\. | ||
The first argument to every construct is always the scope in which it is created, and will almost always be simply `this` because most constructs will be defined within the current scope. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps clarify that 'current scope' means within the constructor or method of another construct. Might be confusing to new-comers without sample code. Or expand the example to include the outer scope? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We don't need to explain scope. It's a fundamental programming concept. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I kind of agree with @sam-goodwin - maybe we could say something like "...defined within the current scope, which is normally the initializer (constructor) or a method of some construct defined in your app". Something like that... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is a fundamental programming concept, but it is ambiguous in this context since we are just now introducing them to the CDK's implementation of scopes. For example, will a novice understand that the scope is also a construct? |
||
|
||
``` | ||
Scopes enable constructs to be composed together to form higher-level abstractions by enabling the framework to group them together into logical units, allocate globally unique identifiers and allow them to consult __context information__ such as the region in which it is going to be deployed into, which AZs are available for my account, etc. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Introduce the scope hierarchy? You haven't described how they are grouped together, only implied it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added an earlier explanation. |
||
|
||
In most cases, the construct initializer will have a third `props` argument that can be used to define the construct's initial configuration. For example: | ||
|
||
```ts | ||
new BeautifulConstruct(this, 'Foo', { | ||
applicationName: 'myApp', | ||
timeout: 300 | ||
favoriteColor: 'green', | ||
timeout: 300 | ||
}); | ||
``` | ||
|
||
**Note** | ||
Associating the construct to its parent as part of initialization is necessary because the construct occasionally needs contextual information from its parent, such as to which the region the stack is deployed\. | ||
The `construct.node` property can be used to interact with the construct's node representation: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You're introducing the concept of a 'node' before explicitly describing the tree. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've reworded the intro. |
||
|
||
Use the following operations to inspect the construct tree\. | ||
* `construct.node.scope` The scope in which this construct was defined. | ||
|
||
aws\-cdk\.Construct\.parent | ||
Gets the path of this construct from the root of the tree\. | ||
* `construct.node.id` Returns the "id" of the construct passed upon creation. | ||
|
||
aws\-cdk\.Construct\.getChildren | ||
Gets an array of all of the contruct's children\. | ||
* `construct.node.uniqueId` Returns an app-wide unique safe ID of this construct. This ID encodes the construct's path into a human readable portion as well as a hash of the full path to ensure global uniqueness. | ||
|
||
aws\-cdk\.Construct\.getChild | ||
Gets the child construct with the specified ID\. | ||
* `construct.node.path` Gets the path of this construct from the root of scope (the `App`)\. | ||
|
||
aws\-cdk\.Construct\.toTreeString\(\) | ||
Gets a string representing the construct's tree\. | ||
## Construct IDs<a name="constructs_ids"></a> | ||
|
||
## Construct Names<a name="constructs_EVER"></a> | ||
Every construct in a CDK app must have an **id** unique within the scope in which the construct is defined. IDs are used to find constructs in the construct hierarchy, and to allocate logical IDs so that AWS CloudFormation can keep track of the generated resources\. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. First mention of the hierarchy is here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Scope and hierarchy are fundamental concepts. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. They still need to be explained in the context of the CDK in my mind. |
||
|
||
Every construct in a CDK app must have a **name** unique among its siblings\. Names are used to track constructs in the construct hierarchy, and to allocate logical IDs so that AWS CloudFormation can keep track of the generated resources\. | ||
|
||
When a construct is created, its name is specified as the second initializer argument: | ||
When a construct is created, its ID is specified as the second initializer argument: | ||
|
||
``` | ||
const c1 = new MyBeautifulConstruct(this, 'OneBeautiful'); | ||
const c2 = new MyBeautifulConstruct(this, 'TwoBeautiful'); | ||
assert(c1.name === 'OneBeautiful'); | ||
assert(c2.name === 'TwoBeautiful'); | ||
assert(c1.node.id === 'OneBeautiful'); | ||
assert(c2.node.id === 'TwoBeautiful'); | ||
``` | ||
|
||
Use the `aws-cdk.Construct.path` property to get the path of this construct from the root of the tree\. | ||
|
||
Note that the name of a construct does not directly map onto the physical name of the resource when it is created\. If you want to give a physical name to a bucket or table, specify the physical name using use the appropriate property, such as `bucketName` or `tableName`, as shown in the following example: | ||
Note that the ID of a construct does not directly map onto the physical name of the resource when it is created\. If you want to give a physical name to a bucket or table, specify the physical name using use the appropriate property, such as `bucketName` or `tableName`, as shown in the following example: | ||
|
||
``` | ||
new Bucket(this, 'MyBucket', { | ||
bucketName: 'physical-bucket-name' | ||
new s3.Bucket(this, 'MyBucket', { | ||
bucketName: 'physical-bucket-name' | ||
}); | ||
``` | ||
|
||
Avoid specifying physical names\. Instead, let AWS CloudFormation generate names for you\. Use attributes, such as `bucket.bucketName`, to discover the generated names\. | ||
In general it's recommended to avoid specifying physical names\. Instead, let AWS CloudFormation generate names for you\. Use attributes, such as `bucket.bucketName`, to discover the generated names\. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we mention how discovered names maps to cloud formation functions? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe in the CloudFormation topic? |
||
|
||
When you synthesize an AWS CDK tree into an AWS CloudFormation template, the AWS CloudFormation logical ID for each resource in the template is allocated according to the path of that resource in the construct tree\. For more information, see [Logical IDs](logical_ids.md)\. | ||
When you synthesize an AWS CDK app into an AWS CloudFormation template, the AWS CloudFormation logical ID for each resource in the template is allocated according to the path of that resource in the scope hierarchy\. For more information, see [Logical IDs](logical_ids.md)\. | ||
|
||
## Construct Properties<a name="constructs_properties"></a> | ||
|
||
Customize constructs by passing a property object as the third parameter \(*props*\)\. Every construct has its own set of parameters, defined as an interface\. You can pass a property object to your construct in two ways: | ||
|
||
``` | ||
// Inline (recommended) | ||
new Queue(this, 'MyQueue', { | ||
new sqs.Queue(this, 'MyQueue', { | ||
visibilityTimeout: 300 | ||
}); | ||
|
||
// Instantiate separate property object | ||
const props: QueueProps = { | ||
visibilityTimeout: 300 | ||
}; | ||
|
||
new Queue(this, 'MyQueue', props); | ||
``` | ||
|
||
## Construct Metadata<a name="constructs_metadata"></a> | ||
|
||
You can attach metadata to a construct using the `aws-cdk.Construct.addMetadata` operation\. Metadata entries automatically include the stack trace from which the metadata entry was added\. Therefore, at any level of a construct you can find the code location, even if metadata was created by a lower\-level library that you don't own\. | ||
You can attach metadata to a construct using the `aws-cdk.Construct.node.addMetadata` operation\. Metadata entries automatically include the stack trace from which the metadata entry was added to allow tracing back to your code, even if the entry was was defined by a lower\-level library that you don't own\. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe you should briefly define the 'scope hierarchy'/'construct tree' here to explain the encapsulation and composability. Having the High/Low level explanation in between seems out of order to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added some more explanatory text.