diff --git a/packages/aws-cdk-docs/src/applets.rst b/packages/aws-cdk-docs/src/applets.rst new file mode 100644 index 0000000000000..da6897a08ff1e --- /dev/null +++ b/packages/aws-cdk-docs/src/applets.rst @@ -0,0 +1,76 @@ +.. Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 + International License (the "License"). You may not use this file except in compliance with the + License. A copy of the License is located at http://creativecommons.org/licenses/by-nc-sa/4.0/. + + This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific language governing permissions and + limitations under the License. + +.. _applets: + +####### +Applets +####### + +.. note:: Currently the |cdk| only supports applets published as JavaScript modules. + +Applets are files in the YAML or JSON format that have the following root attribute, +where MODULE can represent +a local file, such as :code:`./my-module`, +a local dependency, such as :code:`my-dependency`, +or a global module, such as :code:`@aws-cdk/s3` +and CLASS is the name of a class exported by the module. + +.. code:: js + + applet: MODULE[:CLASS] + +If CLASS is not specified, :code:`Applet` is used as the default class name. +Therefore, you need only refer to |cdk| construct libraries that export +an :code:`Applet` class by their library name. + +The rest of the YAML file is applet-dependent. +The object is passed as :code:`props` when the applet object is instantiated +and added to an |cdk| app created by **cdk-applet-js**. + +Use **cdk-applet-js** *applet* to run the applet, create an |cdk| app, +and use that with the |cdk| tools, as shown in the following example. + +.. code-block:: sh + + cdk --app "cdk-applet-js ./my-applet.yaml" synth + +To make the applet file executable and use the host as a shebang +on Unix-based systems, such as Linux, MacOS, or Windows Bash shell, +create a script similar to the following. + +.. code-block:: sh + + #!/usr/bin/env cdk-applet-js + + applet: aws-cdk-codebuild + source: arn:aws:codecommit:::my-repository + image: node:8.9.4 + compute: large + build: + - npm install --unsafe-perm + - npm test + - npm pack --unsafe-perm + +To execute the applet and synthesize an |CFN| template, +use the following command. + +.. code-block:: sh + + cdk synth --app "./build.yaml" + +To avoid needing **--app** for every invocation, +add the following entry to *cdk.json*. + +.. code-block:: json + + { + "app": "./build.yaml" + } diff --git a/packages/aws-cdk-docs/src/apps.rst b/packages/aws-cdk-docs/src/apps.rst new file mode 100644 index 0000000000000..a691385106d2e --- /dev/null +++ b/packages/aws-cdk-docs/src/apps.rst @@ -0,0 +1,84 @@ +.. Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 + International License (the "License"). You may not use this file except in compliance with the + License. A copy of the License is located at http://creativecommons.org/licenses/by-nc-sa/4.0/. + + This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific language governing permissions and + limitations under the License. + +.. _apps: + +#### +Apps +#### + +The main artifact of an |cdk| program is called a *CDK App*. +This is an executable program that can be used to synthesize deployment artifacts +that can be deployed by supporting tools like the |toolkit|, +which are described in :doc:`tools`. + +Tools interact with apps through the program's **argv**/**stdout** interface, +which can be easily implemented using the **App** class, +as shown in the following example. + +.. code-block:: js + + import { App } from '@aws-cdk/core' + + const app = new App(process.argv); // input: ARGV + + // + + process.stdout.write(app.run()); + +An |app-construct| is a collection of |stack| objects, as shown in the following +example. + +.. code-block:: js + + import { App } from '@aws-cdk/core' + import { MyStack } from './my-stack' + + const app = new App(process.argv); + + const dev = new MyStack(app, { name: 'Dev', region: 'us-west-2', dev: true }) + const preProd = new MyStack(app, { name: 'PreProd', region: 'us-west-2', preProd: true }) + const prod = [ + new MyStack(app, { name: 'NAEast', region: 'us-east-1' }), + new MyStack(app, { name: 'NAWest', region: 'us-west-2' }), + new MyStack(app, { name: 'EU', region: 'eu-west-1', encryptedStorage: true }) + ] + + new DeploymentPipeline(app, { + region: 'us-east-1', + strategy: DeploymentStrategy.Waved, + preProdStages: [ preProd ], + prodStages: prod + }); + + process.stdout.write(app.run()); + +Use the |toolkit| to list the stacks in this executable, +as shown in the following example. + +.. code-block:: sh + + cdk list + [ + { name: "Dev", region: "us-west-2" } + { name: "PreProd", region: "us-west-2" }, + { name: "NAEast", region: "us-east-1" }, + { name: "NAWest", region: "us-west-2" }, + { name: "EU", region: "eu-west-1" }, + { name: "DeploymentPipeline", region: 'us-east-1' } + ] + +Or deploy one of the stacks, +as shown in the following example. + +.. code-block:: sh + + cdk deploy Dev + ... diff --git a/packages/aws-cdk-docs/src/cloudformation.rst b/packages/aws-cdk-docs/src/cloudformation.rst index 293c31323dcb9..e1d33200140e7 100644 --- a/packages/aws-cdk-docs/src/cloudformation.rst +++ b/packages/aws-cdk-docs/src/cloudformation.rst @@ -21,18 +21,14 @@ This section includes information about |cdk| features that most developers do n Creating |l1| Constructs ======================== -|l1| constructs are found in the :py:mod:`aws-cdk-resources` package. They map directly onto |cfn| +|l1| constructs are found in the :py:mod:`@aws-cdk/resources` package. They map directly onto |cfn| resources. .. important:: In general, you shouldn't need to use this type of Constructs, unless you have special requirements or there is no Construct Library for the AWS resource you - need yet. You should use other packages with higher-level constructs instead. See - :ref:`l1_vs_l2` for a comparison between the construct types. - -The remainder of this section is for those who need to create a stack using a |l1| construct, -or want to create a |l2| construct from |l1| constructs. + need yet. You should use other packages with higher-level constructs instead. .. _construct_attributes: diff --git a/packages/aws-cdk-docs/src/concepts.rst b/packages/aws-cdk-docs/src/concepts.rst index 9619b7095bc79..69dd789d3f093 100644 --- a/packages/aws-cdk-docs/src/concepts.rst +++ b/packages/aws-cdk-docs/src/concepts.rst @@ -33,632 +33,14 @@ This composition of constructs also means you can easily create sharable constru and make changes to any construct and have those changes available to consumers as shared class libraries. -.. _construct_overview: - -Construct Overview -================== - -Constructs are the building blocks of |cdk| applications. Constructs can have -child constructs, which in turn can have child constructs, forming a -hierarchical tree structure. - -The |cdk| standard library comes with two different levels of constructs: - -|l1| - - These constructs are low-level constructs that provide a direct, one-to-one, - mapping to an |CFN| resource, - as listed in the |CFN| topic `AWS Resource Types Reference `_. - - All |l1| members are found in the :py:mod:`aws-cdk-resources` package. - -|l2| - - These constructs have been handwritten by AWS engineers 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. - - |l2| members are found in the :py:mod:`aws-cdk-RESOURCE` package, - where RESOURCE is the short name for the associated service, - such as SQS for the |l2| for the |SQS| service. - See the :ref:`reference` section for descriptions of the |cdk| - packages and constructs. - -Use an |l2| whenever possible, as they provide the -best developer experience. -See the :ref:`l2_advantages` section for more information about the advantages -of an |l2| over a |l1|. - -At an even higher-level than an |l2|, a |l3| -aggregates multiple, other constructs together -into common architectural patterns, such as a *queue processor* or an *HTTP -service*. - -By leveraging these common patterns, you can assemble your -application even faster than by using an |l2| directly. - -A |l3| -is not included with the standard CDK Construct -Library. Instead, we encourage you to develop and share them inside your -organization or on GitHub. - -.. _construct_structure: - -Construct Structure -=================== - -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 |DDB| tables and |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. - -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 an set of properties for the final parameter, -as shown in the following example. - -.. code-block:: js - - new SomeConstruct(parent, name[, props]); - -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. - -.. code-block:: js - - new BeautifulConstruct(this, 'Foo', { - applicationName: 'myApp', - 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. - -Use the following operations to inspect the construct tree. - -:py:attr:`aws-cdk.Construct.parent` - Gets the construct's parent construct. - -:py:meth:`aws-cdk.Construct.getChildren` - Gets an array of all of the contruct's children. - -:py:meth:`aws-cdk.Construct.getChild` - Gets the child construct with the specified ID. - -:py:meth:`aws-cdk.Construct.toTreeString()` - - Gets a string representing the construct's tree. - -We discuss the advantages of an |l2| over a |l1| -in the :ref:`l2_advantages` section. - -.. _construct_names: - -Construct Names ---------------- - -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 |CFN| can keep track of the generated resources. - -When a construct is created, its name is specified as the second -initializer argument: - -.. code-block:: js - - const c1 = new MyBeautifulConstruct(this, 'OneBeautiful'); - const c2 = new MyBeautifulConstruct(this, 'TwoBeautiful'); - assert(c1.name === 'OneBeautiful'); - assert(c2.name === 'TwoBeautiful'); - -Use the :py:attr:`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``. Example: - -.. code-block:: js - - new Bucket(this, 'MyBucket', { - bucketName: 'physical-bucket-name' - }); - -Avoid specifying physical names. Instead, let -|CFN| generate names for you. -Use attributes, such as **bucket.bucketName**, -to discover the generated names and pass them to your application's runtime -code, as described in :ref:`creating_runtime_value`. - -When you synthesize an |cdk| tree into an |CFN| template, the |CFN| 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 :ref:`logical_ids`. - -.. _construct_properties: - -Construct Properties --------------------- - -Customize constructs by passing a property object as the third -parameter. Every construct has its own set of parameters, defined as an -interface. You can pass a property object to your construct in two ways: - -.. code-block:: js - - // Inline (recommended) - new Queue(this, 'MyQueue', { - visibilityTimeout: 300 - }); - - // Instantiate separate property object - const props: QueueProps = { - visibilityTimeout: 300 - }; - - new Queue(this, 'MyQueue', props); - -.. _construct_metadata: - -Construct Metadata ------------------- - -You can attach metadata to a construct using the -:py:meth:`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. - -.. _l2_advantages: - -Using an |l2| Versusf a |l1| -============================ - -To illustrate the advantages that an |l2| has over -a |l1|, let's look at an example. - -The :py:mod:`aws-cdk-sns` Construct Library includes the `Topic` construct that -you can use to define an |SNS| topic: - -.. code-block:: js - - import { Topic } from '@aws-cdk/sns'; - const topic = new Topic(this, 'MyTopic'); - -An |l2| encapsulate the -details of working with these AWS resources. For example, to subscribe a queue to a topic, -call the :py:meth:`aws-cdk-sns.Topic.subscribeQueue` method with a queue object as the second argument: - -.. code-block:: js - - const topic = new Topic(this, 'MyTopic'); - const queue = new Queue(this, 'MyQueue', { - visibilityTimeoutSec: 300 - }); - - topic.subscribeQueue('TopicToQueue', queue); - -This method: - -1. Creates a subscription and associates it with the topic and the queue. - -2. Adds a queue policy with permissions for the topic to send messages to the queue. - -To achieve a similar result using :py:mod:`aws-cdk-resources`, you have to explicitly define the -subscription and queue policy, since there is no **subscribeToQueue** method in the **TopicResource** class: - -.. code-block:: js - - const topic = new sns.TopicResource(this, 'MyTopic'); - const queue = new sqs.QueueResource(this, 'MyQueue'); - - new sns.SubscriptionResource(this, 'TopicToQueue', { - topicArn: topic.ref, // ref == arn for topics - endpoint: queue.queueName, - protocol: 'sqs' - }); - - const policyDocument = new PolicyDocument(); - policyDocument.addStatement(new PolicyStatement() - .addResource(queue.queueArn) - .addAction('sqs:SendMessage') - .addServicePrincipal('sns.amazonaws.com') - .setCondition('ArnEquals', { 'aws:SourceArn': topic.ref })); - - new sqs.QueuePolicyResource(this, 'MyQueuePolicy', { - policyDocument: policyDocument, - queues: [ queue.ref ] - }); - -Notice how much cleaner the first version is. There is more focus on intent, -rather than mechanism. - -This example shows one of the many benefits -of using an |l2| instead of a |l1|. - -.. _stacks: - -Stacks -====== - -A |stack| is an |cdk| construct that can be deployed into an AWS environment. -The combination of region and account becomes the stack's *environment*, as -described in `Environments`_. Most production apps consist of multiple stacks of -resources that are deployed as a single transaction using a resource -provisioning service like |CFN|. Any resources added directly or indirectly as -children of a stack are included in the stack's template as it is synthesized by -your |cdk| program. - -Define an application stack by extending the |stack-class| class, as -shown in the following example. - -.. code-block:: js - - import { Stack, StackProps } from '@aws-cdk/core' - - interface MyStackProps extends StackProps { - encryptedStorage: boolean; - } - - class MyStack extends Stack { - constructor(parent: Construct, name: string, props?: MyStackProps) { - super(parent, name, props); - - new MyStorageLayer(this, 'Storage', { encryptedStorage: props.encryptedStorage }); - new MyControlPlane(this, 'CPlane'); - new MyDataPlane(this, 'DPlane'); - } - } - -And then, add instances of this class to your app: - -.. code-block:: js - - const app = new App(process.argv); - - new MyStack(app, 'NorthAmerica', { env: { region: 'us-east-1' } }); - new MyStack(app, 'Europe', { env: { region: 'us-west-2' } }); - -.. _logical_ids: - -Logical IDs -=========== - -When you synthesize a stack into a |CFN| template, -the |cdk| assigns a -`logical ID `_, -which must be unique within the template, -to each resource in the stack. - -.. important:: - - When you update the template, |CFN| uses these logical IDs to plan the update - and apply changes. Therefore, logical IDs must remain "stable" across updates. - If you make a modification in your code that results in a change to a logical ID - of a resource, |CFN| deletes the resource and creates a new resource when it - updates 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 |CFN| 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: - -.. code-block:: text - - VPCPrivateSubnet2RouteTable0A19E10E - <-----------human---------><-hash-> - -Resources that are direct children of the |stack-class| class use -their name as their logical ID without modification. This makes it easier to -port existing templates into a CDK app. - -This scheme ensures that: - -Logical IDs have a human-friendly portion - This is useful when interacting directly with the synthesized |CFN| - template during development and deployment. - -Logical IDs are unique within the stack - This is ensured by the MD5 component, - which is based on the absolute path to the resource, - which is unique within a stack. - -Logical IDs remain unchanged across updates - This is true as long as their location within the construct tree doesn't change. - See :ref:`creating_runtime_value` - for information on how to retain - logical IDs despite structural changes in your stack. - -The |cdk| applies some heuristics to improve the human-friendliness of the prefix: - -- If a path component is **Resource**, it is omitted. - This postfix does not normally contribute any additional useful information to the ID. -- If two subsequent names in the path are the same, only one is retained. -- If the prefix exceeds 240 characters, it is trimmed to 240 characters. - This ensures that the total length of the logical ID does not exceed the 255 character - |CFN| limit for logical IDs. - -.. _changing_logical_ids: - -Changing Logical IDs --------------------- - -In some cases changing a resource -results in a structural change, -which results in a different path, -thus changing the logical ID of the resource. - -When a resource's logical ID changes, -|CFN| eventually deletes the old resource and create a new resource, -as it cannot determine that the two resources are the same. -Depending on the nature of the resource, -this can be disastrous in production, such as when deleting a |DDB| table. - -You could use -`AWS CloudFormation Stack Policies -`_ -to protect critical resources in your stack from accidental deletion. -Although this |CFN| feature is not supported in the |cdk| and |toolkit|, -the |cdk| does provide a few other mechanisms to help deal with logical ID changes. - -If you have CDK stacks deployed with persistent resources such as S3 buckets or -DynamoDB tables, you might want to explicitly "rename" the new logical IDs to -match your existing resources. - -First, make sure you compare the newly synthesized template with any deployed -stacks. `cdk diff` will tell you which resources are about to be destroyed: - -.. code:: shell - - [-] ☢️ Destroying MyTable (type: AWS::DynamoDB::Table) - [+] 🆕 Creating MyTableCD117FA1 (type: AWS::DynamoDB::Table) - -- :py:meth:`aws-cdk.Stack.renameLogical` where :code:`from` is either an explicit logical ID or a path. - Call this method after the resource has been added to the stack. -- :py:attr:`aws-cdk.Resource.logicalId` allows assigning a fixed logical ID to a resource, - and opt-out from using the scheme described above. - -.. _environments: - -Environments and Authentication -=============================== - -The |cdk| refers to the combination of an account ID and a Region as an *environment*. -The simplest environment is the one you get by default, -which is the one you get when you have set up your credentials and a default Region as described in -:ref:`credentials_and_region`. - -When you create a |stack-class| instance, you can supply the target deployment environment -for the stack using the **env** property, as shown in the following example, -where REGION is the Region in which you want to create the stack and ACCOUNT is your account ID. - -.. code:: js - - new MyStack(app, { env: { region: 'REGION', account: 'ACCOUNT' } }); - -For each of the two arguments **region** and **account**, the |cdk| uses the -following lookup procedure: - -- If **region** or **account** are provided directly as an property to the - Stack, use that. -- Otherwise, read **default-account** and **default-region** from the application's context. - These can be set in the |toolkit| in either the local |cx-json| file or the global version in - *$HOME/.cdk* on Linux or MacOS or *%USERPROFILE%\\.cdk* on Windows. -- If these are not defined, it will determine them as follows: - - **account**: use account from default SDK credentials. Environment - variables are tried first (**AWS_ACCESS_KEY_ID** and **AWS_SECRET_ACCESS_KEY**), - followed by credentials in *$HOME/.aws/credentials* on Linux or MacOS - or *%USERPROFILE%\\.aws\\credentials* on Windows. - - **region**: use the default region configured in *$HOME/.aws/config* on - Linux or MacOS or *%USERPROFILE%\\.aws\\config* on Windows. - - You can set these defaults manually, but we recommend you use ``aws - configure``, as described in the :doc:`getting-started` topic. - -We recommend you use the default environment for development stacks, -and explicitly specify accounts and Regions for production stacks. - -.. note:: - - Note that even though the region and account might explicitly be set on your - Stack, if you run ``cdk deploy`` the |cdk| will still use the - currently-configured SDK credentials, as provided via the **AWS_** - environment variables or ``aws configure``. This means that if you want to - deploy stacks to multiple accounts, you will have to set the correct - credentials for each invocation to ``cdk deploy STACK``. - - In the future, we will provide the ability to specify credential sources for - individual accounts so that you can deploy to multiple accounts using one - invocation of ``cdk deploy``, but this feature is not available yet. - -.. _environment_context: - -Environmental Context ---------------------- - -When you synthesize a stack to create a |CFN| template, the |cdk| might need information based on the -environment (account and Region), such as the availability zones or AMIs available in the Region. -To enable this feature, the |toolkit| uses *context providers*, -and saves the context information into |cx-json| -the first time you call |cx-synth-code|. - -The |cdk| currently supports the following context providers. - -:py:class:`_aws-cdk_core.AvailabilityZoneProvider` - Use this provider to get the list of all supported availability zones in this environment. - For example, the following code iterates over all of the AZs in the current environment. - -.. code:: js - - const zones: string[] = new AvailabilityZoneProvider(this).availabilityZones; - - for (let zone of zones) { - // do somethning for each zone! - } - -:py:class:`_aws-cdk_core.SSMParameterProvider` - Use this provider to read values from the current Region's SSM parameter store. - For example, the follow code returns the value of the 'my-awesome-value' key: - -.. code:: js - - const ami: string = new SSMParameterProvider(this).getString('my-awesome-value'); - -.. _apps: - -Apps -==== - -The main artifact of an |cdk| program is called a *CDK App*. -This is an executable program that can be used to synthesize deployment artifacts -that can be deployed by supporting tools like the |toolkit|, -which are described in :doc:`tools`. - -Tools interact with apps through the program's **argv**/**stdout** interface, -which can be easily implemented using the **App** class, -as shown in the following example. - -.. code-block:: js - - import { App } from '@aws-cdk/core' - - const app = new App(process.argv); // input: ARGV - - // - - process.stdout.write(app.run()); - -An |app-construct| is a collection of |stack| objects, as shown in the following -example. - -.. code-block:: js - - import { App } from '@aws-cdk/core' - import { MyStack } from './my-stack' - - const app = new App(process.argv); - - const dev = new MyStack(app, { name: 'Dev', region: 'us-west-2', dev: true }) - const preProd = new MyStack(app, { name: 'PreProd', region: 'us-west-2', preProd: true }) - const prod = [ - new MyStack(app, { name: 'NAEast', region: 'us-east-1' }), - new MyStack(app, { name: 'NAWest', region: 'us-west-2' }), - new MyStack(app, { name: 'EU', region: 'eu-west-1', encryptedStorage: true }) - ] - - new DeploymentPipeline(app, { - region: 'us-east-1', - strategy: DeploymentStrategy.Waved, - preProdStages: [ preProd ], - prodStages: prod - }); - - process.stdout.write(app.run()); - -Use the |toolkit| to list the stacks in this executable, -as shown in the following example. - -.. code-block:: sh - - cdk list - [ - { name: "Dev", region: "us-west-2" } - { name: "PreProd", region: "us-west-2" }, - { name: "NAEast", region: "us-east-1" }, - { name: "NAWest", region: "us-west-2" }, - { name: "EU", region: "eu-west-1" }, - { name: "DeploymentPipeline", region: 'us-east-1' } - ] - -Or deploy one of the stacks, -as shown in the following example. - -.. code-block:: sh - - cdk deploy Dev - ... - -.. _applets: - -Applets -======= - -.. note:: Currently the |cdk| only supports applets published as JavaScript modules. - -Applets are files in the YAML or JSON format that have the following root attribute, -where MODULE can represent -a local file, such as :code:`./my-module`, -a local dependency, such as :code:`my-dependency`, -or a global module, such as :code:`aws-cdk-codebuild` -and CLASS is the name of a class exported by the module. - -.. code:: js - - applet: MODULE[:CLASS] - -If CLASS is not specified, :code:`Applet` is used as the default class name. -Therefore, you need only refer to |cdk| construct libraries that export -an :code:`Applet` class by their library name. - -The rest of the YAML file is applet-dependent. -The object is passed as :code:`props` when the applet object is instantiated -and added to an |cdk| app created by **cdk-applet-js**. - -Use **cdk-applet-js** *applet* to run the applet, create an |cdk| app, -and use that with the |cdk| tools, as shown in the following example. - -.. code-block:: sh - - cdk --app "cdk-applet-js ./my-applet.yaml" synth - -To make the applet file executable and use the host as a shebang -on Unix-based systems, such as Linux, MacOS, or Windows Bash shell, -create a script similar to the following. - -.. code-block:: sh - - #!/usr/bin/env cdk-applet-js - - applet: aws-cdk-codebuild - source: arn:aws:codecommit:::my-repository - image: node:8.9.4 - compute: large - build: - - npm install --unsafe-perm - - npm test - - npm pack --unsafe-perm - -To execute the applet and synthesize an |CFN| template, -use the following command. - -.. code-block:: sh - - cdk synth --app "./build.yaml" - -To avoid needing **--app** for every invocation, -add the following entry to *cdk.json*. - -.. code-block:: json - - { - "app": "./build.yaml" - } +.. toctree:: + :titlesonly: + :caption: Topics + :maxdepth: 1 + + constructs + stacks + logical-ids + environments + apps + applets diff --git a/packages/aws-cdk-docs/src/conf.py b/packages/aws-cdk-docs/src/conf.py index 08c54159055c1..c97b1ebfe37de 100644 --- a/packages/aws-cdk-docs/src/conf.py +++ b/packages/aws-cdk-docs/src/conf.py @@ -29,11 +29,11 @@ # The long version of the service or SDK name, such as "Amazon Simple Workflow # Service", "AWS Flow Framework for Ruby" or "AWS SDK for Java" -service_name_long = u'AWS Cloud Development Kit' +service_name_long = u'AWS Cloud Development Kit (BETA)' service_docs_home = u'http://aws.amazon.com/documentation/CDK/' project = u'User Guide' -project_desc = u'AWS Cloud Development Kit User Guide' +project_desc = u'User Guide' project_basename = u'CDK/ug' # This name is used as the manual / PDF name. Don't include the extension diff --git a/packages/aws-cdk-docs/src/constructs.rst b/packages/aws-cdk-docs/src/constructs.rst new file mode 100644 index 0000000000000..962b178f00f8d --- /dev/null +++ b/packages/aws-cdk-docs/src/constructs.rst @@ -0,0 +1,194 @@ +.. Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 + International License (the "License"). You may not use this file except in compliance with the + License. A copy of the License is located at http://creativecommons.org/licenses/by-nc-sa/4.0/. + + This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific language governing permissions and + limitations under the License. + +.. _constructs: + +########## +Constructs +########## + +Constructs are the building blocks of |cdk| applications. Constructs can have +child constructs, which in turn can have child constructs, forming a +hierarchical tree structure. + +The |cdk| includes two different levels of constructs: + +|l1| + + These constructs are low-level constructs that provide a direct, one-to-one, + mapping to an |CFN| resource, + as listed in the |CFN| topic `AWS Resource Types Reference `_. + + All |l1| members are found in the :py:mod:`@aws-cdk/resources` package. + +|l2| + + 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. + + |l2| members are found in the :py:mod:`@aws-cdk/NAMESPACE` packages, + where NAMESPACE is the short name for the associated service, + such as SQS for the |l2| for the |SQS| service. + See the :ref:`reference` section for descriptions of the |cdk| + packages and constructs. + +.. Hide for now + At an even higher-level than an |l2|, a |l3| + aggregates multiple, other constructs together + into common architectural patterns, such as a *queue processor* or an *HTTP + service*. + + By leveraging these common patterns, you can assemble your + application even faster than by using an |l2| directly. + + A |l3| + is not included with the standard CDK Construct + Library. Instead, we encourage you to develop and share them inside your + organization or on GitHub. + +.. _construct_structure: + +Construct Structure +=================== + +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 |DDB| tables and |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. + +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 an set of properties for the final parameter, +as shown in the following example. + +.. code-block:: js + + new SomeConstruct(parent, name[, props]); + +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. + +.. code-block:: js + + new BeautifulConstruct(this, 'Foo', { + applicationName: 'myApp', + 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. + +Use the following operations to inspect the construct tree. + +:py:attr:`aws-cdk.Construct.parent` + Gets the construct's parent construct. + +:py:meth:`aws-cdk.Construct.getChildren` + Gets an array of all of the contruct's children. + +:py:meth:`aws-cdk.Construct.getChild` + Gets the child construct with the specified ID. + +:py:meth:`aws-cdk.Construct.toTreeString()` + + Gets a string representing the construct's tree. + +.. We discuss the advantages of an |l2| over a |l1| in the :ref:`l2_advantages` section. + +.. _construct_names: + +Construct Names +=============== + +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 |CFN| can keep track of the generated resources. + +When a construct is created, its name is specified as the second +initializer argument: + +.. code-block:: js + + const c1 = new MyBeautifulConstruct(this, 'OneBeautiful'); + const c2 = new MyBeautifulConstruct(this, 'TwoBeautiful'); + assert(c1.name === 'OneBeautiful'); + assert(c2.name === 'TwoBeautiful'); + +Use the :py:attr:`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``. Example: + +.. code-block:: js + + new Bucket(this, 'MyBucket', { + bucketName: 'physical-bucket-name' + }); + +Avoid specifying physical names. Instead, let +|CFN| generate names for you. +Use attributes, such as **bucket.bucketName**, +to discover the generated names. + +.. and pass them to your application's runtime + code, as described in :ref:`creating_runtime_value`. + +When you synthesize an |cdk| tree into an |CFN| template, the |CFN| 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 :ref:`logical_ids`. + +.. _construct_properties: + +Construct Properties +==================== + +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: + +.. code-block:: js + + // Inline (recommended) + new Queue(this, 'MyQueue', { + visibilityTimeout: 300 + }); + + // Instantiate separate property object + const props: QueueProps = { + visibilityTimeout: 300 + }; + + new Queue(this, 'MyQueue', props); + +.. _construct_metadata: + +Construct Metadata +================== + +You can attach metadata to a construct using the +:py:meth:`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. diff --git a/packages/aws-cdk-docs/src/creating-constructs.rst b/packages/aws-cdk-docs/src/creating-constructs.rst deleted file mode 100644 index b3a3877571a26..0000000000000 --- a/packages/aws-cdk-docs/src/creating-constructs.rst +++ /dev/null @@ -1,143 +0,0 @@ -.. Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. - - This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 - International License (the "License"). You may not use this file except in compliance with the - License. A copy of the License is located at http://creativecommons.org/licenses/by-nc-sa/4.0/. - - This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - either express or implied. See the License for the specific language governing permissions and - limitations under the License. - -.. _creating_constructs: - -######################### -Creating |cdk| Constructs -######################### - -This topic provides information on how to create constructs in the |cdk|. - -.. _what_are_constructs: - -What Are Constructs? -==================== - -As described in :doc:`concepts`, constructs are components that developers can -combine into other constructs and an application stack to create an |cdk| -application. - -The lowest-level |cdk| construct is a Resource Construct, which represents a -single AWS service resource, such as an |SNS| topic or an |SQS| queue. - -The next level of constructs, which we call a Construct Library Construct, -typicall wraps one or more Resource Constructs and adds higher-level -abstractions. These can include: - -* Convenient defaults. -* Automatic creation of related resources such as policy documents, IAM roles or encryption keys. -* Methods to make the resource interact with other resources. - -For example, the stack described in the :doc:`getting-started` topic consists of -an |SQS| queue, |SNS| topic, a subscription between the topic and the queue, and -an |IAM| policy document. - -The |cdk| includes a variety of Library constructs, and you can create your own -for special needs. You might even consider writing and publishing purpose-built -constructs (:ref:`purpose_built_constructs`) to solve common business needs. Be -sure to have a look at the :ref:`guidelines` section on tips for developing -new constructs. - -Whether you're planning to write a purpose-built construct for your own -application or submit a new Construct Library construct to the CDK, the process -is quite similar. It's described below: - -.. _creating_l2_constructs: - -Creating Construct Library constructs -===================================== - -To create a new Construct Library construct as a pull request to the |cdk|: - -* Fork the |cdk| project to your own GitHub account. -* Clone the repository to your computer: - -.. code-block:: sh - - mkdir ~/cdk - cd ~/cdk - git clone ... - -* Create a new branch to hold your code - -.. code-block:: sh - - git checkout my-branch - -* Create a new folder, *aws-cdk-RESOURCE*, in *packages/*, - where *RESOURCE* is the name of a |CFN| resource. - -* Code goes in *lib/*; tests in *test/*. - -* Create an *index.ts* file that only imports the other *NAME.ts* files, - where *NAME* indicates the functionality within the file. - -* Create *NAME.ts* for each set of related classes, - such as the construct itself and its props interface. - -In *NAME.ts*: - -* Create a class. - -* Create the related props interface. - -* Instantiate the resource. - -* Add enhancements as methods. - -* Set props to reasonable default values - (think clicking through the console and accepting those defaults). - -* Don't forget to implement **validate()**. - -Finally for the package: - -* Add a test, *test.NAME.ts*, for each construct. - -* Create an integration test, *integ.everything.ts*. - -* Commit your changes and push them back to GitHub. - -* Once everything looks good, navigate to the |cdk| project on the GitHub - website, select your branch, and next to the **Branch** menu select **New pull - request**. - -See the **aws-cdk-dynamodb** package for examples. - -Validation ----------- - -Validation happens in one of two places: - -* In the constructor, to validate the properties that are passed in. -* If the Construct offers methods that mutate the state of the Construct, - in the Construct's :py:meth:`_aws-cdk_core.Construct.validate` method. This - method is called by the framework after the Construct hierarchy has been set up, - and is expected to return a list of validation error messages. - -Construct implementors should prefer throwing validation errors in the constructor, -falling back to overriding the :py:meth:`_aws-cdk_core.Construct.validate` method -only if the Construct offers mutating members. - -Example of implementing validate: - -.. code-block:: js - - class MyConstruct extends Construct { - public validate() { - if (this.getChildren().length > 1) { - return [ 'this construct can only have a single child' ]; - } - else { - return [ ]; - } - } - } diff --git a/packages/aws-cdk-docs/src/environments.rst b/packages/aws-cdk-docs/src/environments.rst new file mode 100644 index 0000000000000..3114646ea20ce --- /dev/null +++ b/packages/aws-cdk-docs/src/environments.rst @@ -0,0 +1,96 @@ +.. Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 + International License (the "License"). You may not use this file except in compliance with the + License. A copy of the License is located at http://creativecommons.org/licenses/by-nc-sa/4.0/. + + This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific language governing permissions and + limitations under the License. + +.. _environments: + +############################### +Environments and Authentication +############################### + +The |cdk| refers to the combination of an account ID and a Region as an *environment*. +The simplest environment is the one you get by default, +which is the one you get when you have set up your credentials and a default Region as described in +:ref:`credentials_and_region`. + +When you create a |stack-class| instance, you can supply the target deployment environment +for the stack using the **env** property, as shown in the following example, +where REGION is the Region in which you want to create the stack and ACCOUNT is your account ID. + +.. code:: js + + new MyStack(app, { env: { region: 'REGION', account: 'ACCOUNT' } }); + +For each of the two arguments **region** and **account**, the |cdk| uses the +following lookup procedure: + +- If **region** or **account** are provided directly as an property to the + Stack, use that. +- Otherwise, read **default-account** and **default-region** from the application's context. + These can be set in the |toolkit| in either the local |cx-json| file or the global version in + *$HOME/.cdk* on Linux or MacOS or *%USERPROFILE%\\.cdk* on Windows. +- If these are not defined, it will determine them as follows: + + - **account**: use account from default SDK credentials. Environment + variables are tried first (**AWS_ACCESS_KEY_ID** and **AWS_SECRET_ACCESS_KEY**), + followed by credentials in *$HOME/.aws/credentials* on Linux or MacOS + or *%USERPROFILE%\\.aws\\credentials* on Windows. + - **region**: use the default region configured in *$HOME/.aws/config* on + Linux or MacOS or *%USERPROFILE%\\.aws\\config* on Windows. + - You can set these defaults manually, but we recommend you use ``aws + configure``, as described in the :doc:`getting-started` topic. + +We recommend you use the default environment for development stacks, +and explicitly specify accounts and Regions for production stacks. + +.. note:: + + Note that even though the region and account might explicitly be set on your + Stack, if you run ``cdk deploy`` the |cdk| will still use the + currently-configured SDK credentials, as provided via the **AWS_** + environment variables or ``aws configure``. This means that if you want to + deploy stacks to multiple accounts, you will have to set the correct + credentials for each invocation to ``cdk deploy STACK``. + + In the future, we will provide the ability to specify credential sources for + individual accounts so that you can deploy to multiple accounts using one + invocation of ``cdk deploy``, but this feature is not available yet. + +.. _environment_context: + +Environmental Context +===================== + +When you synthesize a stack to create a |CFN| template, the |cdk| might need information based on the +environment (account and Region), such as the availability zones or AMIs available in the Region. +To enable this feature, the |toolkit| uses *context providers*, +and saves the context information into |cx-json| +the first time you call |cx-synth-code|. + +The |cdk| currently supports the following context providers. + +:py:class:`_aws-cdk_core.AvailabilityZoneProvider` + Use this provider to get the list of all supported availability zones in this environment. + For example, the following code iterates over all of the AZs in the current environment. + +.. code:: js + + const zones: string[] = new AvailabilityZoneProvider(this).availabilityZones; + + for (let zone of zones) { + // do somethning for each zone! + } + +:py:class:`_aws-cdk_core.SSMParameterProvider` + Use this provider to read values from the current Region's SSM parameter store. + For example, the follow code returns the value of the 'my-awesome-value' key: + +.. code:: js + + const ami: string = new SSMParameterProvider(this).getString('my-awesome-value'); diff --git a/packages/aws-cdk-docs/src/examples.rst b/packages/aws-cdk-docs/src/examples.rst index d627cdb7b9e61..70f45786558b9 100644 --- a/packages/aws-cdk-docs/src/examples.rst +++ b/packages/aws-cdk-docs/src/examples.rst @@ -84,7 +84,7 @@ the |cdk|. const prod = [ new MyStack(app, { name: 'NAEast', - env: { region: 'us-east-1' } + env: { region: 'us-east-1' } }), new MyStack(app, { @@ -224,21 +224,15 @@ encryption provided by |S3|. Compiling the Examples ====================== -Compile the TypeScript app *index.ts* into the JavaScript code *index.js* using **jsii**. +These examples apply to a `hello-cdk` app. -:code:`jsii` +Compile the TypeScript app *hello-cdk.ts* into the JavaScript code *hello-cdk.js* using +the following command. -**jsii** creates the file *tsconfig.json* to get code completion in a TypeScript IDE, such as -`Microsoft Visual Code `_, -`Sublime Text `_ with the -`TypeScript `_ plugin, -or -`Atom `_ with the -`TypeScript `_ plugin. +:code:`npm run prepare` -You can have **jsii** watch for source changes and automatically re-compile those changes using the **watch** option. - -:code:`jsii -w` +Use **npm run watch** to automatically re-compile those changes. +Run the command in another command window and do not run it in the background. .. _create_cloud_formation: diff --git a/packages/aws-cdk-docs/src/getting-started.rst b/packages/aws-cdk-docs/src/getting-started.rst index f6902d36659d9..e72f024e65785 100644 --- a/packages/aws-cdk-docs/src/getting-started.rst +++ b/packages/aws-cdk-docs/src/getting-started.rst @@ -27,8 +27,6 @@ Let's use the |cdk| to create an |CFN| an |SQS| queue, an |SNS| topic, a subscri and an |IAM| policy document that enables the topic to send messages to the queue. -.. _hello_cdk_typescript - .. _create_dirs: Create Your Project Structure @@ -44,8 +42,28 @@ For the examples in this section we'll use TypeScript. cd hello-cdk cdk init --language=typescript -The **cdk init** command creates a skeleton |cdk| program for you to work with -and displays some useful commands to help you get started. +The **cdk init** command creates the following: + +* *bin* contains the following files. The command creates *hello-cdk.ts* from a template, + and the other two files as it runs the TypeScript compiler: + + * *hello-cdk.d.ts* + * *hello-cdk.js* + * *hello-cdk.ts* is TypeScript source for the entry point to your app + (the file we'll update later) + +* *cdk.json* specifies the entry point to your app, + so that you can omit the **--app** option, + such as when running **cdk synth** +* *node_module* contains the Node packages you need to develop your TypeScript source +* *package.json* contains metadata for the app. +* *package-lock.json* is the npm lockfile for package.json +* *README.md* contains some information to help you from this point on +* *tsconfig.json* contains definitions for the TypeScript compiler + +The command displays README.md as it finishes to give you information about some useful commands. + +Let's take a look at an annotated version of the file *hello-cdk.ts*. .. note:: You can use an IDE, such as `Microsoft Visual Code `_, @@ -63,24 +81,25 @@ extends **Stack**, and include some construction logic. // You'll need this statement in every app import { App, Stack, StackProps } from '@aws-cdk/core'; - // The SNS resources, such as Topic, are defined in aws-cdk-sns + // The SNS resources, such as Topic, are defined in @aws-cdk/sns import { Topic } from '@aws-cdk/sns'; - // The SQS resources, such as Queue, are defined in aws-cdk-sqs + // The SQS resources, such as Queue, are defined in @aws-cdk/sqs import { Queue } from '@aws-cdk/sqs'; class HelloStack extends Stack { // Instantiate HelloStack with a reference to its parent, + // as it might need some context; // as it might need some context from the app; // a name; and some optional properties. // You'll almost always use these same two lines. constructor(parent: App, name: string, props?: StackProps) { super(parent, name, props); - // Create an SNS topic + // Create an SNS topic const topic = new Topic(this, 'MyTopic'); - // Create an SQS queue + // Create an SQS queue const queue = new Queue(this, 'MyQueue', { // By default you only get 30 seconds to delete a read message after you've read it; // otherwise it becomes available to other consumers. @@ -105,7 +124,7 @@ extends **Stack**, and include some construction logic. Compiling the App ----------------- -Use one of the commands in the following table to compile your app. +Use the command for your programming language in the following table to compile your app. You must compile your app every time you change it. .. list-table:: @@ -116,15 +135,15 @@ You must compile your app every time you change it. - Compilation Command * - TypeScript - - `npm run prepare` - (use `npm run watch` in a separate command window to watch for source changes and automatically recompile) + - **npm run prepare** + (use **npm run watch** in a separate command window to watch for source changes and automatically recompile) .. _create_cloud_formation: Synthesizing a CloudFormation Template -------------------------------------- -Use the **cdk synth** command to synthesize a |CFN| template for a stack in your app. +Use the **cdk synth** command to synthesize an |CFN| template for a stack in your app. You do not need to synthesize your |CFN| template to deploy it. .. code-block:: console @@ -135,46 +154,45 @@ You should see output similar to the following: .. code-block:: yaml - Resources: - MyTopic86869434: - Type: 'AWS::SNS::Topic' - MyTopicTopicToQueue2F98E5BA: - Type: 'AWS::SNS::Subscription' - Properties: - Endpoint: - 'Fn::GetAtt': - - MyQueueE6CA6235 - - Arn - Protocol: sqs - TopicArn: - Ref: MyTopic86869434 - MyQueueE6CA6235: - Type: 'AWS::SQS::Queue' - Properties: - VisibilityTimeout: 300 - MyQueuePolicy6BBEDDAC: - Type: 'AWS::SQS::QueuePolicy' - Properties: - PolicyDocument: - Statement: - - - Action: 'sqs:SendMessage' - Condition: - ArnEquals: - 'aws:SourceArn': - Ref: MyTopic86869434 - Effect: Allow - Principal: - Service: sns.amazonaws.com - Resource: - 'Fn::GetAtt': - - MyQueueE6CA6235 - - Arn - Version: '2012-10-17' - Queues: - - - Ref: MyQueueE6CA6235 - + Resources: + MyTopic86869434: + Type: 'AWS::SNS::Topic' + MyTopicMyQueueSubscription3245B11E: + Type: 'AWS::SNS::Subscription' + Properties: + Endpoint: + 'Fn::GetAtt': + - MyQueueE6CA6235 + - Arn + Protocol: sqs + TopicArn: + Ref: MyTopic86869434 + MyQueueE6CA6235: + Type: 'AWS::SQS::Queue' + Properties: + VisibilityTimeout: 300 + MyQueuePolicy6BBEDDAC: + Type: 'AWS::SQS::QueuePolicy' + Properties: + PolicyDocument: + Statement: + - + Action: 'sqs:SendMessage' + Condition: + ArnEquals: + 'aws:SourceArn': + Ref: MyTopic86869434 + Effect: Allow + Principal: + Service: sns.amazonaws.com + Resource: + 'Fn::GetAtt': + - MyQueueE6CA6235 + - Arn + Version: '2012-10-17' + Queues: + - + Ref: MyQueueE6CA6235 As you can see, the call to :py:meth:`_aws-cdk_sns.TopicRef.subscribeQueue` on the :py:class:`_aws-cdk_sns.Topic` resulted in: @@ -194,14 +212,18 @@ should see information messages, such as feedback from CloudFormation logs. cdk deploy -.. note:: You must specify your default credentials and region to use the **cdk deploy** command. +.. note:: You must specify your default credentials and region to use the **cdk deploy** command, + unless you explicitly set them when you create a stack. + The following examples creates a stack for account *ACCOUNT* in the region *REGION*. + + :code:`new MyStack(app, { env: { region: 'REGION', account: 'ACCOUNT' } });` Use the `AWS Command Line Interface `_ ``aws configure`` command to specify your default credentials and region. Important: make sure that you explicitly specify a **region**. - You can also set environment variables for your default credentials and region. +.. You can also set environment variables for your default credentials and region. Environment variables take precedence over settings in the credentials or config file. * *AWS_ACCESS_KEY_ID* specifies your access key @@ -224,7 +246,10 @@ Let's change the visibility timeout of the queue from 300 to 500. visibilityTimeoutSec: 500 }); -Run the following command to see the difference between the *deployed* stack and your |cdk| project +Compile your app with **npm run prepare** if you aren't running **npm run watch** in a separate window. + +If you've deployed your stack previously, +run the following command to see the difference between the *deployed* stack and your |cdk| project (if you haven't deployed the stack, you won't see any output): .. code-block:: sh @@ -236,10 +261,33 @@ You should see something like the following. .. code-block:: sh - [~] 🛠 Updating MyQueueE6CA6235 (type: AWS::SQS::Queue) - └─ [+] .VisibilityTimeout: - ├ Old value: 300 - └─ New value: 500 + [~] 🛠 Updating HelloCdkPbQueue8837C78B (type: AWS::SQS::Queue) + └─ [~] .VisibilityTimeout: + ├─ [-] Old value: 300 + └─ [+] New value: 500 -If the changes are acceptable, use **cdk deploy** to update your +If the changes are acceptable, run **cdk deploy** to update your infrastructure. + +Let's make a bigger change by adding an |S3| bucket to our stack. +Run the following command to install the |S3| package. + +.. code-block:: sh + + npm install @aws-cdk/s3 + +Add the following to the top of *hello-cdk.ts* (we recommend you keep your import statements sorted): + +.. code-block:: js + + import { Bucket } from '@aws-cdk/s3'; + +Finally, create a bucket by adding the following to your constructor. +Don't forget that |S3| has restrictions on bucket names. +See `Rules for Bucket Naming `_. + +.. code-block:: js + + new Bucket(this, "MyBucket", { + bucketName: "mygroovybucket" + }) diff --git a/packages/aws-cdk-docs/src/glossary.rst b/packages/aws-cdk-docs/src/glossary.rst index da1ee55458c28..1b41c043e43f5 100644 --- a/packages/aws-cdk-docs/src/glossary.rst +++ b/packages/aws-cdk-docs/src/glossary.rst @@ -18,8 +18,13 @@ The |cdk| uses the following terms. Some are based on AWS CloudFormation `concepts `_. app - An executable program that the |cdk| uses to synthesize artifacts - that can contain multiple stacks and be deployed into multiple AWS environments. + An executable program that the |cdk| uses to synthesize a |CFN| template. + Apps are: + + * Written by a user + * Contain one or more stacks that can be deployed into multiple AWS environments + * Define the infrastructure of your application + Apps extend the :py:class:`aws-cdk.App` class. applet @@ -43,17 +48,16 @@ environment The lowest-level construct, which maps directly to an |CFN| resource, as described in the `AWS Resource Types Reference `_. - These constructs are available in the :py:mod:`aws-cdk-resources` package - as the |CFN| name with a **Resource** suffix within the AWS service namespace, + These constructs are available in the :py:mod:`@aws-cdk/resources` package, + as the |CFN| name, in lower case, with a **Resource** suffix within the AWS service namespace, such as **sqs.QueueResource**, which represents an |SQS| queue. |l2| A construct that provides high-level APIs for AWS services. Their names imply the underlying AWS service. - For example, |S3| resources are available through the **aws-cdk-s3** - Construct Library. + For example, |S3| resources are available through the **@aws-cdk/s3** package. -|l3| +.. |l3| A construct that abstracts common architectural patterns on AWS. These are not supplied with the standard |cdk| distribution, but are shared within your organization or on GitHub. @@ -61,4 +65,3 @@ environment stack An |cdk| construct that can be deployed into an environment. Stacks extend the :py:class:`aws-cdk.Stack` class. - diff --git a/packages/aws-cdk-docs/src/guidelines.rst b/packages/aws-cdk-docs/src/guidelines.rst index c75b2069c26ac..2ebb2782b831c 100644 --- a/packages/aws-cdk-docs/src/guidelines.rst +++ b/packages/aws-cdk-docs/src/guidelines.rst @@ -39,7 +39,7 @@ starts with a pull request to the |cdk|: git checkout my-branch -* Create a new folder, *aws-cdk-RESOURCE*, in *packages/*, +* Create a new folder, *RESOURCE*, in *packages/@aws-cdk*, where *RESOURCE* is the name of a |CFN| resource. * Code goes in *lib/*; tests in *test/*. @@ -77,7 +77,7 @@ Finally for the package: website, select your branch, and next to the **Branch** menu select **New pull request**. -See the **aws-cdk-dynamodb** package for examples. +See the **dynamodb** package for examples. .. _general_guidelines: diff --git a/packages/aws-cdk-docs/src/index.rst b/packages/aws-cdk-docs/src/index.rst index a0577f724d360..9f3d8ad002cbc 100644 --- a/packages/aws-cdk-docs/src/index.rst +++ b/packages/aws-cdk-docs/src/index.rst @@ -17,7 +17,6 @@ User Guide .. toctree:: Welcome Getting Started - Developing Apps Developing Libraries Examples Concepts @@ -26,6 +25,7 @@ User Guide Glossary Reference +.. Removed on 6/20/2018: Developing Apps (see https://github.com/awslabs/aws-cdk/pull/142) .. Incorporated into concepts: l1-vs-l2 .. Incorporated into guidelines: creating-constructs .. Skipping: validating-downloads as that info should go in the "Start Here" doc diff --git a/packages/aws-cdk-docs/src/l1-vs-l2.rst b/packages/aws-cdk-docs/src/l1-vs-l2.rst deleted file mode 100644 index c954b5ae0ed6c..0000000000000 --- a/packages/aws-cdk-docs/src/l1-vs-l2.rst +++ /dev/null @@ -1,137 +0,0 @@ -.. Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. - - This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 - International License (the "License"). You may not use this file except in compliance with the - License. A copy of the License is located at http://creativecommons.org/licenses/by-nc-sa/4.0/. - - This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - either express or implied. See the License for the specific language governing permissions and - limitations under the License. - -.. _the_cdk_construct_library: - -########################### -The |cdk| Construct Library -########################### - -The |cdk| standard library comes with two different levels of constructs: - -|l1| Constructs - - These constructs are low-level constructs that provide a direct, one-to-one, - mapping to an |CFN| resource, - as listed in the |CFN| topic `AWS Resource Types Reference `_. - - All |l1| constructs are found in the :py:mod:`_aws-cdk_resources` package. - -|l2| Constructs - - These constructs have been handwritten by AWS engineers 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. - - |l2| constructs are found in the :py:mod:`aws-cdk-RESOURCE` package, - where RESOURCE is the short name for the associated service, - such as SQS for the |l2| constructs for the |SQS| service. - See the :ref:`reference` section for descriptions of the |cdk| - packages and constructs. - -Use |l2| constructs whenever possible, as they provide the -best developer experience. - -Sometimes there are use cases where you need to directly define |CFN| resources, -such as when migrating from an existing template, or when there is no Construct -Library for the AWS resources you need yet. In those case you can use |l1| -constructs to define |CFN| entities such as Resources, Parameters, Outputs, and -Conditions. - -You can define your own higher-level constructs in -addition to the ones already provided, by creating a new class that -pdescribes your construct. - -.. _aws_constructs_versus_cfn_resources: - -|l2| Constructs vs |l1| Constructs -================================== - -To illustrate the advantages that |l2| constructs have over -|l1| constructs, let's look at an example. - -The :py:mod:`_aws-cdk_sns` Construct Library includes the `Topic` construct that -you can use to define an |SNS| topic: - -.. code-block:: js - - import { Topic } from '@aws-cdk/sns'; - const topic = new Topic(this, 'MyTopic'); - -|l2| constructs encapsulate the -details of working with these AWS resources. For example, to subscribe a queue to a topic, -call the :py:meth:`_aws-cdk_sns.Topic.subscribeQueue` method with a queue object as the second argument: - -.. code-block:: js - - const topic = new Topic(this, 'MyTopic'); - const queue = new Queue(this, 'MyQueue', { - visibilityTimeoutSec: 300 - }); - - topic.subscribeQueue('TopicToQueue', queue); - -This method: - -1. Creates a subscription and associates it with the topic and the queue. - -2. Adds a queue policy with permissions for the topic to send messages to the queue. - -To achieve a similar result using :py:mod:`_aws-cdk_resources`, you have to explicitly define the -subscription and queue policy, since there is no **subscribeToQueue** method in the **TopicResource** class: - -.. code-block:: js - - const topic = new sns.TopicResource(this, 'MyTopic'); - const queue = new sqs.QueueResource(this, 'MyQueue'); - - new sns.SubscriptionResource(this, 'TopicToQueue', { - topicArn: topic.ref, // ref == arn for topics - endpoint: queue.queueName, - protocol: 'sqs' - }); - - const policyDocument = new PolicyDocument(); - policyDocument.addStatement(new PolicyStatement() - .addResource(queue.queueArn) - .addAction('sqs:SendMessage') - .addServicePrincipal('sns.amazonaws.com') - .setCondition('ArnEquals', { 'aws:SourceArn': topic.ref })); - - new sqs.QueuePolicyResource(this, 'MyQueuePolicy', { - policyDocument: policyDocument, - queues: [ queue.ref ] - }); - -Notice how much cleaner the first version is. There is more focus on intent, -rather than mechanism. - -This example shows one of the many benefits -of using the |l2| constructs instead of the |l1| constructs. - -.. _purpose_built_constructs: - -|l3| Constructs -=============== - -At an even higher-level than |l2| constructs, |l3| -constructs aggregate multiple, other constructs together -into common architectural patterns, such as a *queue processor* or an *HTTP -service*. - -By leveraging these common patterns, you can assemble your -application even faster than by using |l2| constructs directly. - -The |l3| constructs -are not included with the standard CDK Construct -Library. Instead, we encourage you to develop and share them inside your -organization or on GitHub. diff --git a/packages/aws-cdk-docs/src/logical-ids.rst b/packages/aws-cdk-docs/src/logical-ids.rst new file mode 100644 index 0000000000000..6677ff15e72be --- /dev/null +++ b/packages/aws-cdk-docs/src/logical-ids.rst @@ -0,0 +1,119 @@ +.. Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 + International License (the "License"). You may not use this file except in compliance with the + License. A copy of the License is located at http://creativecommons.org/licenses/by-nc-sa/4.0/. + + This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific language governing permissions and + limitations under the License. + +.. _logical_ids: + +########### +Logical IDs +########### + +When you synthesize a stack into a |CFN| template, +the |cdk| assigns a +`logical ID `_, +which must be unique within the template, +to each resource in the stack. + +.. important:: + + When you update the template, |CFN| uses these logical IDs to plan the update + and apply changes. Therefore, logical IDs must remain "stable" across updates. + If you make a modification in your code that results in a change to a logical ID + of a resource, |CFN| deletes the resource and creates a new resource when it + updates 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 |CFN| 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: + +.. code-block:: text + + VPCPrivateSubnet2RouteTable0A19E10E + <-----------human---------><-hash-> + +Resources that are direct children of the |stack-class| class use +their name as their logical ID without modification. This makes it easier to +port existing templates into a CDK app. + +This scheme ensures that: + +Logical IDs have a human-friendly portion + This is useful when interacting directly with the synthesized |CFN| + template during development and deployment. + +Logical IDs are unique within the stack + This is ensured by the MD5 component, + which is based on the absolute path to the resource, + which is unique within a stack. + +Logical IDs remain unchanged across updates + This is true as long as their location within the construct tree doesn't change. + +.. See :ref:`creating_runtime_value` + for information on how to retain + logical IDs despite structural changes in your stack. + +The |cdk| applies some heuristics to improve the human-friendliness of the prefix: + +- If a path component is **Resource**, it is omitted. + This postfix does not normally contribute any additional useful information to the ID. +- If two subsequent names in the path are the same, only one is retained. +- If the prefix exceeds 240 characters, it is trimmed to 240 characters. + This ensures that the total length of the logical ID does not exceed the 255 character + |CFN| limit for logical IDs. + +.. _changing_logical_ids: + +Changing Logical IDs +==================== + +In some cases changing a resource +results in a structural change, +which results in a different path, +thus changing the logical ID of the resource. + +When a resource's logical ID changes, +|CFN| eventually deletes the old resource and create a new resource, +as it cannot determine that the two resources are the same. +Depending on the nature of the resource, +this can be disastrous in production, such as when deleting a |DDB| table. + +You could use +`AWS CloudFormation Stack Policies +`_ +to protect critical resources in your stack from accidental deletion. +Although this |CFN| feature is not supported in the |cdk| and |toolkit|, +the |cdk| does provide a few other mechanisms to help deal with logical ID changes. + +If you have CDK stacks deployed with persistent resources such as S3 buckets or +DynamoDB tables, you might want to explicitly "rename" the new logical IDs to +match your existing resources. + +First, make sure you compare the newly synthesized template with any deployed +stacks. `cdk diff` will tell you which resources are about to be destroyed: + +.. code:: shell + + [-] ☢️ Destroying MyTable (type: AWS::DynamoDB::Table) + [+] 🆕 Creating MyTableCD117FA1 (type: AWS::DynamoDB::Table) + +- :py:meth:`aws-cdk.Stack.renameLogical` where :code:`from` is either an explicit logical ID or a path. + Call this method after the resource has been added to the stack. +- :py:attr:`aws-cdk.Resource.logicalId` allows assigning a fixed logical ID to a resource, + and opt-out from using the scheme described above. diff --git a/packages/aws-cdk-docs/src/stacks.rst b/packages/aws-cdk-docs/src/stacks.rst new file mode 100644 index 0000000000000..82db49adb8810 --- /dev/null +++ b/packages/aws-cdk-docs/src/stacks.rst @@ -0,0 +1,53 @@ +.. Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 + International License (the "License"). You may not use this file except in compliance with the + License. A copy of the License is located at http://creativecommons.org/licenses/by-nc-sa/4.0/. + + This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific language governing permissions and + limitations under the License. + +.. _stacks: + +###### +Stacks +###### + +A |stack| is an |cdk| construct that can be deployed into an AWS environment. +The combination of region and account becomes the stack's *environment*, as +described in :ref:`environments`. Most production apps consist of multiple stacks of +resources that are deployed as a single transaction using a resource +provisioning service like |CFN|. Any resources added directly or indirectly as +children of a stack are included in the stack's template as it is synthesized by +your |cdk| program. + +Define an application stack by extending the |stack-class| class, as +shown in the following example. + +.. code-block:: js + + import { Stack, StackProps } from '@aws-cdk/core' + + interface MyStackProps extends StackProps { + encryptedStorage: boolean; + } + + class MyStack extends Stack { + constructor(parent: Construct, name: string, props?: MyStackProps) { + super(parent, name, props); + + new MyStorageLayer(this, 'Storage', { encryptedStorage: props.encryptedStorage }); + new MyControlPlane(this, 'CPlane'); + new MyDataPlane(this, 'DPlane'); + } + } + +And then, add instances of this class to your app: + +.. code-block:: js + + const app = new App(process.argv); + + new MyStack(app, 'NorthAmerica', { env: { region: 'us-east-1' } }); + new MyStack(app, 'Europe', { env: { region: 'us-west-2' } }); diff --git a/packages/aws-cdk-docs/src/tools.rst b/packages/aws-cdk-docs/src/tools.rst index 367e36ab6740b..13ba71b8524ed 100644 --- a/packages/aws-cdk-docs/src/tools.rst +++ b/packages/aws-cdk-docs/src/tools.rst @@ -86,8 +86,8 @@ Below are the actions you can take on your CDK app: .. _jsii: -jsii -==== + jsii + ==== .. Hang on, we tell them to use npm run prepare @@ -95,6 +95,6 @@ jsii npm run watch in the getting started topic. Which is it??? -Use this tool to compile your |cdk| TypeScript code into JavaScript. -You can add the **-w** option to have the tool watch for changes in your code, -and automatically compile the changes, using **jsii**, as you save the file. + Use this tool to compile your |cdk| TypeScript code into JavaScript. + You can add the **-w** option to have the tool watch for changes in your code, + and automatically compile the changes, using **jsii**, as you save the file. diff --git a/packages/aws-cdk-docs/src/welcome.rst b/packages/aws-cdk-docs/src/welcome.rst index e3950ce67d99f..90e152b344ab6 100644 --- a/packages/aws-cdk-docs/src/welcome.rst +++ b/packages/aws-cdk-docs/src/welcome.rst @@ -15,14 +15,12 @@ Welcome ####### Welcome to the |cdk-long| (|cdk|) User Guide. - The |cdk| is a software development framework for defining cloud infrastructure in code. - -The |cdk| consists of a core software package, -language bindings, and command-line interface tools. -The |cdk| also provides reusable component libraries, which we call *constructs*. -Constructs are abstractions of cloud infrastructure logic that create AWS resources and are packaged for reuse. -They expose a rich programmatic interface and can be composed together to form |cdk| apps that generate |CFN| templates. +It consists of a core framework library, +which implements the basic programming model; +a command-line toolkit; +and a set of AWS-vended class libraries for defining AWS resources +using rich object-oriented APIs. Here's a short example of creating an |SNS| topic, an |SQS| queue, and subscribing the topic to the queue. @@ -42,8 +40,8 @@ in :doc:`getting-started`. const topic = new Topic(this, 'MyTopic'); - const queue = new Queue(this, 'MyQueue', { - visibilityTimeoutSec: 300 + const queue = new Queue(this, 'MyQueue', { + visibilityTimeoutSec: 300 }); topic.subscribeQueue('TopicToQueue', queue); @@ -59,20 +57,20 @@ The process of creating your AWS resources using the |cdk| is straightforward: 1. Install the |cdk| on your development machine 2. Run the **cdk init** command to create the skeleton of your program - in one of the supported programming lanuages + in one of the supported programming languages 3. Use your favorite development environment to define your AWS application infrastructure using the |l2| 4. Compile your code, if necessary -5. (Optional) Run the |cdk| toolkit **cdk synth** command to see what your |CFN| temlate looks like +5. (Optional) Run the |cdk| toolkit **cdk synth** command to see what your |CFN| template looks like 6. Run the |cdk| toolkit **cdk deploy** command to deploy the resulting |CFN| template and create the AWS resources in your AWS account 7. Repeats steps 3-6 until you are satisfied with your resources .. note:: There is no charge for using the |cdk|, however you may incur AWS charges for creating or using AWS - `chargeable resources `_, - such as running |EC2| instances or using |S3| storage. - Use the - `AWS Simple Monthly Calculator `_ + `chargeable resources `_, + such as running |EC2| instances or using |S3| storage. + Use the + `AWS Simple Monthly Calculator `_ to estimate charges for the use of various AWS resources. .. _aws_cdk_additional_resources: @@ -84,13 +82,15 @@ In addition to this guide, the following are other resources available to |cdk| * `AWS Developer blog `_ * `GitHub repository `_ + * `Documentation source `_ * `Issues `_ + * `License `_ + * :doc:`getting-started` * `TypeScriptLang.org `_ .. TBD: - * License (link) * FAQ (link) * Installing the |cdk| (video) (link) @@ -109,4 +109,4 @@ experimentation, AWS offers a free usage tier, in which services are free below usage. For more information about AWS costs and the free usage tier, see `Test-Driving AWS in the Free Usage Tier `_. -To obtain an AWS account, go to `aws.amazon.com `_ and click :guilabel:`Create a Free Account`. +To obtain an AWS account, go to `aws.amazon.com `_ and click :guilabel:`Create an AWS Account`. diff --git a/packages/aws-cdk-docs/src/writing-cdk-apps.rst b/packages/aws-cdk-docs/src/writing-cdk-apps.rst index 004e4055893d9..bc3eda1ba2dd8 100644 --- a/packages/aws-cdk-docs/src/writing-cdk-apps.rst +++ b/packages/aws-cdk-docs/src/writing-cdk-apps.rst @@ -19,8 +19,76 @@ and compiling them, you'll use the |toolkit| to synthesize or deploy the stacks they describe. To write your CDK app, you can create your own constructs, as described in -:doc:`cloudformation`, or use higher-level constructs. -See the :doc:`concepts` section for an overview of which constructs you should use or create. +:doc:`cloudformation`, or use higher-level constructs, as described in the next section. + +.. _l2_advantages: + +Using an |l2| Versus a |l1| +=========================== +We recommend that you use an |l2| whenever possible, +as they provide the best developer experience. + +To illustrate the advantages that an |l2| has over +a |l1|, let's look at an example. + +The :py:mod:`@aws-cdk/sns` Construct Library includes the `Topic` construct that +you can use to define an |SNS| topic: + +.. code-block:: js + + import { Topic } from '@aws-cdk/sns'; + const topic = new Topic(this, 'MyTopic'); + +An |l2| encapsulate the +details of working with these AWS resources. For example, to subscribe a queue to a topic, +call the :py:meth:`@aws-cdk/sns.Topic.subscribeQueue` method with a queue object as the second argument: + +.. code-block:: js + + const topic = new Topic(this, 'MyTopic'); + const queue = new Queue(this, 'MyQueue', { + visibilityTimeoutSec: 300 + }); + + topic.subscribeQueue('TopicToQueue', queue); + +This method: + +1. Creates a subscription and associates it with the topic and the queue. + +2. Adds a queue policy with permissions for the topic to send messages to the queue. + +To achieve a similar result using :py:mod:`@aws-cdk/resources`, you have to explicitly define the +subscription and queue policy, since there is no **subscribeToQueue** method in the **TopicResource** class: + +.. code-block:: js + + const topic = new sns.TopicResource(this, 'MyTopic'); + const queue = new sqs.QueueResource(this, 'MyQueue'); + + new sns.SubscriptionResource(this, 'TopicToQueue', { + topicArn: topic.ref, // ref == arn for topics + endpoint: queue.queueName, + protocol: 'sqs' + }); + + const policyDocument = new PolicyDocument(); + policyDocument.addStatement(new PolicyStatement() + .addResource(queue.queueArn) + .addAction('sqs:SendMessage') + .addServicePrincipal('sns.amazonaws.com') + .setCondition('ArnEquals', { 'aws:SourceArn': topic.ref })); + + new sqs.QueuePolicyResource(this, 'MyQueuePolicy', { + policyDocument: policyDocument, + queues: [ queue.ref ] + }); + +Notice how much cleaner the first version is. There is more focus on intent, +rather than mechanism. + +This example shows one of the many benefits +of using an |l2| instead of a |l1|. .. _incorporating_external_constructs: