diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000..6bdaa999 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,6 @@ +*Issue #, if available:* + +*Description of changes:* + + +By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. diff --git a/.gitignore b/.gitignore deleted file mode 100644 index c6d8587a..00000000 --- a/.gitignore +++ /dev/null @@ -1,32 +0,0 @@ -# Editor backup files -*~ -*.bak -*.lock - -# System files -.attach* -.DS_Store - -# Build directories -build/ - -# IDE files -.idea/ -.vscode/ -.amazonq/ - -# Generated documentation -*.html -*.pdf -*.docx -*.xlsx -*.rtf -*.mobi - -# Archives -*.7z -*.rar -*.tar - -# Other -*.running.properties.txt \ No newline at end of file diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md deleted file mode 100644 index 5dccd4cf..00000000 --- a/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,4 +0,0 @@ -## Code of Conduct -This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). -For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact -opensource-codeofconduct@amazon.com with any additional questions or comments. \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 50a0d080..00000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,56 +0,0 @@ -# Guidelines for contributing - -Thank you for your interest in contributing to AWS documentation! We greatly value feedback and contributions from our community. - -Please read through this document before you submit any pull requests or issues. It will help us work together more effectively. - -## What to expect when you contribute - -When you submit a pull request, our team is notified and will respond as quickly as we can. We'll do our best to work with you to ensure that your pull request adheres to our style and standards. If we merge your pull request, we might make additional edits later for style or clarity. - -The AWS documentation source files on GitHub aren't published directly to the official documentation website. If we merge your pull request, we'll publish your changes to the documentation website as soon as we can, but they won't appear immediately or automatically. - -We look forward to receiving your pull requests for: - -* New content you'd like to contribute (such as new code samples or tutorials) -* Inaccuracies in the content -* Information gaps in the content that need more detail to be complete -* Typos or grammatical errors -* Suggested rewrites that improve clarity and reduce confusion - -**Note:** We all write differently, and you might not like how we've written or organized something currently. We want that feedback. But please be sure that your request for a rewrite is supported by the previous criteria. If it isn't, we might decline to merge it. - -## How to contribute - -To contribute, send us a pull request. For small changes, such as fixing a typo or adding a link, you can use the [GitHub Edit Button](https://blog.github.com/2011-04-26-forking-with-the-edit-button/). For larger changes: - -1. [Fork the repository](https://help.github.com/articles/fork-a-repo/). -2. In your fork, make your change in a branch that's based on this repo's **main** branch. -3. Commit the change to your fork, using a clear and descriptive commit message. -4. [Create a pull request](https://help.github.com/articles/creating-a-pull-request-from-a-fork/), answering any questions in the pull request form. - -Before you send us a pull request, please be sure that: - -1. You're working from the latest source on the **main** branch. -2. You check [existing open](https://github.com/awsdocs/aws-cdk-guide/pulls), and [recently closed](https://github.com/awsdocs/aws-cdk-guide/pulls?q=is:pr+is:closed), pull requests to be sure that someone else hasn't already addressed the problem. -3. You [create an issue](https://github.com/awsdocs/aws-cdk-guide/issues/new) before working on a contribution that will take a significant amount of your time. - -For contributions that will take a significant amount of time, [open a new issue](https://github.com/awsdocs/aws-cdk-guide/issues/new) to pitch your idea before you get started. Explain the problem and describe the content you want to see added to the documentation. Let us know if you'll write it yourself or if you'd like us to help. We'll discuss your proposal with you and let you know whether we're likely to accept it. We don't want you to spend a lot of time on a contribution that might be outside the scope of the documentation or that's already in the works. - -## Finding contributions to work on - -If you'd like to contribute, but don't have a project in mind, look at the [open issues](https://github.com/awsdocs/aws-cdk-guide/issues) in this repository for some ideas. - -In addition to written content, we really appreciate new examples and code samples for our documentation, such as examples for different platforms or environments, and code samples in additional languages. - -## Code of conduct - -This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). For more information, see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact [opensource-codeofconduct@amazon.com](mailto:opensource-codeofconduct@amazon.com) with any additional questions or comments. - -## Security issue notifications - -If you discover a potential security issue, please notify AWS Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public issue on GitHub. - -## Licensing - -See the [LICENSE](https://github.com/awsdocs/aws-cdk-guide/blob/main/LICENSE) file for this project's licensing. We will ask you to confirm the licensing of your contribution. We may ask you to sign a [Contributor License Agreement (CLA)](http://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes. \ No newline at end of file diff --git a/Config b/Config deleted file mode 100755 index 2e9c79bf..00000000 --- a/Config +++ /dev/null @@ -1,30 +0,0 @@ -# -*-perl-*- - -package.AWSCDKDocs = { - flavors = { - map = single; - generation = 1; - }; - - interfaces = (3.0); - deploy = { - generic = true; - }; - scope = webservices; - - build-system = zonbooktrails; - build-environment = { - chroot = basic; - network-access = blocked; - }; - - build-tools = { - 3.0 = { - ZonBookTrails = 1.0; - - ZonBook = 5.0; - AWSDocsSdkExamplesPublic = 1.0; - AWSDocsChecklistCDK = 2.0; - }; - }; -}; diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..7785b904 --- /dev/null +++ b/LICENSE @@ -0,0 +1,152 @@ +Creative Commons Attribution-ShareAlike 4.0 International Public License + +By exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution-ShareAlike 4.0 International Public License ("Public License"). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions. + +Section 1 – Definitions. + + a. Adapted Material means material subject to Copyright and Similar Rights that is derived from or based upon the Licensed Material and in which the Licensed Material is translated, altered, arranged, transformed, or otherwise modified in a manner requiring permission under the Copyright and Similar Rights held by the Licensor. For purposes of this Public License, where the Licensed Material is a musical work, performance, or sound recording, Adapted Material is always produced where the Licensed Material is synched in timed relation with a moving image. + + b. Adapter's License means the license You apply to Your Copyright and Similar Rights in Your contributions to Adapted Material in accordance with the terms and conditions of this Public License. + + c. BY-SA Compatible License means a license listed at creativecommons.org/compatiblelicenses, approved by Creative Commons as essentially the equivalent of this Public License. + + d. Copyright and Similar Rights means copyright and/or similar rights closely related to copyright including, without limitation, performance, broadcast, sound recording, and Sui Generis Database Rights, without regard to how the rights are labeled or categorized. For purposes of this Public License, the rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights. + + e. Effective Technological Measures means those measures that, in the absence of proper authority, may not be circumvented under laws fulfilling obligations under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, and/or similar international agreements. + + f. Exceptions and Limitations means fair use, fair dealing, and/or any other exception or limitation to Copyright and Similar Rights that applies to Your use of the Licensed Material. + + g. License Elements means the license attributes listed in the name of a Creative Commons Public License. The License Elements of this Public License are Attribution and ShareAlike. + + h. Licensed Material means the artistic or literary work, database, or other material to which the Licensor applied this Public License. + + i. Licensed Rights means the rights granted to You subject to the terms and conditions of this Public License, which are limited to all Copyright and Similar Rights that apply to Your use of the Licensed Material and that the Licensor has authority to license. + + j. Licensor means the individual(s) or entity(ies) granting rights under this Public License. + + k. Share means to provide material to the public by any means or process that requires permission under the Licensed Rights, such as reproduction, public display, public performance, distribution, dissemination, communication, or importation, and to make material available to the public including in ways that members of the public may access the material from a place and at a time individually chosen by them. + + l. Sui Generis Database Rights means rights other than copyright resulting from Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, as amended and/or succeeded, as well as other essentially equivalent rights anywhere in the world. + + m. You means the individual or entity exercising the Licensed Rights under this Public License. Your has a corresponding meaning. + +Section 2 – Scope. + + a. License grant. + + 1. Subject to the terms and conditions of this Public License, the Licensor hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, irrevocable license to exercise the Licensed Rights in the Licensed Material to: + + A. reproduce and Share the Licensed Material, in whole or in part; and + + B. produce, reproduce, and Share Adapted Material. + + 2. Exceptions and Limitations. For the avoidance of doubt, where Exceptions and Limitations apply to Your use, this Public License does not apply, and You do not need to comply with its terms and conditions. + + 3. Term. The term of this Public License is specified in Section 6(a). + + 4. Media and formats; technical modifications allowed. The Licensor authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Licensor waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this Public License, simply making modifications authorized by this Section 2(a)(4) never produces Adapted Material. + + 5. Downstream recipients. + + A. Offer from the Licensor – Licensed Material. Every recipient of the Licensed Material automatically receives an offer from the Licensor to exercise the Licensed Rights under the terms and conditions of this Public License. + + B. Additional offer from the Licensor – Adapted Material. Every recipient of Adapted Material from You automatically receives an offer from the Licensor to exercise the Licensed Rights in the Adapted Material under the conditions of the Adapter’s License You apply. + + C. No downstream restrictions. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Licensed Material if doing so restricts exercise of the Licensed Rights by any recipient of the Licensed Material. + + 6. No endorsement. Nothing in this Public License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Licensed Material is, connected with, or sponsored, endorsed, or granted official status by, the Licensor or others designated to receive attribution as provided in Section 3(a)(1)(A)(i). + + b. Other rights. + + 1. Moral rights, such as the right of integrity, are not licensed under this Public License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise. + + 2. Patent and trademark rights are not licensed under this Public License. + + 3. To the extent possible, the Licensor waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties. + +Section 3 – License Conditions. + +Your exercise of the Licensed Rights is expressly made subject to the following conditions. + + a. Attribution. + + 1. If You Share the Licensed Material (including in modified form), You must: + + A. retain the following if it is supplied by the Licensor with the Licensed Material: + + i. identification of the creator(s) of the Licensed Material and any others designated to receive attribution, in any reasonable manner requested by the Licensor (including by pseudonym if designated); + + ii. a copyright notice; + + iii. a notice that refers to this Public License; + + iv. a notice that refers to the disclaimer of warranties; + + v. a URI or hyperlink to the Licensed Material to the extent reasonably practicable; + + B. indicate if You modified the Licensed Material and retain an indication of any previous modifications; and + + C. indicate the Licensed Material is licensed under this Public License, and include the text of, or the URI or hyperlink to, this Public License. + + 2. You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Licensed Material. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information. + + 3. If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable. + + b. ShareAlike.In addition to the conditions in Section 3(a), if You Share Adapted Material You produce, the following conditions also apply. + + 1. The Adapter’s License You apply must be a Creative Commons license with the same License Elements, this version or later, or a BY-SA Compatible License. + + 2. You must include the text of, or the URI or hyperlink to, the Adapter's License You apply. You may satisfy this condition in any reasonable manner based on the medium, means, and context in which You Share Adapted Material. + + 3. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, Adapted Material that restrict exercise of the rights granted under the Adapter's License You apply. + +Section 4 – Sui Generis Database Rights. + +Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material: + + a. for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share all or a substantial portion of the contents of the database; + + b. if You include all or a substantial portion of the database contents in a database in which You have Sui Generis Database Rights, then the database in which You have Sui Generis Database Rights (but not its individual contents) is Adapted Material, including for purposes of Section 3(b); and + + c. You must comply with the conditions in Section 3(a) if You Share all or a substantial portion of the contents of the database. +For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights. + +Section 5 – Disclaimer of Warranties and Limitation of Liability. + + a. Unless otherwise separately undertaken by the Licensor, to the extent possible, the Licensor offers the Licensed Material as-is and as-available, and makes no representations or warranties of any kind concerning the Licensed Material, whether express, implied, statutory, or other. This includes, without limitation, warranties of title, merchantability, fitness for a particular purpose, non-infringement, absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not known or discoverable. Where disclaimers of warranties are not allowed in full or in part, this disclaimer may not apply to You. + + b. To the extent possible, in no event will the Licensor be liable to You on any legal theory (including, without limitation, negligence) or otherwise for any direct, special, indirect, incidental, consequential, punitive, exemplary, or other losses, costs, expenses, or damages arising out of this Public License or use of the Licensed Material, even if the Licensor has been advised of the possibility of such losses, costs, expenses, or damages. Where a limitation of liability is not allowed in full or in part, this limitation may not apply to You. + + c. The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability. + +Section 6 – Term and Termination. + + a. This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this Public License, then Your rights under this Public License terminate automatically. + + b. Where Your right to use the Licensed Material has terminated under Section 6(a), it reinstates: + + 1. automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or + + 2. upon express reinstatement by the Licensor. + + c. For the avoidance of doubt, this Section 6(b) does not affect any right the Licensor may have to seek remedies for Your violations of this Public License. + + d. For the avoidance of doubt, the Licensor may also offer the Licensed Material under separate terms or conditions or stop distributing the Licensed Material at any time; however, doing so will not terminate this Public License. + + e. Sections 1, 5, 6, 7, and 8 survive termination of this Public License. + +Section 7 – Other Terms and Conditions. + + a. The Licensor shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed. + + b. Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are separate from and independent of the terms and conditions of this Public License. + +Section 8 – Interpretation. + + a. For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Licensed Material that could lawfully be made without permission under this Public License. + + b. To the extent possible, if any provision of this Public License is deemed unenforceable, it shall be automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot be reformed, it shall be severed from this Public License without affecting the enforceability of the remaining terms and conditions. + + c. No term or condition of this Public License will be waived and no failure to comply consented to unless expressly agreed to by the Licensor. + + d. Nothing in this Public License constitutes or may be interpreted as a limitation upon, or waiver of, any privileges and immunities that apply to the Licensor or You, including from the legal processes of any jurisdiction or authority. diff --git a/LICENSE-SAMPLECODE b/LICENSE-SAMPLECODE new file mode 100644 index 00000000..14aabc34 --- /dev/null +++ b/LICENSE-SAMPLECODE @@ -0,0 +1,14 @@ +Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of this +software and associated documentation files (the "Software"), to deal in the Software +without restriction, including without limitation the rights to use, copy, modify, +merge, publish, distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/LICENSE-SUMMARY b/LICENSE-SUMMARY new file mode 100644 index 00000000..56888df1 --- /dev/null +++ b/LICENSE-SUMMARY @@ -0,0 +1,5 @@ +Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + +The documentation is made available under the Creative Commons Attribution-ShareAlike 4.0 International License. See the LICENSE file. + +The sample code within this documentation is made available under a modified MIT license. See the LICENSE-SAMPLECODE file. diff --git a/README.md b/README.md index 0634f8fd..d7cc26b2 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,33 @@ # Welcome to the AWS CDK Developer Guide -This is the GitHub repository for the [AWS CDK Developer Guide](https://docs.aws.amazon.com/cdk/latest/guide/home.html). +This is the GitHub repository for the [AWS CDK Developer Guide](https://docs.aws.amazon.com/cdk/latest/guide/home.html). You're welcome to [report issues](https://github.com/awsdocs/aws-cdk-guide/issues/new) with the documentation here or, if you have a moment, to submit a Pull Request with your suggested changes. PRs should target the main branch, not master, which has been deprecated. +* `v1` - contains the Markdown files for the CDK v1 Developer Guide * `v2` - contains the Markdown files for the CDK v2 Developer Guide Feel free to make a Pull Request against only one of these content sets (we'll make sure it gets into both). -Issues reported through the Feedback link at the bottom of the individual pages of the AWS CDK Developer Guide go to an internal Amazon issue tracker and may not appear here. However, we try to track most substantive AWS CDK Developer Guide work on GitHub +Issues reported through the Feedback link at the bottom of the individual pages of the AWS CDK Developer Guide go to an internal +Amazon issue tracker and may not appear here. However, we try to track most substantive AWS CDK Developer Guide work on GitHub so the community can see, comment, and contribute. +> :memo: **NOTE** - +> The Markdown files in this repository are an *output* of the AWS CDK Developer Guide build process, not the actual source files. +Periodically, we update the Markdown files here from our builds. Changes may appear on docs.aws.amazon.com before they appear +here. + ## Other Documentation Issues * Issues with the [API Reference](https://docs.aws.amazon.com/cdk/api/latest/docs/aws-construct-library.html) should be [filed](https://github.com/aws/aws-cdk/issues/new/choose) against the [AWS CDK repo](https://github.com/aws/aws-cdk/). * Issues with the [CDK Workshop](https://cdkworkshop.com/) should be [filed](https://github.com/aws-samples/aws-cdk-intro-workshop/issues/new/choose) against the [CDK Workshop repo](https://github.com/aws-samples/aws-cdk-intro-workshop). +## Project Board + +Have a look at the AWS CDK Developer Guide [Project Board](https://github.com/awsdocs/aws-cdk-guide/projects/1) +to see what we're working on at the moment. Note that items on the Wishlist may not be in any particular order. You can help us prioritize our work by +1'ing issues that are important to you. + ## Contributor Grant of License -By submitting a Pull Request against this repo, you grant Amazon the right to use use, modify, copy, and redistribute your contribution under any license we choose. \ No newline at end of file +By submitting a Pull Request against this repo, you grant Amazon the right to use use, modify, copy, and redistribute your contribution +under any license we choose. diff --git a/build b/build deleted file mode 120000 index d386ee6d..00000000 --- a/build +++ /dev/null @@ -1 +0,0 @@ -/workplace/pgasca/AWSCDKDocs_1/build/AWSCDKDocs/AWSCDKDocs-3.0/AL2_x86_64/DEV.STD.PTHREAD/build \ No newline at end of file diff --git a/build-info.xml b/build-info.xml deleted file mode 100755 index 108b995d..00000000 --- a/build-info.xml +++ /dev/null @@ -1,51 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<buildinfo> - <docsets> - <docset id="CDK"> - <pathslug>cdk</pathslug> - <title>AWS Cloud Development Kit</title> - <forumID>0</forumID> - <feedbackCTI>CDK</feedbackCTI> - <options> - <hide-github-link>0</hide-github-link> - </options> - - <guides> - - <guide id="awscdkv2"> - <pathslug>guide</pathslug> - <basename>awscdk</basename> - <title>Developer Guide</title> - <abbr>CDK</abbr> - <api>v2</api> - <version>v2</version> - <asciidoc-source>v2/guide</asciidoc-source> - <locale>en_us</locale> - - <builds> - <html> - <rss> - <title>Developer Guide Updates</title> - <filename>awscdkv2</filename> - </rss> - </html> - <asciidoc> - <include-html-profiling>1</include-html-profiling> - </asciidoc> - <markdown/> - <pdf/> - </builds> - - <github> - <user>awsdocs</user> - <repo>aws-cdk-guide</repo> - <branch>main</branch> - <source-folder>v2/guide</source-folder> - </github> - - </guide> - - </guides> - </docset> - </docsets> -</buildinfo> diff --git a/build.xml b/build.xml deleted file mode 100755 index e8ba5d4f..00000000 --- a/build.xml +++ /dev/null @@ -1,13 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<project xmlns:ht="happytrails" basedir="." default="build" name="AWSCDKDocs-3.0"> - <description>This is the entry point for happy trails builds (package builder and eclipse).</description> - <import file="${happytrails.root}/zonbooktrails.xml"/> -<!-- -<target name="zbuild-custom-pre"> - <exec executable="bash"> - <arg value="update-snippets" /> - </exec> -</target> ---> -<ht:import file="zfast/zonbook-4.5.xml"/> -</project> \ No newline at end of file diff --git a/doc_source/my_ecs_construct-stack.yaml b/doc_source/my_ecs_construct-stack.yaml new file mode 100644 index 00000000..29d6b889 --- /dev/null +++ b/doc_source/my_ecs_construct-stack.yaml @@ -0,0 +1,515 @@ +Resources: + MyVpcF9F0CA6F: + Type: AWS::EC2::VPC + Properties: + CidrBlock: 10.0.0.0/16 + EnableDnsHostnames: true + EnableDnsSupport: true + InstanceTenancy: default + Tags: + - Key: Name + Value: MyEcsConstruct/MyVpc + Metadata: + aws:cdk:path: MyEcsConstruct/MyVpc/Resource + MyVpcPublicSubnet1SubnetF6608456: + Type: AWS::EC2::Subnet + Properties: + CidrBlock: 10.0.0.0/18 + VpcId: + Ref: MyVpcF9F0CA6F + AvailabilityZone: + Fn::Select: + - 0 + - Fn::GetAZs: "" + MapPublicIpOnLaunch: true + Tags: + - Key: Name + Value: MyEcsConstruct/MyVpc/PublicSubnet1 + - Key: aws-cdk:subnet-name + Value: Public + - Key: aws-cdk:subnet-type + Value: Public + Metadata: + aws:cdk:path: MyEcsConstruct/MyVpc/PublicSubnet1/Subnet + MyVpcPublicSubnet1RouteTableC46AB2F4: + Type: AWS::EC2::RouteTable + Properties: + VpcId: + Ref: MyVpcF9F0CA6F + Tags: + - Key: Name + Value: MyEcsConstruct/MyVpc/PublicSubnet1 + Metadata: + aws:cdk:path: MyEcsConstruct/MyVpc/PublicSubnet1/RouteTable + MyVpcPublicSubnet1RouteTableAssociation2ECEE1CB: + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + RouteTableId: + Ref: MyVpcPublicSubnet1RouteTableC46AB2F4 + SubnetId: + Ref: MyVpcPublicSubnet1SubnetF6608456 + Metadata: + aws:cdk:path: MyEcsConstruct/MyVpc/PublicSubnet1/RouteTableAssociation + MyVpcPublicSubnet1DefaultRoute95FDF9EB: + Type: AWS::EC2::Route + Properties: + RouteTableId: + Ref: MyVpcPublicSubnet1RouteTableC46AB2F4 + DestinationCidrBlock: 0.0.0.0/0 + GatewayId: + Ref: MyVpcIGW5C4A4F63 + DependsOn: + - MyVpcVPCGW488ACE0D + Metadata: + aws:cdk:path: MyEcsConstruct/MyVpc/PublicSubnet1/DefaultRoute + MyVpcPublicSubnet1EIP096967CB: + Type: AWS::EC2::EIP + Properties: + Domain: vpc + Metadata: + aws:cdk:path: MyEcsConstruct/MyVpc/PublicSubnet1/EIP + MyVpcPublicSubnet1NATGatewayAD3400C1: + Type: AWS::EC2::NatGateway + Properties: + AllocationId: + Fn::GetAtt: + - MyVpcPublicSubnet1EIP096967CB + - AllocationId + SubnetId: + Ref: MyVpcPublicSubnet1SubnetF6608456 + Tags: + - Key: Name + Value: MyEcsConstruct/MyVpc/PublicSubnet1 + Metadata: + aws:cdk:path: MyEcsConstruct/MyVpc/PublicSubnet1/NATGateway + MyVpcPublicSubnet2Subnet492B6BFB: + Type: AWS::EC2::Subnet + Properties: + CidrBlock: 10.0.64.0/18 + VpcId: + Ref: MyVpcF9F0CA6F + AvailabilityZone: + Fn::Select: + - 1 + - Fn::GetAZs: "" + MapPublicIpOnLaunch: true + Tags: + - Key: Name + Value: MyEcsConstruct/MyVpc/PublicSubnet2 + - Key: aws-cdk:subnet-name + Value: Public + - Key: aws-cdk:subnet-type + Value: Public + Metadata: + aws:cdk:path: MyEcsConstruct/MyVpc/PublicSubnet2/Subnet + MyVpcPublicSubnet2RouteTable1DF17386: + Type: AWS::EC2::RouteTable + Properties: + VpcId: + Ref: MyVpcF9F0CA6F + Tags: + - Key: Name + Value: MyEcsConstruct/MyVpc/PublicSubnet2 + Metadata: + aws:cdk:path: MyEcsConstruct/MyVpc/PublicSubnet2/RouteTable + MyVpcPublicSubnet2RouteTableAssociation227DE78D: + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + RouteTableId: + Ref: MyVpcPublicSubnet2RouteTable1DF17386 + SubnetId: + Ref: MyVpcPublicSubnet2Subnet492B6BFB + Metadata: + aws:cdk:path: MyEcsConstruct/MyVpc/PublicSubnet2/RouteTableAssociation + MyVpcPublicSubnet2DefaultRoute052936F6: + Type: AWS::EC2::Route + Properties: + RouteTableId: + Ref: MyVpcPublicSubnet2RouteTable1DF17386 + DestinationCidrBlock: 0.0.0.0/0 + GatewayId: + Ref: MyVpcIGW5C4A4F63 + DependsOn: + - MyVpcVPCGW488ACE0D + Metadata: + aws:cdk:path: MyEcsConstruct/MyVpc/PublicSubnet2/DefaultRoute + MyVpcPublicSubnet2EIP8CCBA239: + Type: AWS::EC2::EIP + Properties: + Domain: vpc + Metadata: + aws:cdk:path: MyEcsConstruct/MyVpc/PublicSubnet2/EIP + MyVpcPublicSubnet2NATGateway91BFBEC9: + Type: AWS::EC2::NatGateway + Properties: + AllocationId: + Fn::GetAtt: + - MyVpcPublicSubnet2EIP8CCBA239 + - AllocationId + SubnetId: + Ref: MyVpcPublicSubnet2Subnet492B6BFB + Tags: + - Key: Name + Value: MyEcsConstruct/MyVpc/PublicSubnet2 + Metadata: + aws:cdk:path: MyEcsConstruct/MyVpc/PublicSubnet2/NATGateway + MyVpcPrivateSubnet1Subnet5057CF7E: + Type: AWS::EC2::Subnet + Properties: + CidrBlock: 10.0.128.0/18 + VpcId: + Ref: MyVpcF9F0CA6F + AvailabilityZone: + Fn::Select: + - 0 + - Fn::GetAZs: "" + MapPublicIpOnLaunch: false + Tags: + - Key: Name + Value: MyEcsConstruct/MyVpc/PrivateSubnet1 + - Key: aws-cdk:subnet-name + Value: Private + - Key: aws-cdk:subnet-type + Value: Private + Metadata: + aws:cdk:path: MyEcsConstruct/MyVpc/PrivateSubnet1/Subnet + MyVpcPrivateSubnet1RouteTable8819E6E2: + Type: AWS::EC2::RouteTable + Properties: + VpcId: + Ref: MyVpcF9F0CA6F + Tags: + - Key: Name + Value: MyEcsConstruct/MyVpc/PrivateSubnet1 + Metadata: + aws:cdk:path: MyEcsConstruct/MyVpc/PrivateSubnet1/RouteTable + MyVpcPrivateSubnet1RouteTableAssociation56D38C7E: + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + RouteTableId: + Ref: MyVpcPrivateSubnet1RouteTable8819E6E2 + SubnetId: + Ref: MyVpcPrivateSubnet1Subnet5057CF7E + Metadata: + aws:cdk:path: MyEcsConstruct/MyVpc/PrivateSubnet1/RouteTableAssociation + MyVpcPrivateSubnet1DefaultRouteA8CDE2FA: + Type: AWS::EC2::Route + Properties: + RouteTableId: + Ref: MyVpcPrivateSubnet1RouteTable8819E6E2 + DestinationCidrBlock: 0.0.0.0/0 + NatGatewayId: + Ref: MyVpcPublicSubnet1NATGatewayAD3400C1 + Metadata: + aws:cdk:path: MyEcsConstruct/MyVpc/PrivateSubnet1/DefaultRoute + MyVpcPrivateSubnet2Subnet0040C983: + Type: AWS::EC2::Subnet + Properties: + CidrBlock: 10.0.192.0/18 + VpcId: + Ref: MyVpcF9F0CA6F + AvailabilityZone: + Fn::Select: + - 1 + - Fn::GetAZs: "" + MapPublicIpOnLaunch: false + Tags: + - Key: Name + Value: MyEcsConstruct/MyVpc/PrivateSubnet2 + - Key: aws-cdk:subnet-name + Value: Private + - Key: aws-cdk:subnet-type + Value: Private + Metadata: + aws:cdk:path: MyEcsConstruct/MyVpc/PrivateSubnet2/Subnet + MyVpcPrivateSubnet2RouteTableCEDCEECE: + Type: AWS::EC2::RouteTable + Properties: + VpcId: + Ref: MyVpcF9F0CA6F + Tags: + - Key: Name + Value: MyEcsConstruct/MyVpc/PrivateSubnet2 + Metadata: + aws:cdk:path: MyEcsConstruct/MyVpc/PrivateSubnet2/RouteTable + MyVpcPrivateSubnet2RouteTableAssociation86A610DA: + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + RouteTableId: + Ref: MyVpcPrivateSubnet2RouteTableCEDCEECE + SubnetId: + Ref: MyVpcPrivateSubnet2Subnet0040C983 + Metadata: + aws:cdk:path: MyEcsConstruct/MyVpc/PrivateSubnet2/RouteTableAssociation + MyVpcPrivateSubnet2DefaultRoute9CE96294: + Type: AWS::EC2::Route + Properties: + RouteTableId: + Ref: MyVpcPrivateSubnet2RouteTableCEDCEECE + DestinationCidrBlock: 0.0.0.0/0 + NatGatewayId: + Ref: MyVpcPublicSubnet2NATGateway91BFBEC9 + Metadata: + aws:cdk:path: MyEcsConstruct/MyVpc/PrivateSubnet2/DefaultRoute + MyVpcIGW5C4A4F63: + Type: AWS::EC2::InternetGateway + Properties: + Tags: + - Key: Name + Value: MyEcsConstruct/MyVpc + Metadata: + aws:cdk:path: MyEcsConstruct/MyVpc/IGW + MyVpcVPCGW488ACE0D: + Type: AWS::EC2::VPCGatewayAttachment + Properties: + VpcId: + Ref: MyVpcF9F0CA6F + InternetGatewayId: + Ref: MyVpcIGW5C4A4F63 + Metadata: + aws:cdk:path: MyEcsConstruct/MyVpc/VPCGW + MyCluster4C1BA579: + Type: AWS::ECS::Cluster + Metadata: + aws:cdk:path: MyEcsConstruct/MyCluster/Resource + MyFargateServiceLBDE830E97: + Type: AWS::ElasticLoadBalancingV2::LoadBalancer + Properties: + LoadBalancerAttributes: [] + Scheme: internet-facing + SecurityGroups: + - Fn::GetAtt: + - MyFargateServiceLBSecurityGroup6FBF16F1 + - GroupId + Subnets: + - Ref: MyVpcPublicSubnet1SubnetF6608456 + - Ref: MyVpcPublicSubnet2Subnet492B6BFB + Type: application + DependsOn: + - MyVpcPublicSubnet1DefaultRoute95FDF9EB + - MyVpcPublicSubnet2DefaultRoute052936F6 + Metadata: + aws:cdk:path: MyEcsConstruct/MyFargateService/LB/Resource + MyFargateServiceLBSecurityGroup6FBF16F1: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: Automatically created Security Group for ELB MyEcsConstructMyFargateServiceLB5E4E9AE3 + SecurityGroupEgress: [] + SecurityGroupIngress: + - CidrIp: 0.0.0.0/0 + Description: Allow from anyone on port 80 + FromPort: 80 + IpProtocol: tcp + ToPort: 80 + VpcId: + Ref: MyVpcF9F0CA6F + Metadata: + aws:cdk:path: MyEcsConstruct/MyFargateService/LB/SecurityGroup/Resource + MyFargateServiceLBSecurityGrouptoMyEcsConstructMyFargateServiceSecurityGroup67F71DB380B308A4F1: + Type: AWS::EC2::SecurityGroupEgress + Properties: + GroupId: + Fn::GetAtt: + - MyFargateServiceLBSecurityGroup6FBF16F1 + - GroupId + IpProtocol: tcp + Description: Load balancer to target + DestinationSecurityGroupId: + Fn::GetAtt: + - MyFargateServiceSecurityGroup7016792A + - GroupId + FromPort: 80 + ToPort: 80 + Metadata: + aws:cdk:path: MyEcsConstruct/MyFargateService/LB/SecurityGroup/to MyEcsConstructMyFargateServiceSecurityGroup67F71DB3:80 + MyFargateServiceLBPublicListener61A1042F: + Type: AWS::ElasticLoadBalancingV2::Listener + Properties: + DefaultActions: + - TargetGroupArn: + Ref: MyFargateServiceLBPublicListenerECSGroup4A3EDF05 + Type: forward + LoadBalancerArn: + Ref: MyFargateServiceLBDE830E97 + Port: 80 + Protocol: HTTP + Certificates: [] + Metadata: + aws:cdk:path: MyEcsConstruct/MyFargateService/LB/PublicListener/Resource + MyFargateServiceLBPublicListenerECSGroup4A3EDF05: + Type: AWS::ElasticLoadBalancingV2::TargetGroup + Properties: + Port: 80 + Protocol: HTTP + TargetGroupAttributes: [] + Targets: [] + TargetType: ip + VpcId: + Ref: MyVpcF9F0CA6F + Metadata: + aws:cdk:path: MyEcsConstruct/MyFargateService/LB/PublicListener/ECSGroup/Resource + MyFargateServiceTaskDefTaskRole62C7D397: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Statement: + - Action: sts:AssumeRole + Effect: Allow + Principal: + Service: + Fn::Join: + - "" + - - ecs-tasks. + - Ref: AWS::URLSuffix + Version: "2012-10-17" + Metadata: + aws:cdk:path: MyEcsConstruct/MyFargateService/TaskDef/TaskRole/Resource + MyFargateServiceTaskDef5DA17B39: + Type: AWS::ECS::TaskDefinition + Properties: + ContainerDefinitions: + - Essential: true + Image: amazon/amazon-ecs-sample + Links: [] + LogConfiguration: + LogDriver: awslogs + Options: + awslogs-group: + Ref: MyFargateServiceTaskDefwebLogGroup4A6C44E8 + awslogs-stream-prefix: MyFargateService + awslogs-region: + Ref: AWS::Region + MountPoints: [] + Name: web + PortMappings: + - ContainerPort: 80 + Protocol: tcp + Ulimits: [] + VolumesFrom: [] + Cpu: "512" + ExecutionRoleArn: + Fn::GetAtt: + - MyFargateServiceTaskDefExecutionRoleD6305504 + - Arn + Family: MyEcsConstructMyFargateServiceTaskDef164AB9B9 + Memory: "2048" + NetworkMode: awsvpc + RequiresCompatibilities: + - FARGATE + TaskRoleArn: + Fn::GetAtt: + - MyFargateServiceTaskDefTaskRole62C7D397 + - Arn + Volumes: [] + Metadata: + aws:cdk:path: MyEcsConstruct/MyFargateService/TaskDef/Resource + MyFargateServiceTaskDefwebLogGroup4A6C44E8: + Type: AWS::Logs::LogGroup + DeletionPolicy: Retain + Metadata: + aws:cdk:path: MyEcsConstruct/MyFargateService/TaskDef/web/LogGroup/Resource + MyFargateServiceTaskDefExecutionRoleD6305504: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Statement: + - Action: sts:AssumeRole + Effect: Allow + Principal: + Service: + Fn::Join: + - "" + - - ecs-tasks. + - Ref: AWS::URLSuffix + Version: "2012-10-17" + Metadata: + aws:cdk:path: MyEcsConstruct/MyFargateService/TaskDef/ExecutionRole/Resource + MyFargateServiceTaskDefExecutionRoleDefaultPolicyEC22B20F: + Type: AWS::IAM::Policy + Properties: + PolicyDocument: + Statement: + - Action: + - logs:CreateLogStream + - logs:PutLogEvents + Effect: Allow + Resource: + Fn::GetAtt: + - MyFargateServiceTaskDefwebLogGroup4A6C44E8 + - Arn + Version: "2012-10-17" + PolicyName: MyFargateServiceTaskDefExecutionRoleDefaultPolicyEC22B20F + Roles: + - Ref: MyFargateServiceTaskDefExecutionRoleD6305504 + Metadata: + aws:cdk:path: MyEcsConstruct/MyFargateService/TaskDef/ExecutionRole/DefaultPolicy/Resource + MyFargateServiceF490C034: + Type: AWS::ECS::Service + Properties: + TaskDefinition: + Ref: MyFargateServiceTaskDef5DA17B39 + Cluster: + Ref: MyCluster4C1BA579 + DeploymentConfiguration: + MaximumPercent: 200 + MinimumHealthyPercent: 50 + DesiredCount: 6 + HealthCheckGracePeriodSeconds: 60 + LaunchType: FARGATE + LoadBalancers: + - ContainerName: web + ContainerPort: 80 + TargetGroupArn: + Ref: MyFargateServiceLBPublicListenerECSGroup4A3EDF05 + NetworkConfiguration: + AwsvpcConfiguration: + AssignPublicIp: DISABLED + SecurityGroups: + - Fn::GetAtt: + - MyFargateServiceSecurityGroup7016792A + - GroupId + Subnets: + - Ref: MyVpcPrivateSubnet1Subnet5057CF7E + - Ref: MyVpcPrivateSubnet2Subnet0040C983 + ServiceRegistries: [] + DependsOn: + - MyFargateServiceLBPublicListenerECSGroup4A3EDF05 + - MyFargateServiceLBPublicListener61A1042F + Metadata: + aws:cdk:path: MyEcsConstruct/MyFargateService/Service/Service + MyFargateServiceSecurityGroup7016792A: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: MyEcsConstruct/MyFargateService/Service/SecurityGroup + SecurityGroupEgress: + - CidrIp: 0.0.0.0/0 + Description: Allow all outbound traffic by default + IpProtocol: "-1" + SecurityGroupIngress: [] + VpcId: + Ref: MyVpcF9F0CA6F + Metadata: + aws:cdk:path: MyEcsConstruct/MyFargateService/Service/SecurityGroup/Resource + MyFargateServiceSecurityGroupfromMyEcsConstructMyFargateServiceLBSecurityGroup8793A2F780B3ABD3C6: + Type: AWS::EC2::SecurityGroupIngress + Properties: + IpProtocol: tcp + Description: Load balancer to target + FromPort: 80 + GroupId: + Fn::GetAtt: + - MyFargateServiceSecurityGroup7016792A + - GroupId + SourceSecurityGroupId: + Fn::GetAtt: + - MyFargateServiceLBSecurityGroup6FBF16F1 + - GroupId + ToPort: 80 + Metadata: + aws:cdk:path: MyEcsConstruct/MyFargateService/Service/SecurityGroup/from MyEcsConstructMyFargateServiceLBSecurityGroup8793A2F7:80 +Outputs: + MyFargateServiceLoadBalancerDNS704F6391: + Value: + Fn::GetAtt: + - MyFargateServiceLBDE830E97 + - DNSName diff --git a/v1/about_examples.md b/v1/about_examples.md new file mode 100644 index 00000000..eea1ebeb --- /dev/null +++ b/v1/about_examples.md @@ -0,0 +1,3 @@ +# AWS CDK examples<a name="about_examples"></a> + +For more examples of AWS CDK stacks and apps in your favorite supported programming language, see the [CDK Examples](https://github.com/aws-samples/aws-cdk-examples) repository on GitHub\. \ No newline at end of file diff --git a/v1/apps.md b/v1/apps.md new file mode 100644 index 00000000..6001dcf4 --- /dev/null +++ b/v1/apps.md @@ -0,0 +1,228 @@ +# Apps<a name="apps"></a> + +As described in [Constructs](constructs.md), to provision infrastructure resources, all constructs that represent AWS resources must be defined, directly or indirectly, within the scope of a [Stack](https://docs.aws.amazon.com/cdk/api/v1/docs/core/stack.html) construct\. An [App](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.App.html) is a container for one or more stacks: it serves as each stack's scope\. Stacks within a single `App` can easily refer to each others' resources \(and attributes of those resources\)\. The AWS CDK infers dependencies between stacks so that they can be deployed in the correct order\. You can deploy any or all of the stacks defined within an app at with a single `cdk deploy` command\. + +The following example declares a stack class named `MyFirstStack` that includes a single Amazon S3 bucket\. However, this only declares a stack\. You still need to define \(also known as to instantiate\) it in some scope to deploy it\. + +------ +#### [ TypeScript ] + +``` +class MyFirstStack extends Stack { + constructor(scope: Construct, id: string, props?: StackProps) { + super(scope, id, props); + + new s3.Bucket(this, 'MyFirstBucket'); + } +} +``` + +------ +#### [ JavaScript ] + +``` +class MyFirstStack extends Stack { + constructor(scope, id, props) { + super(scope, id, props); + + new s3.Bucket(this, 'MyFirstBucket'); + } +} +``` + +------ +#### [ Python ] + +``` +class MyFirstStack(Stack): + + def __init__(self, scope: Construct, id: str, **kwargs): + super().__init__(scope, id, **kwargs) + + s3.Bucket(self, "MyFirstBucket") +``` + +------ +#### [ Java ] + +``` +public class MyFirstStack extends Stack { + public MyFirstStack(final Construct scope, final String id) { + this(scope, id, null); + } + + public MyFirstStack(final Construct scope, final String id, final StackProps props) { + super(scope, id, props); + + new Bucket(this, "MyFirstBucket"); + } +} +``` + +------ +#### [ C\# ] + +``` +public class MyFirstStack : Stack +{ + public MyFirstStack(Stack scope, string id, StackProps props = null) : base(scope, id, props) + { + new Bucket(this, "MyFirstBucket"); + } +} +``` + +------ + +However, this code has only *declared* a stack\. For the stack to actually be synthesized into a AWS CloudFormation template and deployed, it needs to be instantiated\. And, like all CDK constructs, it must be instantiated in some context\. The `App` is that context\. + +## The app construct<a name="apps_construct"></a> + +To define the previous stack within the scope of an application, use the [App](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.App.html) construct\. The following example app instantiates a `MyFirstStack` and produces the AWS CloudFormation template that the stack defined\. + +------ +#### [ TypeScript ] + +``` +const app = new App(); +new MyFirstStack(app, 'hello-cdk'); +app.synth(); +``` + +------ +#### [ JavaScript ] + +``` +const app = new App(); +new MyFirstStack(app, 'hello-cdk'); +app.synth(); +``` + +------ +#### [ Python ] + +``` +app = App() +MyFirstStack(app, "hello-cdk") +app.synth() +``` + +------ +#### [ Java ] + +``` +App app = new App(); +new MyFirstStack(app, "hello-cdk"); +app.synth(); +``` + +------ +#### [ C\# ] + +``` +var app = new App(); +new MyFirstStack(app, "hello-cdk"); +app.Synth(); +``` + +------ + +The `App` construct doesn't require any initialization arguments, because it's the only construct that can be used as a root for the construct tree\. You can now use the `App` instance as a scope for defining a single instance of your stack\. + +## App lifecycle<a name="lifecycle"></a> + +The following diagram shows the phases that the AWS CDK goes through when you call the cdk deploy\. This command deploys the resources that your app defines\. + +![\[Image NOT FOUND\]](http://docs.aws.amazon.com/cdk/v1/guide/images/Lifecycle.png) + +An AWS CDK app goes through the following phases in its lifecycle\. + +1\. Construction \(or Initialization\) + Your code instantiates all of the defined constructs and then links them together\. In this stage, all of the constructs \(app, stacks, and their child constructs\) are instantiated and the constructor chain is executed\. Most of your app code is executed in this stage\. + +2\. Preparation +All constructs that have implemented the `prepare` method participate in a final round of modifications, to set up their final state\. The preparation phase happens automatically\. As a user, you don't see any feedback from this phase\. It's rare to need to use the "prepare" hook, and generally not recommended\. You should be very careful when mutating the construct tree during this phase, because the order of operations could impact behavior\. + +3\. Validation +All constructs that have implemented the `validate` method can validate themselves to ensure that they're in a state that will correctly deploy\. You will get notified of any validation failures that happen during this phase\. Generally, we recommend that you perform validation as soon as possible \(usually as soon as you get some input\) and throw exceptions as early as possible\. Performing validation early improves diagnosability as stack traces will be more accurate, and ensures that your code can continue to execute safely\. + +4\. Synthesis +This is the final stage of the execution of your AWS CDK app\. It's triggered by a call to `app.synth()`, and it traverses the construct tree and invokes the `synthesize` method on all constructs\. Constructs that implement `synthesize` can participate in synthesis and emit deployment artifacts to the resulting cloud assembly\. These artifacts include AWS CloudFormation templates, AWS Lambda application bundles, file and Docker image assets, and other deployment artifacts\. [Cloud assemblies](#apps_cloud_assembly) describes the output of this phase\. In most cases, you won't need to implement the `synthesize` method + +5\. Deployment +In this phase, the AWS CDK Toolkit takes the deployment artifacts cloud assembly produced by the synthesis phase and deploys it to an AWS environment\. It uploads assets to Amazon S3 and Amazon ECR, or wherever they need to go, and then starts an AWS CloudFormation deployment to deploy the application and create the resources\. + +By the time the AWS CloudFormation deployment phase \(step 5\) starts, your AWS CDK app has already finished and exited\. This has the following implications: ++ The AWS CDK app can't respond to events that happen during deployment, such as a resource being created or the whole deployment finishing\. To run code during the deployment phase, you must inject it into the AWS CloudFormation template as a [custom resource](cfn_layer.md#cfn_layer_custom)\. For more information about adding a custom resource to your app, see the [AWS CloudFormation module](https://docs.aws.amazon.com/cdk/api/v1/docs/aws-cloudformation-readme.html), or the [custom\-resource](https://github.com/aws-samples/aws-cdk-examples/tree/CDKv1/typescript/custom-resource/) example\. ++ The AWS CDK app might have to work with values that can't be known at the time it runs\. For example, if the AWS CDK app defines an Amazon S3 bucket with an automatically generated name, and you retrieve the `bucket.bucketName` \(Python: `bucket_name`\) attribute, that value is not the name of the deployed bucket\. Instead, you get a `Token` value\. To determine whether a particular value is available, call `cdk.isUnresloved(value)` \(Python: `is_unresolved`\)\. See [Tokens](tokens.md) for details\. + +## Cloud assemblies<a name="apps_cloud_assembly"></a> + +The call to `app.synth()` is what tells the AWS CDK to synthesize a cloud assembly from an app\. Typically you don't interact directly with cloud assemblies\. They are files that include everything needed to deploy your app to a cloud environment\. For example, it includes an AWS CloudFormation template for each stack in your app, and a copy of any file assets or Docker images that you reference in your app\. + +See the [cloud assembly specification](https://github.com/aws/aws-cdk/blob/master/design/cloud-assembly.md) for details on how cloud assemblies are formatted\. + +To interact with the cloud assembly that your AWS CDK app creates, you typically use the AWS CDK Toolkit, a command\-line tool\. But any tool that can read the cloud assembly format can be used to deploy your app\. + +The CDK Toolkit needs to know how to execute your AWS CDK app\. If you created the project from a template using the `cdk init` command, your app's `cdk.json` file includes an `app` key that specifies the necessary command for the language the app is written in\. If your language requires compilation, the command line performs this step before running the app, so you can't forget to do it\. + +------ +#### [ TypeScript ] + +``` +{ + "app": "npx ts-node --prefer-ts-exts bin/my-app.ts" +} +``` + +------ +#### [ JavaScript ] + +``` +{ + "app": "node bin/my-app.js" +} +``` + +------ +#### [ Python ] + +``` +{ + "app": "python app.py" +} +``` + +------ +#### [ Java ] + +``` +{ + "app": "mvn -e -q compile exec:java" +} +``` + +------ +#### [ C\# ] + +``` +{ + "app": "dotnet run -p src/MyApp/MyApp.csproj" +} +``` + +------ + +If you did not create your project using the CDK Toolkit, or wish to override the command line given in `cdk.json`, you can use the \-\-app option when issuing the `cdk` command\. + +``` +cdk --app 'executable' cdk-command ... +``` + +The *executable* part of the command indicates the command that should be run to execute your CDK application\. Use quotation marks as shown, since such commands contain spaces\. The *cdk\-command* is a subcommand like synth or deploy that tells the CDK Toolkit what you want to do with your app\. Follow this with any additional options needed for that subcommand\. + +The CLI can also interact directly with an already\-synthesized cloud assembly\. To do that, just pass the directory in which the cloud assembly is stored in \-\-app\. The following example lists the stacks defined in the cloud assembly stored under `./my-cloud-assembly`\. + +``` +cdk --app ./my-cloud-assembly ls +``` \ No newline at end of file diff --git a/v1/aspects.md b/v1/aspects.md new file mode 100644 index 00000000..202cda09 --- /dev/null +++ b/v1/aspects.md @@ -0,0 +1,222 @@ +# Aspects<a name="aspects"></a> + +Aspects are a way to apply an operation to all constructs in a given scope\. The aspect could modify the constructs, such as by adding tags, or it could verify something about the state of the constructs, such as ensuring that all buckets are encrypted\. + +To apply an aspect to a construct and all constructs in the same scope, call [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.Aspects.html#static-ofscope](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.Aspects.html#static-ofscope)`.of(SCOPE).add()` with a new aspect, as shown in the following example\. + +------ +#### [ TypeScript ] + +``` +Aspects.of(myConstruct).add(new SomeAspect(...)); +``` + +------ +#### [ JavaScript ] + +``` +Aspects.of(myConstruct).add(new SomeAspect(...)); +``` + +------ +#### [ Python ] + +``` +Aspects.of(my_construct).add(SomeAspect(...)) +``` + +------ +#### [ Java ] + +``` +Aspects.of(myConstruct).add(new SomeAspect(...)); +``` + +------ +#### [ C\# ] + +``` +Aspects.Of(myConstruct).add(new SomeAspect(...)); +``` + +------ + +The AWS CDK uses aspects to [tag resources](tagging.md), but the framework can also be used for other purposes\. For example, you can use it to validate or change the AWS CloudFormation resources that are defined for you by higher\-level constructs\. + +## Aspects in detail<a name="aspects_detail"></a> + +Aspects employ the [visitor pattern](https://en.wikipedia.org/wiki/Visitor_pattern)\. An aspect is a class that implements the following interface\. + +------ +#### [ TypeScript ] + +``` +interface IAspect { + visit(node: IConstruct): void;} +``` + +------ +#### [ JavaScript ] + +JavaScript doesn't have interfaces as a language feature, so an aspect is simply an instance of a class having a `visit` method that accepts the node to be operated on\. + +------ +#### [ Python ] + +Python doesn't have interfaces as a language feature, so an aspect is simply an instance of a class having a `visit` method that accepts the node to be operated on\. + +------ +#### [ Java ] + +``` +public interface IAspect { + public void visit(Construct node); +} +``` + +------ +#### [ C\# ] + +``` +public interface IAspect +{ + void Visit(IConstruct node); +} +``` + +------ + +When you call `Aspects.of(SCOPE).add(...)`, the construct adds the aspect to an internal list of aspects\. You can obtain the list with `Aspects.of(SCOPE)`\. + +During the [prepare phase](apps.md#lifecycle), the AWS CDK calls the `visit` method of the object for the construct and each of its children in top\-down order\. + +The `visit` method is free to change anything in the construct\. In strongly\-typed languages, cast the received construct to a more specific type before accessing construct\-specific properties or methods\. + +Aspects don't propagate across `Stage` construct boundaries, because `Stages` are self\-contained and immutable after definition\. Apply aspects on the `Stage` construct itself \(or lower\) if you want them to visit constructs inside the `Stage`\. + +## Example<a name="aspects_example"></a> + +The following example validates that all buckets created in the stack have versioning enabled\. The aspect adds an error annotation to the constructs that fail the validation, which results in the synth operation failing and prevents deploying the resulting cloud assembly\. + +------ +#### [ TypeScript ] + +``` +class BucketVersioningChecker implements IAspect { + public visit(node: IConstruct): void { + // See that we're dealing with a CfnBucket + if (node instanceof s3.CfnBucket) { + + // Check for versioning property, exclude the case where the property + // can be a token (IResolvable). + if (!node.versioningConfiguration + || (!Tokenization.isResolvable(node.versioningConfiguration) + && node.versioningConfiguration.status !== 'Enabled') { + Annotations.of(node).addError('Bucket versioning is not enabled'); + } + } + } +} + +// Later, apply to the stack +Aspects.of(stack).add(new BucketVersioningChecker()); +``` + +------ +#### [ JavaScript ] + +``` +class BucketVersioningChecker { + visit(node) { + // See that we're dealing with a CfnBucket + if ( node instanceof s3.CfnBucket) { + + // Check for versioning property, exclude the case where the property + // can be a token (IResolvable). + if (!node.versioningConfiguration + || !Tokenization.isResolvable(node.versioningConfiguration) + && node.versioningConfiguration.status !== 'Enabled') { + Annotations.of(node).addError('Bucket versioning is not enabled'); + } + } + } +} + +// Later, apply to the stack +Aspects.of(stack).add(new BucketVersioningChecker()); +``` + +------ +#### [ Python ] + +``` +@jsii.implements(core.IAspect) +class BucketVersioningChecker: + + def visit(self, node): + # See that we're dealing with a CfnBucket + if isinstance(node, s3.CfnBucket): + + # Check for versioning property, exclude the case where the property + # can be a token (IResolvable). + if (not node.versioning_configuration or + not Tokenization.is_resolvable(node.versioning_configuration) + and node.versioning_configuration.status != "Enabled"): + Annotations.of(node).add_error('Bucket versioning is not enabled') + +# Later, apply to the stack +Aspects.of(stack).add(BucketVersioningChecker()) +``` + +------ +#### [ Java ] + +``` +public class BucketVersioningChecker implements IAspect +{ + @Override + public void visit(Construct node) + { + // See that we're dealing with a CfnBucket + if (node instanceof CfnBucket) + { + CfnBucket bucket = (CfnBucket)node; + Object versioningConfiguration = bucket.getVersioningConfiguration(); + if (versioningConfiguration == null || + !Tokenization.isResolvable(versioningConfiguration.toString()) && + !versioningConfiguration.toString().contains("Enabled")) + Annotations.of(bucket.getNode()).addError("Bucket versioning is not enabled"); + } + } +} + + +// Later, apply to the stack +Aspects.of(stack).add(new BucketVersioningChecker()); +``` + +------ +#### [ C\# ] + +``` +class BucketVersioningChecker : Amazon.Jsii.Runtime.Deputy.DeputyBase, IAspect +{ + public void Visit(IConstruct node) + { + // See that we're dealing with a CfnBucket + if (node is CfnBucket) + { + var bucket = (CfnBucket)node; + if (bucket.VersioningConfiguration is null || + !Tokenization.IsResolvable(bucket.VersioningConfiguration) && + !bucket.VersioningConfiguration.ToString().Contains("Enabled")) + Annotations.Of(bucket.Node).AddError("Bucket versioning is not enabled"); + } + } +} + +// Later, apply to the stack +Aspects.Of(stack).add(new BucketVersioningChecker()); +``` + +------ \ No newline at end of file diff --git a/v1/assets.md b/v1/assets.md new file mode 100644 index 00000000..bddb2319 --- /dev/null +++ b/v1/assets.md @@ -0,0 +1,886 @@ +# Assets<a name="assets"></a> + +Assets are local files, directories, or Docker images that can be bundled into AWS CDK libraries and apps; for example, a directory that contains the handler code for an AWS Lambda function\. Assets can represent any artifact that the app needs to operate\. + +You add assets through APIs that are exposed by specific AWS constructs\. For example, when you define a [lambda\.Function](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-lambda.Function.html) construct, the [code](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-lambda.Function.html#code) property lets you pass an [asset](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-lambda.Code.html#static-fromassetpath) \(directory\)\. `Function` uses assets to bundle the contents of the directory and use it for the function's code\. Similarly, [ecs\.ContainerImage\.fromAsset](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-ecs.ContainerImage.html#static-from-assetdirectory-props) uses a Docker image built from a local directory when defining an Amazon ECS task definition\. + +## Assets in detail<a name="assets_details"></a> + +When you refer to an asset in your app, the [cloud assembly](apps.md#apps_cloud_assembly) synthesized from your application includes metadata information with instructions for the AWS CDK CLI on where to find the asset on the local disk, and what type of bundling to perform based on the type of asset, such as a directory to compress \(zip\) or a Docker image to build\. + +The AWS CDK generates a source hash for assets, which can be used at construction time to determine whether the contents of an asset have changed\. + +By default, the AWS CDK creates a copy of the asset in the cloud assembly directory, which defaults to `cdk.out`, under the source hash\. This is so that the cloud assembly is self\-contained and moved over to a different host for deployment\. See [Cloud assemblies](apps.md#apps_cloud_assembly) for details\. + +The AWS CDK also synthesizes AWS CloudFormation parameters that the AWS CDK CLI specifies during deployment\. The AWS CDK uses those parameters to refer to the deploy\-time values of the asset\. + +When the AWS CDK deploys an app that references assets \(either directly by the app code or through a library\), the AWS CDK CLI first prepares and publishes them to Amazon S3 or Amazon ECR, and only then deploys the stack\. The AWS CDK specifies the locations of the published assets as AWS CloudFormation parameters to the relevant stacks, and uses that information to enable referencing these locations within an AWS CDK app\. + +This section describes the low\-level APIs available in the framework\. + +## Asset types<a name="assets_types"></a> + +The AWS CDK supports the following types of assets: + +Amazon S3 Assets +These are local files and directories that the AWS CDK uploads to Amazon S3\. + +Docker Image +These are Docker images that the AWS CDK uploads to Amazon ECR\. + +These asset types are explained in the following sections\. + +### Amazon S3 assets<a name="assets_types_s3"></a> + +You can define local files and directories as assets, and the AWS CDK packages and uploads them to Amazon S3 through the [aws\-s3\-assets](https://docs.aws.amazon.com/cdk/api/v1/docs/aws-s3-assets-readme.html) module\. + +The following example defines a local directory asset and a file asset\. + +------ +#### [ TypeScript ] + +``` +import { Asset } from '@aws-cdk/aws-s3-assets'; + +// Archived and uploaded to Amazon S3 as a .zip file +const directoryAsset = new Asset(this, "SampleZippedDirAsset", { + path: path.join(__dirname, "sample-asset-directory") +}); + +// Uploaded to Amazon S3 as-is +const fileAsset = new Asset(this, 'SampleSingleFileAsset', { + path: path.join(__dirname, 'file-asset.txt') +}); +``` + +------ +#### [ JavaScript ] + +``` +const { Asset } = require('@aws-cdk/aws-s3-assets'); + +// Archived and uploaded to Amazon S3 as a .zip file +const directoryAsset = new Asset(this, "SampleZippedDirAsset", { + path: path.join(__dirname, "sample-asset-directory") +}); + +// Uploaded to Amazon S3 as-is +const fileAsset = new Asset(this, 'SampleSingleFileAsset', { + path: path.join(__dirname, 'file-asset.txt') +}); +``` + +------ +#### [ Python ] + +``` +import os.path +dirname = os.path.dirname(__file__) + +from aws_cdk.aws_s3_assets import Asset + +# Archived and uploaded to Amazon S3 as a .zip file +directory_asset = Asset(self, "SampleZippedDirAsset", + path=os.path.join(dirname, "sample-asset-directory") +) + +# Uploaded to Amazon S3 as-is +file_asset = Asset(self, 'SampleSingleFileAsset', + path=os.path.join(dirname, 'file-asset.txt') +) +``` + +------ +#### [ Java ] + +``` +import java.io.File; + +import software.amazon.awscdk.services.s3.assets.Asset; + +// Directory where app was started +File startDir = new File(System.getProperty("user.dir")); + +// Archived and uploaded to Amazon S3 as a .zip file +Asset directoryAsset = Asset.Builder.create(this, "SampleZippedDirAsset") + .path(new File(startDir, "sample-asset-directory").toString()).build(); + +// Uploaded to Amazon S3 as-is +Asset fileAsset = Asset.Builder.create(this, "SampleSingleFileAsset") + .path(new File(startDir, "file-asset.txt").toString()).build(); +``` + +------ +#### [ C\# ] + +``` +using System.IO; +using Amazon.CDK.AWS.S3.Assets; + +// Archived and uploaded to Amazon S3 as a .zip file +var directoryAsset = new Asset(this, "SampleZippedDirAsset", new AssetProps +{ + Path = Path.Combine(Directory.GetCurrentDirectory(), "sample-asset-directory") +}); + +// Uploaded to Amazon S3 as-is +var fileAsset = new Asset(this, "SampleSingleFileAsset", new AssetProps +{ + Path = Path.Combine(Directory.GetCurrentDirectory(), "file-asset.txt") +}); +``` + +------ + +In most cases, you don't need to directly use the APIs in the `aws-s3-assets` module\. Modules that support assets, such as `aws-lambda`, have convenience methods that enable you to use assets\. For Lambda functions, the [fromAsset\(\)](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-lambda.Code.html#static-assetpath) static method enables you to specify a directory or a \.zip file in the local file system\. + +#### Lambda function example<a name="assets_types_s3_lambda"></a> + +A common use case is to create AWS Lambda functions with the handler code, which is the entry point for the function, as an Amazon S3 asset\. + +The following example uses an Amazon S3 asset to define a Python handler in the local directory `handler` and creates a Lambda function with the local directory asset as the `code` property\. Below is the Python code for the handler\. + +``` +def lambda_handler(event, context): + message = 'Hello World!' + return { + 'message': message + } +``` + +The code for the main AWS CDK app should look like the following\. + +------ +#### [ TypeScript ] + +``` +import * as cdk from '@aws-cdk/core'; +import * as lambda from '@aws-cdk/aws-lambda'; +import * as path from 'path'; + +export class HelloAssetStack extends cdk.Stack { + constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { + super(scope, id, props); + + new lambda.Function(this, 'myLambdaFunction', { + code: lambda.Code.fromAsset(path.join(__dirname, 'handler')), + runtime: lambda.Runtime.PYTHON_3_6, + handler: 'index.lambda_handler' + }); + } +} +``` + +------ +#### [ JavaScript ] + +``` +const cdk = require('@aws-cdk/core'); +const lambda = require('@aws-cdk/aws-lambda'); +const path = require('path'); + +class HelloAssetStack extends cdk.Stack { + constructor(scope, id, props) { + super(scope, id, props); + + new lambda.Function(this, 'myLambdaFunction', { + code: lambda.Code.fromAsset(path.join(__dirname, 'handler')), + runtime: lambda.Runtime.PYTHON_3_6, + handler: 'index.lambda_handler' + }); + } +} + +module.exports = { HelloAssetStack } +``` + +------ +#### [ Python ] + +``` +from aws_cdk.core import Stack, Construct +from aws_cdk import aws_lambda as lambda_ + +import os.path +dirname = os.path.dirname(__file__) + +class HelloAssetStack(Stack): + def __init__(self, scope: Construct, id: str, **kwargs): + super().__init__(scope, id, **kwargs) + + lambda_.Function(self, 'myLambdaFunction', + code=lambda_.Code.from_asset(os.path.join(dirname, 'handler')), + runtime=lambda_.Runtime.PYTHON_3_6, + handler="index.lambda_handler") +``` + +------ +#### [ Java ] + +``` +import java.io.File; + +import software.amazon.awscdk.core.Stack; +import software.amazon.awscdk.core.StackProps; +import software.amazon.awscdk.services.lambda.Function; +import software.amazon.awscdk.services.lambda.Runtime; + +public class HelloAssetStack extends Stack { + + public HelloAssetStack(final App scope, final String id) { + this(scope, id, null); + } + + public HelloAssetStack(final App scope, final String id, final StackProps props) { + super(scope, id, props); + + File startDir = new File(System.getProperty("user.dir")); + + Function.Builder.create(this, "myLambdaFunction") + .code(Code.fromAsset(new File(startDir, "handler").toString())) + .runtime(Runtime.PYTHON_3_6) + .handler("index.lambda_handler").build(); + } +} +``` + +------ +#### [ C\# ] + +``` +using Amazon.CDK; +using Amazon.CDK.AWS.Lambda; +using System.IO; + +public class HelloAssetStack : Stack +{ + public HelloAssetStack(Construct scope, string id, StackProps props) : base(scope, id, props) + { + new Function(this, "myLambdaFunction", new FunctionProps + { + Code = Code.FromAsset(Path.Combine(Directory.GetCurrentDirectory(), "handler")), + Runtime = Runtime.PYTHON_3_6, + Handler = "index.lambda_handler" + }); + } +} +``` + +------ + +The `Function` method uses assets to bundle the contents of the directory and use it for the function's code\. + +**Tip** +Java `.jar` files are ZIP files with a different extension\. These will be uploaded as\-is to Amazon S3, but when they are deployed as a Lambda function, the files they contain will be extracted, which probably isn't what you want\. To avoid this, place the `.jar` file in a directory and specify that directory as the asset\. + +#### Deploy\-time attributes example<a name="assets_types_s3_deploy"></a> + +Amazon S3 asset types also expose [deploy\-time attributes](resources.md#resources_attributes) that can be referenced in AWS CDK libraries and apps\. The AWS CDK CLI command cdk synth displays asset properties as AWS CloudFormation parameters\. + +The following example uses deploy\-time attributes to pass the location of an image asset into a Lambda function as environment variables\. \(The kind of file doesn't matter; the PNG image used here is just an example\.\) + +------ +#### [ TypeScript ] + +``` +import { Asset } from '@aws-cdk/aws-s3-assets'; +import * as path from 'path'; + +const imageAsset = new Asset(this, "SampleAsset", { + path: path.join(__dirname, "images/my-image.png") +}); + +new lambda.Function(this, "myLambdaFunction", { + code: lambda.Code.asset(path.join(__dirname, "handler")), + runtime: lambda.Runtime.PYTHON_3_6, + handler: "index.lambda_handler", + environment: { + 'S3_BUCKET_NAME': imageAsset.s3BucketName, + 'S3_OBJECT_KEY': imageAsset.s3ObjectKey, + 'S3_URL': imageAsset.s3Url + } +}); +``` + +------ +#### [ JavaScript ] + +``` +const { Asset } = require('@aws-cdk/aws-s3-assets'); +const path = require('path'); + +const imageAsset = new Asset(this, "SampleAsset", { + path: path.join(__dirname, "images/my-image.png") +}); + +new lambda.Function(this, "myLambdaFunction", { + code: lambda.Code.asset(path.join(__dirname, "handler")), + runtime: lambda.Runtime.PYTHON_3_6, + handler: "index.lambda_handler", + environment: { + 'S3_BUCKET_NAME': imageAsset.s3BucketName, + 'S3_OBJECT_KEY': imageAsset.s3ObjectKey, + 'S3_URL': imageAsset.s3Url + } +}); +``` + +------ +#### [ Python ] + +``` +import os.path + +from aws_cdk import aws_lambda as lambda_ +from aws_cdk.aws_s3_assets import Asset + +dirname = os.path.dirname(__file__) + +image_asset = Asset(self, "SampleAsset", + path=os.path.join(dirname, "images/my-image.png")) + +lambda_.Function(self, "myLambdaFunction", + code=lambda_.Code.asset(os.path.join(dirname, "handler")), + runtime=lambda_.Runtime.PYTHON_3_6, + handler="index.lambda_handler", + environment=dict( + S3_BUCKET_NAME=image_asset.s3_bucket_name, + S3_OBJECT_KEY=image_asset.s3_object_key, + S3_URL=image_asset.s3_url)) +``` + +------ +#### [ Java ] + +``` +import java.io.File; + +import software.amazon.awscdk.core.Stack; +import software.amazon.awscdk.core.StackProps; +import software.amazon.awscdk.services.lambda.Function; +import software.amazon.awscdk.services.lambda.Runtime; +import software.amazon.awscdk.services.s3.assets.Asset; + +public class FunctionStack extends Stack { + public FunctionStack(final App scope, final String id, final StackProps props) { + super(scope, id, props); + + File startDir = new File(System.getProperty("user.dir")); + + Asset imageAsset = Asset.Builder.create(this, "SampleAsset") + .path(new File(startDir, "images/my-image.png").toString()).build()) + + Function.Builder.create(this, "myLambdaFunction") + .code(Code.fromAsset(new File(startDir, "handler").toString())) + .runtime(Runtime.PYTHON_3_6) + .handler("index.lambda_handler") + .environment(java.util.Map.of( // Java 9 or later + "S3_BUCKET_NAME", imageAsset.getS3BucketName(), + "S3_OBJECT_KEY", imageAsset.getS3ObjectKey(), + "S3_URL", imageAsset.getS3Url())) + .build(); + } +} +``` + +------ +#### [ C\# ] + +``` +using Amazon.CDK; +using Amazon.CDK.AWS.Lambda; +using Amazon.CDK.AWS.S3.Assets; +using System.IO; +using System.Collections.Generic; + +var imageAsset = new Asset(this, "SampleAsset", new AssetProps +{ + Path = Path.Combine(Directory.GetCurrentDirectory(), @"images\my-image.png") +}); + +new Function(this, "myLambdaFunction", new FunctionProps +{ + Code = Code.FromAsset(Path.Combine(Directory.GetCurrentDirectory(), "handler")), + Runtime = Runtime.PYTHON_3_6, + Handler = "index.lambda_handler", + Environment = new Dictionary<string, string> + { + ["S3_BUCKET_NAME"] = imageAsset.S3BucketName, + ["S3_OBJECT_KEY"] = imageAsset.S3ObjectKey, + ["S3_URL"] = imageAsset.S3Url + } +}); +``` + +------ + +#### Permissions<a name="assets_types_s3_permissions"></a> + +If you use Amazon S3 assets directly through the [aws\-s3\-assets](https://docs.aws.amazon.com/cdk/api/v1/docs/aws-s3-assets-readme.html) module, IAM roles, users, or groups, and need to read assets in runtime, grant those assets IAM permissions through the [asset\.grantRead](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-s3-assets.Asset.html#grant-readgrantee) method\. + +The following example grants an IAM group read permissions on a file asset\. + +------ +#### [ TypeScript ] + +``` +import { Asset } from '@aws-cdk/aws-s3-assets'; +import * as path from 'path'; + +const asset = new Asset(this, 'MyFile', { + path: path.join(__dirname, 'my-image.png') +}); + +const group = new iam.Group(this, 'MyUserGroup'); +asset.grantRead(group); +``` + +------ +#### [ JavaScript ] + +``` +const { Asset } = require('@aws-cdk/aws-s3-assets'); +const path = require('path'); + +const asset = new Asset(this, 'MyFile', { + path: path.join(__dirname, 'my-image.png') +}); + +const group = new iam.Group(this, 'MyUserGroup'); +asset.grantRead(group); +``` + +------ +#### [ Python ] + +``` +from aws_cdk.aws_s3_assets import Asset +from aws_cdk import aws_iam as iam + +import os.path +dirname = os.path.dirname(__file__) + + asset = Asset(self, "MyFile", + path=os.path.join(dirname, "my-image.png")) + + group = iam.Group(self, "MyUserGroup") + asset.grant_read(group) +``` + +------ +#### [ Java ] + +``` +import java.io.File; + +import software.amazon.awscdk.core.Stack; +import software.amazon.awscdk.core.StackProps; +import software.amazon.awscdk.services.iam.Group; +import software.amazon.awscdk.services.s3.assets.Asset; + +public class GrantStack extends Stack { + public GrantStack(final App scope, final String id, final StackProps props) { + super(scope, id, props); + + File startDir = new File(System.getProperty("user.dir")); + + Asset asset = Asset.Builder.create(this, "SampleAsset") + .path(new File(startDir, "images/my-image.png").toString()).build(); + + Group group = new Group(this, "MyUserGroup"); + asset.grantRead(group); } +} +``` + +------ +#### [ C\# ] + +``` +using Amazon.CDK; +using Amazon.CDK.AWS.IAM; +using Amazon.CDK.AWS.S3.Assets; +using System.IO; + +var asset = new Asset(this, "MyFile", new AssetProps { + Path = Path.Combine(Path.Combine(Directory.GetCurrentDirectory(), @"images\my-image.png")) +}); + +var group = new Group(this, "MyUserGroup"); +asset.GrantRead(group); +``` + +------ + +### Docker image assets<a name="assets_types_docker"></a> + +The AWS CDK supports bundling local Docker images as assets through the [aws\-ecr\-assets](https://docs.aws.amazon.com/cdk/api/v1/docs/aws-ecr-assets-readme.html) module\. + +The following example defines a docker image that is built locally and pushed to Amazon ECR\. Images are built from a local Docker context directory \(with a Dockerfile\) and uploaded to Amazon ECR by the AWS CDK CLI or your app's CI/CD pipeline, and can be naturally referenced in your AWS CDK app\. + +------ +#### [ TypeScript ] + +``` +import { DockerImageAsset } from '@aws-cdk/aws-ecr-assets'; + +const asset = new DockerImageAsset(this, 'MyBuildImage', { + directory: path.join(__dirname, 'my-image') +}); +``` + +------ +#### [ JavaScript ] + +``` +const { DockerImageAsset } = require('@aws-cdk/aws-ecr-assets'); + +const asset = new DockerImageAsset(this, 'MyBuildImage', { + directory: path.join(__dirname, 'my-image') +}); +``` + +------ +#### [ Python ] + +``` +from aws_cdk.aws_ecr_assets import DockerImageAsset + +import os.path +dirname = os.path.dirname(__file__) + +asset = DockerImageAsset(self, 'MyBuildImage', + directory=os.path.join(dirname, 'my-image')) +``` + +------ +#### [ Java ] + +``` +import software.amazon.awscdk.services.ecr.assets.DockerImageAsset; + +File startDir = new File(System.getProperty("user.dir")); + +DockerImageAsset asset = DockerImageAsset.Builder.create(this, "MyBuildImage") + .directory(new File(startDir, "my-image").toString()).build(); +``` + +------ +#### [ C\# ] + +``` +using System.IO; +using Amazon.CDK.AWS.ECR.Assets; + +var asset = new DockerImageAsset(this, "MyBuildImage", new DockerImageAssetProps +{ + Directory = Path.Combine(Path.Combine(Directory.GetCurrentDirectory(), "my-image")) +}); +``` + +------ + +The `my-image` directory must include a Dockerfile\. The AWS CDK CLI builds a Docker image from `my-image`, pushes it to an Amazon ECR repository, and specifies the name of the repository as an AWS CloudFormation parameter to your stack\. Docker image asset types expose [deploy\-time attributes](resources.md#resources_attributes) that can be referenced in AWS CDK libraries and apps\. The AWS CDK CLI command cdk synth displays asset properties as AWS CloudFormation parameters\. + +#### Amazon ECS task definition example<a name="assets_types_docker_ecs"></a> + +A common use case is to create an Amazon ECS [TaskDefinition](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-ecs.TaskDefinition.html) to run docker containers\. The following example specifies the location of a Docker image asset that the AWS CDK builds locally and pushes to Amazon ECR\. + +------ +#### [ TypeScript ] + +``` +import * as ecs from '@aws-cdk/aws-ecs'; +import * as path from 'path'; + +const taskDefinition = new ecs.FargateTaskDefinition(this, "TaskDef", { + memoryLimitMiB: 1024, + cpu: 512 +}); + +taskDefinition.addContainer("my-other-container", { + image: ecs.ContainerImage.fromAsset(path.join(__dirname, "..", "demo-image")) +}); +``` + +------ +#### [ JavaScript ] + +``` +const ecs = require('@aws-cdk/aws-ecs'); +const path = require('path'); + +const taskDefinition = new ecs.FargateTaskDefinition(this, "TaskDef", { + memoryLimitMiB: 1024, + cpu: 512 +}); + +taskDefinition.addContainer("my-other-container", { + image: ecs.ContainerImage.fromAsset(path.join(__dirname, "..", "demo-image")) +}); +``` + +------ +#### [ Python ] + +``` +import aws_cdk.aws_ecs as ecs + +import os.path +dirname = os.path.dirname(__file__) + +task_definition = ecs.FargateTaskDefinition(self, "TaskDef", + memory_limit_mib=1024, + cpu=512) + +task_definition.add_container("my-other-container", + image=ecs.ContainerImage.from_asset( + os.path.join(dirname, "..", "demo-image"))) +``` + +------ +#### [ Java ] + +``` +import java.io.File; + +import software.amazon.awscdk.services.ecs.FargateTaskDefinition; +import software.amazon.awscdk.services.ecs.ContainerDefinitionOptions; +import software.amazon.awscdk.services.ecs.ContainerImage; + +File startDir = new File(System.getProperty("user.dir")); + +FargateTaskDefinition taskDefinition = FargateTaskDefinition.Builder.create( + this, "TaskDef").memoryLimitMiB(1024).cpu(512).build(); + +taskDefinition.addContainer("my-other-container", + ContainerDefinitionOptions.builder() + .image(ContainerImage.fromAsset(new File(startDir, + "demo-image").toString())).build()); +``` + +------ +#### [ C\# ] + +``` +using System.IO; +using Amazon.CDK.AWS.ECS; + +var taskDefinition = new FargateTaskDefinition(this, "TaskDef", new FargateTaskDefinitionProps +{ + MemoryLimitMiB = 1024, + Cpu = 512 +}); + +taskDefinition.AddContainer("my-other-container", new ContainerDefinitionOptions +{ + Image = ContainerImage.FromAsset(Path.Combine(Directory.GetCurrentDirectory(), "demo-image"); +}); +``` + +------ + +#### Deploy\-time attributes example<a name="assets_types_docker_deploy"></a> + +The following example shows how to use the deploy\-time attributes `repository` and `imageUri` to create an Amazon ECS task definition with the AWS Fargate launch type\. Note that the Amazon ECR repo lookup requires the image's tag, not its URI, so we snip it from the end of the asset's URI\. + +------ +#### [ TypeScript ] + +``` +import * as ecs from '@aws-cdk/aws-ecs'; +import * as path from 'path'; +import { DockerImageAsset } from '@aws-cdk/aws-ecr-assets'; + +const asset = new DockerImageAsset(this, 'my-image', { + directory: path.join(__dirname, "..", "demo-image") +}); + +const taskDefinition = new ecs.FargateTaskDefinition(this, "TaskDef", { + memoryLimitMiB: 1024, + cpu: 512 +}); + +taskDefinition.addContainer("my-other-container", { + image: ecs.ContainerImage.fromEcrRepository(asset.repository, asset.imageUri.split(":").pop()) +}); +``` + +------ +#### [ JavaScript ] + +``` +const ecs = require('@aws-cdk/aws-ecs'); +const path = require('path'); +const { DockerImageAsset } = require('@aws-cdk/aws-ecr-assets'); + +const asset = new DockerImageAsset(this, 'my-image', { + directory: path.join(__dirname, "..", "demo-image") +}); + +const taskDefinition = new ecs.FargateTaskDefinition(this, "TaskDef", { + memoryLimitMiB: 1024, + cpu: 512 +}); + +taskDefinition.addContainer("my-other-container", { + image: ecs.ContainerImage.fromEcrRepository(asset.repository, asset.imageUri.split(":").pop()) +}); +``` + +------ +#### [ Python ] + +``` +import aws_cdk.aws_ecs as ecs +from aws_cdk.aws_ecr_assets import DockerImageAsset + +import os.path +dirname = os.path.dirname(__file__) + +asset = DockerImageAsset(self, 'my-image', + directory=os.path.join(dirname, "..", "demo-image")) + +task_definition = ecs.FargateTaskDefinition(self, "TaskDef", + memory_limit_mib=1024, cpu=512) + +task_definition.add_container("my-other-container", + image=ecs.ContainerImage.from_ecr_repository( + asset.repository, asset.image_uri.rpartition(":")[-1])) +``` + +------ +#### [ Java ] + +``` +import java.io.File; + +import software.amazon.awscdk.services.ecr.assets.DockerImageAsset; + +import software.amazon.awscdk.services.ecs.FargateTaskDefinition; +import software.amazon.awscdk.services.ecs.ContainerDefinitionOptions; +import software.amazon.awscdk.services.ecs.ContainerImage; + +File startDir = new File(System.getProperty("user.dir")); + +DockerImageAsset asset = DockerImageAsset.Builder.create(this, "my-image") + .directory(new File(startDir, "demo-image").toString()).build(); + +FargateTaskDefinition taskDefinition = FargateTaskDefinition.Builder.create( + this, "TaskDef").memoryLimitMiB(1024).cpu(512).build(); + +// extract the tag from the asset's image URI for use in ECR repo lookup +String imageUri = asset.getImageUri(); +String imageTag = imageUri.substring(imageUri.lastIndexOf(":") + 1); + +taskDefinition.addContainer("my-other-container", + ContainerDefinitionOptions.builder().image(ContainerImage.fromEcrRepository( + asset.getRepository(), imageTag)).build()); +``` + +------ +#### [ C\# ] + +``` +using System.IO; +using Amazon.CDK.AWS.ECS; +using Amazon.CDK.AWS.ECR.Assets; + +var asset = new DockerImageAsset(this, "my-image", new DockerImageAssetProps { + Directory = Path.Combine(Directory.GetCurrentDirectory(), "demo-image") +}); + +var taskDefinition = new FargateTaskDefinition(this, "TaskDef", new FargateTaskDefinitionProps +{ + MemoryLimitMiB = 1024, + Cpu = 512 +}); + +taskDefinition.AddContainer("my-other-container", new ContainerDefinitionOptions +{ + Image = ContainerImage.FromEcrRepository(asset.Repository, asset.ImageUri.Split(":").Last()) +}); +``` + +------ + +#### Build arguments example<a name="assets_types_docker_build"></a> + +You can provide customized build arguments for the Docker build step through the `buildArgs` \(Python: `build_args`\) property option when the AWS CDK CLI builds the image during deployment\. + +------ +#### [ TypeScript ] + +``` +const asset = new DockerImageAsset(this, 'MyBuildImage', { + directory: path.join(__dirname, 'my-image'), + buildArgs: { + HTTP_PROXY: 'http://10.20.30.2:1234' + } +}); +``` + +------ +#### [ JavaScript ] + +``` +const asset = new DockerImageAsset(this, 'MyBuildImage', { + directory: path.join(__dirname, 'my-image'), + buildArgs: { + HTTP_PROXY: 'http://10.20.30.2:1234' + } +}); +``` + +------ +#### [ Python ] + +``` +asset = DockerImageAsset(self, "MyBulidImage", + directory=os.path.join(dirname, "my-image"), + build_args=dict(HTTP_PROXY="http://10.20.30.2:1234")) +``` + +------ +#### [ Java ] + +``` +DockerImageAsset asset = DockerImageAsset.Builder.create(this, "my-image"), + .directory(new File(startDir, "my-image").toString()) + .buildArgs(java.util.Map.of( // Java 9 or later + "HTTP_PROXY", "http://10.20.30.2:1234")) + .build(); +``` + +------ +#### [ C\# ] + +``` +var asset = new DockerImageAsset(this, "MyBuildImage", new DockerImageAssetProps { + Directory = Path.Combine(Directory.GetCurrentDirectory(), "my-image"), + BuildArgs = new Dictionary<string, string> + { + ["HTTP_PROXY"] = "http://10.20.30.2:1234" + } +}); +``` + +------ + +#### Permissions<a name="assets_types_docker_permissions"></a> + +If you use a module that supports Docker image assets, such as [aws\-ecs](https://docs.aws.amazon.com/cdk/api/v1/docs/aws-ecs-readme.html), the AWS CDK manages permissions for you when you use assets directly or through [ContainerImage\.fromEcrRepository](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-ecs.ContainerImage.html#static-from-ecr-repositoryrepository-tag) \(Python: `from_ecr_repository`\)\. If you use Docker image assets directly, you need to ensure that the consuming principal has permissions to pull the image\. + +In most cases, you should use [asset\.repository\.grantPull](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-ecr.Repository.html#grant-pullgrantee) method \(Python: `grant_pull`\. This modifies the IAM policy of the principal to enable it to pull images from this repository\. If the principal that is pulling the image is not in the same account or is an AWS service, such as AWS CodeBuild, that does not assume a role in your account, you must grant pull permissions on the resource policy and not on the principal's policy\. Use the [asset\.repository\.addToResourcePolicy](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-ecr.Repository.html#add-to-resource-policystatement) method \(Python: `add_to_resource_policy`\) to grant the appropriate principal permissions\. + +## AWS CloudFormation resource metadata<a name="assets_cfn"></a> + +**Note** +This section is relevant only for construct authors\. In certain situations, tools need to know that a certain CFN resource is using a local asset\. For example, you can use the AWS SAM CLI to invoke Lambda functions locally for debugging purposes\. See [AWS SAM integration](sam.md) for details\. + +To enable such use cases, external tools consult a set of metadata entries on AWS CloudFormation resources: ++ `aws:asset:path` – Points to the local path of the asset\. ++ `aws:asset:property` – The name of the resource property where the asset is used\. + +Using these two metadata entries, tools can identify that assets are used by a certain resource, and enable advanced local experiences\. + +To add these metadata entries to a resource, use the `asset.addResourceMetadata` \(Python: `add_resource_metadata`\) method\. \ No newline at end of file diff --git a/v1/best-practices.md b/v1/best-practices.md new file mode 100644 index 00000000..23787f26 --- /dev/null +++ b/v1/best-practices.md @@ -0,0 +1,185 @@ +# Best practices for developing and deploying cloud infrastructure with the AWS CDK<a name="best-practices"></a> + +The AWS CDK allows developers or administrators to define their cloud infrastructure using a supported programming language\. CDK applications should be organized into logical units, such as API, database, and monitoring resources, and optionally have a pipeline for automated deployments\. The logical units should be implemented as constructs including the infrastructure \(e\.g\. Amazon S3 buckets, Amazon RDS databases, Amazon VPC network\), runtime code \(e\.g\. AWS Lambda functions\), and configuration code\. Stacks define the deployment model of these logical units\. For a more detailed introduction to the concepts behind the CDK, see [Getting started with the AWS CDK](getting_started.md)\. + +The AWS CDK reflects careful consideration of the needs of our customers and internal teams and of the failure patterns that often arise during the deployment and ongoing maintenance of complex cloud applications\. We discovered that failures are often related to "out\-of\-band" changes to an application, such as configuration changes, that were not fully tested\. Therefore, we developed the AWS CDK around a model in which your entire application, not just business logic but also infrastructure and configuration, is defined in code\. That way, proposed changes can be carefully reviewed, comprehensively tested in environments resembling production to varying degrees, and fully rolled back if something goes wrong\. + +![\[Image NOT FOUND\]](http://docs.aws.amazon.com/cdk/v1/guide/images/all-in-one.jpg) + +At deployment time, the AWS CDK synthesizes a cloud assembly that contains not only AWS CloudFormation templates describing your infrastructure in all target environments, but file assets containing your runtime code and their supporting files\. With the CDK, every commit in your application's main version control branch can represent a complete, consistent, deployable version of your application\. Your application can then be deployed automatically whenever a change is made\. + +The philosophy behind the AWS CDK leads to our recommended best practices, which we have divided into four broad categories\. ++ [Organization best practices](#best-practices-organization) ++ [Coding best practices](#best-practices-code) ++ [Construct best practices](#best-practices-constructs) ++ [Application best practices](#best-practices-apps) + +**Tip** +In addition to the guidance in this document, you should also consider [best practices for AWS CloudFormation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/best-practices.html) as well as for the individual AWS services you use, where they are obviously applicable to CDK\-defined infrastructure\. + +## Organization best practices<a name="best-practices-organization"></a> + +In the beginning stages of AWS CDK adoption, it's important to consider how to set up your organization for success\. It's a best practice to have a team of experts responsible for training and guiding the rest of the company as they adopt the CDK\. The size of this team may vary, from one or two people at a small company to a full\-fledged Cloud Center of Excellence \(CCoE\) at a larger company\. This team is responsible for setting standards and policies for how cloud infrastructure will be done at your company, as well as for training and mentoring developers\. + +The CCoE may provide guidance on what programming languages should be used for cloud infrastructure\. The details will vary from one organization to the next, but a good policy helps make sure developers can easily understand and maintain all cloud infrastructure throughout the company\. + +The CCoE also creates a "landing zone" that defines your organizational units within AWS\. A landing zone is a pre\-configured, secure, scalable, multi\-account AWS environment based on best practice blueprints\. You can tie together the services that make up your landing zone with [AWS Control Tower](https://aws.amazon.com/controltower/), a high\-level service configures and manages your entire multi\-account system from a single user interface\. + +Development teams should be able use their own accounts for testing and have the ability to deploy new resources in these accounts as needed\. Individual developers can treat these resources as extensions of their own development workstation\. Using [CDK Pipelines](cdk_pipeline.md), the AWS CDK applications can then be deployed via a CI/CD account to testing, integration, and production environments \(each isolated in its own AWS region and/or account\) by merging the developers' code into your organization's canonical repository\. + +![\[Image NOT FOUND\]](http://docs.aws.amazon.com/cdk/v1/guide/images/best-practice-deploy-to-multiple-accounts.png) + +## Coding best practices<a name="best-practices-code"></a> + +This section presents best practices for organizing your AWS CDK code\. The diagram below shows the relationship between a team and that team's code repositories, packages, applications, and construct libraries\. + +![\[Image NOT FOUND\]](http://docs.aws.amazon.com/cdk/v1/guide/images/code-organization.jpg) + +### Start simple and add complexity only when you need it<a name="best-practices-code-kiss"></a> + +The guiding principle for most of our best practices is to keep things simple as possible—but no simpler\. Add complexity only when your requirements dictate a more complicated solution\. With the AWS CDK, you can always refactor your code as necessary to support new requirements, so it doesn't make sense to architect for all possible scenarios up front\. + +### Align with the AWS Well\-Architected framework<a name="best-practices-code-well-architected"></a> + +The [AWS Well\-Architected](http://aws.amazon.com/architecture/well-architected/) framework defines a *component* as the code, configuration, and AWS resources that together deliver against a requirement\. A component is often the unit of technical ownership, and is decoupled from other components\. The term *workload* is used to identify a set of components that together deliver business value\. A workload is usually the level of detail that business and technology leaders communicate about\. + +An AWS CDK application maps to a component as defined by the AWS Well\-Architected Framework\. AWS CDK apps are a mechanism to codify and deliver Well\-Architected cloud application best practices\. You can also create and share components as reusable code libraries through artifact repositories, such as AWS CodeArtifact\. + +### Every application starts with a single package in a single repository<a name="best-practices-code-package"></a> + +A single package is the entry point of your AWS CDK app\. This is where you define how and where the different logical units of your application are deployed, as well as the CI/CD pipeline to deploy the application\. The app's constructs define the logical units of your solution\. + +Use additional packages for constructs that you use in more than one application\. \(Shared constructs should also have their own lifecycle and testing strategy\.\) Dependencies between packages in the same repository are managed by your repo's build tooling\. + +Though it is possible, it is not recommended to put multiple applications in the same repository, especially when using automated deployment pipelines, because this increases the "blast radius" of changes during deployment\. With multiple applications in a repository, not only do changes to one application trigger deployment of the others \(even if they have not changed\), but a break in one application prevents the other applications from being deployed\. + +### Move code into repositories based on code lifecycle or team ownership<a name="best-practices-code-repo"></a> + +When packages begin to be used in multiple applications, move them to their own repository, so they can be referenced by the build systems of the applications that use them, but updated on cadences independent of the lifecycles of those applications\. It may make sense to put all shared constructs in one repository at first\. + +Also move packages to their own repo when different teams are working on them, to help enforce access control\. + +To consume packages across repository boundaries, you now need a private package repository—similar to NPM, PyPi, or Maven Central, but internal to your organization, and a release process that builds, tests, and publishes the package to the private package repository\. [CodeArtifact](https://docs.aws.amazon.com/codeartifact/latest/ug/) can host packages for most popular programming languages\. + +Dependencies on packages in the package repository are managed by your language's package manager, for example NPM for TypeScript or JavaScript applications\. Your package manager helps to make sure builds are repeatable by recording the specific versions of every package your application depends on and allows you to upgrade those dependencies in a controlled manner\. + +Shared packages need a different testing strategy: although for a single application it might be good enough to deploy the application to a testing environment and confirm that it still works, shared packages need to be tested independently of the consuming application, as if they were being released to the public\. \(Your organization might in fact choose to actually release some shared packages to the public\.\) + +Keep in mind that a construct can be arbitrarily simple or complex\. A `Bucket` is a construct, but `CameraShopWebsite` could be a construct, too\. + +### Infrastructure and runtime code live in the same package<a name="best-practices-code-all"></a> + +The AWS CDK not only generates AWS CloudFormation templates for deploying infrastructure, it also bundles runtime assets like Lambda functions and Docker images and deploys them alongside your infrastructure\. So it's not only possible to combine the code that defines your infrastructure and the code that implements your runtime logic into a single construct— it's a best practice\. These two kinds of code don't need to live in separate repositories or even in separate packages\. + +A construct that is self\-contained, in other words that completely describes a piece of functionality including its infrastructure and logic, makes it easy to evolve the two kinds of code together, test them in isolation, share and reuse the code across projects, and version all the code in sync\. + +## Construct best practices<a name="best-practices-constructs"></a> + +This section contains best practices for developing constructs\. Constructs are reusable, composable modules that encapsulate resources, and the building blocks of AWS CDK apps\. + +### Model with constructs, deploy with stacks<a name="best-practices-constructs-model"></a> + +Stacks are the unit of deployment: everything in a stack is deployed together\. So when building your application's higher\-level logical units from multiple AWS resources, represent each logical unit as a [https://docs.aws.amazon.com/cdk/api/v1/docs/constructs.Construct.html](https://docs.aws.amazon.com/cdk/api/v1/docs/constructs.Construct.html), not as a [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.Stack.html](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.Stack.html)\. Use stacks only to describe how your constructs should be composed and connected for your various deployment scenarios\. + +If one of your logical units is a Web site, for example, the constructs that make it up \(Amazon S3 bucket, API Gateway, Lambda functions, Amazon RDS tables, etc\.\) should be composed into a single high\-level construct, and then that construct should be instantiated in one or more stacks for deployment\. + +By using constructs for building and stacks for deploying, you improve reuse potential of your infrastructure and give yourself more flexibility in how it is deployed\. + +### Configure with properties and methods, not environment variables<a name="best-practices-constructs-config"></a> + +Environment variable lookups inside constructs and stacks are a common anti\-pattern\. Both constructs and stacks should accept a properties object to allow for full configurability completely in code\. To do otherwise is to introduce a dependency on the machine that the code will run on, which becomes another bit of configuration information you have to keep track of and manage\. + +In general, environment variable lookups should be limited to the top level of an AWS CDK app, and should be used to pass in information needed for running in a development environment; see [Environments](environments.md)\. + +### Unit test your infrastructure<a name="best-practices-constructs-test"></a> + +If you avoid network lookups during synthesis and model all your production stages in code \(best practices we cover later\), you can run a full suite of unit tests at build time, consistently, in all environments\. If any single commit always results in the same generated template, you can trust the unit tests that you write to confirm that the generated templates look how you expect them to\. See [Testing constructs](testing.md)\. + +### Don't change the logical ID of stateful resources<a name="best-practices-constructs-logicalid"></a> + +Changing the logical ID of a resource results in the resource being replaced with a new one at the next deployment\. For stateful resources like databases and buckets, or persistent infrastructure like an Amazon VPC, this is almost never what you want\. Be careful about any refactor of your AWS CDK code that could cause the ID to change, and write unit tests that assert that the logical IDs of your stateful resources remain static\. The logical ID is derived from the `id` you specify when you instantiate the construct, and the construct's position in the construct tree; see [Logical IDs](identifiers.md#identifiers_logical_ids)\. + +### Constructs aren't enough for compliance<a name="best-practices-constructs-compliance"></a> + +Many enterprise customers are writing their own wrappers for L2 constructs \(the "curated" constructs that represent individual AWS resources with built\-in sane defaults and best practices\) to enforce security best practices such as static encryption and specific IAM policies\. For example, you might create a `MyCompanyBucket` that you then use in your applications in place of the usual Amazon S3 `Bucket` construct\. This pattern is useful for surfacing security guidance early in the software development lifecycle, but it cannot be relied on as the sole means of enforcement\. + +Instead, use AWS features such as [service control policies](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps.html) and [permission boundaries](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html) to enforce your security guardrails at the organization level\. Use [Aspects](aspects.md) or tools like [CloudFormation Guard](https://github.com/aws-cloudformation/cloudformation-guard) to make assertions about the security properties of infrastructure elements before deployment\. Use AWS CDK for what it does best\. + +Finally, keep in mind that writing your own "L2\+" constructs like these may prevent your developers from taking advantage of the growing ecosystems of AWS CDK packages, such as [AWS Solutions Constructs](https://docs.aws.amazon.com/solutions/latest/constructs/welcome.html), as these are typically built upon standard AWS CDK constructs and won't be able to use your custom versions\. + +## Application best practices<a name="best-practices-apps"></a> + +In this section we discuss how best to write your AWS CDK applications, combining constructs to define how your AWS resources are connected\. + +### Make decisions at synthesis time<a name="best-practices-apps-synth"></a> + +Although AWS CloudFormation lets you make decisions at deployment time \(using `Conditions`, `{ Fn::If }`, and `Parameters`\), and the AWS CDK gives you some access to these mechanisms, we recommend against using them\. The types of values you can use, and the types of operations you can perform on them, are quite limited compared to those available in a general\-purpose programming language\. + +Instead, try to make all decisions, such as which construct to instantiate, in your AWS CDK application, using your programming language's `if` statements and other features\. For example, a common CDK idiom, iterating over a list and instantiating a construct with values from each item in the list, simply isn't possible using AWS CloudFormation expressions\. + +Treat AWS CloudFormation as an implementation detail that the AWS CDK uses for robust cloud deployments, not as a language target\. You're not writing AWS CloudFormation templates in TypeScript or Python, you're writing CDK code that happens to use CloudFormation for deployment\. + +### Use generated resource names, not physical names<a name="best-practices-apps-names"></a> + +Names are a precious resource\. Every name can only be used once, so if you hard\-code a table name or bucket name into your infrastructure and application, you can't deploy that piece of infrastructure twice in the same account\. \(The name we're talking about here is the name specified by, for example, the `bucketName` property on an Amazon S3 bucket construct\.\) + +What's worse, you can't make changes to the resource that require it to be replaced\. If a property can only be set at resource creation, for example the `KeySchema` of an Amazon DynamoDB table, that property is immutable, and changing it requires a new resource\. But the new resource must have the same name in order to be a true replacement, and it can't while the existing resource is still using that name\. + +A better approach is to specify as few names as possible\. If you leave out resource names, the AWS CDK will generate them for you, and it'll do so in a way that won't cause these problems\. You then, for example, pass the generated table name \(which you can reference as `table.tableName` in your AWS CDK application\) as an environment variable into your AWS Lambda function, or you generate a configuration file on your Amazon EC2 instance on startup, or you write the actual table name to AWS Systems Manager Parameter Store and your application reads it from there\. + +If the place you need it is another AWS CDK stack, that's even easier\. Given one stack that defines the resource and another than needs to use it: ++ If the two stacks are in the same AWS CDK app, just pass a reference between the two stacks\. For example, save a reference to the resource's construct as an attribute of the defining stack \(`this.stack.uploadBucket = myBucket`\), then pass that attribute to the constructor of the stack that needs the resource\. ++ When the two stacks are in different AWS CDK apps, use a static `from` method to use an externally\-defined resource based on its ARN, name, or other attributes \(for example, `Table.fromArn()` for a DynamoDB table\)\. Use the `CfnOutput` construct to print the ARN or other required value in the output of `cdk deploy`, or look in the AWS console\. Or the second app can parse the CloudFormation template generated by the first app and retrieve that value from the Outputs section\. + +### Define removal policies and log retention<a name="best-practices-apps-removal-logs"></a> + +The AWS CDK does its best to keep you from losing data by defaulting to policies that retain everything you create\. For example, the default removal policy on resources that contain data \(such as Amazon S3 buckets and database tables\) is to never delete the resource when it is removed from the stack, but rather orphan the resource from the stack\. Similarly, the CDK's default is to retain all logs forever\. In production environments, these defaults can quickly result in the storage of large amounts of data you don't actually need, and a corresponding AWS bill\. + +Consider carefully what you want these policies to actually be for each production resource and specify them accordingly\. Use [Aspects](aspects.md) to validate the removal and logging policies in your stack\. + +### Separate your application into multiple stacks as dictated by deployment requirements<a name="best-practices-apps-separate"></a> + +There is no hard and fast rule to how many stacks your application needs\. You'll usually end up basing the decision on your deployment patterns\. Keep in mind the following guidelines: ++ It's typically easier to keep as many resources in the same stack as possible, so keep them together unless you know you want them separated\. ++ Consider keeping stateful resources \(like databases\) in a separate stack from stateless resources\. You can then turn on termination protection on the stateful stack, and can freely destroy or create multiple copies of the stateless stack without risk of data loss\. ++ Stateful resources are more sensitive to construct renaming—renaming leads to resource replacement—so it makes sense not to nest them inside constructs that are likely to be moved around or renamed \(unless the state can be rebuilt if lost, like a cache\)\. This is another good reason to put stateful resources in their own stack\. + +### Commit `cdk.context.json` to avoid non\-deterministic behavior<a name="best-practices-apps-context"></a> + +Determinism is key to successful AWS CDK deployments\. A AWS CDK app should have essentially the same result whenever it is deployed to a given environment\. + +Since your AWS CDK app is written in a general\-purpose programming language, it can execute arbitrary code, use arbitrary libraries, and make arbitrary network calls\. For example, you could use an AWS SDK to retrieve some information from your AWS account while synthesizing your app\. Recognize that doing so will result in additional credential setup requirements, increased latency, and a chance, however small, of failure every time you run `cdk synth`\. + +You should never modify your AWS account or resources during synthesis; synthesizing an app should not have side effects\. Changes to your infrastructure should happen only in the deployment phase, after the AWS CloudFormation template has been generated\. This way, if there's a problem, AWS CloudFormation will automatically roll back the change\. To make changes that can't be easily made within the AWS CDK framework, use [custom resources](https://docs.aws.amazon.com/cdk/api/v1/docs/custom-resources-readme.html) to execute arbitrary code at deployment time\. + +Even strictly read\-only calls are not necessarily safe\. Consider what happens if the value returned by a network call changes\. What part of your infrastructure will that impact? What will happen to already\-deployed resources? Here are just two of the situations in which a sudden change in values might cause a problem\. ++ If you provision an Amazon VPC to all available Availability Zones in a specified region, and the number of AZs is two on deployment day, your IP space gets split in half\. If AWS launches a new Availability Zone the next day, the next deployment after that tries to split your IP space into thirds, requiring all subnets to be recreated\. This probably won't be possible because your Amazon EC2 instances are still running, and you'll have to clean this up manually\. ++ If you query for the latest Amazon Linux machine image and deploy an Amazon EC2 instance, and the next day a new image is released, a subsequent deployment picks up the new AMI and replaces all your instances\. This may not be what you expected to happen\. + +These situations can be particularly pernicious because the AWS\-side change may occur after months or years of successful deployments\. Suddenly your deployments are failing "for no reason" and you long ago forgot what you did and why\. + +Fortunately, the AWS CDK includes a mechanism called *context providers* to record a snapshot of non\-deterministic values, allowing future synthesis operations produce exactly the same template\. The only changes in the new template are the changes *you* made in your code\. When you use a construct's `.fromLookup()` method, the result of the call is cached in `cdk.context.json`, which you should commit to version control along with the rest of your code to ensure future executions of your CDK app use the same value\. The CDK Toolkit includes commands to manage the context cache, so you can refresh specific entries when you need to\. For more information, see [Runtime context](context.md)\. + +If you need some value \(from AWS or elsewhere\) for which there is no native CDK context provider, we recommend writing a separate script to retrieve the value and write it to a file, then read that file in your CDK app\. Run the script only when you want to refresh the stored value, not as part of your regular build process\. + +### Let the AWS CDK manage roles and security groups<a name="best-practices-apps-roles"></a> + +One of the great features of the AWS CDK construct library is the `grant()` convenience methods that allow quick and simple creation of AWS Identity and Access Management roles granting access to one resource by another using minimally\-scoped permissions\. For example, consider a line like the following: + +``` +myBucket.grantRead(myLambda) +``` + +This single line results in a policy being added to the Lambda function's role \(which is also created for you\)\. That role and its policies are more than a dozen lines of CloudFormation that you don't have to write, and the AWS CDK grants only the minimal permissions required for the function to read from the bucket\. + +If you require developers to always use predefined roles that were created by a security team, AWS CDK coding becomes much more complicated, and your teams lose a lot of flexibility in how they design their applications\. A better alternative is to use [service control policies](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps.html) and [permission boundaries](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html) to ensure that developers stay within the guardrails\. + +### Model all production stages in code<a name="best-practices-apps-stages"></a> + +In traditional AWS CloudFormation scenarios, your goal is to produce a single artifact that is parameterized so that it can be deployed to various target environments after applying configuration values specific to those environments\. In the CDK, you can, and should, build that configuration right into your source code\. Create a stack for your production environment, and a separate one for each of your other stages, and put the configuration values for each right there in the code\. Use services like [Secrets Manager](https://aws.amazon.com/secrets-manager/) and [Systems Manager](https://aws.amazon.com/systems-manager/) Parameter Store for sensitive values that you don't want to check in to source control, using the names or ARNs of those resources\. + +When you synthesize your application, the cloud assembly created in the `cdk.out` folder contains a separate template for each environment\. Your entire build is deterministic: there are no out\-of\-band changes to your application, and any given commit always yields the exact same AWS CloudFormation template and accompanying assets, which makes unit testing much more reliable\. + +### Measure everything<a name="best-practices-apps-measure"></a> + +Achieving the goal of full continuous deployment, with no human intervention, requires a high level of automation, and that automation isn't possible without extensive amounts of monitoring\. Create metrics, alarms, and dashboards to measure all aspects of your deployed resources\. And don't just measure simple things like CPU usage and disk space: also record your business metrics, and use those measurements to automate deployment decisions like rollbacks\. Most of the L2 constructs in AWS CDK have convenience methods to help you create metrics, such as the `metricUserErrors()` method on the [dynamodb\.Table](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-dynamodb.Table.html) class\. \ No newline at end of file diff --git a/v1/bootstrapping.md b/v1/bootstrapping.md new file mode 100644 index 00000000..a6a3ee3a --- /dev/null +++ b/v1/bootstrapping.md @@ -0,0 +1,654 @@ +# Bootstrapping<a name="bootstrapping"></a> + +Deploying AWS CDK apps into an AWS [environment](environments.md) \(a combination of an AWS account and region\) may require that you provision resources the AWS CDK needs to perform the deployment\. These resources include an Amazon S3 bucket for storing files and IAM roles that grant permissions needed to perform deployments\. The process of provisioning these initial resources is called *bootstrapping*\. + +An environment needs to be bootstrapped if any of the following apply\. ++ An AWS CDK stack being deployed uses [Assets](assets.md)\. ++ An AWS CloudFormation template generated by the app exceeds 50 kilobytes\. ++ One or more of the stacks uses the `DefaultSynthesizer`\. We will explain stack synthesizers in more detail shortly, but in brief, the `DefaultSynthesizer` is used if you have set the `@aws-cdk/core:newStyleStackSynthesis` [feature flag](featureflags.md) in your app's `cdk.json` *or* if you explicitly create a `DefaultSynthesizer` and pass it to your stack\. [CDK Pipelines](cdk_pipeline.md) use the `DefaultSynthesizer`, so if your app uses CDK Pipelines, you must bootstrap the environments you will deploy into as well as the environment that contains the pipeline\. + +The required resources are defined in a AWS CloudFormation stack, called the *bootstrap stack*, which is usually named `CDKToolkit`\. Like any AWS CloudFormation stack, it appears in the AWS CloudFormation console once it has been deployed\. + +The AWS CDK supports two bootstrap templates\. At this writing, the AWS CDK is transitioning from one of these templates to the other, but the original template \(dubbed "legacy"\) is still the default\. The newer template \("modern"\) is required by CDK Pipelines today, and will become the default at some point in the future\. For details, see [Bootstrapping templates](#bootstrapping-templates)\. + +Environments are independent, so if you want to deploy to multiple environments \(different AWS accounts or different regions in the same account\), each environment must be bootstrapped separately\. + +**Important** +You may incur AWS charges for data stored in the bootstrapped resources\. + +**Note** +Older versions of the modern template created a Customer Master Key \(CMK\) in each bootstrapped environment by default\. To avoid charges for the CMK, re\-bootstrap these environments using `--no-bootstrap-customer-key`\. The current default is to not use a CMK to avoid these charges\. + +If you attempt to deploy an AWS CDK application that requires bootstrap resources into an environment that does not have them, you receive an error message telling you that you need to bootstrap\. + +If you are using CDK Pipelines to deploy into another account's environment, and you receive a message like the following: + +``` +Policy contains a statement with one or more invalid principals +``` + +This error message means that the appropriate IAM roles do not exist in the other environment, which is most likely caused by a lack of bootstrapping\. + +**Note** +Do not delete and recreate an account's bootstrap stack if you are using CDK Pipelines to deploy into that account\. The pipeline will stop working\. To update the bootstrap stack to a new version, instead re\-run `cdk bootstrap` to update the bootstrap stack in place\. + +## How to bootstrap<a name="bootstrapping-howto"></a> + +Bootstrapping is the deployment of a AWS CloudFormation template to a specific AWS environment \(account and region\)\. The bootstrapping template accepts parameters that customize some aspects of the bootstrapped resources \(see [Customizing bootstrapping](#bootstrapping-customizing)\)\. Thus, you can bootstrap in one of two ways\. ++ Use the AWS CDK Toolkit's cdk bootstrap command\. This is the simplest method and works well if you have only a few environments to bootstrap\. ++ Deploy the template provided by the AWS CDK Toolkit using another AWS CloudFormation deployment tool\. This lets you use AWS CloudFormation Stack Sets or AWS Control Tower as well as the AWS CloudFormation console or the AWS CLI\. You can even make small modifications to the template before deployment\. This approach is more flexible and is suitable for large\-scale deployments\. + +It is not an error to bootstrap an environment more than once\. If an environment you bootstrap has already been bootstrapped, its bootstrap stack will be upgraded if necessary; otherwise, nothing happens\. + +### Bootstrapping with the AWS CDK Toolkit<a name="bootstrapping-howto-cli"></a> + +Use the `cdk bootstrap` command to bootstrap one or more AWS environments\. In its basic form, this command bootstraps one or more specified AWS environments \(two, in this example\)\. + +``` +cdk bootstrap aws://ACCOUNT-NUMBER-1/REGION-1 aws://ACCOUNT-NUMBER-2/REGION-2 ... +``` + +The following examples illustrate bootstrapping of one and two environments, respectively\. \(Both use the same AWS account\.\) As shown in the second example, the `aws://` prefix is optional when specifying an environment\. + +``` +cdk bootstrap aws://123456789012/us-east-1 +cdk bootstrap 123456789012/us-east-1 123456789012/us-west-1 +``` + +The CDK Toolkit always synthesizes the AWS CDK app in the current directory\. If you do not specify at least one environment in the `cdk bootstrap` command, it bootstraps all the environments referenced in the app\. If a stack is environment\-agnostic \(that is, it does not have an `env` property\), the CDK's environment \(for example, the one specified using \-\-profile, or the default AWS environment otherwise\) is applied to make the stack environment\-specific, and that environment is then bootstrapped\. + +For example, the following command synthesizes the current AWS CDK app using the `prod` AWS profile, then bootstraps its environments\. + +``` +cdk bootstrap --profile prod +``` + +### Bootstrapping from the AWS CloudFormation template<a name="bootstrapping-howto-cfn"></a> + +AWS CDK bootstrapping is performed by an AWS CloudFormation template\. To get a copy of this template in the file `bootstrap-template.yaml`, run the following command\. + +------ +#### [ macOS/Linux ] + +``` +cdk bootstrap --show-template > bootstrap-template.yaml +``` + +------ +#### [ Windows ] + +On Windows, PowerShell must be used to preserve the encoding of the template\. + +``` +powershell "cdk bootstrap --show-template | Out-File -encoding utf8 bootstrap-template.yaml" +``` + +------ + +The template is also available in the [AWS CDK GitHub repository](https://github.com/aws/aws-cdk/blob/master/packages/aws-cdk/lib/api/bootstrap/bootstrap-template.yaml)\. + +Deploy this template using cdk bootstrap \-\-template *TEMPLATE\_FILENAME* or your preferred deployment mechanism for AWS CloudFormation templates\. For example, the following command deploys the template using the AWS CLI: + +------ +#### [ macOS/Linux ] + +``` +aws cloudformation create-stack \ + --stack-name CDKToolkit \ + --template-body file://bootstrap-template.yaml +``` + +------ +#### [ Windows ] + +``` +aws cloudformation create-stack ^ + --stack-name CDKToolkit ^ + --template-body file://bootstrap-template.yaml +``` + +------ + +## Bootstrapping templates<a name="bootstrapping-templates"></a> + +At this writing, the AWS CDK is transitioning from one set of bootstrap resources to another\. The original bootstrap template, which shipped with the very first version of the AWS CDK, is called the **legacy** template\. A newer version of the template with additional resources was added in version 1\.25\.0\. This newer template is called the **modern** template\. + +The legacy template is still fully supported by the AWS CDK and is in fact the template that is selected by default when you issue `cdk bootstrap`\. The modern template is required primarily by the CDK Pipelines module, which can be used to set up a continuous delivery pipeline for your CDK applications\. More precisely, the modern template is used by the `DefaultSynthesizer` \(see [Stack synthesizers](#bootstrapping-synthesizers)\), and CDK Pipelines requires this synthesizer, + +The main differences between the templates are as follows\. + +[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/cdk/v1/guide/bootstrapping.html) + +\* *We will add additional resources to the modern template as needed\.* + +In AWS CDK version 2, the modern template will be the default bootstrapping template\. In version 1, manually select the modern template when bootstrapping by setting the `CDK_NEW_BOOTSTRAP` environment variable\. + +------ +#### [ macOS/Linux ] + +``` +export CDK_NEW_BOOTSTRAP=1 +cdk bootstrap aws://ACCOUNT-NUMBER/REGION +``` + +------ +#### [ Windows ] + +``` +set CDK_NEW_BOOTSTRAP=1 +cdk bootstrap aws://ACCOUNT-NUMBER/REGION +``` + +------ + +The modern template is also selected when you issue cdk bootstrap in an AWS CDK app directory where the `@aws-cdk/core:newStyleStackSynthesis` feature flag is set in the app's `cdk.json` file\. + +``` +{ + // ... + "context": { + "@aws-cdk/core:newStyleStackSynthesis": true + } +} +``` + +**Tip** +We recommend always setting `CDK_NEW_BOOTSTRAP` when you want to bootstrap using the modern template\. The context key is supported to make sure you bootstrap correctly if your app uses the `DefaultStackSynthesizer`, but relies on you being in an app's directory when bootstrapping\. + +These two ways to specify the modern template also apply to `cdk bootstrap --show-template`, which will display the modern template if either of these flags is present\. + +If the environment you are bootstrapping with the modern template has already been bootstrapped with the legacy template, the environment is upgraded to the modern template\. The Amazon S3 bucket from the legacy stack is orphaned in the process\. Re\-deploy all AWS CDK applications in the environment at least once before deleting the legacy bucket\. + +## Customizing bootstrapping<a name="bootstrapping-customizing"></a> + +There are two ways to customize the bootstrapping resources\. ++ Use command\-line parameters with the `cdk bootstrap` command\. This lets you modify a few aspects of the template\. ++ Modify the default bootstrap template and deploy it yourself\. This gives you unlimited control over the bootstrap resources\. + +The following command\-line options, when used with CDK Toolkit's cdk bootstrap, provide commonly\-needed adjustments to the bootstrapping template\. ++ \-\-bootstrap\-bucket\-name overrides the name of the Amazon S3 bucket\. May require changes to your CDK app \(see [Stack synthesizers](#bootstrapping-synthesizers)\)\. ++ \-\-bootstrap\-kms\-key\-id overrides the AWS KMS key used to encrypt the S3 bucket\. ++ \-\-tags adds one or more AWS CloudFormation tags to the bootstrap stack\. ++ \-\-termination\-protection prevents the bootstrap stack from being deleted \(see [Protecting a stack from being deleted](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-protect-stacks.html) in the AWS CloudFormation User Guide\) + +The following additional switches are available only with the modern bootstrapping template\. ++ \-\-cloudformation\-execution\-policies specifies the ARNs of managed policies that should be attached to the deployment role assumed by AWS CloudFormation during deployment of your stacks\. By default, stacks are deployed with full administrator privileges using the `AdministratorAccess` policy\. + + The policy ARNs must be passed as a single string argument, with the individual ARNs separated by commas\. For example: + + ``` + --cloudformation-execution-policies "arn:aws:iam::aws:policy/AWSLambda_FullAccess,arn:aws:iam::aws:policy/AWSCodeDeployFullAccess". + ``` +**Important** +To avoid deployment failures, be sure the policies you specify are sufficient for any deployments you will perform in the environment being bootstrapped\. ++ \-\-trust lists the AWS accounts that may deploy into the environment being bootstrapped\. Use this flag when bootstrapping an environment that a CDK Pipeline in another environment will deploy into\. The account doing the bootstrapping is always trusted\. ++ \-\-trust\-for\-lookup lists the AWS accounts that may look up context information from the environment being bootstrapped\. Use this flag to give accounts permission to synthesize stacks that will be deployed into the environment, without actually giving them permission to deploy those stacks directly\. ++ \-\-qualifier a string that is added to the names of all resources in the bootstrap stack\. A qualifier lets you avoid resource name clashes when you provision multiple bootstrap stacks in the same environment using \-\-toolkit\-stack\-name\. The default is `hnb659fds` \(this value has no significance\)\. Changing the qualifier also requires that your CDK app pass the changed value to the stack synthesizer\(see [Stack synthesizers](#bootstrapping-synthesizers)\)\. + +**Important** +The modern bootstrap template effectively grants the permissions implied by the `--cloudformation-execution-policies` to any AWS account in the `--trust` list, which by default will extend permissions to read and write to any resource in the bootstrapped account\. Make sure to [configure the bootstrapping stack](#bootstrapping-customizing) with policies and trusted accounts you are comfortable with\. + +### Customizing the template<a name="bootstrapping-customizing-extended"></a> + +When you need more customization than the AWS CDK Toolkit switches can provide, you can modify the bootstrap template to suit your needs\. Remember that you can obtain the template by using the \-\-show\-template flag\. Optionally, set the CDK\_NEW\_BOOTSTRAP environment variable to get the modern template \(otherwise, you'll get the legacy template\)\. + +------ +#### [ macOS/Linux ] + +``` +export CDK_NEW_BOOTSTRAP=1 +cdk bootstrap --show-template +``` + +------ +#### [ Windows ] + +``` +set CDK_NEW_BOOTSTRAP=1 +powershell "cdk bootstrap --show-template | Out-File -encoding utf8 bootstrap-template.yaml" +``` + +------ + +Any modifications you make must adhere to the [bootstrapping template contract](#bootstrapping-contract)\. + +Deploy your modified template as described in [Bootstrapping from the AWS CloudFormation template](#bootstrapping-howto-cfn), or using cdk bootstrap \-\-template\. + +``` +cdk bootstrap --template bootstrap-template.yaml +``` + +## Stack synthesizers<a name="bootstrapping-synthesizers"></a> + +Your AWS CDK app needs to know about the bootstrapping resources available to it in order to successfully synthesize a stack that can be deployed\. The *stack synthesizer* is an AWS CDK class that controls how the stack's template is synthesized, including how it uses bootstrapping resources \(for example, how it refers to assets stored in the bootstrap bucket\)\. + +The AWS CDK includes two stack synthesizers: ++ `LegacyStackSynthesizer` can be used with either bootstrap template\. \(It requires only an Amazon S3 bucket, and both templates include one\.\) ++ `DefaultStackSynthesizer` requires the modern bootstrap template\. It includes capabilities for cross\-account deployments and [CDK Pipelines](cdk_pipeline.md) deployments\. + +You can pass a stack synthesizer to a stack when you instantiate it using the `synthesizer` property\. + +------ +#### [ TypeScript ] + +``` +new MyStack(this, 'MyStack', { + // stack properties + synthesizer: new DefaultStackSynthesizer({ + // synthesizer properties + }), +}); +``` + +------ +#### [ JavaScript ] + +``` +new MyStack(this, 'MyStack', { + // stack properties + synthesizer: new DefaultStackSynthesizer({ + // synthesizer properties + }), +}); +``` + +------ +#### [ Python ] + +``` +MyStack(self, "MyStack", + # stack properties + synthesizer=DefaultStackSynthesizer( + # synthesizer properties +)) +``` + +------ +#### [ Java ] + + + +``` +new MyStack(app, "MyStack", StackProps.builder() + // stack properties + .synthesizer(DefaultStackSynthesizer.Builder.create() + // synthesizer properties + .build()) + .build(); +``` + +------ +#### [ C\# ] + +``` +new MyStack(app, "MyStack", new StackProps +// stack properties +{ + Synthesizer = new DefaultStackSynthesizer(new DefaultStackSynthesizerProps + { + // synthesizer properties + }) +}); +``` + +------ + +If you don't provide the `synthesizer` property, the default behavior depends on whether the context key `@aws-cdk/core:newStyleStackSynthesis` is set, either in the AWS CDK app's source code or in `cdk.json`\. If it is set, synthesis uses a `DefaultStackSynthesizer`; otherwise, a `LegacyStackSynthesizer` is used\. This is the usual way of choosing a synthesizer unless you have customized the bootstrap template\. + +The most important differences between the two built\-in stack synthesizers are summarized here\. + + +| Feature | LegacyStackSynthesizer | DefaultStackSynthesizer | +| --- | --- | --- | +| Bootstrap stack | Both legacy and modern bootstrap stack | Modern bootstrap stack only | +| Deployments | AWS CDK Toolkit deployments only | AWS CDK Toolkit and CDK Pipelines deployments | +| Assets | Uses AWS CloudFormation parameters to reference assets | Expects assets to be in a predictable location | +| Docker image assets | Creates Amazon ECR repository on demand | Pushes images to Amazon ECR repository provisioned by bootstrapping | +| Roles | Uses AWS CDK Toolkit's current permissions to deploy | Uses roles and permissions provisioned by bootstrapping to deploy | +| Versioning | Not supported | Confirms versions of bootstrapping resources via embedded AWS CloudFormation rule | + +## Customizing synthesis<a name="bootstrapping-custom-synth"></a> + +Depending on the changes you made to the bootstrap template, you may also need to customize synthesis\. The `DefaultStackSynthesizer` can be customized using the properties described below\. If none of these properties provide the customizations you require, you can write your synthesizer as a class that implements `IStackSynthesizer` \(perhaps deriving from `DefaultStackSynthesizer`\)\. + +**Note** +The `LegacyStackSynthesizer` does not offer any customization properties\. + +### Changing the qualifier<a name="bootstrapping-custom-synth-qualifiers"></a> + +The *qualifier* is added to the name of bootstrap resources to distinguish the resources in separate bootstrap stacks\. To deploy two different versions of the bootstrap stack in the same environment \(AWS account and region\), then, the stacks must have different qualifiers\. This feature is intended for name isolation between automated tests of the CDK itself\. Unless you can very precisely scope down the IAM permissions given to the AWS CloudFormation execution role, there are no privilege isolation benefits to having two different bootstrap stacks in a single account, so there is usually no need to change this value\. + +To change the qualifier, configure the `DefaultStackSynthesizer` either by instantiating the synthesizer with the property: + +------ +#### [ TypeScript ] + +``` +new MyStack(this, 'MyStack', { + synthesizer: new DefaultStackSynthesizer({ + qualifier: 'MYQUALIFIER', + }), +}); +``` + +------ +#### [ JavaScript ] + +``` +new MyStack(this, 'MyStack', { + synthesizer: new DefaultStackSynthesizer({ + qualifier: 'MYQUALIFIER', + }), +}) +``` + +------ +#### [ Python ] + +``` +MyStack(self, "MyStack", + synthesizer=DefaultStackSynthesizer( + qualifier="MYQUALIFIER" +)) +``` + +------ +#### [ Java ] + +``` +new MyStack(app, "MyStack", StackProps.builder() + .synthesizer(DefaultStackSynthesizer.Builder.create() + .qualifier("MYQUALIFIER") + .build()) + .build(); +``` + +------ +#### [ C\# ] + +``` +new MyStack(app, "MyStack", new StackProps +{ + Synthesizer = new DefaultStackSynthesizer(new DefaultStackSynthesizerProps + { + Qualifier = "MYQUALIFIER" + }) +}); +``` + +------ + +Or by configuring the qualifier as a context key in `cdk.json`\. + +``` +{ + "app": "...", + "context": { + "@aws-cdk/core:bootstrapQualifier": "MYQUALIFIER" + } +} +``` + +### Changing the resource names<a name="bootstrapping-custom-synth-names"></a> + +All the other `DefaultStackSynthesizer` properties relate to the names of the resources in the modern bootstrapping template\. You only need to provide any of these properties if you modified the bootstrap template and changed the resource names or naming scheme\. + +All properties accept the special placeholders `${Qualifier}`, `${AWS::Partition}`, `${AWS::AccountId}`, and `${AWS::Region}`\. These placeholders are replaced with the values of the `qualifier` parameter and with the values of the AWS partition, account ID, and region for the stack's environment, respectively\. + +The following example shows the most commonly\-used properties for `DefaultStackSynthesizer` along with their default values, as if you were instantiating the synthesizer\. For a complete list, see [DefaultStackSynthesizerProps](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.DefaultStackSynthesizerProps.html#properties)\. + +------ +#### [ TypeScript ] + +``` +new DefaultStackSynthesizer({ + // Name of the S3 bucket for file assets + fileAssetsBucketName: 'cdk-${Qualifier}-assets-${AWS::AccountId}-${AWS::Region}', + bucketPrefix: '', + + // Name of the ECR repository for Docker image assets + imageAssetsRepositoryName: 'cdk-${Qualifier}-container-assets-${AWS::AccountId}-${AWS::Region}', + + // ARN of the role assumed by the CLI and Pipeline to deploy here + deployRoleArn: 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-deploy-role-${AWS::AccountId}-${AWS::Region}', + deployRoleExternalId: '', + + // ARN of the role used for file asset publishing (assumed from the deploy role) + fileAssetPublishingRoleArn: 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-file-publishing-role-${AWS::AccountId}-${AWS::Region}', + fileAssetPublishingExternalId: '', + + // ARN of the role used for Docker asset publishing (assumed from the deploy role) + imageAssetPublishingRoleArn: 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-image-publishing-role-${AWS::AccountId}-${AWS::Region}', + imageAssetPublishingExternalId: '', + + // ARN of the role passed to CloudFormation to execute the deployments + cloudFormationExecutionRole: 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-cfn-exec-role-${AWS::AccountId}-${AWS::Region}', + + // ARN of the role used to look up context information in an environment + lookupRoleArn: 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-lookup-role-${AWS::AccountId}-${AWS::Region}', + lookupRoleExternalId: '', + + // Name of the SSM parameter which describes the bootstrap stack version number + bootstrapStackVersionSsmParameter: '/cdk-bootstrap/${Qualifier}/version', + + // Add a rule to every template which verifies the required bootstrap stack version + generateBootstrapVersionRule: true, + +}) +``` + +------ +#### [ JavaScript ] + +``` +new DefaultStackSynthesizer({ + // Name of the S3 bucket for file assets + fileAssetsBucketName: 'cdk-${Qualifier}-assets-${AWS::AccountId}-${AWS::Region}', + bucketPrefix: '', + + // Name of the ECR repository for Docker image assets + imageAssetsRepositoryName: 'cdk-${Qualifier}-container-assets-${AWS::AccountId}-${AWS::Region}', + + // ARN of the role assumed by the CLI and Pipeline to deploy here + deployRoleArn: 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-deploy-role-${AWS::AccountId}-${AWS::Region}', + deployRoleExternalId: '', + + // ARN of the role used for file asset publishing (assumed from the deploy role) + fileAssetPublishingRoleArn: 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-file-publishing-role-${AWS::AccountId}-${AWS::Region}', + fileAssetPublishingExternalId: '', + + // ARN of the role used for Docker asset publishing (assumed from the deploy role) + imageAssetPublishingRoleArn: 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-image-publishing-role-${AWS::AccountId}-${AWS::Region}', + imageAssetPublishingExternalId: '', + + // ARN of the role passed to CloudFormation to execute the deployments + cloudFormationExecutionRole: 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-cfn-exec-role-${AWS::AccountId}-${AWS::Region}', + + // ARN of the role used to look up context information in an environment + lookupRoleArn: 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-lookup-role-${AWS::AccountId}-${AWS::Region}', + lookupRoleExternalId: '', + + // Name of the SSM parameter which describes the bootstrap stack version number + bootstrapStackVersionSsmParameter: '/cdk-bootstrap/${Qualifier}/version', + + // Add a rule to every template which verifies the required bootstrap stack version + generateBootstrapVersionRule: true, +}) +``` + +------ +#### [ Python ] + +``` +DefaultStackSynthesizer( + # Name of the S3 bucket for file assets + file_assets_bucket_name="cdk-${Qualifier}-assets-${AWS::AccountId}-${AWS::Region}", + bucket_prefix="", + + # Name of the ECR repository for Docker image assets + image_assets_repository_name="cdk-${Qualifier}-container-assets-${AWS::AccountId}-${AWS::Region}", + + # ARN of the role assumed by the CLI and Pipeline to deploy here + deploy_role_arn="arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-deploy-role-${AWS::AccountId}-${AWS::Region}", + deploy_role_external_id="", + + # ARN of the role used for file asset publishing (assumed from the deploy role) + file_asset_publishing_role_arn="arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-file-publishing-role-${AWS::AccountId}-${AWS::Region}", + file_asset_publishing_external_id="", + + # ARN of the role used for Docker asset publishing (assumed from the deploy role) + image_asset_publishing_role_arn="arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-image-publishing-role-${AWS::AccountId}-${AWS::Region}", + image_asset_publishing_external_id="", + + # ARN of the role passed to CloudFormation to execute the deployments + cloud_formation_execution_role="arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + + # ARN of the role used to look up context information in an environment + lookup_role_arn="arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-lookup-role-${AWS::AccountId}-${AWS::Region}", + lookup_role_external_id="", + + # Name of the SSM parameter which describes the bootstrap stack version number + bootstrap_stack_version_ssm_parameter="/cdk-bootstrap/${Qualifier}/version", + + # Add a rule to every template which verifies the required bootstrap stack version + generate_bootstrap_version_rule=True, +) +``` + +------ +#### [ Java ] + +``` +DefaultStackSynthesizer.Builder.create() + // Name of the S3 bucket for file assets + .fileAssetsBucketName("cdk-${Qualifier}-assets-${AWS::AccountId}-${AWS::Region}") + .bucketPrefix('') + + // Name of the ECR repository for Docker image assets + .imageAssetsRepositoryName("cdk-${Qualifier}-container-assets-${AWS::AccountId}-${AWS::Region}") + + // ARN of the role assumed by the CLI and Pipeline to deploy here + .deployRoleArn("arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-deploy-role-${AWS::AccountId}-${AWS::Region}") + .deployRoleExternalId("") + + // ARN of the role used for file asset publishing (assumed from the deploy role) + .fileAssetPublishingRoleArn("arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-file-publishing-role-${AWS::AccountId}-${AWS::Region}") + .fileAssetPublishingExternalId("") + + // ARN of the role used for Docker asset publishing (assumed from the deploy role) + .imageAssetPublishingRoleArn("arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-image-publishing-role-${AWS::AccountId}-${AWS::Region}") + .imageAssetPublishingExternalId("") + + // ARN of the role passed to CloudFormation to execute the deployments + .cloudFormationExecutionRole("arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-cfn-exec-role-${AWS::AccountId}-${AWS::Region}") + + .lookupRoleArn("arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-lookup-role-${AWS::AccountId}-${AWS::Region}") + .lookupRoleExternalId("") + + // Name of the SSM parameter which describes the bootstrap stack version number + .bootstrapStackVersionSsmParameter("/cdk-bootstrap/${Qualifier}/version") + + // Add a rule to every template which verifies the required bootstrap stack version + .generateBootstrapVersionRule(true) +.build() +``` + +------ +#### [ C\# ] + +``` +new DefaultStackSynthesizer(new DefaultStackSynthesizerProps +{ + // Name of the S3 bucket for file assets + FileAssetsBucketName = "cdk-${Qualifier}-assets-${AWS::AccountId}-${AWS::Region}", + BucketPrefix = "", + + // Name of the ECR repository for Docker image assets + ImageAssetsRepositoryName = "cdk-${Qualifier}-container-assets-${AWS::AccountId}-${AWS::Region}", + + // ARN of the role assumed by the CLI and Pipeline to deploy here + DeployRoleArn = "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-deploy-role-${AWS::AccountId}-${AWS::Region}", + DeployRoleExternalId = "", + + // ARN of the role used for file asset publishing (assumed from the deploy role) + FileAssetPublishingRoleArn = "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-file-publishing-role-${AWS::AccountId}-${AWS::Region}", + FileAssetPublishingExternalId = "", + + // ARN of the role used for Docker asset publishing (assumed from the deploy role) + ImageAssetPublishingRoleArn = "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-image-publishing-role-${AWS::AccountId}-${AWS::Region}", + ImageAssetPublishingExternalId = "", + + // ARN of the role passed to CloudFormation to execute the deployments + CloudFormationExecutionRole = "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + + LookupRoleArn = "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-lookup-role-${AWS::AccountId}-${AWS::Region}", + LookupRoleExternalId = "", + + // Name of the SSM parameter which describes the bootstrap stack version number + BootstrapStackVersionSsmParameter = "/cdk-bootstrap/${Qualifier}/version", + + // Add a rule to every template which verifies the required bootstrap stack version + GenerateBootstrapVersionRule = true, +}) +``` + +------ + +## The bootstrapping template contract<a name="bootstrapping-contract"></a> + +The requirements of the bootstrapping stack depend on the stack synthesizer in use\. If you write your own stack synthesizer, you have complete control of the bootstrap resources that your synthesizer requires and how the synthesizer finds them\. This section describes the expectations that the `DefaultStackSynthesizer` has of the bootstrapping template\. + +### Versioning<a name="bootstrapping-contract-versioning"></a> + +The template should contain a resource to create an SSM parameter with a well\-known name and an output to reflect the template's version\. + +``` +Resources: + CdkBootstrapVersion: + Type: AWS::SSM::Parameter + Properties: + Type: String + Name: + Fn::Sub: '/cdk-bootstrap/${Qualifier}/version' + Value: 4 +Outputs: + BootstrapVersion: + Value: + Fn::GetAtt: [CdkBootstrapVersion, Value] +``` + +### Roles<a name="bootstrapping-contract-roles"></a> + +The `DefaultStackSynthesizer` requires five IAM roles for five different purposes\. If you are not using the default roles, the synthesizer needs to be told the ARNs for the roles you want to use\. The roles are: ++ The *deployment role* is assumed by the AWS CDK Toolkit and by AWS CodePipeline to deploy into an environment\. Its `AssumeRolePolicy` controls who can deploy into the environment\. The permissions this role needs can be seen in the template\. ++ The *lookup role* is assumed by the AWS CDK Toolkit to perform context lookups in an environment\. Its `AssumeRolePolicy` controls who can deploy into the environment\. The permissions this role needs can be seen in the template\. ++ The *file publishing role* and the *image publishing role* are assumed by the AWS CDK Toolkit and by AWS CodeBuild projects to publish assets into an environment: that is, to write to the S3 bucket and the ECR repository, respectively\. These roles require write access to these resources\. ++ *The AWS CloudFormation execution role* is passed to AWS CloudFormation to perform the actual deployment\. Its permissions are the permissions that the deployment will execute under\. The permissions are passed to the stack as a parameter that lists managed policy ARNs\. + +### Outputs<a name="bootstrapping-contract-outputs"></a> + +The AWS CDK Toolkit requires that the following CloudFormation outputs exist on the bootstrap stack\. ++ `BucketName`: the name of the file asset bucket ++ `BucketDomainName`: the file asset bucket in domain name format ++ `BootstrapVersion`: the current version of the bootstrap stack + +### Template history<a name="bootstrap-template-history"></a> + +The bootstrap template is versioned and evolves over time with the AWS CDK itself\. If you provide your own bootstrap template, keep it up\-to\-date with the canonical default template to ensure that yours continues to work with all CDK features\. This section contains a list of the changes made in each version\. + + +| Template version | AWS CDK version | Changes | +| --- | --- | --- | +| 1 | 1\.40\.0 | Initial version of template with Bucket, Key, Repository and Roles\. | +| 2 | 1\.45\.0 | Split asset publishing role into separate file and image publishing roles\. | +| 3 | 1\.46\.0 | Add FileAssetKeyArn export to be able to add decrypt permissions to asset consumers\. | +| 4 | 1\.61\.0 | KMS permissions are now implicit via S3 and no longer require FileAsetKeyArn, Add CdkBootstrapVersion SSM parameter so the bootstrap stack version can be verified without knowing the stack name\. | +| 5 | 1\.87\.0 | Deployment role can read SSM parameter\. | +| 6 | 1\.108\.0 | Add lookup role separate from deployment role\. | +| 6 | 1\.109\.0 | Attach aws\-cdk:bootstrap\-role tag to deployment, file publishing, and image publishing roles\. | +| 7 | 1\.110\.0 | Deployment role can no longer read Buckets in the target account directly \(however, this role is effectively an administrator, and could always use its AWS CloudFormation permissions to make the bucket readable anyway\)\. | +| 8 | 1\.114\.0 | The lookup role has full read\-only permissions to the target environment, and has a aws\-cdk:bootstrap\-role tag as well\. | +| 9 | 1\.135\.0 | Fixes S3 asset uploads from being rejected by commonly referenced encryption SCP\. | +| 10 | 1\.139\.0 | ECR ScanOnPush is now enabled by default\. | +| 11 | 1\.150\.0 | Adds policy allowing Lambda to pull from Amazon ECR repos so it survives rebootstrapping\. | +| 12 | 1\.152\.0 | Adds support for experimental cdk import\. | \ No newline at end of file diff --git a/v1/cdk_pipeline.md b/v1/cdk_pipeline.md new file mode 100644 index 00000000..871b270b --- /dev/null +++ b/v1/cdk_pipeline.md @@ -0,0 +1,1493 @@ +# Continuous integration and delivery \(CI/CD\) using CDK Pipelines<a name="cdk_pipeline"></a> + +[CDK Pipelines](https://docs.aws.amazon.com/cdk/api/v1/docs/pipelines-readme.html) is a construct library module for painless continuous delivery of AWS CDK applications\. Whenever you check your AWS CDK app's source code in to AWS CodeCommit, GitHub, or CodeStar, CDK Pipelines can automatically build, test, and deploy your new version\. + +CDK Pipelines are self\-updating: if you add application stages or stacks, the pipeline automatically reconfigures itself to deploy those new stages and/or stacks\. + +**Note** +CDK Pipelines supports two APIs: the original API that was made available in the Developer Preview, and a modern one that incorporates feedback from CDK customers received during the preview phase\. The examples in this topic use the modern API\. For details on the differences between the two supported APIs, see [CDK Pipelines original API](https://github.com/aws/aws-cdk/blob/master/packages/@aws-cdk/pipelines/ORIGINAL_API.md)\. + +## Bootstrap your AWS environments<a name="cdk_pipeline_bootstrap"></a> + +Before you can use CDK Pipelines, you must bootstrap the AWS environment\(s\) to which you will deploy your stacks\. An [environment](environments.md) is an account/region pair to which you want to deploy a CDK stack\. A CDK Pipeline involves at least two environments: the environment where the pipeline is provisioned, and the environment where you want to deploy the application's stacks \(or its stages, which are groups of related stacks\)\. These environments can be the same, though best practices recommend you isolate stages from each other in different AWS accounts or regions\. + +**Note** +See [Bootstrapping](bootstrapping.md) for more information on the kinds of resources created by bootstrapping and how to customize the bootstrap stack\. + +You may have already bootstrapped one or more environments so you can deploy assets and Lambda functions using the AWS CDK\. Continuous deployment with CDK Pipelines requires that the CDK Toolkit stack include additional resources, so the bootstrap stack has been extended to include an additional Amazon S3 bucket, an Amazon ECR repository, and IAM roles to give the various parts of a pipeline the permissions they need\. This new style of CDK Toolkit stack will eventually become the default, but at this writing, you must opt in\. The AWS CDK Toolkit will upgrade your existing bootstrap stack or create a new one, as necessary\. + +To bootstrap an environment that can provision an AWS CDK pipeline, set the environment variable `CDK_NEW_BOOTSTRAP` before invoking `cdk bootstrap`, as shown below\. Invoking the AWS CDK Toolkit via the `npx` command installs it if necessary, and will use the version of the Toolkit installed in the current project if one exists\. + +\-\-cloudformation\-execution\-policies specifies the ARN of a policy under which future CDK Pipelines deployments will execute\. The default `AdministratorAccess` policy ensures that your pipeline can deploy every type of AWS resource\. If you use this policy, make sure you trust all the code and dependencies that make up your AWS CDK app\. + +Most organizations mandate stricter controls on what kinds of resources can be deployed by automation\. Check with the appropriate department within your organization to determine the policy your pipeline should use\. + +You may omit the \-\-profile option if your default AWS profile contains the necessary credentials or to instead use the environment variables `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, and `AWS_DEFAULT_REGION` to provide your AWS account credentials\. + +------ +#### [ macOS/Linux ] + +``` +export CDK_NEW_BOOTSTRAP=1 +npx cdk bootstrap aws://ACCOUNT-NUMBER/REGION --profile ADMIN-PROFILE \ + --cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess +``` + +------ +#### [ Windows ] + +``` +set CDK_NEW_BOOTSTRAP=1 +cdk bootstrap aws://ACCOUNT-NUMBER/REGION --profile ADMIN-PROFILE ^ + --cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess +``` + +------ + +To bootstrap additional environments into which AWS CDK applications will be deployed by the pipeline, use the commands below instead\. The \-\-trust option indicates which other account should have permissions to deploy AWS CDK applications into this environment; specify the pipeline's AWS account ID\. + +Again, you may omit the \-\-profile option if your default AWS profile contains the necessary credentials or if you are using the `AWS_*` environment variables to provide your AWS account credentials\. + +------ +#### [ macOS/Linux ] + +``` +export CDK_NEW_BOOTSTRAP=1 +cdk bootstrap aws://ACCOUNT-NUMBER/REGION --profile ADMIN-PROFILE \ + --cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess \ + --trust PIPELINE-ACCOUNT-NUMBER +``` + +------ +#### [ Windows ] + +``` +set CDK_NEW_BOOTSTRAP=1 +cdk bootstrap aws://ACCOUNT-NUMBER/REGION --profile ADMIN-PROFILE ^ + --cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess ^ + --trust PIPELINE-ACCOUNT-NUMBER +``` + +------ + +**Tip** +Use administrative credentials only to bootstrap and to provision the initial pipeline\. Afterward, use the pipeline itself, not your local machine, to deploy changes\. + +If you are upgrading a legacy\-bootstrapped environment, the old Amazon S3 bucket is orphaned when the new bucket is created\. Delete it manually using the Amazon S3 console\. + +## Initialize project<a name="cdk_pipeline_init"></a> + +Create a new, empty GitHub project and clone it to your workstation in the `my-pipeline` directory\. \(Our code examples in this topic use GitHub; you can also use CodeStar or AWS CodeCommit\.\) + +``` +git clone GITHUB-CLONE-URL my-pipeline +cd my-pipeline +``` + +**Note** +You may use a name other than `my-pipeline` for your app's main directory, but since the AWS CDK Toolkit bases some file and class names on the name of the main directory, you'll need to tweak these later in this topic\. + +After cloning, initialize the project as usual\. + +------ +#### [ TypeScript ] + +``` +cdk init app --language typescript +``` + +------ +#### [ JavaScript ] + +``` +cdk init app --language javascript +``` + +------ +#### [ Python ] + +``` +cdk init app --language python +``` + +After the app has been created, also enter the following two commands to activate the app's Python virtual environment and install the AWS CDK core dependencies\. + +``` +source .venv/bin/activate +python -m pip install -r requirements.txt +``` + +------ +#### [ Java ] + +``` +cdk init app --language java +``` + +If you are using an IDE, you can now open or import the project\. In Eclipse, for example, choose **File** > **Import** > **Maven** > **Existing Maven Projects**\. Make sure that the project settings are set to use Java 8 \(1\.8\)\. + +------ +#### [ C\# ] + +``` +cdk init app --language csharp +``` + +If you are using Visual Studio, open the solution file in the `src` directory\. + +------ + +Install the CDK Pipelines module along with any others you'll be using\. + +**Important** +Be sure to commit your `cdk.json` and `cdk.context.json` files to source control\. The context information \(such as feature flags and cached values retrieved from your AWS account\) are part of your project's state\. The values may be different in another environment, which can cause unexpected changes in your results\. For more information, see [Runtime context](context.md)\. + +------ +#### [ TypeScript ] + +``` +npm install @aws-cdk/pipelines @aws-cdk/aws-lambda +``` + +------ +#### [ JavaScript ] + +``` +npm install @aws-cdk/pipelines @aws-cdk/aws-lambda +``` + +------ +#### [ Python ] + +``` +python -m pip install aws_cdk.pipelines aws_cdk.aws_lambda +``` + +Add the project's dependencies to `requirements.txt` so they can be installed in the CI/CD environment\. It is convenient to use `pip freeze` for this\. + +**macOS/Linux** + +``` +python -m pip freeze | grep -v '^[-#]' > requirements.txt +``` + +**Windows** + +``` +python -m pip freeze | findstr /R /B /V "[-#]" > requirements.txt +``` + +------ +#### [ Java ] + +Edit your project's `pom.xml` and add a `<dependency>` element for the `pipeline` module and the others you'll need\. Follow the template below for each module, placing each inside the existing `<dependencies>` container\. + +``` +<dependency> + <groupId>software.amazon.awscdk</groupId> + <artifactId>cdk-pipelines</artifactId> + <version>${cdk.version}</version> +</dependency> +<dependency> + <groupId>software.amazon.awscdk</groupId> + <artifactId>lambda</artifactId> + <version>${cdk.version}</version> +</dependency> +``` + +After updating `pom.xml`, issue `mvn package` to install the new modules\. + +------ +#### [ C\# ] + +In Visual Studio, choose **Tools** > **NuGet Package Manager** > **Manage NuGet Packages for Solution** in Visual Studio and add the following packages\. + +``` +Amazon.CDK.Pipelines +Amazon.CDK.AWS.Lambda +``` + +------ + +Finally, add the `@aws-cdk/core:newStyleStackSynthesis` [feature flag](featureflags.md) to the new project's `cdk.json` file\. The file will already contain some context values; add this new one inside the `context` object if it's not already there\. + +``` +{ + ... + "context": { + ... + "@aws-cdk/core:newStyleStackSynthesis": true + } +} +``` + +In a future release of the AWS CDK, "new style" stack synthesis will become the default, but for now we need to opt in using the feature flag\. + +## Define a pipeline<a name="cdk_pipeline_define"></a> + +Your CDK Pipelines application will include at least two stacks: one that represents the pipeline itself, and one or more stacks that represent the application deployed through it\. Stacks can also be grouped into *stages*, which you can use to deploy copies of infrastructure stacks to different environments\. For now, we'll consider the pipeline, and later delve into the application it will deploy\. + +The construct [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_pipelines.CodePipeline.html](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_pipelines.CodePipeline.html) is the construct that represents a CDK Pipeline that uses AWS CodePipeline as its deployment engine\. When you instantiate `CodePipeline` in a stack, you define the source location for the pipeline \(e\.g\. a GitHub repository\) and the commands to build the app\. For example, the following defines a pipeline whose source is stored in a GitHub repository, and includes a build step for a TypeScript CDK application\. Fill in the information about your GitHub repo where indicated\. + +**Note** +By default, the pipeline authenticates to GitHub using a personal access token stored in Secrets Manager under the name `github-token`\. + +You'll also need to update the instantiation of the pipeline stack to specify the AWS account and region\. + +------ +#### [ TypeScript ] + +In `lib/my-pipeline-stack.ts` \(may vary if your project folder isn't named `my-pipeline`\): + +``` +import * as cdk from '@aws-cdk/core'; +import { CodePipeline, CodePipelineSource, ShellStep } from '@aws-cdk/pipelines'; + +export class MyPipelineStack extends cdk.Stack { + constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { + super(scope, id, props); + + const pipeline = new CodePipeline(this, 'Pipeline', { + pipelineName: 'MyPipeline', + synth: new ShellStep('Synth', { + input: CodePipelineSource.gitHub('OWNER/REPO', 'main'), + commands: ['npm ci', 'npm run build', 'npx cdk synth'] + }) + }); + } +} +``` + +In `bin/my-pipeline.ts` \(may vary if your project folder isn't named `my-pipeline`\): + +``` +#!/usr/bin/env node +import 'source-map-support/register'; +import * as cdk from '@aws-cdk/core'; +import { MyPipelineStack } from '../lib/my-pipeline-stack'; + +const app = new cdk.App(); +new MyPipelineStack(app, 'MyPipelineStack', { + env: { + account: '111111111111', + region: 'eu-west-1', + } +}); + +app.synth(); +``` + +------ +#### [ JavaScript ] + +In `lib/my-pipeline-stack.js` \(may vary if your project folder isn't named `my-pipeline`\): + +``` +const cdk = require('@aws-cdk/core'); +const { CodePipeline, CodePipelineSource, ShellStep } = require('@aws-cdk/pipelines'); + + class MyPipelineStack extends cdk.Stack { + constructor(scope, id, props) { + super(scope, id, props); + + const pipeline = new CodePipeline(this, 'Pipeline', { + pipelineName: 'MyPipeline', + synth: new ShellStep('Synth', { + input: CodePipelineSource.gitHub('OWNER/REPO', 'main'), + commands: ['npm ci', 'npm run build', 'npx cdk synth'] + }) + }); + } +} + +module.exports = { MyPipelineStack } +``` + +In `bin/my-pipeline.js` \(may vary if your project folder isn't named `my-pipeline`\): + +``` +#!/usr/bin/env node + +const cdk = require('@aws-cdk/core'); +const { MyPipelineStack } = require('../lib/my-pipeline-stack'); + +const app = new cdk.App(); +new MyPipelineStack(app, 'MyPipelineStack', { + env: { + account: '111111111111', + region: 'eu-west-1', + } +}); + +app.synth(); +``` + +------ +#### [ Python ] + +In `my-pipeline/my-pipeline-stack.py` \(may vary if your project folder isn't named `my-pipeline`\): + +``` +from aws_cdk import core as cdk +from aws_cdk.pipelines import CodePipeline, CodePipelineSource, ShellStep + +class MyPipelineStack(cdk.Stack): + + def __init__(self, scope: cdk.Construct, construct_id: str, **kwargs) -> None: + super().__init__(scope, construct_id, **kwargs) + + pipeline = CodePipeline(self, "Pipeline", + pipeline_name="MyPipeline", + synth=ShellStep("Synth", + input=CodePipelineSource.git_hub("OWNER/REPO", "main"), + commands=["npm install -g aws-cdk", + "python -m pip install -r requirements.txt", + "cdk synth"] + ) + ) +``` + +In `app.py`: + +``` +#!/usr/bin/env python3 +from aws_cdk import core as cdk +from my_pipeline.my_pipeline_stack import MyPipelineStack + +app = cdk.App() +MyPipelineStack(app, "MyPipelineStack", + env=cdk.Environment(account="111111111111", region="eu-west-1") +) + +app.synth() +``` + +------ +#### [ Java ] + +In `src/main/java/com/myorg/MyPipelineStack.java` \(may vary if your project folder isn't named `my-pipeline`\): + +``` +package com.myorg; + +import java.util.Arrays; +import software.amazon.awscdk.core.Construct; +import software.amazon.awscdk.core.Stack; +import software.amazon.awscdk.core.StackProps; +import software.amazon.awscdk.pipelines.CodePipeline; +import software.amazon.awscdk.pipelines.CodePipelineSource; +import software.amazon.awscdk.pipelines.ShellStep; + +public class MyPipelineStack extends Stack { + public MyPipelineStack(final Construct scope, final String id) { + this(scope, id, null); + } + + public MyPipelineStack(final Construct scope, final String id, final StackProps props) { + super(scope, id, props); + + CodePipeline pipeline = CodePipeline.Builder.create(this, "pipeline") + .pipelineName("MyPipeline") + .synth(ShellStep.Builder.create("Synth") + .input(CodePipelineSource.gitHub("OWNER/REPO", "main")) + .commands(Arrays.asList("npm install -g aws-cdk", "cdk synth")) + .build()) + .build(); + } +} +``` + +In `src/main/java/com/myorg/MyPipelineApp.java` \(may vary if your project folder isn't named `my-pipeline`\): + +``` +package com.myorg; + +import software.amazon.awscdk.core.App; +import software.amazon.awscdk.core.Environment; +import software.amazon.awscdk.core.StackProps; + +public class MyPipelineApp { + public static void main(final String[] args) { + App app = new App(); + + new MyPipelineStack(app, "PipelineStack", StackProps.builder() + .env(Environment.builder() + .account("111111111111") + .region("eu-west-1") + .build()) + .build()); + + app.synth(); + } +} +``` + +------ +#### [ C\# ] + +In `src/MyPipeline/MyPipelineStack.cs` \(may vary if your project folder isn't named `my-pipeline`\): + +``` +using Amazon.CDK; +using Amazon.CDK.Pipelines; + +namespace MyPipeline +{ + public class MyPipelineStack : Stack + { + internal MyPipelineStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) + { + var pipeline = new CodePipeline(this, "pipeline", new CodePipelineProps + { + PipelineName = "MyPipeline", + Synth = new ShellStep("Synth", new ShellStepProps + { + Input = CodePipelineSource.GitHub("OWNER/REPO", "main"), + Commands = new string[] { "npm install -g aws-cdk", "cdk synth" } + }) + }); + } + } +} +``` + +In `src/MyPipeline/Program.cs` \(may vary if your project folder isn't named `my-pipeline`\): + +``` +using Amazon.CDK; + +namespace MyPipeline +{ + sealed class Program + { + public static void Main(string[] args) + { + var app = new App(); + new MyPipelineStack(app, "MyPipelineStack", new StackProps + { + Env = new Amazon.CDK.Environment { + Account = "111111111111", Region = "eu-west-1" } + }); + + app.Synth(); + } + } +} +``` + +------ + +You must deploy a pipeline manually once\. After that, the pipeline will keep itself up to date from the source code repository, so make sure the code in the repo is the code you want deployed\. Check in your changes and push to GitHub, then deploy: + +``` +git add --all +git commit -m "initial commit" +git push +cdk deploy +``` + +**Tip** +Now that you've done the initial deployment, your local AWS account no longer needs administrative access, because all changes to your app will be deployed via the pipeline\. All you need to be able to do is push to GitHub\. + +## Application stages<a name="cdk_pipeline_stages"></a> + +To define a multi\-stack AWS application that can be added to the pipeline all at once, define a subclass of `[Stage](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.Stage.html)` \(not to be confused with `CdkStage` in the CDK Pipelines module\)\. + +The stage contains the stacks that make up your application\. If there are dependencies between the stacks, the stacks are automatically added to the pipeline in the right order\. Stacks that don't depend on each other are deployed in parallel\. You can add a dependency relationship between stacks by calling `stack1.addDependency(stack2)`\. + +Stages accept a default `env` argument, which becomes the default environment for the stacks inside it\. \(Stacks can still have their own environment specified\.\)\. + +An application is added to the pipeline by calling `[addStage](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_pipelines.CodePipeline.html#addwbrstagestage-options)()` with instances of `Stage`\. A stage can be instantiated and added to the pipeline multiple times to define different stages of your DTAP or multi\-region application pipeline: + +We will create a stack containing a simple Lambda function and place that stack in a stage\. Then we will add the stage to the pipeline so it can be deployed\. + +------ +#### [ TypeScript ] + +Create the new file `lib/my-pipeline-lambda-stack.ts` to hold our application stack containing a Lambda function\. + +``` +import * as cdk from '@aws-cdk/core'; +import { Function, InlineCode, Runtime } from '@aws-cdk/aws-lambda'; + +export class MyLambdaStack extends cdk.Stack { + constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { + super(scope, id, props); + + new Function(this, 'LambdaFunction', { + runtime: Runtime.NODEJS_12_X, + handler: 'index.handler', + code: new InlineCode('exports.handler = _ => "Hello, CDK";') + }); + } +} +``` + +Create the new file `lib/my-pipeline-app-stage.ts` to hold our stage\. + +``` +import * as cdk from '@aws-cdk/core'; +import { MyLambdaStack } from './my-pipeline-lambda-stack'; + +export class MyPipelineAppStage extends cdk.Stage { + + constructor(scope: cdk.Construct, id: string, props?: cdk.StageProps) { + super(scope, id, props); + + const lambdaStack = new MyLambdaStack(this, 'LambdaStack'); + } +} +``` + +Edit `lib/my-pipeline-stack.ts` to add the stage to our pipeline\. + +``` +import * as cdk from '@aws-cdk/core'; +import { CodePipeline, CodePipelineSource, ShellStep } from '@aws-cdk/pipelines'; +import { MyPipelineAppStage } from './my-pipeline-app-stage'; + +export class MyPipelineStack extends cdk.Stack { + constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { + super(scope, id, props); + + const pipeline = new CodePipeline(this, 'Pipeline', { + pipelineName: 'MyPipeline', + synth: new ShellStep('Synth', { + input: CodePipelineSource.gitHub('OWNER/REPO', 'main'), + commands: ['npm ci', 'npm run build', 'npx cdk synth'] + }) + }); + + pipeline.addStage(new MyPipelineAppStage(this, "test", { + env: { account: "111111111111", region: "eu-west-1" } + })); + } +} +``` + +------ +#### [ JavaScript ] + +Create the new file `lib/my-pipeline-lambda-stack.js` to hold our application stack containing a Lambda function\. + +``` +const cdk = require('@aws-cdk/core'); +const { Function, InlineCode, Runtime } = require('@aws-cdk/aws-lambda'); + +class MyLambdaStack extends cdk.Stack { + constructor(scope, id, props) { + super(scope, id, props); + + new Function(this, 'LambdaFunction', { + runtime: Runtime.NODEJS_12_X, + handler: 'index.handler', + code: new InlineCode('exports.handler = _ => "Hello, CDK";') + }); + } +} + +module.exports = { MyLambdaStack } +``` + +Create the new file `lib/my-pipeline-app-stage.js` to hold our stage\. + +``` +const cdk = require('@aws-cdk/core'); +const { MyLambdaStack } = require('./my-pipeline-lambda-stack'); + +class MyPipelineAppStage extends cdk.Stage { + + constructor(scope, id, props) { + super(scope, id, props); + + const lambdaStack = new MyLambdaStack(this, 'LambdaStack'); + } +} + +module.exports = { MyPipelineAppStage }; +``` + +Edit `lib/my-pipeline-stack.ts` to add the stage to our pipeline\. + +``` +const cdk = require('@aws-cdk/core'); +const { CodePipeline, CodePipelineSource, ShellStep } = require('@aws-cdk/pipelines'); +const { MyPipelineAppStage } = require('./my-pipeline-app-stage'); + + class MyPipelineStack extends cdk.Stack { + constructor(scope, id, props) { + super(scope, id, props); + + const pipeline = new CodePipeline(this, 'Pipeline', { + pipelineName: 'MyPipeline', + synth: new ShellStep('Synth', { + input: CodePipelineSource.gitHub('OWNER/REPO', 'main'), + commands: ['npm ci', 'npm run build', 'npx cdk synth'] + }) + }); + + pipeline.addStage(new MyPipelineAppStage(this, "test", { + env: { account: "111111111111", region: "eu-west-1" } + })); + + } +} + +module.exports = { MyPipelineStack } +``` + +------ +#### [ Python ] + +Create the new file `my_pipeline/my_pipeline_lambda_stack.py` to hold our application stack containing a Lambda function\. + +``` +from aws_cdk import core as cdk +from aws_cdk.aws_lambda import Function, InlineCode, Runtime + +class MyLambdaStack(cdk.Stack): + def __init__(self, scope: cdk.Construct, construct_id: str, **kwargs) -> None: + super().__init__(scope, construct_id, **kwargs) + + Function(self, "LambdaFunction", + runtime=Runtime.NODEJS_12_X, + handler="index.handler", + code=InlineCode("exports.handler = _ => 'Hello, CDK';") + ) +``` + +Create the new file `my_pipeline/my_pipeline_app_stage.py` to hold our stage\. + +``` +from aws_cdk import core as cdk +from my_pipeline.my_pipeline_lambda_stack import MyLambdaStack + +class MyPipelineAppStage(cdk.Stage): + def __init__(self, scope: cdk.Construct, construct_id: str, **kwargs) -> None: + super().__init__(scope, construct_id, **kwargs) + + lambdaStack = MyLambdaStack(self, "LambdaStack") +``` + +Edit `my_pipeline/my_pipeline_stack.py` to add the stage to our pipeline\. + +``` +from aws_cdk import core as cdk +from aws_cdk.pipelines import CodePipeline, CodePipelineSource, ShellStep +from my_pipeline.my_pipeline_app_stage import MyPipelineAppStage + +class MyPipelineStack(cdk.Stack): + + def __init__(self, scope: cdk.Construct, construct_id: str, **kwargs) -> None: + super().__init__(scope, construct_id, **kwargs) + + pipeline = CodePipeline(self, "Pipeline", + pipeline_name="MyPipeline", + synth=ShellStep("Synth", + input=CodePipelineSource.git_hub("OWNER/REPO", "main"), + commands=["npm install -g aws-cdk", + "python -m pip install -r requirements.txt", + "cdk synth"])) + + pipeline.add_stage(MyPipelineAppStage(self, "test", + env=cdk.Environment(account="111111111111", region="eu-west-1"))) +``` + +------ +#### [ Java ] + +Create the new file `src/main/java/com.myorg/MyPipelineLambdaStack.java` to hold our application stack containing a Lambda function\. + +``` +package com.myorg; + +import software.amazon.awscdk.core.Construct; +import software.amazon.awscdk.core.Stack; +import software.amazon.awscdk.core.StackProps; + +import software.amazon.awscdk.services.lambda.Function; +import software.amazon.awscdk.services.lambda.Runtime; +import software.amazon.awscdk.services.lambda.InlineCode; + +public class MyPipelineLambdaStack extends Stack { + public MyPipelineLambdaStack(final Construct scope, final String id) { + this(scope, id, null); + } + + public MyPipelineLambdaStack(final Construct scope, final String id, final StackProps props) { + super(scope, id, props); + + Function.Builder.create(this, "LambdaFunction") + .runtime(Runtime.NODEJS_12_X) + .handler("index.handler") + .code(new InlineCode("exports.handler = _ => 'Hello, CDK';")) + .build(); + + } + +} +``` + +Create the new file `src/main/java/com.myorg/MyPipelineAppStage.java` to hold our stage\. + +``` +package com.myorg; + +import software.amazon.awscdk.core.Construct; +import software.amazon.awscdk.core.Stack; +import software.amazon.awscdk.core.Stage; +import software.amazon.awscdk.core.StageProps; + +public class MyPipelineAppStage extends Stage { + public MyPipelineAppStage(final Construct scope, final String id) { + this(scope, id, null); + } + + public MyPipelineAppStage(final Construct scope, final String id, final StageProps props) { + super(scope, id, props); + + Stack lambdaStack = new MyPipelineLambdaStack(this, "LambdaStack"); + } + +} +``` + +Edit `src/main/java/com.myorg/MyPipelineStack.java` to add the stage to our pipeline\. + +``` +package com.myorg; + +import java.util.Arrays; +import software.amazon.awscdk.core.Construct; +import software.amazon.awscdk.core.Environment; +import software.amazon.awscdk.core.Stack; +import software.amazon.awscdk.core.StackProps; +import software.amazon.awscdk.core.StageProps; +import software.amazon.awscdk.pipelines.CodePipeline; +import software.amazon.awscdk.pipelines.CodePipelineSource; +import software.amazon.awscdk.pipelines.ShellStep; + +public class MyPipelineStack extends Stack { + public MyPipelineStack(final Construct scope, final String id) { + this(scope, id, null); + } + + public MyPipelineStack(final Construct scope, final String id, final StackProps props) { + super(scope, id, props); + + final CodePipeline pipeline = CodePipeline.Builder.create(this, "pipeline") + .pipelineName("MyPipeline") + .synth(ShellStep.Builder.create("Synth") + .input(CodePipelineSource.gitHub("OWNER/REPO", "main")) + .commands(Arrays.asList("npm install -g aws-cdk", "cdk synth")) + .build()) + .build(); + + pipeline.addStage(new MyPipelineAppStage(this, "test", StageProps.builder() + .env(Environment.builder() + .account("111111111111") + .region("eu-west-1") + .build()) + .build())); + } +} +``` + +------ +#### [ C\# ] + +Create the new file `src/MyPipeline/MyPipelineLambdaStack.cs` to hold our application stack containing a Lambda function\. + +``` +using Amazon.CDK; +using Amazon.CDK.AWS.Lambda; + +namespace MyPipeline +{ + class MyPipelineLambdaStack : Stack + { + public MyPipelineLambdaStack(Construct scope, string id, StackProps props=null) : base(scope, id, props) + { + new Function(this, "LambdaFunction", new FunctionProps + { + Runtime = Runtime.NODEJS_12_X, + Handler = "index.handler", + Code = new InlineCode("exports.handler = _ => 'Hello, CDK';") + }); + } + } +} +``` + +Create the new file `src/MyPipeline/MyPipelineAppStage.cs` to hold our stage\. + +``` +using Amazon.CDK; + +namespace MyPipeline +{ + class MyPipelineAppStage : Stage + { + public MyPipelineAppStage(Construct scope, string id, StageProps props=null) : base(scope, id, props) + { + Stack lambdaStack = new MyPipelineLambdaStack(this, "LambdaStack"); + } + } +} +``` + +Edit `src/MyPipeline/MyPipelineStack.cs` to add the stage to our pipeline\. + +``` +using Amazon.CDK; +using Amazon.CDK.Pipelines; + +namespace MyPipeline +{ + public class MyPipelineStack : Stack + { + internal MyPipelineStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) + { + var pipeline = new CodePipeline(this, "pipeline", new CodePipelineProps + { + PipelineName = "MyPipeline", + Synth = new ShellStep("Synth", new ShellStepProps + { + Input = CodePipelineSource.GitHub("OWNER/REPO", "main"), + Commands = new string[] { "npm install -g aws-cdk", "cdk synth" } + }) + }); + + pipeline.AddStage(new MyPipelineAppStage(this, "test", new StageProps + { + Env = new Environment + { + Account = "111111111111", Region = "eu-west-1" + } + })); + } + } +} +``` + +------ + +Every application stage added by `addStage()` results in the addition of a corresponding pipeline stage, represented by a [StageDeployment](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_pipelines.StageDeployment.html) instance returned by the `addStage()` call\. You can add pre\-deployment or post\-deployment actions to the stage by calling its `addPre()` or `addPost()` method\. + +------ +#### [ TypeScript ] + +``` +// import { ManualApprovalStep } from '@aws-cdk/pipelines'; + +const testingStage = pipeline.addStage(new MyPipelineAppStage(this, 'testing', { + env: { account: '111111111111', region: 'eu-west-1' } +})); + + testingStage.addPost(new ManualApprovalStep('approval')); +``` + +------ +#### [ JavaScript ] + +``` +// const { ManualApprovalStep } = require('@aws-cdk/pipelines'); + +const testingStage = pipeline.addStage(new MyPipelineAppStage(this, 'testing', { + env: { account: '111111111111', region: 'eu-west-1' } +})); + +testingStage.addPost(new ManualApprovalStep('approval')); +``` + +------ +#### [ Python ] + +``` +# from aws_cdk.pipelines import ManualApprovalStep + +testing_stage = pipeline.add_stage(MyPipelineAppStage(self, "testing", + env=cdk.Environment(account="111111111111", region="eu-west-1"))) + +testing_stage.add_post(ManualApprovalStep('approval')) +``` + +------ +#### [ Java ] + +``` +// import software.amazon.awscdk.pipelines.StageDeployment; +// import software.amazon.awscdk.pipelines.ManualApprovalStep; + +StageDeployment testingStage = + pipeline.addStage(new MyPipelineAppStage(this, "test", StageProps.builder() + .env(Environment.builder() + .account("111111111111") + .region("eu-west-1") + .build()) + .build())); + +testingStage.addPost(new ManualApprovalStep("approval")); +``` + +------ +#### [ C\# ] + +``` +var testingStage = pipeline.AddStage(new MyPipelineAppStage(this, "test", new StageProps +{ + Env = new Environment + { + Account = "111111111111", Region = "eu-west-1" + } +})); + +testingStage.AddPost(new ManualApprovalStep("approval")); +``` + +------ + +You can add stages to a [Wave](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_pipelines.Wave.html) to deploy them in parallel, for example when deploying a stage to multiple accounts or regions\. + +------ +#### [ TypeScript ] + +``` +const wave = pipeline.addWave('wave'); +wave.addStage(new MyApplicationStage(this, 'MyAppEU', { + env: { account: '111111111111', region: 'eu-west-1' } +})); +wave.addStage(new MyApplicationStage(this, 'MyAppUS', { + env: { account: '111111111111', region: 'us-west-1' } +})); +``` + +------ +#### [ JavaScript ] + +``` +const wave = pipeline.addWave('wave'); +wave.addStage(new MyApplicationStage(this, 'MyAppEU', { + env: { account: '111111111111', region: 'eu-west-1' } +})); +wave.addStage(new MyApplicationStage(this, 'MyAppUS', { + env: { account: '111111111111', region: 'us-west-1' } +})); +``` + +------ +#### [ Python ] + +``` +wave = pipeline.add_wave("wave") +wave.add_stage(MyApplicationStage(self, "MyAppEU", + env=cdk.Environment(account="111111111111", region="eu-west-1"))) +wave.add_stage(MyApplicationStage(self, "MyAppUS", + env=cdk.Environment(account="111111111111", region="us-west-1"))) +``` + +------ +#### [ Java ] + +``` +// import software.amazon.awscdk.pipelines.Wave; +final Wave wave = pipeline.addWave("wave"); +wave.addStage(new MyPipelineAppStage(this, "MyAppEU", StageProps.builder() + .env(Environment.builder() + .account("111111111111") + .region("eu-west-1") + .build()) + .build())); +wave.addStage(new MyPipelineAppStage(this, "MyAppUS", StageProps.builder() + .env(Environment.builder() + .account("111111111111") + .region("us-west-1") + .build()) + .build())); +``` + +------ +#### [ C\# ] + +``` +var wave = pipeline.AddWave("wave"); +wave.AddStage(new MyPipelineAppStage(this, "MyAppEU", new StageProps +{ + Env = new Environment + { + Account = "111111111111", Region = "eu-west-1" + } +})); +wave.AddStage(new MyPipelineAppStage(this, "MyAppUS", new StageProps +{ + Env = new Environment + { + Account = "111111111111", Region = "us-west-1" + } +})); +``` + +------ + +## Testing deployments<a name="cdk_pipeline_validation"></a> + +You can add steps to a CDK Pipeline to validate the deployments you are performing\. Using the CDK Pipeline library's `[ShellStep](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_pipelines.ShellStep.html)`, you can try to access a just\-deployed Amazon API Gateway backed by a Lambda function, for example, or issue an AWS CLI command to check some setting of a deployed resource\. + +In its simplest form, adding validation actions looks like this: + +------ +#### [ TypeScript ] + +``` +// stage was returned by pipeline.addStage + +stage.addPost(new ShellStep("validate", { + commands: ['curl -Ssf https://my.webservice.com/'], +})); +``` + +------ +#### [ JavaScript ] + +``` +// stage was returned by pipeline.addStage + +stage.addPost(new ShellStep("validate", { + commands: ['curl -Ssf https://my.webservice.com/'], +})); +``` + +------ +#### [ Python ] + +``` +# stage was returned by pipeline.add_stage + +stage.add_post(ShellStep("validate", + commands=['curl -Ssf https://my.webservice.com/'] +)) +``` + +------ +#### [ Java ] + +``` +// stage was returned by pipeline.addStage + +stage.addPost(ShellStep.Builder.create("validate") + .commands(Arrays.asList("curl -Ssf https://my.webservice.com/")) + .build()); +``` + +------ +#### [ C\# ] + +``` +// stage was returned by pipeline.addStage + +stage.AddPost(new ShellStep("validate", new ShellStepProps +{ + Commands = new string[] { "curl -Ssf https://my.webservice.com/" } +})); +``` + +------ + +Because many AWS CloudFormation deployments result in the generation of resources with unpredictable names, CDK Pipelines provide a way to read AWS CloudFormation outputs after a deployment\. This makes it possible to pass \(for example\) the generated URL of a load balancer to a test action\. + +To use outputs, expose the `CfnOutput` object you're interested in and pass it in a step's `envFromCfnOutputs` property to make it available as an environment variable within that step\. + +------ +#### [ TypeScript ] + +``` +// given a stack lbStack that exposes a load balancer construct as loadBalancer +this.loadBalancerAddress = new cdk.CfnOutput(lbStack, 'LbAddress', { + value: `https://${lbStack.loadBalancer.loadBalancerDnsName}/` +}); + +// pass the load balancer address to a shell step +stage.addPost(new ShellStep("lbaddr", { + envFromCfnOutputs: {lb_addr: lbStack.loadBalancerAddress}, + commands: ['echo $lb_addr'] +})); +``` + +------ +#### [ JavaScript ] + +``` +// given a stack lbStack that exposes a load balancer construct as loadBalancer +this.loadBalancerAddress = new cdk.CfnOutput(lbStack, 'LbAddress', { + value: `https://${lbStack.loadBalancer.loadBalancerDnsName}/` +}); + +// pass the load balancer address to a shell step +stage.addPost(new ShellStep("lbaddr", { + envFromCfnOutputs: {lb_addr: lbStack.loadBalancerAddress}, + commands: ['echo $lb_addr'] +})); +``` + +------ +#### [ Python ] + +``` +# given a stack lb_stack that exposes a load balancer construct as load_balancer +self.load_balancer_address = cdk.CfnOutput(lb_stack, "LbAddress", + value=f"https://{lb_stack.load_balancer.load_balancer_dns_name}/") + +# pass the load balancer address to a shell step +stage.add_post(ShellStep("lbaddr", + env_from_cfn_outputs={"lb_addr": lb_stack.load_balancer_address} + commands=["echo $lb_addr"])) +``` + +------ +#### [ Java ] + +``` +// given a stack lbStack that exposes a load balancer construct as loadBalancer +loadBalancerAddress = CfnOutput.Builder.create(lbStack, "LbAddress") + .value(String.format("https://%s/", + lbStack.loadBalancer.loadBalancerDnsName)) + .build(); + +stage.addPost(ShellStep.Builder.create("lbaddr") + .envFromCfnOutputs( // Map.of requires Java 9 or later + java.util.Map.of("lbAddr", loadBalancerAddress)) + .commands(Arrays.asList("echo $lbAddr")) + .build()); +``` + +------ +#### [ C\# ] + +``` +// given a stack lbStack that exposes a load balancer construct as loadBalancer +loadBalancerAddress = new CfnOutput(lbStack, "LbAddress", new CfnOutputProps +{ + Value = string.Format("https://{0}/", lbStack.loadBalancer.LoadBalancerDnsName) +}); + +stage.AddPost(new ShellStep("lbaddr", new ShellStepProps +{ + EnvFromCfnOutputs = new Dictionary<string, CfnOutput> + { + { "lbAddr", loadBalancerAddress } + }, + Commands = new string[] { "echo $lbAddr" } +})); +``` + +------ + +You can write simple validation tests right in the `ShellStep`, but this approach becomes unwieldy when the test is more than a few lines\. For more complex tests, you can bring additional files \(such as complete shell scripts, or programs in other languages\) into the `ShellStep` via the `inputs` property\. The inputs can be any step that has an output, including a source \(such as a GitHub repo\) or another `ShellStep`\. + +Bringing in files from the source repository is appropriate if the files are directly usable in the test \(for example, if they are themselves executable\)\. In this example, we declare our GitHub repo as `source` \(rather than instantiating it inline as part of the `CodePipeline`\), then pass this fileset to both the pipeline and the validation test\. + +------ +#### [ TypeScript ] + +``` +const source = CodePipelineSource.gitHub('OWNER/REPO', 'main'); + +const pipeline = new CodePipeline(this, 'Pipeline', { + pipelineName: 'MyPipeline', + synth: new ShellStep('Synth', { + input: source, + commands: ['npm ci', 'npm run build', 'npx cdk synth'] + }) +}); + +const stage = pipeline.addStage(new MyPipelineAppStage(this, 'test', { + env: { account: '111111111111', region: 'eu-west-1' } +})); + +stage.addPost(new ShellStep('validate', { + input: source, + commands: ['sh ./tests/validate.sh'] +})); +``` + +------ +#### [ JavaScript ] + +``` +const source = CodePipelineSource.gitHub('OWNER/REPO', 'main'); + +const pipeline = new CodePipeline(this, 'Pipeline', { + pipelineName: 'MyPipeline', + synth: new ShellStep('Synth', { + input: source, + commands: ['npm ci', 'npm run build', 'npx cdk synth'] + }) +}); + +const stage = pipeline.addStage(new MyPipelineAppStage(this, 'test', { + env: { account: '111111111111', region: 'eu-west-1' } +})); + +stage.addPost(new ShellStep('validate', { + input: source, + commands: ['sh ./tests/validate.sh'] +})); +``` + +------ +#### [ Python ] + +``` +source = CodePipelineSource.git_hub("OWNER/REPO", "main") + +pipeline = CodePipeline(self, "Pipeline", + pipeline_name="MyPipeline", + synth=ShellStep("Synth", + input=source, + commands=["npm install -g aws-cdk", + "python -m pip install -r requirements.txt", + "cdk synth"])) + +stage = pipeline.add_stage(MyApplicationStage(self, "test", + env=cdk.Environment(account="111111111111", region="eu-west-1"))) + +stage.add_post(ShellStep("validate", input=source, + commands=["curl -Ssf https://my.webservice.com/"], +)) +``` + +------ +#### [ Java ] + +``` +final CodePipelineSource source = CodePipelineSource.gitHub("OWNER/REPO", "main"); + +final CodePipeline pipeline = CodePipeline.Builder.create(this, "pipeline") + .pipelineName("MyPipeline") + .synth(ShellStep.Builder.create("Synth") + .input(source) + .commands(Arrays.asList("npm install -g aws-cdk", "cdk synth")) + .build()) + .build(); + +final StageDeployment stage = + pipeline.addStage(new MyPipelineAppStage(this, "test", StageProps.builder() + .env(Environment.builder() + .account("111111111111") + .region("eu-west-1") + .build()) + .build())); + +stage.addPost(ShellStep.Builder.create("validate") + .input(source) + .commands(Arrays.asList("sh ./tests/validate.sh")) + .build()); +``` + +------ +#### [ C\# ] + +``` +var source = CodePipelineSource.GitHub("OWNER/REPO", "main"); + +var pipeline = new CodePipeline(this, "pipeline", new CodePipelineProps +{ + PipelineName = "MyPipeline", + Synth = new ShellStep("Synth", new ShellStepProps + { + Input = source, + Commands = new string[] { "npm install -g aws-cdk", "cdk synth" } + }) +}); + +var stage = pipeline.AddStage(new MyPipelineAppStage(this, "test", new StageProps +{ + Env = new Environment + { + Account = "111111111111", Region = "eu-west-1" + } +})); + +stage.AddPost(new ShellStep("validate", new ShellStepProps +{ + Input = source, + Commands = new string[] { "sh ./tests/validate.sh" } +})); +``` + +------ + +Getting the additional files from the synth step is appropriate if your tests need to be compiled, which is done as part of synthesis\. + +------ +#### [ TypeScript ] + +``` +const synthStep = new ShellStep('Synth', { + input: CodePipelineSource.gitHub('OWNER/REPO', 'main'), + commands: ['npm ci', 'npm run build', 'npx cdk synth'], +}); + +const pipeline = new CodePipeline(this, 'Pipeline', { + pipelineName: 'MyPipeline', + synth: synthStep +}); + +const stage = pipeline.addStage(new MyPipelineAppStage(this, 'test', { + env: { account: '111111111111', region: 'eu-west-1' } +})); + +// run a script that was transpiled from TypeScript during synthesis +stage.addPost(new ShellStep('validate', { + input: synthStep, + commands: ['node tests/validate.js'] +})); +``` + +------ +#### [ JavaScript ] + +``` +const synthStep = new ShellStep('Synth', { + input: CodePipelineSource.gitHub('OWNER/REPO', 'main'), + commands: ['npm ci', 'npm run build', 'npx cdk synth'], +}); + +const pipeline = new CodePipeline(this, 'Pipeline', { + pipelineName: 'MyPipeline', + synth: synthStep +}); + +const stage = pipeline.addStage(new MyPipelineAppStage(this, "test", { + env: { account: "111111111111", region: "eu-west-1" } +})); + +// run a script that was transpiled from TypeScript during synthesis +stage.addPost(new ShellStep('validate', { + input: synthStep, + commands: ['node tests/validate.js'] +})); +``` + +------ +#### [ Python ] + +``` +synth_step = ShellStep("Synth", + input=CodePipelineSource.git_hub("OWNER/REPO", "main"), + commands=["npm install -g aws-cdk", + "python -m pip install -r requirements.txt", + "cdk synth"]) + +pipeline = CodePipeline(self, "Pipeline", + pipeline_name="MyPipeline", + synth=synth_step) + +stage = pipeline.add_stage(MyApplicationStage(self, "test", + env=cdk.Environment(account="111111111111", region="eu-west-1"))) + +# run a script that was compiled during synthesis +stage.add_post(ShellStep("validate", + input=synth_step, + commands=["node test/validate.js"], +)) +``` + +------ +#### [ Java ] + +``` +final ShellStep synth = ShellStep.Builder.create("Synth") + .input(CodePipelineSource.gitHub("OWNER/REPO", "main")) + .commands(Arrays.asList("npm install -g aws-cdk", "cdk synth")) + .build(); + +final CodePipeline pipeline = CodePipeline.Builder.create(this, "pipeline") + .pipelineName("MyPipeline") + .synth(synth) + .build(); + +final StageDeployment stage = + pipeline.addStage(new MyPipelineAppStage(this, "test", StageProps.builder() + .env(Environment.builder() + .account("111111111111") + .region("eu-west-1") + .build()) + .build())); + +stage.addPost(ShellStep.Builder.create("validate") + .input(synth) + .commands(Arrays.asList("node ./tests/validate.js")) + .build()); +``` + +------ +#### [ C\# ] + +``` +var synth = new ShellStep("Synth", new ShellStepProps +{ + Input = CodePipelineSource.GitHub("OWNER/REPO", "main"), + Commands = new string[] { "npm install -g aws-cdk", "cdk synth" } +}); + +var pipeline = new CodePipeline(this, "pipeline", new CodePipelineProps +{ + PipelineName = "MyPipeline", + Synth = synth +}); + +var stage = pipeline.AddStage(new MyPipelineAppStage(this, "test", new StageProps +{ + Env = new Environment + { + Account = "111111111111", Region = "eu-west-1" + } +})); + +stage.AddPost(new ShellStep("validate", new ShellStepProps +{ + Input = synth, + Commands = new string[] { "node ./tests/validate.js" } +})); +``` + +------ + +## Security notes<a name="cdk_pipeline_security"></a> + +Any form of continuous delivery has inherent security risks\. Under the AWS [Shared Responsibility Model](https://aws.amazon.com/compliance/shared-responsibility-model/), you are responsible for the security of your information in the AWS cloud\. The CDK Pipelines library gives you a head start by incorporating secure defaults and modeling best practices, but by its very nature a library that needs a high level of access to fulfill its intended purpose cannot assure complete security\. There are many attack vectors outside of AWS and your organization\. + +In particular, keep in mind the following\. ++ Be mindful of the software you depend on\. Vet all third\-party software you run in your pipeline, as it has the ability to change the infrastructure that gets deployed\. ++ Use dependency locking to prevent accidental upgrades\. CDK Pipelines respects `package-lock.json` and `yarn.lock` to ensure your dependencies are the ones you expect\. ++ Credentials for production environments should be short\-lived\. After bootstrapping and initial provisioning, there is no need for developers to have account credentials at all; changes can be deployed through the pipeline\. Eliminate the possibility of credentials leaking by not needing them in the first place\! + +## Troubleshooting<a name="cdk_pipeline_troubleshooting"></a> + +The following issues are commonly encountered while getting started with CDK Pipelines\. + +**Pipeline: Internal Failure** + +``` +CREATE_FAILED | AWS::CodePipeline::Pipeline | Pipeline/Pipeline +Internal Failure +``` + Check your GitHub access token\. It might be missing, or might not have the permissions to access the repository\. + +**Key: Policy contains a statement with one or more invalid principals** + +``` +CREATE_FAILED | AWS::KMS::Key | Pipeline/Pipeline/ArtifactsBucketEncryptionKey +Policy contains a statement with one or more invalid principals. +``` + One of the target environments has not been bootstrapped with the new bootstrap stack\. Make sure all your target environments are bootstrapped\. + +**Stack is in ROLLBACK\_COMPLETE state and can not be updated\.** + +``` +Stack STACK_NAME is in ROLLBACK_COMPLETE state and can not be updated. (Service: +AmazonCloudFormation; Status Code: 400; Error Code: ValidationError; Request +ID: ...) +``` +The stack failed its previous deployment and is in a non\-retryable state\. Delete the stack from the AWS CloudFormation console and retry the deployment\. \ No newline at end of file diff --git a/v1/cfn_layer.md b/v1/cfn_layer.md new file mode 100644 index 00000000..32063e5a --- /dev/null +++ b/v1/cfn_layer.md @@ -0,0 +1,452 @@ +# Abstractions and escape hatches<a name="cfn_layer"></a> + +The AWS CDK lets you describe AWS resources using constructs that operate at varying levels of abstraction\. ++ *Layer 1 \(L1\)* constructs directly represent AWS CloudFormation resources as defined by the CloudFormation specification\. These constructs can be identified via a name beginning with "Cfn," so they are also referred to as "Cfn constructs\." If a resource exists in AWS CloudFormation, it exists in the CDK as a L1 construct\. ++ *Layer 2 \(L2\)* or "curated" constructs are thoughtfully developed to provide a more ergonomic developer experience compared to the L1 construct they're built upon\. In a typical CDK app, L2 constructs are usually the most widely used type\. Often, L2 constructs define additional supporting resources, such as IAM policies, Amazon SNS topics, or AWS KMS keys\. L2 constructs provide sensible defaults, best\-practice security policies, and a more ergonomic developer experience\. ++ *Layer 3 \(L3\)* constructs or *patterns* define entire collections of AWS resources for specific use cases, making it easy to stand up a build pipeline, an Amazon ECS application, or one of many other types of common deployment scenarios\. Because they can constitute complete system designs, or substantial parts of a larger system, L3 constructs are often "opinionated"—they are built around a very particular approach toward solving the problem at hand, and things work out best when you follow their lead\. + +**Tip** +For more details on AWS CDK constructs, see [Constructs](constructs.md)\. + +At the highest level, your AWS CDK application and the stacks in it are themselves abstractions of your entire cloud infrastructure, or significant chunks of it, and may be parameterized to deploy them in different environments or for different needs\. + +Abstractions are powerful tools for designing and implementing cloud applications\. The AWS CDK gives you the power not only to build with its abstractions, but also to create new abstractions\. Using the existing open\-source L2 and L3 constructs as guidance, you can build your own L2 and L3 constructs to reflect your own organization's best practices and opinions\. + +No abstraction is perfect, and even good abstractions cannot cover every possible use case\. While the value of the AWS CDK's model is plain, sometimes you'll come upon a construct that's perfect for your needs—if only you could make a small \(or large\) tweak\. For this reason, the AWS CDK provides ways to "break out" of the construct model, moving to a lower level of abstraction or to a different model entirely\. As their name implies, the CDK's *escape hatches* let you "escape" the AWS CDK paradigm and extend it in ways the AWS CDK designers never anticipated\. Then you can wrap all that in a new construct to hide the underlying complexity and provide a clean API for developers\. + +Some situations in which you'll reach for escape hatches include: ++ An AWS service feature is available through AWS CloudFormation, but there are no L2 constructs for it\. ++ An AWS service feature is available through AWS CloudFormation, and there are L2 constructs for the service, but these don't yet expose the feature\. Because L2 constructs are developed "by hand," they may sometimes lag behind the L1 constructs\. ++ The feature is not yet available through AWS CloudFormation at all\. + +To determine whether a feature is available through AWS CloudFormation, see [AWS Resource and Property Types Reference](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html)\. + +## Using AWS CloudFormation constructs directly<a name="cfn_layer_cfn"></a> + +If there are no L23 classes available for the service, you can fall back to the automatically generated L1 constructs, which map 1:1 onto all available AWS CloudFormation resources and properties\. These resources can be recognized by their name starting with `Cfn`, such as `CfnBucket` or `CfnRole`\. You instantiate them exactly as you would use the equivalent AWS CloudFormation resource\. For more information, see [AWS Resource and Property Types Reference](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html)\. + +For example, to instantiate a low\-level Amazon S3 bucket L1 with analytics enabled, you would write something like the following\. + +------ +#### [ TypeScript ] + +``` +new s3.CfnBucket(this, 'MyBucket', { + analyticsConfigurations: [ + { + id: 'Config', + // ... + } + ] +}); +``` + +------ +#### [ JavaScript ] + +``` +new s3.CfnBucket(this, 'MyBucket', { + analyticsConfigurations: [ + { + id: 'Config' + // ... + } + ] +}); +``` + +------ +#### [ Python ] + +``` +s3.CfnBucket(self, "MyBucket", + analytics_configurations: [ + dict(id="Config", + # ... + ) + ] +) +``` + +------ +#### [ Java ] + +``` +CfnBucket.Builder.create(this, "MyBucket") + .analyticsConfigurations(Arrays.asList(java.util.Map.of( // Java 9 or later + "id", "Config", // ... + ))).build(); +``` + +------ +#### [ C\# ] + +``` +new CfnBucket(this, 'MyBucket', new CfnBucketProps { + AnalyticsConfigurations = new Dictionary<string, string> + { + ["id"] = "Config", + // ... + } +}); +``` + +------ + +In the rare case where you want to define a resource that doesn't have a corresponding `CfnXxx` class, such as a new resource type that hasn't yet been published in the AWS CloudFormation resource specification, you can instantiate the `cdk.CfnResource` directly and specify the resource type and properties\. This is shown in the following example\. + +------ +#### [ TypeScript ] + +``` +new cdk.CfnResource(this, 'MyBucket', { + type: 'AWS::S3::Bucket', + properties: { + // Note the PascalCase here! These are CloudFormation identifiers. + AnalyticsConfigurations: [ + { + Id: 'Config', + // ... + } + ] + } +}); +``` + +------ +#### [ JavaScript ] + +``` +new cdk.CfnResource(this, 'MyBucket', { + type: 'AWS::S3::Bucket', + properties: { + // Note the PascalCase here! These are CloudFormation identifiers. + AnalyticsConfigurations: [ + { + Id: 'Config' + // ... + } + ] + } +}); +``` + +------ +#### [ Python ] + +``` +cdk.CfnResource(self, 'MyBucket', + type="AWS::S3::Bucket", + properties=dict( + # Note the PascalCase here! These are CloudFormation identifiers. + "AnalyticsConfigurations": [ + { + "Id": "Config", + # ... + } + ] + } +) +``` + +------ +#### [ Java ] + +``` +CfnResource.Builder.create(this, "MyBucket") + .type("AWS::S3::Bucket") + .properties(java.util.Map.of( // Map.of requires Java 9 or later + // Note the PascalCase here! These are CloudFormation identifiers + "AnalyticsConfigurations", Arrays.asList( + java.util.Map.of("Id", "Config", // ... + )))) + .build(); +``` + +------ +#### [ C\# ] + +``` +new CfnResource(this, "MyBucket", new CfnResourceProps +{ + Type = "AWS::S3::Bucket", + Properties = new Dictionary<string, object> + { // Note the PascalCase here! These are CloudFormation identifiers + ["AnalyticsConfigurations"] = new Dictionary<string, string>[] + { + new Dictionary<string, string> { + ["Id"] = "Config" + } + } + } +}); +``` + +------ + +For more information, see [AWS Resource and Property Types Reference](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html)\. + +## Modifying the AWS CloudFormation resource behind AWS constructs<a name="cfn_layer_resource"></a> + +If a L2 construct is missing a feature or you are trying to work around an issue, you can modify the L1 construct that is encapsulated by the L2 construct\. + +All L2 constructs contain within them the corresponding L1 construct\. For example, the high\-level `Bucket` construct wraps the low\-level `CfnBucket` construct\. Because the `CfnBucket` corresponds directly to the AWS CloudFormation resource, it exposes all features that are available through AWS CloudFormation\. + +The basic approach to get access to the L1 class is to use `construct.node.defaultChild` \(Python: `default_child`\), cast it to the right type \(if necessary\), and modify its properties\. Again, let's take the example of a `Bucket`\. + +------ +#### [ TypeScript ] + +``` +// Get the CloudFormation resource +const cfnBucket = bucket.node.defaultChild as s3.CfnBucket; + +// Change its properties +cfnBucket.analyticsConfiguration = [ + { + id: 'Config', + // ... + } +]; +``` + +------ +#### [ JavaScript ] + +``` +// Get the CloudFormation resource +const cfnBucket = bucket.node.defaultChild; + +// Change its properties +cfnBucket.analyticsConfiguration = [ + { + id: 'Config' + // ... + } +]; +``` + +------ +#### [ Python ] + +``` +# Get the CloudFormation resource +cfn_bucket = bucket.node.default_child + +# Change its properties +cfn_bucket.analytics_configuration = [ + { + "id": "Config", + # ... + } +] +``` + +------ +#### [ Java ] + +``` +// Get the CloudFormation resource +CfnBucket cfnBucket = (CfnBucket)bucket.getNode().getDefaultChild(); + +cfnBucket.setAnalyticsConfigurations( + Arrays.asList(java.util.Map.of( // Java 9 or later + "Id", "Config", // ... + )); +``` + +------ +#### [ C\# ] + +``` +// Get the CloudFormation resource +var cfnBucket = (CfnBucket)bucket.Node.DefaultChild; + +cfnBucket.AnalyticsConfigurations = new List<object> { + new Dictionary<string, string> + { + ["Id"] = "Config", + // ... + } +}; +``` + +------ + +You can also use this object to change AWS CloudFormation options such as `Metadata` and `UpdatePolicy`\. + +------ +#### [ TypeScript ] + +``` +cfnBucket.cfnOptions.metadata = { + MetadataKey: 'MetadataValue' +}; +``` + +------ +#### [ JavaScript ] + +``` +cfnBucket.cfnOptions.metadata = { + MetadataKey: 'MetadataValue' +}; +``` + +------ +#### [ Python ] + +``` +cfn_bucket.cfn_options.metadata = { + "MetadataKey": "MetadataValue" +} +``` + +------ +#### [ Java ] + +``` +cfnBucket.getCfnOptions().setMetadata(java.util.Map.of( // Java 9+ + "MetadataKey", "Metadatavalue")); +``` + +------ +#### [ C\# ] + +``` +cfnBucket.CfnOptions.Metadata = new Dictionary<string, object> +{ + ["MetadataKey"] = "Metadatavalue" +}; +``` + +------ + +## Raw overrides<a name="cfn_layer_raw"></a> + +If there are properties that are missing from the L1 construct, you can bypass all typing using raw overrides\. This also makes it possible to delete synthesized properties\. + +Use one of the `addOverride` methods \(Python: `add_override`\) methods, as shown in the following example\. + +------ +#### [ TypeScript ] + +``` +// Get the CloudFormation resource +const cfnBucket = bucket.node.defaultChild as s3.CfnBucket; + +// Use dot notation to address inside the resource template fragment +cfnBucket.addOverride('Properties.VersioningConfiguration.Status', 'NewStatus'); +cfnBucket.addDeletionOverride('Properties.VersioningConfiguration.Status'); + +// use index (0 here) to address an element of a list +cfnBucket.addOverride('Properties.Tags.0.Value', 'NewValue'); +cfnBucket.addDeletionOverride('Properties.Tags.0'); + +// addPropertyOverride is a convenience function for paths starting with "Properties." +cfnBucket.addPropertyOverride('VersioningConfiguration.Status', 'NewStatus'); +cfnBucket.addPropertyDeletionOverride('VersioningConfiguration.Status'); +cfnBucket.addPropertyOverride('Tags.0.Value', 'NewValue'); +cfnBucket.addPropertyDeletionOverride('Tags.0'); +``` + +------ +#### [ JavaScript ] + +``` +// Get the CloudFormation resource +const cfnBucket = bucket.node.defaultChild ; + +// Use dot notation to address inside the resource template fragment +cfnBucket.addOverride('Properties.VersioningConfiguration.Status', 'NewStatus'); +cfnBucket.addDeletionOverride('Properties.VersioningConfiguration.Status'); + +// use index (0 here) to address an element of a list +cfnBucket.addOverride('Properties.Tags.0.Value', 'NewValue'); +cfnBucket.addDeletionOverride('Properties.Tags.0'); + +// addPropertyOverride is a convenience function for paths starting with "Properties." +cfnBucket.addPropertyOverride('VersioningConfiguration.Status', 'NewStatus'); +cfnBucket.addPropertyDeletionOverride('VersioningConfiguration.Status'); +cfnBucket.addPropertyOverride('Tags.0.Value', 'NewValue'); +cfnBucket.addPropertyDeletionOverride('Tags.0'); +``` + +------ +#### [ Python ] + +``` +# Get the CloudFormation resource +cfn_bucket = bucket.node.default_child + +# Use dot notation to address inside the resource template fragment +cfn_bucket.add_override("Properties.VersioningConfiguration.Status", "NewStatus") +cfn_bucket.add_deletion_override("Properties.VersioningConfiguration.Status") + +# use index (0 here) to address an element of a list +cfn_bucket.add_override("Properties.Tags.0.Value", "NewValue") +cfn_bucket.add_deletion_override("Properties.Tags.0") + +# addPropertyOverride is a convenience function for paths starting with "Properties." +cfn_bucket.add_property_override("VersioningConfiguration.Status", "NewStatus") +cfn_bucket.add_property_deletion_override("VersioningConfiguration.Status") +cfn_bucket.add_property_override("Tags.0.Value", "NewValue") +cfn_bucket.add_property_deletion_override("Tags.0") +``` + +------ +#### [ Java ] + +``` +// Get the CloudFormation resource +CfnBucket cfnBucket = (CfnBucket)bucket.getNode().getDefaultChild(); + +// Use dot notation to address inside the resource template fragment +cfnBucket.addOverride("Properties.VersioningConfiguration.Status", "NewStatus"); +cfnBucket.addDeletionOverride("Properties.VersioningConfiguration.Status"); + +// use index (0 here) to address an element of a list +cfnBucket.addOverride("Properties.Tags.0.Value", "NewValue"); +cfnBucket.addDeletionOverride("Properties.Tags.0"); + +// addPropertyOverride is a convenience function for paths starting with "Properties." +cfnBucket.addPropertyOverride("VersioningConfiguration.Status", "NewStatus"); +cfnBucket.addPropertyDeletionOverride("VersioningConfiguration.Status"); +cfnBucket.addPropertyOverride("Tags.0.Value", "NewValue"); +cfnBucket.addPropertyDeletionOverride("Tags.0"); +``` + +------ +#### [ C\# ] + +``` +// Get the CloudFormation resource +var cfnBucket = (CfnBucket)bucket.node.defaultChild; + +// Use dot notation to address inside the resource template fragment +cfnBucket.AddOverride("Properties.VersioningConfiguration.Status", "NewStatus"); +cfnBucket.AddDeletionOverride("Properties.VersioningConfiguration.Status"); + +// use index (0 here) to address an element of a list +cfnBucket.AddOverride("Properties.Tags.0.Value", "NewValue"); +cfnBucket.AddDeletionOverride("Properties.Tags.0"); + +// addPropertyOverride is a convenience function for paths starting with "Properties." +cfnBucket.AddPropertyOverride("VersioningConfiguration.Status", "NewStatus"); +cfnBucket.AddPropertyDeletionOverride("VersioningConfiguration.Status"); +cfnBucket.AddPropertyOverride("Tags.0.Value", "NewValue"); +cfnBucket.AddPropertyDeletionOverride("Tags.0"); +``` + +------ + +## Custom resources<a name="cfn_layer_custom"></a> + +If the feature isn't available through AWS CloudFormation, but only through a direct API call, the only solution is to write an AWS CloudFormation Custom Resource to make the API call you need\. Don't worry, the AWS CDK makes it easier to write these, and wrap them up into a regular construct interface, so from another user's perspective the feature feels native\. + +Building a custom resource involves writing a Lambda function that responds to a resource's CREATE, UPDATE and DELETE lifecycle events\. If your custom resource needs to make only a single API call, consider using the [AwsCustomResource](https://github.com/awslabs/aws-cdk/tree/master/packages/%40aws-cdk/custom-resources)\. This makes it possible to perform arbitrary SDK calls during an AWS CloudFormation deployment\. Otherwise, you should write your own Lambda function to perform the work you need to get done\. + +The subject is too broad to completely cover here, but the following links should get you started: ++ [Custom Resources](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-custom-resources.html) ++ [Custom\-Resource Example](https://github.com/aws-samples/aws-cdk-examples/tree/master/typescript/custom-resource/) ++ For a more fully fledged example, see the [DnsValidatedCertificate](https://github.com/awslabs/aws-cdk/blob/master/packages/@aws-cdk/aws-certificatemanager/lib/dns-validated-certificate.ts) class in the CDK standard library\. This is implemented as a custom resource\. \ No newline at end of file diff --git a/v1/cli.md b/v1/cli.md new file mode 100644 index 00000000..c4a6fb69 --- /dev/null +++ b/v1/cli.md @@ -0,0 +1,1007 @@ +# AWS CDK Toolkit \(`cdk` command\)<a name="cli"></a> + +The AWS CDK Toolkit, the CLI command `cdk`, is the primary tool for interacting with your AWS CDK app\. It executes your app, interrogates the application model you defined, and produces and deploys the AWS CloudFormation templates generated by the AWS CDK\. It also provides other features useful for creating and working with AWS CDK projects\. This topic contains information about common use cases of the CDK Toolkit\. + +The AWS CDK Toolkit is installed with the Node Package Manager\. In most cases, we recommend installing it globally\. + +``` +npm install -g aws-cdk@1.x # install latest 1.x version +npm install -g aws-cdk@X.YY.Z # install specific version +``` + +You may also use CDK Toolkit v2\.x with CDK v1\.x projects\. An exception is that CDK Toolkit v2 creates CDK v2 projects\. You cannot create CDK v1 projects while CDK Toolkit v2\.x is installed globally; uninstall the global version and use npx to run the latest 1\.x release\. + +``` +npx aws-cdk@1.x init app --language typescript +``` + +**Tip** +If you regularly work with multiple versions of the AWS CDK, you may want to install a matching version of the AWS CDK Toolkit in individual CDK projects\. TypeScript and JavaScript projects have a local copy of the CDK Toolkit already\. For other languages, omit `-g` from the `npm install` command\. Then use `npx aws-cdk` to invoke cdk; this will run the local version if one exists, falling back to a global version if not\. + +## Toolkit commands<a name="cli-commands"></a> + +All CDK Toolkit commands start with `cdk`, which is followed by a subcommand \(`list`, `synthesize`, `deploy`, etc\.\)\. Some subcommands have a shorter version \(`ls`, `synth`, etc\.\) that is equivalent\. Options and arguments follow the subcommand in any order\. The available commands are summarized here\. + + +| Command | Function | +| --- | --- | +| `cdk list` \(`ls`\) | Lists the stacks in the app | +| `cdk synthesize` \(`synth`\) | Synthesizes and prints the CloudFormation template for the specified stack\(s\) | +| `cdk bootstrap` | Deploys the CDK Toolkit staging stack; see [Bootstrapping](bootstrapping.md) | +| `cdk deploy` | Deploys the specified stack\(s\) | +| `cdk destroy` | Destroys the specified stack\(s\) | +| `cdk diff` | Compares the specified stack and its dependencies with the deployed stack\(s\) or a local CloudFormation template | +| `cdk metadata` | Displays metadata about the specified stack | +| `cdk init` | Creates a new CDK project in the current directory from a specified template | +| `cdk context` | Manages cached context values | +| `cdk docs` \(`doc`\) | Opens the CDK API reference in your browser | +| `cdk doctor` | Checks your CDK project for potential problems | + +For the options available for each command, see [Toolkit reference](#cli-ref) or [Built\-in help](#cli-help)\. + +## Specifying options and their values<a name="cli-options"></a> + +Command line options begin with two hyphens \(`--`\)\. Some frequently\-used options have single\-letter synonyms that begin with a single hyphen \(for example, `--app` has a synonym `-a`\)\. The order of options in an AWS CDK Toolkit command is not important\. + +All options accept a value, which must follow the option name\. The value may be separated from the name by whitespace or by an equals sign `=`\. The following two options are equivalent + +``` +--toolkit-stack-name MyBootstrapStack +--toolkit-stack-name=MyBootstrapStack +``` + +Some options are flags \(Booleans\)\. You may specify `true` or `false` as their value\. If you do not provide a value, the value is taken to be `true`\. You may also prefix the option name with `no-` to imply `false`\. + +``` +# sets staging flag to true +--staging +--staging=true +--staging true + +# sets staging flag to false +--no-staging +--staging=false +--staging false +``` + +A few options, namely `--context`, `--parameters`, `--plugin`, `--tags`, and `--trust`, may be specified more than once to specify multiple values\. These are noted as having `[array]` type in the CDK Toolkit help\. For example: + +``` +cdk bootstrap --tags costCenter=0123 --tags responsibleParty=jdoe +``` + +## Built\-in help<a name="cli-help"></a> + +The AWS CDK Toolkit has integrated help\. You can see general help about the utility and a list of the provided subcommands by issuing: + +``` +cdk --help +``` + +To see help for a particular subcommand, for example `deploy`, specify it before the `--help` flag\. + +``` +cdk deploy --help +``` + +Issue `cdk version` to display the version of the AWS CDK Toolkit\. Provide this information when requesting support\. + +## Version reporting<a name="version_reporting"></a> + +To gain insight into how the AWS CDK is used, the constructs used by AWS CDK applications are collected and reported by using a resource identified as `AWS::CDK::Metadata`\. This resource is added to AWS CloudFormation templates, and can easily be reviewed\. This information can also be used by AWS to identify stacks using a construct with known security or reliability issues, and to contact their users with important information\. + +**Note** +Prior to version 1\.93\.0, the AWS CDK reported the names and versions of the modules loaded during synthesis, rather than the constructs used in the stack\. + +By default, the AWS CDK reports the use of constructs in the following NPM modules that are used in the stack: ++ AWS CDK core module ++ AWS Construct Library modules ++ AWS Solutions Constructs module ++ AWS Render Farm Deployment Kit module + +The `AWS::CDK::Metadata` resource looks something like the following\. + +``` +CDKMetadata: + Type: "AWS::CDK::Metadata" + Properties: + Analytics: "v2:deflate64:H4sIAND9SGAAAzXKSw5AMBAA0L1b2PdzBYnEAdio3RglglY60zQi7u6TWL/XKmNUlxeQSOKwaPTBqrNhwEWU3hGHiCzK0dWWfAxoL/Fd8mvk+QkS/0X6BdjnCdgmOOQKWz+AqqLDt2Y3YMnLYWwAAAA=" +``` + +The `Analytics` property is a gzipped, base64\-encoded, prefix\-encoded list of the constructs present in the stack\. + +To opt out of version reporting, use one of the following methods: ++ Use the cdk command with the \-\-no\-version\-reporting argument to opt out for a single command\. + + ``` + cdk --no-version-reporting synth + ``` + + Remember, the AWS CDK Toolkit synthesizes fresh templates before deploying, so you should also add `--no-version-reporting` to `cdk deploy` commands\. ++ Set versionReporting to **false** in `./cdk.json` or `~/.cdk.json`\. This opts out unless you opt in by specifying `--version-reporting` on an individual command\. + + ``` + { + "app": "...", + "versionReporting": false + } + ``` + +## Specifying credentials and region<a name="cli-environment"></a> + +The CDK Toolkit needs to know your AWS account credentials and the AWS region into which you are deploying, not only for deployment operations but also to retrieve context values during synthesis\. Together, your account and region make up the *environment*\. + +**Important** +We strongly recommend against using your main AWS account for day\-to\-day tasks\. Instead, create a user in IAM and use its credentials with the CDK\. + +Credentials and region may be specified using environment variables or in configuration files\. These are the same variables and files used by other AWS tools such as the AWS CLI and the various AWS SDKs\. The CDK Toolkit looks for this information in the following order\. ++ The `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, and `AWS_DEFAULT_REGION` environment variables\. Always specify all three variables, not just one or two\. ++ A specific profile defined in the standard AWS `config` and `credentials` files, and specified using the `--profile` option on `cdk` commands\. ++ The `[default]` section of the standard AWS `config` and `credentials` files\. + +**Note** +The standard AWS `config` and `credentials` files are located at `~/.aws/config` and `~/.aws/credentials` \(macOS/Linux\) or `%USERPROFILE%\.aws\config` and `%USERPROFILE%\.aws\credentials` \(Windows\)\. + +The environment specified in your AWS CDK app using the stack's `env` property is used during synthesis to generate an environment\-specific AWS CloudFormation template and during deployment to override the account or region specified by one of the above methods\. For more information, see [Environments](environments.md)\. + +If you have the AWS CLI installed, the easiest way to configure your account credentials and a default region is to issue the following command: + +``` +aws configure +``` + +Provide your AWS access key ID, secret access key, and default region when prompted\. These values are written to the `[default]` section of the `config` and `credentials` files\. + +If you don't have the AWS CLI installed, you can manually create or edit the `config` and `credentials` files to contain default credentials and a default region, in the following format\. ++ In `~/.aws/config` or `%USERPROFILE%\.aws\config` + + ``` + [default] + region=us-west-2 + ``` ++ In `~/.aws/credentials` or `%USERPROFILE%\.aws\credentials` + + ``` + [default] + aws_access_key_id=AKIAI44QH8DHBEXAMPLE + aws_secret_access_key=je7MtGbClwBF/2Zp9Utk/h3yCo8nvbEXAMPLEKEY + ``` + +Besides specifying AWS credentials and a region in the `[default]` section, you can also add one or more `[profile NAME]` sections, where *NAME* is the name of the profile\. ++ In `~/.aws/config` or `%USERPROFILE%\.aws\config` + + ``` + [profile test] + region=us-east-1 + + [profile prod] + region=us-west-1 + ``` ++ In `~/.aws/credentials` or `%USERPROFILE%\.aws\credentials` + + ``` + [profile test] + aws_access_key_id=AKIAI44QH8DHBEXAMPLE + aws_secret_access_key=je7MtGbClwBF/2Zp9Utk/h3yCo8nvbEXAMPLEKEY + + [profile test] + aws_access_key_id=AKIAI44QH8DHBEXAMPLE + aws_secret_access_key=je7MtGbClwBF/2Zp9Utk/h3yCo8nvbEXAMPLEKEY + ``` + +Always add named profiles to both the `config` and `credentials` files\. The AWS CDK Toolkit does not fall back to using the region in the `[default]` section when the specified named profile is not found in the `config` file, as some other AWS tools do\. + +**Important** +Do not name a profile `default`: that is, do not use a `[profile default]` section in either `config` or `credentials`\. + +**Note** +Although the AWS CDK uses credentials from the same sources files as other AWS tools and SDKs, including the [AWS Command Line Interface](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html), it may behave slightly differently from these tools\. See [Setting credentials](https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/setting-credentials.html) for complete details on setting up credentials for the AWS SDK for JavaScript, which the AWS CDK uses under the hood\. + +You may optionally use the `--role-arn` \(or `-r`\) option to specify the ARN of an IAM role that should be used for deployment\. This role must be assumable by the AWS account being used\. + +## Specifying the app command<a name="cli-app-command"></a> + +Many features of the CDK Toolkit require one or more AWS CloudFormation templates be synthesized, which in turn requires running your application\. Since the AWS CDK supports programs written in a variety of languages, it uses a configuration option to specify the exact command necessary to run your app\. This option can be specified in two ways\. + +First, and most commonly, it can be specified using the `app` key inside the file `cdk.json`, which is in the main directory of your AWS CDK project\. The CDK Toolkit provides an appropriate command when creating a new project with `cdk init`\. Here is the `cdk.json` from a fresh TypeScript project, for instance\. + +``` +{ + "app": "npx ts-node bin/hello-cdk.ts" +} +``` + +The CDK Toolkit looks for `cdk.json` in the current working directory when attempting to run your app, so you might keep a shell open in your project's main directory for issuing CDK Toolkit commands\. + +The CDK Toolkit also looks for the app key in `~/.cdk.json` \(that is, in your home directory\) if it can't find it in `./cdk.json`\. Adding the app command here can be useful if you usually work with CDK code in the same language\. + +If you are in some other directory, or if you want to run your app via a command other than the one in `cdk.json`, you can use the `--app` \(or `-a`\) option to specify it\. + +``` +cdk --app "npx ts-node bin/hello-cdk.ts" ls +``` + +When deploying, you may also specify a directory containing synthesized cloud assemblies, such as `cdk.out`, as the value of \-\-app\. The specified stacks are deployed from this directory; the app is not synthesized\. + +## Specifying stacks<a name="cli-stacks"></a> + +Many CDK Toolkit commands \(for example, `cdk deploy`\) work on stacks defined in your app\. If your app contains only one stack, the CDK Toolkit assumes you mean that one if you don't specify a stack explicitly\. + +Otherwise, you must specify the stack or stacks you want to work with\. You can do this by specifying the desired stacks by ID individually on the command line\. Recall that the ID is the value specified by the second argument when you instantiate the stack\. + +``` +cdk synth PipelineStack LambdaStack +``` + +You may also use wildcards to specify IDs that match a pattern\. ++ `?` matches any single character ++ `*` matches any number of characters \(`*` alone matches all stacks\) ++ `**` matches everything in a hierarchy + +You may also use the \-\-all option to specify all stacks\. + +If your app uses [CDK Pipelines](cdk_pipeline.md), the CDK Toolkit understands your stacks and stages as a hierarchy, and the \-\-all option and the `*` wildcard only match top\-level stacks\. To match all the stacks, use `**`\. Also use `**` to indicate all the stacks under a particular hierarchy\. + +When using wildcards, enclose the pattern in quotes, or escape the wildcards with `\`\. If you don't, your shell may try to expand the pattern to the names of files in the current directory\. At best, this won't do what you expect; at worst, you could deploy stacks you didn't intend to\. This isn't strictly necessary on Windows because `cmd.exe` does not expand wildcards, but is good practice nonetheless\. + +``` +cdk synth "*Stack" # PipelineStack, LambdaStack, etc. +cdk synth 'Stack?' # StackA, StackB, Stack1, etc. +cdk synth \* # All stacks in the app, or all top-level stacks in a CDK Pipelines app +cdk synth '**' # All stacks in a CDK Pipelines app +cdk synth 'PipelineStack/Prod/**' # All stacks in Prod stage in a CDK Pipelines app +``` + +**Note** +The order in which you specify the stacks is not necessarily the order in which they will be processed\. The AWS CDK Toolkit takes into account dependencies between stacks when deciding the order in which to process them\. For example, if one stack uses a value produced by another \(such as the ARN of a resource defined in the second stack\), the second stack is synthesized before the first one because of this dependency\. You can add dependencies between stacks manually using the stack's [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.Stack.html#addwbrdependencytarget-reason](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.Stack.html#addwbrdependencytarget-reason) method\. + +## Bootstrapping your AWS environment<a name="cli-bootstrap"></a> + +Deploying stacks that contain [assets](assets.md), synthesize to large templates, or use [CDK Pipelines](cdk_pipeline.md) require special dedicated AWS CDK resources to be provisioned\. The `cdk bootstrap` command creates the necessary resources for you\. You only need to bootstrap if you are deploying a stack that requires these dedicated resources\. See [Bootstrapping](bootstrapping.md) for details\. + +``` +cdk bootstrap +``` + +If issued with no arguments, as shown here, the `cdk bootstrap` command synthesizes the current app and bootstraps the environments its stacks will be deployed to\. If the app contains environment\-agnostic stacks, which do not explicitly specify an environment so they can be deployed anywhere, the default account and region are bootstrapped, or the environment specified using `--profile`\. + +Outside of an app, you must explicitly specify the environment to be bootstrapped\. You may also do so to bootstrap an environment that's not specified in your app or local AWS profile\. Credentials must be configured \(e\.g\. in `~/.aws/credentials`\) for the specified account and region\. You may specify a profile that contains the required credentials\. + +``` +cdk bootstrap ACCOUNT-NUMBER/REGION # e.g. +cdk bootstrap 1111111111/us-east-1 +cdk bootstrap --profile test 1111111111/us-east-1 +``` + +**Important** +Each environment \(account/region combination\) to which you deploy such a stack must be bootstrapped separately\. + +You may incur AWS charges for what the AWS CDK stores in the bootstrapped resources\. Additionally, if you use `-bootstrap-customer-key`, a Customer Master Key \(CMK\) will be created, which also incurs charges per environment\. + +**Note** +Older versions of the modern template created a Customer Master Key by default\. To avoid charges, re\-bootstrap using `--no-bootstrap-customer-key`\. + +The CDK Toolkit supports two bootstrap templates: the modern template and the legacy template\. The legacy template is the default, but the modern template is required by CDK Pipelines\. For more information, see [Bootstrapping](bootstrapping.md)\. + +**Important** +The modern bootstrap template effectively grants the permissions implied by the `--cloudformation-execution-policies` to any AWS account in the `--trust` list, which by default will extend permissions to read and write to any resource in the bootstrapped account\. Make sure to [configure the bootstrapping stack](bootstrapping.md#bootstrapping-customizing) with policies and trusted accounts you are comfortable with\. + +## Creating a new app<a name="cli-init"></a> + +To create a new app, create a directory for it, then, inside the directory, issue `cdk init`\. + +``` +mkdir my-cdk-app +cd my-cdk-app +cdk init TEMPLATE --language LANGUAGE +``` + +**Tip** +If you have installed CDK Toolkit v2 globally, cdk init creates CDK v2 projects\. To avoid this, see [CDK Toolkit v2 compatibility](work-with-cdk-v2.md#work-with-cdk-v2-cli)\. + +The supported languages \(*LANGUAGE*\) are: + + +| Code | Language | +| --- | --- | +| `typescript` | TypeScript | +| `javascript` | JavaScript | +| `python` | Python | +| `java` | Java | +| `csharp` | C\# | + +*TEMPLATE* is an optional template\. If the desired template is *app*, the default, you may omit it\. The available templates are: + + +| Template | Description | +| --- | --- | +| `app` \(default\) | Creates an empty AWS CDK app\. | +| `sample-app` | Creates an AWS CDK app with a stack containing an Amazon SQS queue and an Amazon SNS topic\. | + +The templates use the name of the project folder to generate names for files and classes inside your new app\. + +## Listing stacks<a name="cli-list"></a> + +To see a list of the IDs of the stacks in your AWS CDK application, enter one of the following equivalent commands: + +``` +cdk list +cdk ls +``` + +If your application contains [CDK Pipelines](cdk_pipeline.md) stacks, the CDK Toolkit displays stack names as paths according to their location in the pipeline hierarchy \(e\.g\., `PipelineStack`, `PipelineStack/Prod`, `PipelineStack/Prod/MyService`, etc\)\. + +If your app contains many stacks, you can specify full or partial stack IDs of the stacks to be listed; see [Specifying stacks](#cli-stacks)\. + +Add the `--long` flag to see more information about the stacks, including the stack names and their environments \(AWS account and region\)\. + +## Synthesizing stacks<a name="cli-synth"></a> + +The `cdk synthesize` command \(almost always abbreviated `synth`\) synthesizes a stack defined in your app into a CloudFormation template\. + +``` +cdk synth # if app contains only one stack +cdk synth MyStack +cdk synth Stack1 Stack2 +cdk synth "*" # all stacks in app +``` + +**Note** +The CDK Toolkit actually runs your app and synthesizes fresh templates before most operations \(e\.g\. when deploying or comparing stacks\)\. These templates are stored by default in the `cdk.out` directory\. The `cdk synth` command simply prints the generated templates for the specified stack\(s\)\. + +See `cdk synth --help` for all available options\. A few of the most\-frequently\-used options are covered below\. + +### Specifying context values<a name="w55aac33b7c35c11"></a> + +Use the `--context` or `-c` option to pass [runtime context](context.md) values to your CDK app\. + +``` +# specify a single context value +cdk synth --context key=value MyStack + +# specify multiple context values (any number) +cdk synth --context key1=value1 --context key2=value2 MyStack +``` + +When deploying multiple stacks, the specified context values are normally passed to all of them\. If you wish, you may specify different values for each stack by prefixing the stack name to the context value\. + +``` +# different context values for each stack +cdk synth --context Stack1:key=value Stack2:key=value Stack1 Stack2 +``` + +### Specifying display format<a name="w55aac33b7c35c13"></a> + +By default, the synthesized template is displayed in YAML format\. Add the `--json` flag to display it in JSON format instead\. + +``` +cdk synth --json MyStack +``` + +### Specifying output directory<a name="w55aac33b7c35c15"></a> + +Add the `--output` \(`-o`\) option to write the synthesized templates to a directory other than `cdk.out`\. + +``` +cdk synth --output=~/templates +``` + +## Deploying stacks<a name="cli-deploy"></a> + +The `cdk deploy` subcommand deploys the specified stack\(s\) to your AWS account\. + +``` +cdk deploy # if app contains only one stack +cdk deploy MyStack +cdk deploy Stack1 Stack2 +cdk deploy "*" # all stacks in app +``` + +**Note** +The CDK Toolkit runs your app and synthesizes fresh AWS CloudFormation templates before deploying anything\. Therefore, most command line options you can use with `cdk synth` \(for example, `--context`\) can also be used with `cdk deploy`\. + +See `cdk deploy --help` for all available options\. A few of the most useful options are covered below\. + +### Skipping synthesis<a name="cli-deploy-nosynth"></a> + +The cdk deploy command normally synthesizes your app's stacks before deploying to make sure the deployment reflects the latest version of your app\. If you know that you haven't made any changes to your code since your last cdk synth, you may suppress the redundant synthesis step when deploying\. Simply specify your project's `cdk.out` directory in the \-\-app option\. + +``` +cdk deploy --app cdk.out StackOne StackTwo +``` + +### Disabling rollback<a name="cli-deploy-norollback"></a> + +One of AWS CloudFormation's marquee features is its ability to roll back changes so that deployments are atomic—they either succeed or fail as a whole\. The AWS CDK inherits this capability because it synthesizes and deploys AWS CloudFormation templates\. + +Rollback makes sure your resources are in a consistent state at all times, which is vital for production stacks\. However, while you're still developing your infrastructure, some failures are inevitable, and rolling back failed deployments just slows you down\. + +For this reason, the CDK Toolkit allows you to disable rollback by adding `--no-rollback` to your `cdk deploy` command\. With this flag, failed deployments are not rolled back\. Instead, resources deployed before the failed resource remain in place, and the next deployment starts with the failed resource\. You'll spend a lot less time waiting for deployments and a lot more time developing your infrastructure\. + +### Hot swapping<a name="cli-deploy-hotswap"></a> + +Use the `--hotswap` flag with `cdk deploy` to attempt to update your AWS resources directly instead of generating a AWS CloudFormation changeset and deploying it\. Deployment falls back to AWS CloudFormation deployment if hot swapping is not possible\. + +Currently hot swapping supports Lambda functions, Step Functions state machines, and Amazon ECS container images\. The `--hotswap` flag also disables rollback \(i\.e\., implies `--no-rollback`\)\. + +**Important** +Hot\-swapping is not recommended for production deployments\. + +### Watch mode<a name="cli-deploy-watch"></a> + +The CDK Toolkit's watch mode \( cdk deploy \-\-watch, or cdk watch for short\) continuously monitors your CDK app's source files and assets for changes and immediately performs a deployment of the specified stacks when a change is detected\. + +By default, these deployments use the `--hotswap` flag, which fast\-tracks deployment of changes to Lambda functions, and falls back to deploying through AWS CloudFormation if you have changed infrastructure configuration\. To have `cdk watch` always perform full AWS CloudFormation deployments, add the `--no-hotswap` flag to `cdk watch`\. + +Any changes made while `cdk watch` is already performing a deployment will be combined into a single deployment, which will begin as soon as the in\-progress deployment is complete\. + +Watch mode uses the `"watch"` key in the project's `cdk.json` to determine which files to monitor\. By default, these files are your application files and assets, but this can be changed by modifying the `"include"` and `"exclude"` entries in the `"watch"` key\. The following `cdk.json` file shows an example of these entries\. + +``` +{ + "app": "mvn -e -q compile exec:java", + "watch": { + "include": "src/main/**", + "exclude": "target/*" + } +} +``` + +`cdk watch` executes the `"build"` command from `cdk.json` to build your app before synthesis\. If your deployment requires any commands to build or package your Lambda code \(or anything else that's not in your CDK app proper\), add it here\. + +Git\-style wildcards, both `*` and `**`, can be used in the `"watch"` and `"build"` keys\. Each path is interpreted relative to the parent directory of `cdk.json`\. The default value of `include` is `**/*`, meaning all files and directories in the project root directory\. `exclude` is optional\. + +**Important** +Watch mode is not recommended for production deployments\. + +### Specifying AWS CloudFormation parameters<a name="w55aac33b7c37c19"></a> + +The AWS CDK Toolkit supports specifying AWS CloudFormation [parameters](parameters.md) at deployment\. You may provide these on the command line following the `--parameters` flag\. + +``` +cdk deploy MyStack --parameters uploadBucketName=UploadBucket +``` + +To define multiple parameters, use multiple `--parameters` flags\. + +``` +cdk deploy MyStack --parameters uploadBucketName=UpBucket --parameters downloadBucketName=DownBucket +``` + +If you are deploying multiple stacks, you can specify a different value of each parameter for each stack by prefixing the name of the parameter with the stack name and a colon\. Otherwise, the same value is passed to all stacks\. + +``` +cdk deploy MyStack YourStack --parameters MyStack:uploadBucketName=UploadBucket --parameters YourStack:uploadBucketName=UpBucket +``` + +By default, the AWS CDK retains values of parameters from previous deployments and uses them in later deployments if they are not specified explicitly\. Use the `--no-previous-parameters` flag to require all parameters to be specified\. + +### Specifying outputs file<a name="w55aac33b7c37c21"></a> + +If your stack declares AWS CloudFormation outputs, these are normally displayed on the screen at the conclusion of deployment\. To write them to a file in JSON format, use the `--outputs-file` flag\. + +``` +cdk deploy --outputs-file outputs.json MyStack +``` + +### Security\-related changes<a name="cli-security"></a> + +To protect you against unintended changes that affect your security posture, the AWS CDK Toolkit prompts you to approve security\-related changes before deploying them\. You can specify the level of change that requires approval: + +``` +cdk deploy --require-approval LEVEL +``` + +*LEVEL* can be one of the following: + + +| Term | Meaning | +| --- | --- | +| `never` | Approval is never required | +| `any-change` | Requires approval on any IAM or security\-group\-related change | +| `broadening` \(default\) | Requires approval when IAM statements or traffic rules are added; removals don't require approval | + +The setting can also be configured in the `cdk.json` file\. + +``` +{ + "app": "...", + "requireApproval": "never" +} +``` + +## Comparing stacks<a name="cli-diff"></a> + +The `cdk diff` command compares the current version of a stack \(and its dependencies\) defined in your app with the already\-deployed version\(s\), or with a saved AWS CloudFormation template, and displays a list of changes\. + +``` +Stack HelloCdkStack +IAM Statement Changes +┌───┬──────────────────────────────┬────────┬──────────────────────────────┬──────────────────────────────┬───────────┐ +│ │ Resource │ Effect │ Action │ Principal │ Condition │ +├───┼──────────────────────────────┼────────┼──────────────────────────────┼──────────────────────────────┼───────────┤ +│ + │ ${Custom::S3AutoDeleteObject │ Allow │ sts:AssumeRole │ Service:lambda.amazonaws.com │ │ +│ │ sCustomResourceProvider/Role │ │ │ │ │ +│ │ .Arn} │ │ │ │ │ +├───┼──────────────────────────────┼────────┼──────────────────────────────┼──────────────────────────────┼───────────┤ +│ + │ ${MyFirstBucket.Arn} │ Allow │ s3:DeleteObject* │ AWS:${Custom::S3AutoDeleteOb │ │ +│ │ ${MyFirstBucket.Arn}/* │ │ s3:GetBucket* │ jectsCustomResourceProvider/ │ │ +│ │ │ │ s3:GetObject* │ Role.Arn} │ │ +│ │ │ │ s3:List* │ │ │ +└───┴──────────────────────────────┴────────┴──────────────────────────────┴──────────────────────────────┴───────────┘ +IAM Policy Changes +┌───┬────────────────────────────────────────────────────────┬────────────────────────────────────────────────────────┐ +│ │ Resource │ Managed Policy ARN │ +├───┼────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────┤ +│ + │ ${Custom::S3AutoDeleteObjectsCustomResourceProvider/Ro │ {"Fn::Sub":"arn:${AWS::Partition}:iam::aws:policy/serv │ +│ │ le} │ ice-role/AWSLambdaBasicExecutionRole"} │ +└───┴────────────────────────────────────────────────────────┴────────────────────────────────────────────────────────┘ +(NOTE: There may be security-related changes not in this list. See https://github.com/aws/aws-cdk/issues/1299) + +Parameters +[+] Parameter AssetParameters/4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392/S3Bucket AssetParameters4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392S3BucketBF7A7F3F: {"Type":"String","Description":"S3 bucket for asset \"4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392\""} +[+] Parameter AssetParameters/4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392/S3VersionKey AssetParameters4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392S3VersionKeyFAF93626: {"Type":"String","Description":"S3 key for asset version \"4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392\""} +[+] Parameter AssetParameters/4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392/ArtifactHash AssetParameters4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392ArtifactHashE56CD69A: {"Type":"String","Description":"Artifact hash for asset \"4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392\""} + +Resources +[+] AWS::S3::BucketPolicy MyFirstBucket/Policy MyFirstBucketPolicy3243DEFD +[+] Custom::S3AutoDeleteObjects MyFirstBucket/AutoDeleteObjectsCustomResource MyFirstBucketAutoDeleteObjectsCustomResourceC52FCF6E +[+] AWS::IAM::Role Custom::S3AutoDeleteObjectsCustomResourceProvider/Role CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092 +[+] AWS::Lambda::Function Custom::S3AutoDeleteObjectsCustomResourceProvider/Handler CustomS3AutoDeleteObjectsCustomResourceProviderHandler9D90184F +[~] AWS::S3::Bucket MyFirstBucket MyFirstBucketB8884501 + ├─ [~] DeletionPolicy + │ ├─ [-] Retain + │ └─ [+] Delete + └─ [~] UpdateReplacePolicy + ├─ [-] Retain + └─ [+] Delete +``` + +To compare your app's stack\(s\) with the existing deployment: + +``` +cdk diff MyStack +``` + +To compare your app's stack\(s\) with a saved CloudFormation template: + +``` +cdk diff --template ~/stacks/MyStack.old MyStack +``` + +## Configuration \(`cdk.json`\)<a name="cli-config"></a> + +Default values for many CDK Toolkit command\-line flags may be stored in a project's `cdk.json` file or in the `.cdk.json` file in your user directory\. Below is an alphabetical reference to the supported configuration settings\. + + +| Key | Notes | CDK Toolkit option | +| --- | --- | --- | +| app | The command that executes the CDK application\. | \-\-app | +| assetMetadata | If false, CDK does not add metadata to resources that use assets\. | \-\-no\-asset\-metadata | +| bootstrapKmsKeyId | Overrides the ID of the AWS KMS key used to encrypt the Amazon S3 deployment bucket\. | \-\-bootstrap\-kms\-key\-id | +| build | The command that compiles or builds the CDK application before synthesis\. Not permitted in \~/\.cdk\.json\. | \-\-build | +| browser | The command for launching a Web browser for the cdk docs subcommand\. | \-\-browser | +| context | See [Runtime context](context.md)\. Context values in a configuration file will not be erased by cdk context \-\-clear\. \(The CDK Toolkit places cached context values in cdk\.context\.json\.\) | \-\-context | +| debug | If true, CDK Toolkit emits more detailed information useful for debugging\. | \-\-debug | +| language | The language to be used for initializing new projects\. | \-\-language | +| lookups | If false, no context lookups are permitted\. Synthesis will fail if any context lookups need to be performed\. | \-\-no\-lookups | +| notices | If false, suppresses the display of messages about security vulnerabilities, regressions, and unsupported versions\. | \-\-no\-notices | +| output | The name of the directory into which the synthesized cloud assembly will be emitted \(default "cdk\.out"\)\. | \-\-outputs\-file | +| outputsFile | The file to which AWS CloudFormation outputs from deployed stacks will be written \(in JSON format\)\. | \-\-outputs\-file | +| pathMetadata | If false, CDK path metadata is not added to synthesized templates\. | \-\-no\-path\-metadata | +| plugin | JSON array specifying the package names or local paths of packages that extend the CDK | \-\-plugin | +| profile | Name of the default AWS profile used for specifying region and account credentials\. | \-\-profile | +| progress | If set to "events", the CDK Toolkit displays all AWS CloudFormation events during deployment, rather than a progress bar\. | \-\-progress | +| requireApproval | Default approval level for security changes\. See [Security\-related changes](#cli-security) | \-\-require\-approval | +| rollback | If false, failed deployments are not rolled back\. | \-\-no\-rollback | +| staging | If false, assets are not copied to the output directory \(use for local debugging of the source files with AWS SAM\)\. | \-\-no\-staging | +| tags | JSON object containing tags \(key\-value pairs\) for the stack\. | \-\-tags | +| toolkitBucketName | The name of the Amazon S3 bucket used for deploying assets such as Lambda functions and container images \(see [Bootstrapping your AWS environment](#cli-bootstrap)\. | \-\-toolkit\-bucket\-name | +| toolkitStackName | The name of the bootstrap stack \(see [Bootstrapping your AWS environment](#cli-bootstrap)\. | \-\-toolkit\-stack\-name | +| versionReporting | If false, opts out of version reporting\. | \-\-no\-version\-reporting | +| watch | JSON object containing "include" and "exclude" keys that indicate which files should \(or should not\) trigger a rebuild of the project when changed\. See [Watch mode](#cli-deploy-watch)\. | \-\-watch | + +## Toolkit reference<a name="cli-ref"></a> + +This section provides a reference for the AWS CDK Toolkit derived from its help, first a general reference with the options available with all commands, then \(in collapsible sections\) specific references with options available only with specific subcommands\. + +``` +Usage: cdk -a <cdk-app> COMMAND + +Commands: + + cdk list [STACKS..] Lists all stacks in the app [aliases: ls] + + cdk synthesize [STACKS..] Synthesizes and prints the CloudFormation + template for this stack [aliases: synth] + + cdk bootstrap [ENVIRONMENTS..] Deploys the CDK toolkit stack into an AWS + environment + + cdk deploy [STACKS..] Deploys the stack(s) named STACKS into your + AWS account + + cdk import [STACK] Import existing resource(s) into the given + STACK + + cdk watch [STACKS..] Shortcut for 'deploy --watch' + + cdk destroy [STACKS..] Destroy the stack(s) named STACKS + + cdk diff [STACKS..] Compares the specified stack with the deployed + stack or a local template file, and returns + with status 1 if any difference is found + + cdk metadata [STACK] Returns all metadata associated with this + stack + + cdk acknowledge [ID] Acknowledge a notice so that it does not show + up anymore [aliases: ack] + + cdk notices Returns a list of relevant notices + + cdk init [TEMPLATE] Create a new, empty CDK project from a + template. + + cdk context Manage cached context values + + cdk docs Opens the reference documentation in a browser + [aliases: doc] + + cdk doctor Check your set-up for potential problems + +Options: + + -a, --app REQUIRED: command-line for executing your app or a + cloud assembly directory (e.g. "node bin/my-app.js") + [string] + + --build Command-line for a pre-synth build [string] + + -c, --context Add contextual string parameter (KEY=VALUE) [array] + + -p, --plugin Name or path of a node package that extend the CDK + features. Can be specified multiple times [array] + + --trace Print trace for stack warnings [boolean] + + --strict Do not construct stacks with warnings [boolean] + + --lookups Perform context lookups (synthesis fails if this is + disabled and context lookups need to be performed) + [boolean] [default: true] + + --ignore-errors Ignores synthesis errors, which will likely produce + an invalid output [boolean] [default: false] + + -j, --json Use JSON output instead of YAML when templates are + printed to STDOUT [boolean] [default: false] + + -v, --verbose Show debug logs (specify multiple times to increase + verbosity) [count] [default: false] + + --debug Enable emission of additional debugging information, + such as creation stack traces of tokens + [boolean] [default: false] + + --profile Use the indicated AWS profile as the default + environment [string] + + --proxy Use the indicated proxy. Will read from HTTPS_PROXY + environment variable if not specified [string] + + --ca-bundle-path Path to CA certificate to use when validating HTTPS + requests. Will read from AWS_CA_BUNDLE environment + variable if not specified [string] + + -i, --ec2creds Force trying to fetch EC2 instance credentials. + Default: guess EC2 instance status [boolean] + + --version-reporting Include the "AWS::CDK::Metadata" resource in + synthesized templates (enabled by default) [boolean] + + --path-metadata Include "aws:cdk:path" CloudFormation metadata for + each resource (enabled by default) + [boolean] [default: true] + + --asset-metadata Include "aws:asset:*" CloudFormation metadata for + resources that uses assets (enabled by default) + [boolean] [default: true] + + -r, --role-arn ARN of Role to use when invoking CloudFormation + [string] + + --staging Copy assets to the output directory (use --no-staging + to disable, needed for local debugging the source + files with SAM CLI) [boolean] [default: true] + + -o, --output Emits the synthesized cloud assembly into a directory + (default: cdk.out) [string] + + --notices Show relevant notices [boolean] + + --no-color Removes colors and other style from console output + [boolean] [default: false] + + --version Show version number [boolean] + + -h, --help Show help [boolean] + +If your app has a single stack, there is no need to specify the stack name + +If one of cdk.json or ~/.cdk.json exists, options specified there will be used +as defaults. Settings in cdk.json take precedence. +``` + +### `cdk list` \(`ls`\)<a name="w55aac33b7c43b7b1"></a> + +``` +cdk list [STACKS..] + +Lists all stacks in the app + +Options: + + -l, --long Display environment information for each stack + [boolean] [default: false] +``` + +### `cdk synthesize` \(`synth`\)<a name="w55aac33b7c43b7b3"></a> + +``` +cdk synthesize [STACKS..] + +Synthesizes and prints the CloudFormation template for this stack + +Options: + + -e, --exclusively Only synthesize requested stacks, don't include + dependencies [boolean] + + --validation After synthesis, validate stacks with the + "validateOnSynth" attribute set (can also be + controlled with CDK_VALIDATION) + [boolean] [default: true] + + -q, --quiet Do not output CloudFormation Template to stdout + [boolean] [default: false] +``` + +### `cdk bootstrap`<a name="w55aac33b7c43b7b5"></a> + +``` +cdk bootstrap [ENVIRONMENTS..] + +Deploys the CDK toolkit stack into an AWS environment + +Options: + + -b, --bootstrap-bucket-name, The name of the CDK toolkit bucket; + --toolkit-bucket-name bucket will be created and must not + exist [string] + + --bootstrap-kms-key-id AWS KMS master key ID used for the + SSE-KMS encryption [string] + + --bootstrap-customer-key Create a Customer Master Key (CMK) + for the bootstrap bucket (you will + be charged but can customize + permissions, modern bootstrapping + only) [boolean] + + --qualifier String which must be unique for each + bootstrap stack. You must configure + it on your CDK app if you change + this from the default. [string] + + --public-access-block-configuration Block public access configuration + on CDK toolkit bucket (enabled by + default) [boolean] + + -t, --tags Tags to add for the stack + (KEY=VALUE) [array] [default: []] + + --execute Whether to execute ChangeSet + (--no-execute will NOT execute the + ChangeSet) [boolean] [default: true] + + --trust The AWS account IDs that should be + trusted to perform deployments into + this environment (may be repeated, + modern bootstrapping only) + [array] [default: []] + + --trust-for-lookup The AWS account IDs that should be + trusted to look up values in this + environment (may be repeated, modern + bootstrapping only) + [array] [default: []] + + --cloudformation-execution-policies The Managed Policy ARNs that should + be attached to the role performing + deployments into this environment + (may be repeated, modern + bootstrapping only) + [array] [default: []] + + -f, --force Always bootstrap even if it would + downgrade template version + [boolean] [default: false] + + --termination-protection Toggle CloudFormation termination + protection on the bootstrap stacks + [boolean] + + --show-template Instead of actual bootstrapping, + print the current CLI's + bootstrapping template to stdout for + customization + [boolean] [default: false] + + --toolkit-stack-name The name of the CDK toolkit stack to + create [string] + + --template Use the template from the given file + instead of the built-in one (use + --show-template to obtain an + example) [string] +``` + +### `cdk deploy`<a name="w55aac33b7c43b7b7"></a> + +``` +cdk deploy [STACKS..] + +Deploys the stack(s) named STACKS into your AWS account + +Options: + + --all Deploy all available stacks + [boolean] [default: false] + + -E, --build-exclude Do not rebuild asset with the given ID. Can be + specified multiple times [array] [default: []] + + -e, --exclusively Only deploy requested stacks, don't include + dependencies [boolean] + + --require-approval What security-sensitive changes need manual + approval + [string] [choices: "never", "any-change", "broadening"] + + --ci Force CI detection [boolean] [default: false] + + --notification-arns ARNs of SNS topics that CloudFormation will notify + with stack related events [array] + + -t, --tags Tags to add to the stack (KEY=VALUE), overrides + tags from Cloud Assembly (deprecated) [array] + + --execute Whether to execute ChangeSet (--no-execute will NOT + execute the ChangeSet) [boolean] [default: true] + + --change-set-name Name of the CloudFormation change set to create + [string] + + -f, --force Always deploy stack even if templates are identical + [boolean] [default: false] + + --parameters Additional parameters passed to CloudFormation at + deploy time (STACK:KEY=VALUE) [array] [default: {}] + + -O, --outputs-file Path to file where stack outputs will be written as + JSON [string] + + --previous-parameters Use previous values for existing parameters (you + must specify all parameters on every deployment if + this is disabled) [boolean] [default: true] + + --toolkit-stack-name The name of the existing CDK toolkit stack (only + used for app using legacy synthesis) [string] + + --progress Display mode for stack activity events + [string] [choices: "bar", "events"] + + --rollback Rollback stack to stable state on failure. Defaults + to 'true', iterate more rapidly with --no-rollback + or -R. Note: do **not** disable this flag for + deployments with resource replacements, as that + will always fail [boolean] + + --hotswap Attempts to perform a 'hotswap' deployment, which + skips CloudFormation and updates the resources + directly, and falls back to a full deployment if + that is not possible. Do not use this in production + environments [boolean] + + --watch Continuously observe the project files, and deploy + the given stack(s) automatically when changes are + detected. Implies --hotswap by default [boolean] + + --logs Show CloudWatch log events from all resources in + the selected Stacks in the terminal. 'true' by + default, use --no-logs to turn off. Only in effect + if specified alongside the '--watch' option + [boolean] [default: true] +``` + +### `cdk destroy`<a name="w55aac33b7c43b7b9"></a> + +``` +cdk destroy [STACKS..] + +Destroy the stack(s) named STACKS + +Options: + + --all Destroy all available stacks + [boolean] [default: false] + + -e, --exclusively Only destroy requested stacks, don't include + dependees [boolean] + + -f, --force Do not ask for confirmation before destroying the + stacks [boolean] +``` + +### `cdk diff`<a name="w55aac33b7c43b7c11"></a> + +``` +cdk diff [STACKS..] + +Compares the specified stack with the deployed stack or a local template file, +and returns with status 1 if any difference is found + +Options: + + -e, --exclusively Only diff requested stacks, don't include + dependencies [boolean] + + --context-lines Number of context lines to include in arbitrary JSON + diff rendering [number] [default: 3] + + --template The path to the CloudFormation template to compare + with [string] + + --security-only Only diff for broadened security changes + [boolean] [default: false] + + --fail Fail with exit code 1 in case of diff + [boolean] [default: false] +``` + +### `cdk init`<a name="w55aac33b7c43b7c13"></a> + +``` +cdk init [TEMPLATE] + +Create a new, empty CDK project from a template. + +Options: + + -l, --language The language to be used for the new project (default + can be configured in ~/.cdk.json) + [string] [choices: "csharp", "fsharp", "go", "java", "javascript", "python", + "typescript"] + + --list List the available templates [boolean] + + --generate-only If true, only generates project files, without + executing additional operations such as setting up a + git repo, installing dependencies or compiling the + project [boolean] [default: false] +``` + +### `cdk context`<a name="w55aac33b7c43b7c15"></a> + +``` +cdk context + +Manage cached context values + +Options: + + -e, --reset The context key (or its index) to reset [string] + + --clear Clear all context [boolean] +``` \ No newline at end of file diff --git a/v1/compliance-validation.md b/v1/compliance-validation.md new file mode 100644 index 00000000..67d4b7a1 --- /dev/null +++ b/v1/compliance-validation.md @@ -0,0 +1,16 @@ +# Compliance validation for the AWS Cloud Development Kit \(AWS CDK\)<a name="compliance-validation"></a> + +The AWS CDK follows the [shared responsibility model](https://aws.amazon.com/compliance/shared-responsibility-model/) through the specific Amazon Web Services \(AWS\) services it supports\. For AWS service security information, see the [AWS service security documentation page](https://docs.aws.amazon.com/security/?id=docs_gateway#aws-security) and [AWS services that are in scope of AWS compliance efforts by compliance program](https://aws.amazon.com/compliance/services-in-scope/)\. + +The security and compliance of AWS services is assessed by third\-party auditors as part of multiple AWS compliance programs\. These include SOC, PCI, FedRAMP, HIPAA, and others\. AWS provides a frequently updated list of AWS services in scope of specific compliance programs at [AWS Services in Scope by Compliance Program](https://aws.amazon.com/compliance/services-in-scope/)\. + +Third\-party audit reports are available for you to download using AWS Artifact\. For more information, see [Downloading Reports in AWS Artifact](https://docs.aws.amazon.com/artifact/latest/ug/downloading-documents.html)\. + +For more information about AWS compliance programs, see [AWS Compliance Programs](https://aws.amazon.com/compliance/programs/)\. + +Your compliance responsibility when using the AWS CDK to access an AWS service is determined by the sensitivity of your data, your organization's compliance objectives, and applicable laws and regulations\. If your use of an AWS service is subject to compliance with standards such as HIPAA, PCI, or FedRAMP, AWS provides resources to help: ++ [Security and Compliance Quick Start Guides](https://aws.amazon.com/quickstart/?quickstart-all.sort-by=item.additionalFields.updateDate&quickstart-all.sort-order=desc&awsf.quickstart-homepage-filter=categories%23security-identity-compliance) – Deployment guides that discuss architectural considerations and provide steps for deploying security\-focused and compliance\-focused baseline environments on AWS\. ++ [Architecting for HIPAA Security and Compliance Whitepaper](https://d0.awsstatic.com/whitepapers/compliance/AWS_HIPAA_Compliance_Whitepaper.pdf) – A whitepaper that describes how companies can use AWS to create HIPAA\-compliant applications\. ++ [AWS Compliance Resources](https://aws.amazon.com/compliance/resources/) – A collection of workbooks and guides that might apply to your industry and location\. ++ [AWS Config](https://aws.amazon.com/config/) – A service that assesses how well your resource configurations comply with internal practices, industry guidelines, and regulations\. ++ [AWS Security Hub](https://aws.amazon.com/security-hub/) – A comprehensive view of your security state within AWS that helps you check your compliance with security industry standards and best practices\. \ No newline at end of file diff --git a/v1/constructs.md b/v1/constructs.md new file mode 100644 index 00000000..dac22dc5 --- /dev/null +++ b/v1/constructs.md @@ -0,0 +1,1013 @@ +# Constructs<a name="constructs"></a> + +Constructs are the basic building blocks of AWS CDK apps\. A construct represents a "cloud component" and encapsulates everything AWS CloudFormation needs to create the component\. + +**Note** +Constructs are part of the Construct Programming Model \(CPM\) and are also used by other tools such as CDK for Terraform \(CDKtf\), CDK for Kubernetes \(CDK8s\), and Projen\. + +A construct can represent a single AWS resource, such as an Amazon Simple Storage Service \(Amazon S3\) bucket, or it can be a higher\-level abstraction consisting of multiple related AWS resources\. Examples of such components include a worker queue with its associated compute capacity, or a scheduled job with monitoring resources and a dashboard\. + +The AWS CDK includes a collection of constructs called the AWS Construct Library, containing constructs for every AWS service\. [Construct Hub](https://constructs.dev/search?q=&cdk=aws-cdk&cdkver=1&sort=downloadsDesc&offset=0) is a resource to help you discover additional constructs from AWS, third parties, and the open\-source CDK community\. + +## AWS Construct library<a name="constructs_lib"></a> + +The AWS CDK includes the [AWS Construct Library](https://docs.aws.amazon.com/cdk/api/v1/docs/aws-construct-library.html), which contains constructs representing AWS resources\. + +This library includes constructs that represent all the resources available on AWS\. For example, the `[s3\.Bucket](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-s3.Bucket.html)` class represents an Amazon S3 bucket, and the `[dynamodb\.Table](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-dynamodb.Table.html)` class represents an Amazon DynamoDB table\. + +There are three different levels of constructs in this library, beginning with low\-level constructs, which we call *CFN Resources* \(or L1, short for "layer 1"\)\. These constructs directly represent all resources available in AWS CloudFormation\. CFN Resources are periodically generated from the [AWS CloudFormation Resource Specification](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-resource-specification.html)\. They are named **Cfn***Xyz*, where *Xyz* is name of the resource\. For example, [CfnBucket](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-s3.CfnBucket.html) represents the [AWS::S3::Bucket](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket.html) AWS CloudFormation resource\. When you use Cfn resources, you must explicitly configure all resource properties, which requires a complete understanding of the details of the underlying AWS CloudFormation resource model\. + +The next level of constructs, **L2**, also represent AWS resources, but with a higher\-level, intent\-based API\. They provide similar functionality, but provide the defaults, boilerplate, and glue logic you'd be writing yourself with a CFN Resource construct\. AWS constructs offer convenient defaults and reduce the need to know all the details about the AWS resources they represent, while providing convenience methods that make it simpler to work with the resource\. For example, the [s3\.Bucket](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-s3.Bucket.html) class represents an Amazon S3 bucket with additional properties and methods, such as [bucket\.addLifeCycleRule\(\)](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-s3.Bucket.html#add-wbr-lifecycle-wbr-rulerule), which adds a lifecycle rule to the bucket\. + +Finally, the AWS Construct Library includes **L3** constructs, which we call *patterns*\. These constructs are designed to help you complete common tasks in AWS, often involving multiple kinds of resources\. For example, the [aws\-ecs\-patterns\.ApplicationLoadBalancedFargateService](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-ecs-patterns.ApplicationLoadBalancedFargateService.html) construct represents an architecture that includes an AWS Fargate container cluster employing an Application Load Balancer \(ALB\)\. The [aws\-apigateway\.LambdaRestApi](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-apigateway.LambdaRestApi.html) construct represents an Amazon API Gateway API that's backed by an AWS Lambda function\. + +For more information about how to navigate the library and discover constructs that can help you build your apps, see the [API Reference](https://docs.aws.amazon.com/cdk/api/v1/docs/aws-construct-library.html)\. + +## Composition<a name="constructs_composition"></a> + +*Composition* is the key pattern for defining higher\-level abstractions through constructs\. A high\-level construct can be composed from any number of lower\-level constructs, and in turn, those could be composed from even lower\-level constructs, which eventually are composed from AWS resources\. From a bottom\-up perspective, you use constructs to organize the individual AWS resources you want to deploy using whatever abstractions are convenient for your purpose, with as many layers as you need\. + +Composition lets you define reusable components and share them like any other code\. For example, a team can define a construct that implements the company's best practice for a DynamoDB table with backup, global replication, auto\-scaling, and monitoring, and share it with other teams in their organization, or publicly\. Teams can now use this construct as they would any other library package in their preferred programming language to define their tables and comply with their team's best practices\. When the library is updated, developers will get access to the new version's bug fixes and improvements through the workflows they already have for their other types of code\. + +## Initialization<a name="constructs_init"></a> + +Constructs are implemented in classes that extend the [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.Construct.html](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.Construct.html) base class\. You define a construct by instantiating the class\. All constructs take three parameters when they are initialized: ++ **scope** — The construct's parent or owner, either a stack or another construct, which determines its place in the [construct tree](#constructs_tree)\. You should usually pass `this` \(or `self` in Python\), which represents the current object, for the scope\. ++ **id** — An [identifier](identifiers.md) that must be unique within this scope\. The identifier serves as a namespace for everything that's defined within the current construct and is used to generate unique identifiers such as [resource names](resources.md#resources_physical_names) and AWS CloudFormation logical IDs\. ++ **props** — A set of properties or keyword arguments, depending upon the language, that define the construct's initial configuration\. In most cases, constructs provide sensible defaults, and if all props elements are optional, you can leave out the **props** parameter completely\. + +Identifiers need only be unique within a scope\. This lets you instantiate and reuse constructs without concern for the constructs and identifiers they might contain, and enables composing constructs into higher level abstractions\. In addition, scopes make it possible to refer to groups of constructs all at once, for example for [tagging](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.Tag.html) or for specifying where the constructs will be deployed\. + +## Apps and stacks<a name="constructs_apps_stacks"></a> + +We call your CDK application an *app*, which is represented by the AWS CDK class [App](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.App.html)\. The following example defines an app with a single stack that contains a single Amazon S3 bucket with versioning enabled: + +------ +#### [ TypeScript ] + +``` +import { App, Stack, StackProps } from '@aws-cdk/core'; +import * as s3 from '@aws-cdk/aws-s3'; + +class HelloCdkStack extends Stack { + constructor(scope: App, id: string, props?: StackProps) { + super(scope, id, props); + + new s3.Bucket(this, 'MyFirstBucket', { + versioned: true + }); + } +} + +const app = new App(); +new HelloCdkStack(app, "HelloCdkStack"); +``` + +------ +#### [ JavaScript ] + +``` +const { App , Stack } = require('@aws-cdk/core'); +const s3 = require('@aws-cdk/aws-s3'); + +class HelloCdkStack extends Stack { + constructor(scope, id, props) { + super(scope, id, props); + + new s3.Bucket(this, 'MyFirstBucket', { + versioned: true + }); + } +} + +const app = new App(); +new HelloCdkStack(app, "HelloCdkStack"); +``` + +------ +#### [ Python ] + +``` +from aws_cdk.core import App, Stack +from aws_cdk import aws_s3 as s3 + +class HelloCdkStack(core.Stack): + + def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + s3.Bucket(self, "MyFirstBucket", versioned=True) + +app = core.App() +HelloCdkStack(app, "HelloCdkStack") +``` + +------ +#### [ Java ] + +``` +import software.amazon.awscdk.core.*; +import software.amazon.awscdk.services.s3.*; + +public class HelloCdkStack extends Stack { + public HelloCdkStack(final Construct scope, final String id) { + this(scope, id, null); + } + + public HelloCdkStack(final Construct scope, final String id, final StackProps props) { + super(scope, id, props); + + Bucket.Builder.create(this, "MyFirstBucket") + .versioned(true).build(); + } +} +``` + +------ +#### [ C\# ] + +``` +using Amazon.CDK; +using Amazon.CDK.AWS.S3; + +namespace HelloCdkApp +{ + internal static class Program + { + public static void Main(string[] args) + { + var app = new App(); + new HelloCdkStack(app, "HelloCdkStack"); + app.Synth(); + } + } + + public class HelloCdkStack : Stack + { + public HelloCdkStack(Construct scope, string id, IStackProps props=null) : base(scope, id, props) + { + new Bucket(this, "MyFirstBucket", new BucketProps { Versioned = true }); + } + } +} +``` + +------ + +As you can see, you need a scope within which to define your bucket\. Since resources eventually need to be deployed as part of a AWS CloudFormation stack into an *AWS [environment](environments.md)*, which covers a specific AWS account and AWS region\. AWS constructs, such as `s3.Bucket`, must be defined within the scope of a [Stack](https://docs.aws.amazon.com/cdk/api/v1/docs/core/stack.html)\. + +Stacks in AWS CDK apps extend the **Stack** base class, as shown in the previous example\. This is a common pattern when creating a stack within your AWS CDK app: extend the **Stack** class, define a constructor that accepts **scope**, **id**, and **props**, and invoke the base class constructor via `super` with the received **scope**, **id**, and **props**, as shown in the following example\. + +------ +#### [ TypeScript ] + +``` +class HelloCdkStack extends Stack { + constructor(scope: App, id: string, props?: StackProps) { + super(scope, id, props); + + //... + } +} +``` + +------ +#### [ JavaScript ] + +``` +class HelloCdkStack extends Stack { + constructor(scope, id, props) { + super(scope, id, props); + + //... + } +} +``` + +------ +#### [ Python ] + +``` +class HelloCdkStack(core.Stack): + + def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + # ... +``` + +------ +#### [ Java ] + +``` +public class HelloCdkStack extends Stack { + public HelloCdkStack(final Construct scope, final String id) { + this(scope, id, null); + } + + public HelloCdkStack(final Construct scope, final String id, final StackProps props) { + super(scope, id, props); + + // ... + } +} +``` + +------ +#### [ C\# ] + +``` +public class HelloCdkStack : Stack +{ + public HelloCdkStack(Construct scope, string id, IStackProps props=null) : base(scope, id, props) + { + //... + } +} +``` + +------ + +## Using L1 constructs<a name="constructs_l1_using"></a> + +Once you have defined a stack, you can populate it with resources by instantiating constructs\. First, we'll do it with an L1 construct\. + +L1 constructs are exactly the resources defined by AWS CloudFormation—no more, no less\. You must provide the resource's required configuration yourself\. Here, for example, is how to create an Amazon S3 bucket using the `CfnBucket` class\. \(You'll see a similar definition using the `Bucket` class in the next section\.\) + +------ +#### [ TypeScript ] + +``` +const bucket = new s3.CfnBucket(this, "MyBucket", { + bucketName: "MyBucket" +}); +``` + +------ +#### [ JavaScript ] + +``` +const bucket = new s3.CfnBucket(this, "MyBucket", { + bucketName: "MyBucket" +}); +``` + +------ +#### [ Python ] + +``` +bucket = s3.CfnBucket(self, "MyBucket", bucket_name="MyBucket") +``` + +------ +#### [ Java ] + +``` +CfnBucket bucket = new CfnBucket.Builder().bucketName("MyBucket").build(); +``` + +------ +#### [ C\# ] + +``` +var bucket = new CfnBucket(this, "MyBucket", new CfnBucketProps +{ + BucketName= "MyBucket" +}); +``` + +------ + +In Python, Java, and C\#, L1 construct properties that aren't simple Booleans, strings, numbers, or containers are represented by types defined as inner classes of the L1 construct\. For example, the optional property `corsConfiguration` of a `CfnBucket` requires a wrapper of type `CfnBucket.CorsConfigurationProperty`\. Here we are defining `corsConfiguration` on a `CfnBucket` instance\. + +------ +#### [ TypeScript ] + +``` +const bucket = new s3.CfnBucket(this, "MyBucket", { + bucketName: "MyBucket", + corsConfiguration: { + corsRules: [{ + allowedOrigins: ["*"], + allowedMethods: ["GET"] + }] + } +}); +``` + +------ +#### [ JavaScript ] + +``` +const bucket = new s3.CfnBucket(this, "MyBucket", { + bucketName: "MyBucket", + corsConfiguration: { + corsRules: [{ + allowedOrigins: ["*"], + allowedMethods: ["GET"] + }] + } +}); +``` + +------ +#### [ Python ] + +``` +bucket = CfnBucket(self, "MyBucket", bucket_name="MyBucket", + cors_configuration=CfnBucket.CorsConfigurationProperty( + cors_rules=[CfnBucket.CorsRuleProperty( + allowed_origins=["*"], + allowed_methods=["GET"] + )] + ) +) +``` + +------ +#### [ Java ] + +``` +CfnBucket bucket = CfnBucket.Builder.create(this, "MyBucket") + .bucketName("MyBucket") + .corsConfiguration(new CfnBucket.CorsConfigurationProperty.Builder() + .corsRules(Arrays.asList(new CfnBucket.CorsRuleProperty.Builder() + .allowedOrigins(Arrays.asList("*")) + .allowedMethods(Arrays.asList("GET")) + .build())) + .build()) + .build(); +``` + +------ +#### [ C\# ] + +``` +var bucket = new CfnBucket(this, "MyBucket", new CfnBucketProps +{ + BucketName = "MyBucket", + CorsConfiguration = new CfnBucket.CorsConfigurationProperty + { + CorsRules = new object[] { + new CfnBucket.CorsRuleProperty + { + AllowedOrigins = new string[] { "*" }, + AllowedMethods = new string[] { "GET" }, + } + } + } +}); +``` + +------ + +**Important** +You can't use L2 property types with L1 constructs, or vice versa\. When working with L1 constructs, always use the types defined inside the L1 construct you're using\. Do not use types from other L1 constructs \(some may have the same name, but they are not the same type\)\. +Some of our language\-specific API references currently have errors in the paths to L1 property types, or don't document these classes at all\. We hope to fix this soon\. In the meantime, just remember that such types are always inner classes of the L1 construct they are used with\. + +## Using L2 constructs<a name="constructs_using"></a> + +The following example defines an Amazon S3 bucket by creating an instance of the [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-s3.Bucket.html](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-s3.Bucket.html) class, an L2 construct\. + +------ +#### [ TypeScript ] + +``` +import * as s3 from '@aws-cdk/aws-s3'; + +// "this" is HelloCdkStack +new s3.Bucket(this, 'MyFirstBucket', { + versioned: true +}); +``` + +------ +#### [ JavaScript ] + +``` +const s3 = require('@aws-cdk/aws-s3'); + +// "this" is HelloCdkStack +new s3.Bucket(this, 'MyFirstBucket', { + versioned: true +}); +``` + +------ +#### [ Python ] + +``` +from aws_cdk import aws_s3 as s3 + +# "self" is HelloCdkStack +s3.Bucket(self, "MyFirstBucket", versioned=True) +``` + +------ +#### [ Java ] + +``` +import software.amazon.awscdk.services.s3.*; + +public class HelloCdkStack extends Stack { + public HelloCdkStack(final Construct scope, final String id) { + this(scope, id, null); + } + + public HelloCdkStack(final Construct scope, final String id, final StackProps props) { + super(scope, id, props); + + Bucket.Builder.create(this, "MyFirstBucket") + .versioned(true).build(); + } +} +``` + +------ +#### [ C\# ] + +``` +using Amazon.CDK.AWS.S3; + +// "this" is HelloCdkStack +new Bucket(this, "MyFirstBucket", new BucketProps +{ + Versioned = true +}); +``` + +------ + +The [AWS Construct Library](https://docs.aws.amazon.com/cdk/api/v1/docs/aws-construct-library.html) includes constructs that represent many AWS resources\. + +**Note** +`MyFirstBucket` is not the name of the bucket that AWS CloudFormation creates\. It is a logical identifier given to the new construct\. See [Physical Names](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.Resource.html#physicalname-span-class-api-icon-api-icon-experimental-title-this-api-element-is-experimental-it-may-change-without-notice-span) for details\. + +## Configuration<a name="constructs_config"></a> + +Most constructs accept `props` as their third argument \(or in Python, keyword arguments\), a name/value collection that defines the construct's configuration\. The following example defines a bucket with AWS Key Management Service \(AWS KMS\) encryption and static website hosting enabled\. Since it does not explicitly specify an encryption key, the `Bucket` construct defines a new `kms.Key` and associates it with the bucket\. + +------ +#### [ TypeScript ] + +``` +new s3.Bucket(this, 'MyEncryptedBucket', { + encryption: s3.BucketEncryption.KMS, + websiteIndexDocument: 'index.html' +}); +``` + +------ +#### [ JavaScript ] + +``` +new s3.Bucket(this, 'MyEncryptedBucket', { + encryption: s3.BucketEncryption.KMS, + websiteIndexDocument: 'index.html' +}); +``` + +------ +#### [ Python ] + +``` +s3.Bucket(self, "MyEncryptedBucket", encryption=s3.BucketEncryption.KMS, + website_index_document="index.html") +``` + +------ +#### [ Java ] + +``` +Bucket.Builder.create(this, "MyEncryptedBucket") + .encryption(BucketEncryption.KMS_MANAGED) + .websiteIndexDocument("index.html").build(); +``` + +------ +#### [ C\# ] + +``` +new Bucket(this, "MyEncryptedBucket", new BucketProps +{ + Encryption = BucketEncryption.KMS_MANAGED, + WebsiteIndexDocument = "index.html" +}); +``` + +------ + + AWS constructs are designed around the concept of "sensible defaults\." Most constructs have a minimal required configuration, enabling you to quickly get started while also providing full control over the configuration when you need it\. + +## Interacting with constructs<a name="constructs_interact"></a> + +Constructs are classes that extend the base [Construct](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.Construct.html) class\. After you instantiate a construct, the construct object exposes a set of methods and properties that enable you to interact with the construct and pass it around as a reference to other parts of the system\. The AWS CDK framework doesn't put any restrictions on the APIs of constructs; authors can define any API they wish\. However, the AWS constructs that are included with the AWS Construct Library, such as `s3.Bucket`, follow guidelines and common patterns in order to provide a consistent experience across all AWS resources\. + +For example, almost all AWS constructs have a set of [grant](permissions.md#permissions_grants) methods that you can use to grant AWS Identity and Access Management \(IAM\) permissions on that construct to a principal\. The following example grants the IAM group `data-science` permission to read from the Amazon S3 bucket `raw-data`\. + +------ +#### [ TypeScript ] + +``` +const rawData = new s3.Bucket(this, 'raw-data'); +const dataScience = new iam.Group(this, 'data-science'); +rawData.grantRead(dataScience); +``` + +------ +#### [ JavaScript ] + +``` +const rawData = new s3.Bucket(this, 'raw-data'); +const dataScience = new iam.Group(this, 'data-science'); +rawData.grantRead(dataScience); +``` + +------ +#### [ Python ] + +``` +raw_data = s3.Bucket(self, 'raw-data') +data_science = iam.Group(self, 'data-science') +raw_data.grant_read(data_science) +``` + +------ +#### [ Java ] + +``` +Bucket rawData = new Bucket(this, "raw-data"); +Group dataScience = new Group(this, "data-science"); +rawData.grantRead(dataScience); +``` + +------ +#### [ C\# ] + +``` +var rawData = new Bucket(this, "raw-data"); +var dataScience = new Group(this, "data-science"); +rawData.GrantRead(dataScience); +``` + +------ + +Another common pattern is for AWS constructs to set one of the resource's attributes, such as its Amazon Resource Name \(ARN\), name, or URL from data supplied elsewhere\. For example, the following code defines an AWS Lambda function and associates it with an Amazon Simple Queue Service \(Amazon SQS\) queue through the queue's URL in an environment variable\. + +------ +#### [ TypeScript ] + +``` +const jobsQueue = new sqs.Queue(this, 'jobs'); +const createJobLambda = new lambda.Function(this, 'create-job', { + runtime: lambda.Runtime.NODEJS_14_X, + handler: 'index.handler', + code: lambda.Code.fromAsset('./create-job-lambda-code'), + environment: { + QUEUE_URL: jobsQueue.queueUrl + } +}); +``` + +------ +#### [ JavaScript ] + +``` +const jobsQueue = new sqs.Queue(this, 'jobs'); +const createJobLambda = new lambda.Function(this, 'create-job', { + runtime: lambda.Runtime.NODEJS_14_X, + handler: 'index.handler', + code: lambda.Code.fromAsset('./create-job-lambda-code'), + environment: { + QUEUE_URL: jobsQueue.queueUrl + } +}); +``` + +------ +#### [ Python ] + +``` +jobs_queue = sqs.Queue(self, "jobs") +create_job_lambda = lambda_.Function(self, "create-job", + runtime=lambda_.Runtime.NODEJS_14_X, + handler="index.handler", + code=lambda_.Code.from_asset("./create-job-lambda-code"), + environment=dict( + QUEUE_URL=jobs_queue.queue_url + ) +) +``` + +------ +#### [ Java ] + +``` +final Queue jobsQueue = new Queue(this, "jobs"); +Function createJobLambda = Function.Builder.create(this, "create-job") + .handler("index.handler") + .code(Code.fromAsset("./create-job-lambda-code")) + .environment(java.util.Map.of( // Map.of is Java 9 or later + "QUEUE_URL", jobsQueue.getQueueUrl()) + .build(); +``` + +------ +#### [ C\# ] + +``` +var jobsQueue = new Queue(this, "jobs"); +var createJobLambda = new Function(this, "create-job", new FunctionProps +{ + Runtime = Runtime.NODEJS_14_X, + Handler = "index.handler", + Code = Code.FromAsset(@".\create-job-lambda-code"), + Environment = new Dictionary<string, string> + { + ["QUEUE_URL"] = jobsQueue.QueueUrl + } +}); +``` + +------ + +For information about the most common API patterns in the AWS Construct Library, see [Resources](resources.md)\. + +## Writing your own constructs<a name="constructs_author"></a> + +In addition to using existing constructs like `s3.Bucket`, you can also write your own constructs, and then anyone can use them in their apps\. All constructs are equal in the AWS CDK\. An AWS CDK construct such as `s3.Bucket` or `sns.Topic` behaves the same as a construct from a third\-party library that someone published via NPM or Maven or PyPI—or to your company's internal package repository\. + +To declare a new construct, create a class that extends the [Construct](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.Construct.html) base class, then follow the pattern for initializer arguments\. + +For example, you could declare a construct that represents an Amazon S3 bucket which sends an Amazon Simple Notification Service \(Amazon SNS\) notification every time someone uploads a file into it: + +------ +#### [ TypeScript ] + +``` +export interface NotifyingBucketProps { + prefix?: string; +} + +export class NotifyingBucket extends Construct { + constructor(scope: Construct, id: string, props: NotifyingBucketProps = {}) { + super(scope, id); + const bucket = new s3.Bucket(this, 'bucket'); + const topic = new sns.Topic(this, 'topic'); + bucket.addObjectCreatedNotification(new s3notify.SnsDestination(topic), + { prefix: props.prefix }); + } +} +``` + +------ +#### [ JavaScript ] + +``` +class NotifyingBucket extends Construct { + constructor(scope, id, props = {}) { + super(scope, id); + const bucket = new s3.Bucket(this, 'bucket'); + const topic = new sns.Topic(this, 'topic'); + bucket.addObjectCreatedNotification(new s3notify.SnsDestination(topic), + { prefix: props.prefix }); + } +} + +module.exports = { NotifyingBucket } +``` + +------ +#### [ Python ] + +``` +class NotifyingBucket(core.Construct): + + def __init__(self, scope: core.Construct, id: str, *, prefix=None): + super().__init__(scope, id) + bucket = s3.Bucket(self, "bucket") + topic = sns.Topic(self, "topic") + bucket.add_object_created_notification(s3notify.SnsDestination(topic), + s3.NotificationKeyFilter(prefix=prefix)) +``` + +------ +#### [ Java ] + +``` +public class NotifyingBucket extends Construct { + + public NotifyingBucket(final Construct scope, final String id) { + this(scope, id, null, null); + } + + public NotifyingBucket(final Construct scope, final String id, final BucketProps props) { + this(scope, id, props, null); + } + + public NotifyingBucket(final Construct scope, final String id, final String prefix) { + this(scope, id, null, prefix); + } + + public NotifyingBucket(final Construct scope, final String id, final BucketProps props, final String prefix) { + super(scope, id); + + Bucket bucket = new Bucket(this, "bucket"); + Topic topic = new Topic(this, "topic"); + if (prefix != null) + bucket.addObjectCreatedNotification(new SnsDestination(topic), + NotificationKeyFilter.builder().prefix(prefix).build()); + } +} +``` + +------ +#### [ C\# ] + +``` +public class NotifyingBucketProps : BucketProps +{ + public string Prefix { get; set; } +} + +public class NotifyingBucket : Construct +{ + public NotifyingBucket(Construct scope, string id, NotifyingBucketProps props = null) : base(scope, id) + { + var bucket = new Bucket(this, "bucket"); + var topic = new Topic(this, "topic"); + bucket.AddObjectCreatedNotification(new SnsDestination(topic), new NotificationKeyFilter + { + Prefix = props?.Prefix + }); + } +} +``` + +------ + +**Note** +Our `NotifyingBucket` construct inherits not from `Bucket` but rather from `Construct`\. We are using composition, not inheritance, to bundle an Amazon S3 bucket and an Amazon SNS topic together\. In general, composition is preferred over inheritance when developing AWS CDK constructs\. + +The `NotifyingBucket` constructor has a typical construct signature: `scope`, `id`, and `props`\. The last argument, `props`, is optional \(gets the default value `{}`\) because all props are optional\. \(The base `Construct` class does not take a `props` argument\.\) You could define an instance of this construct in your app without `props`, for example: + +------ +#### [ TypeScript ] + +``` +new NotifyingBucket(this, 'MyNotifyingBucket'); +``` + +------ +#### [ JavaScript ] + +``` +new NotifyingBucket(this, 'MyNotifyingBucket'); +``` + +------ +#### [ Python ] + +``` +NotifyingBucket(self, "MyNotifyingBucket") +``` + +------ +#### [ Java ] + +``` +new NotifyingBucket(this, "MyNotifyingBucket"); +``` + +------ +#### [ C\# ] + +``` +new NotifyingBucket(this, "MyNotifyingBucket"); +``` + +------ + +Or you could use `props` \(in Java, an additional parameter\) to specify the path prefix to filter on, for example: + +------ +#### [ TypeScript ] + +``` +new NotifyingBucket(this, 'MyNotifyingBucket', { prefix: 'images/' }); +``` + +------ +#### [ JavaScript ] + +``` +new NotifyingBucket(this, 'MyNotifyingBucket', { prefix: 'images/' }); +``` + +------ +#### [ Python ] + +``` +NotifyingBucket(self, "MyNotifyingBucket", prefix="images/") +``` + +------ +#### [ Java ] + +``` +new NotifyingBucket(this, "MyNotifyingBucket", "/images"); +``` + +------ +#### [ C\# ] + +``` +new NotifyingBucket(this, "MyNotifyingBucket", new NotifyingBucketProps +{ + Prefix = "/images" +}); +``` + +------ + +Typically, you would also want to expose some properties or methods on your constructs\. For example, it's not very useful to have a topic hidden behind your construct, because it wouldn't be possible for users of your construct to subscribe to it\. Adding a `topic` property allows consumers to access the inner topic, as shown in the following example: + +------ +#### [ TypeScript ] + +``` +export class NotifyingBucket extends Construct { + public readonly topic: sns.Topic; + + constructor(scope: Construct, id: string, props: NotifyingBucketProps) { + super(scope, id); + const bucket = new s3.Bucket(this, 'bucket'); + this.topic = new sns.Topic(this, 'topic'); + bucket.addObjectCreatedNotification(new s3notify.SnsDestination(this.topic), { prefix: props.prefix }); + } +} +``` + +------ +#### [ JavaScript ] + +``` +class NotifyingBucket extends Construct { + + constructor(scope, id, props) { + super(scope, id); + const bucket = new s3.Bucket(this, 'bucket'); + this.topic = new sns.Topic(this, 'topic'); + bucket.addObjectCreatedNotification(new s3notify.SnsDestination(this.topic), { prefix: props.prefix }); + } +} + +module.exports = { NotifyingBucket } +``` + +------ +#### [ Python ] + +``` +class NotifyingBucket(core.Construct): + + def __init__(self, scope: core.Construct, id: str, *, prefix=None, **kwargs): + super().__init__(scope, id) + bucket = s3.Bucket(self, "bucket") + self.topic = sns.Topic(self, "topic") + bucket.add_object_created_notification(s3notify.SnsDestination(self.topic), + s3.NotificationKeyFilter(prefix=prefix)) +``` + +------ +#### [ Java ] + +``` +public class NotifyingBucket extends Construct { + + public Topic topic = null; + + public NotifyingBucket(final Construct scope, final String id) { + this(scope, id, null, null); + } + + public NotifyingBucket(final Construct scope, final String id, final BucketProps props) { + this(scope, id, props, null); + } + + public NotifyingBucket(final Construct scope, final String id, final String prefix) { + this(scope, id, null, prefix); + } + + public NotifyingBucket(final Construct scope, final String id, final BucketProps props, final String prefix) { + super(scope, id); + + Bucket bucket = new Bucket(this, "bucket"); + topic = new Topic(this, "topic"); + if (prefix != null) + bucket.addObjectCreatedNotification(new SnsDestination(topic), + NotificationKeyFilter.builder().prefix(prefix).build()); + } +} +``` + +------ +#### [ C\# ] + +``` +public class NotifyingBucket : Construct +{ + public readonly Topic topic; + + public NotifyingBucket(Construct scope, string id, NotifyingBucketProps props = null) : base(scope, id) + { + var bucket = new Bucket(this, "bucket"); + topic = new Topic(this, "topic"); + bucket.AddObjectCreatedNotification(new SnsDestination(topic), new NotificationKeyFilter + { + Prefix = props?.Prefix + }); + } +} +``` + +------ + +Now, consumers can subscribe to the topic, for example: + +------ +#### [ TypeScript ] + +``` +const queue = new sqs.Queue(this, 'NewImagesQueue'); +const images = new NotifyingBucket(this, '/images'); +images.topic.addSubscription(new sns_sub.SqsSubscription(queue)); +``` + +------ +#### [ JavaScript ] + +``` +const queue = new sqs.Queue(this, 'NewImagesQueue'); +const images = new NotifyingBucket(this, '/images'); +images.topic.addSubscription(new sns_sub.SqsSubscription(queue)); +``` + +------ +#### [ Python ] + +``` +queue = sqs.Queue(self, "NewImagesQueue") +images = NotifyingBucket(self, prefix="Images") +images.topic.add_subscription(sns_sub.SqsSubscription(queue)) +``` + +------ +#### [ Java ] + +``` +NotifyingBucket images = new NotifyingBucket(this, "MyNotifyingBucket", "/images"); +images.topic.addSubscription(new SqsSubscription(queue)); +``` + +------ +#### [ C\# ] + +``` +var queue = new Queue(this, "NewImagesQueue"); +var images = new NotifyingBucket(this, "MyNotifyingBucket", new NotifyingBucketProps +{ + Prefix = "/images" +}); +images.topic.AddSubscription(new SqsSubscription(queue)); +``` + +------ + +## The construct tree<a name="constructs_tree"></a> + +As we've already seen, in AWS CDK apps, you define constructs "inside" other constructs using the `scope` argument passed to every construct\. In this way, an AWS CDK app defines a hierarchy of constructs known as the *construct tree*\. + +The root of this tree is your app—that is, an instance of the `App` class\. Within the app, you instantiate one or more stacks\. Within stacks, you instantiate either AWS CloudFormation resources or higher\-level constructs, which may themselves instantiate resources or other constructs, and so on down the tree\. + +Constructs are *always* explicitly defined within the scope of another construct, so there is never any doubt about the relationships between constructs\. Almost always, you should pass `this` \(in Python, `self`\) as the scope, indicating that the new construct is a child of the current construct\. The intended pattern is that you derive your construct from [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.Construct.html](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.Construct.html), then instantiate the constructs it uses in its constructor\. + +Passing the scope explicitly allows each construct to add itself to the tree, with this behavior entirely contained within the [`Construct` base class](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.Construct.html)\. It works the same way in every language supported by the AWS CDK and does not require introspection or other "magic\." + +**Important** +Technically, it's possible to pass some scope other than `this` when instantiating a construct, which allows you to add constructs anywhere in the tree, or even in another stack in the same app\. For example, you could write a mixin\-style function that adds constructs to a scope passed in as an argument\. The practical difficulty here is that you can't easily ensure that the IDs you choose for your constructs are unique within someone else's scope\. The practice also makes your code more difficult to understand, maintain, and reuse\. It is virtually always better to find a way to express your intent without resorting to abusing the `scope` argument\. + +The AWS CDK uses the IDs of all constructs in the path from the tree's root to each child construct to generate the unique IDs required by AWS CloudFormation\. This approach means that construct IDs need be unique only within their scope, rather than within the entire stack as in native AWS CloudFormation\. It does, however, mean that if you move a construct to a different scope, its generated stack\-unique ID will change, and AWS CloudFormation will no longer consider it the same resource\. + +The construct tree is separate from the constructs you define in your AWS CDK code, but it is accessible through any construct's `node` attribute, which is a reference to the node that represents that construct in the tree\. Each node is a [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.ConstructNode.html](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.ConstructNode.html) instance, the attributes of which provide access to the tree's root and to the node's parent scopes and children\. ++ `node.children` – The direct children of the construct\. ++ `node.id` – The identifier of the construct within its scope\. ++ `node.path` – The full path of the construct including the IDs of all of its parents\. ++ `node.root` – The root of the construct tree \(the app\)\. ++ `node.scope` – The scope \(parent\) of the construct, or undefined if the node is the root\. ++ `node.scopes` – All parents of the construct, up to the root\. ++ `node.uniqueId` – The unique alphanumeric identifier for this construct within the tree \(by default, generated from `node.path` and a hash\)\. + +The construct tree defines an implicit order in which constructs are synthesized to resources in the final AWS CloudFormation template\. Where one resource must be created before another, AWS CloudFormation or the AWS Construct Library will generally infer the dependency and make sure the resources are created in the right order\. You can also add an explicit dependency between two nodes using `node.addDependency()`; see [Dependencies](https://docs.aws.amazon.com/cdk/api/v1/docs/core-readme.html#dependencies) in the AWS CDK API Reference\. + +The AWS CDK provides a simple way to visit every node in the construct tree and perform an operation on each one\. See [Aspects](aspects.md)\. \ No newline at end of file diff --git a/v1/context.md b/v1/context.md new file mode 100644 index 00000000..6ca690ff --- /dev/null +++ b/v1/context.md @@ -0,0 +1,329 @@ +# Runtime context<a name="context"></a> + +Context values are key\-value pairs that can be associated with an app, stack, or construct\. They may be supplied to your app from a file \(usually either `cdk.json` or `cdk.context.json` in your project directory\) or on the command line\. + +The CDK Toolkit uses context to cache values retrieved from your AWS account during synthesis, such as the Availability Zones in your account or the Amazon Machine Image \(AMI\) IDs currently available for Amazon EC2 instances\. Because these values are provided by your AWS account, they can change between runs of your CDK application, which makes them a potential source of unintended change\. The CDK Toolkit's caching behavior "freezes" these values for your CDK app until you decide to accept the new values\. + +Without context caching, if you had specified "latest Amazon Linux" as the AMI for your Amazon EC2 instances, and a new version of this AMI were released, then the next time you deployed your CDK stack, your already\-deployed instances would be using the outdated \("wrong"\) AMI and would therefore need to be upgraded\. Upgrading would result in replacing all your existing instances with new ones, which would probably be unexpected and undesired\. + +Instead, the CDK records your account's available AMIs in your project's `cdk.context.json` file, and uses the stored value for future synthesis operations\. This way, the list of AMIs is no longer a potential source of change, and you can be sure that your stacks will always synthesize to the same AWS CloudFormation templates\. + +Not all context values are cached values from your AWS environment\. [Feature flags](featureflags.md) are also context values\. You can also create your own context values for use by your apps or constructs\. + +Context keys are strings\. Values may be any type supported by JSON: numbers, strings, arrays, or objects\. + +**Tip** +If your constructs create their own context values, incorporate your library's package name in its keys so they won't conflict with other packages' context values\. + +Many context values are associated with a particular AWS environment, and a given CDK app can be deployed in more than one environment\. The key for such values includes the AWS account and region so that values from different environments do not conflict\. + +The context key below illustrates the format used by the AWS CDK, including the account and region\. + +``` +availability-zones:account=123456789012:region=eu-central-1 +``` + +**Important** +Cached context values are managed by the AWS CDK and its constructs, including constructs you may write\. Do not add or change cached context values by manually editing files\. It can be useful, however, to review `cdk.context.json` occasionally to see what values are being cached\. Context values that do not represent cached values should be stored under the `context` key of `cdk.json` so they won't be cleared when cached values are cleared\. + +## Sources of context values<a name="context_construct"></a> + +Context values can be provided to your AWS CDK app in six different ways: ++ Automatically from the current AWS account\. ++ Through the \-\-context option to the cdk command\. \(These values are always strings\.\) ++ In the project's `cdk.context.json` file\. ++ In the `context` key of the project's `cdk.json` file\. ++ In the `context` key of your `~/.cdk.json` file\. ++ In your AWS CDK app using the `construct.node.setContext()` method\. + +The project file `cdk.context.json` is where the AWS CDK caches context values retrieved from your AWS account\. This practice avoids unexpected changes to your deployments when, for example, a new Availability Zone is introduced\. The AWS CDK does not write context data to any of the other files listed\. + +**Important** +Because they are part of your application's state, `cdk.json` and `cdk.context.json` must be committed to source control along with the rest of your app's source code\. Otherwise, deployments in other environments \(for example, a CI pipeline\) may produce inconsistent results\. + +Context values are scoped to the construct that created them; they are visible to child constructs, but not to parents or siblings\. Context values set by the AWS CDK Toolkit \(the cdk command\), whether automatically, from a file, or from the \-\-context option, are implicitly set on the `App` construct, and so are visible to every construct in every stack in the app\. + +Your app can read a context value using the `construct.node.tryGetContext` method\. If the requested entry is not found on the current construct or any of its parents, the result is `undefined` \(or your language's equivalent, such as `None` in Python\)\. + +## Context methods<a name="context_methods"></a> + +The AWS CDK supports several context methods that enable AWS CDK apps to obtain contextual information from the AWS environment\. For example, you can get a list of Availability Zones that are available in a given AWS account and region, using the [stack\.availabilityZones](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.Stack.html#availabilityzones) method\. + +The following are the context methods: + +[HostedZone\.fromLookup](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-route53.HostedZone.html#static-from-wbr-lookupscope-id-query) +Gets the hosted zones in your account\. + +[stack\.availabilityZones](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.Stack.html#availabilityzones) +Gets the supported Availability Zones\. + +[StringParameter\.valueFromLookup](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-ssm.StringParameter.html#static-value-wbr-from-wbr-lookupscope-parametername) +Gets a value from the current Region's Amazon EC2 Systems Manager Parameter Store\. + +[Vpc\.fromLookup](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-ec2.Vpc.html#static-from-wbr-lookupscope-id-options) +Gets the existing Amazon Virtual Private Clouds in your accounts\. + +[LookupMachineImage](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-ec2.LookupMachineImage.html) +Looks up a machine image for use with a NAT instance in an Amazon Virtual Private Cloud\. + +If a required context value isn't available, the AWS CDK app notifies the CDK Toolkit that the context information is missing\. The CLI then queries the current AWS account for the information, stores the resulting context information in the `cdk.context.json` file, and executes the AWS CDK app again with the context values\. + +## Viewing and managing context<a name="context_viewing"></a> + +Use the cdk context command to view and manage the information in your `cdk.context.json` file\. To see this information, use the cdk context command without any options\. The output should be something like the following\. + +``` +Context found in cdk.json: + +┌───┬─────────────────────────────────────────────────────────────┬─────────────────────────────────────────────────────────┐ +│ # │ Key │ Value │ +├───┼─────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────┤ +│ 1 │ availability-zones:account=123456789012:region=eu-central-1 │ [ "eu-central-1a", "eu-central-1b", "eu-central-1c" ] │ +├───┼─────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────┤ +│ 2 │ availability-zones:account=123456789012:region=eu-west-1 │ [ "eu-west-1a", "eu-west-1b", "eu-west-1c" ] │ +└───┴─────────────────────────────────────────────────────────────┴─────────────────────────────────────────────────────────┘ + +Run cdk context --reset KEY_OR_NUMBER to remove a context key. If it is a cached value, it will be refreshed on the next cdk synth. +``` + +To remove a context value, run cdk context \-\-reset, specifying the value's corresponding key or number\. The following example removes the value that corresponds to the second key in the preceding example, which is the list of availability zones in the Ireland region\. + +``` +cdk context --reset 2 +``` + +``` +Context value +availability-zones:account=123456789012:region=eu-west-1 +reset. It will be refreshed on the next SDK synthesis run. +``` + +Therefore, if you want to update to the latest version of the Amazon Linux AMI, you can use the preceding example to do a controlled update of the context value and reset it, and then synthesize and deploy your app again\. + +``` +cdk synth +``` + +To clear all of the stored context values for your app, run cdk context \-\-clear, as follows\. + +``` +cdk context --clear +``` + +Only context values stored in `cdk.context.json` can be reset or cleared\. The AWS CDK does not touch other context values\. To protect a context value from being reset using these commands, then, you might copy the value to `cdk.json`\. + +## AWS CDK Toolkit `--context` flag<a name="context_cli"></a> + +Use the `--context` \(`-c` for short\) option to pass runtime context values to your CDK app during synthesis or deployment\. + +``` +cdk synth --context key=value MyStack +``` + +To specify multiple context values, repeat the \-\-context option any number of times, providing one key\-value pair each time\. + +``` +cdk synth --context key1=value1 --context key2=value2 MyStack +``` + +When synthesizing multiple stacks, the specified context values are passed to all stacks\. To provide different context values to individual stacks, either use different keys for the values, or use multiple cdk synth or cdk deploy commands\. + +Context values passed from the command line are always strings\. If a value is usually of some other type, your code must be prepared to convert or parse the value\. To allow non\-string context values provided in other ways \(for example, in `cdk.context.json`\) to work as expected, make sure the value is a string before converting it\. + +## Example<a name="context_example"></a> + +Below is an example of referencing an existing Amazon VPC using AWS CDK context\. + +------ +#### [ TypeScript ] + +``` +import * as cdk from '@aws-cdk/core'; +import * as ec2 from '@aws-cdk/aws-ec2'; + +export class ExistsVpcStack extends cdk.Stack { + + constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { + + super(scope, id, props); + + const vpcid = this.node.tryGetContext('vpcid'); + const vpc = ec2.Vpc.fromLookup(this, 'VPC', { + vpcId: vpcid, + }); + + const pubsubnets = vpc.selectSubnets({subnetType: ec2.SubnetType.PUBLIC}); + + new cdk.CfnOutput(this, 'publicsubnets', { + value: pubsubnets.subnetIds.toString(), + }); + } +} +``` + +------ +#### [ JavaScript ] + +``` +const cdk = require('@aws-cdk/core'); +const ec2 = require('@aws-cdk/aws-ec2'); + +class ExistsVpcStack extends cdk.Stack { + + constructor(scope, id, props) { + + super(scope, id, props); + + const vpcid = this.node.tryGetContext('vpcid'); + const vpc = ec2.Vpc.fromLookup(this, 'VPC', { + vpcId: vpcid + }); + + const pubsubnets = vpc.selectSubnets({subnetType: ec2.SubnetType.PUBLIC}); + + new cdk.CfnOutput(this, 'publicsubnets', { + value: pubsubnets.subnetIds.toString() + }); + } +} + +module.exports = { ExistsVpcStack } +``` + +------ +#### [ Python ] + +``` +import aws_cdk.core as cdk +import aws_cdk.aws_ec2 as ec2 + +class ExistsVpcStack(cdk.Stack): + + def __init__(scope: cdk.Construct, id: str, **kwargs): + + super().__init__(scope, id, **kwargs) + + vpcid = self.node.try_get_context("vpcid") + vpc = ec2.Vpc.from_lookup(self, "VPC", vpc_id=vpcid) + + pubsubnets = vpc.select_subnets(subnetType=ec2.SubnetType.PUBLIC) + + cdk.CfnOutput(self, "publicsubnets", + value=pubsubnets.subnet_ids.to_string()) +``` + +------ +#### [ Java ] + +``` +import software.amazon.awscdk.core.CfnOutput; + +import software.amazon.awscdk.services.ec2.Vpc; +import software.amazon.awscdk.services.ec2.VpcLookupOptions; +import software.amazon.awscdk.services.ec2.SelectedSubnets; +import software.amazon.awscdk.services.ec2.SubnetSelection; +import software.amazon.awscdk.services.ec2.SubnetType; + +public class ExistsVpcStack extends Stack { + public ExistsVpcStack(App context, String id) { + this(context, id, null); + } + + public ExistsVpcStack(App context, String id, StackProps props) { + super(context, id, props); + + String vpcId = (String)this.getNode().tryGetContext("vpcid"); + Vpc vpc = (Vpc)Vpc.fromLookup(this, "VPC", VpcLookupOptions.builder() + .vpcId(vpcId).build()); + + SelectedSubnets pubSubNets = vpc.selectSubnets(SubnetSelection.builder() + .subnetType(SubnetType.PUBLIC).build()); + + CfnOutput.Builder.create(this, "publicsubnets") + .value(pubSubNets.getSubnetIds().toString()).build(); + } +} +``` + +------ +#### [ C\# ] + +``` +using Amazon.CDK; +using Amazon.CDK.AWS.EC2; + +class ExistsVpcStack : Stack +{ + public ExistsVpcStack(App scope, string id, StackProps props) : base(scope, id, props) + { + var vpcId = (string)this.Node.TryGetContext("vpcid"); + var vpc = Vpc.FromLookup(this, "VPC", new VpcLookupOptions + { + VpcId = vpcId + }); + + SelectedSubnets pubSubNets = vpc.SelectSubnets([new SubnetSelection + { + SubnetType = SubnetType.PUBLIC + }]); + + new CfnOutput(this, "publicsubnets", new CfnOutputProps { + Value = pubSubNets.SubnetIds.ToString() + }); + } +} +``` + +------ + +You can use cdk diff to see the effects of passing in a context value on the command line: + +``` +cdk diff -c vpcid=vpc-0cb9c31031d0d3e22 +``` + +``` +Stack ExistsvpcStack +Outputs +[+] Output publicsubnets publicsubnets: {"Value":"subnet-06e0ea7dd302d3e8f,subnet-01fc0acfb58f3128f"} +``` + +The resulting context values can be viewed as shown here\. + +``` +cdk context -j +``` + +``` +{ + "vpc-provider:account=123456789012:filter.vpc-id=vpc-0cb9c31031d0d3e22:region=us-east-1": { + "vpcId": "vpc-0cb9c31031d0d3e22", + "availabilityZones": [ + "us-east-1a", + "us-east-1b" + ], + "privateSubnetIds": [ + "subnet-03ecfc033225be285", + "subnet-0cded5da53180ebfa" + ], + "privateSubnetNames": [ + "Private" + ], + "privateSubnetRouteTableIds": [ + "rtb-0e955393ced0ada04", + "rtb-05602e7b9f310e5b0" + ], + "publicSubnetIds": [ + "subnet-06e0ea7dd302d3e8f", + "subnet-01fc0acfb58f3128f" + ], + "publicSubnetNames": [ + "Public" + ], + "publicSubnetRouteTableIds": [ + "rtb-00d1fdfd823c82289", + "rtb-04bb1969b42969bcb" + ] + } +} +``` \ No newline at end of file diff --git a/v1/core_concepts.md b/v1/core_concepts.md new file mode 100644 index 00000000..d9e45d36 --- /dev/null +++ b/v1/core_concepts.md @@ -0,0 +1,5 @@ +# Concepts<a name="core_concepts"></a> + +This topic describes some of the concepts \(the why and how\) behind the AWS CDK\. It also discusses the AWS Construct Library\. + +AWS CDK apps are composed of building blocks known as [Constructs](constructs.md), which are composed together to form [stacks](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.Stack.html) and [apps](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.App.html)\. \ No newline at end of file diff --git a/v1/disaster-recovery-resiliency.md b/v1/disaster-recovery-resiliency.md new file mode 100644 index 00000000..c99d21f9 --- /dev/null +++ b/v1/disaster-recovery-resiliency.md @@ -0,0 +1,11 @@ +# Resilience for the AWS Cloud Development Kit \(AWS CDK\)<a name="disaster-recovery-resiliency"></a> + +The Amazon Web Services \(AWS\) global infrastructure is built around AWS Regions and Availability Zones\. + +AWS Regions provide multiple physically separated and isolated Availability Zones, which are connected with low\-latency, high\-throughput, and highly redundant networking\. + +With Availability Zones, you can design and operate applications and databases that automatically fail over between Availability Zones without interruption\. Availability Zones are more highly available, fault tolerant, and scalable than traditional single or multiple data center infrastructures\. + +For more information about AWS Regions and Availability Zones, see [AWS Global Infrastructure](https://aws.amazon.com/about-aws/global-infrastructure/)\. + +The AWS CDK follows the [shared responsibility model](https://aws.amazon.com/compliance/shared-responsibility-model/) through the specific Amazon Web Services \(AWS\) services it supports\. For AWS service security information, see the [AWS service security documentation page](https://docs.aws.amazon.com/security/?id=docs_gateway#aws-security) and [AWS services that are in scope of AWS compliance efforts by compliance program](https://aws.amazon.com/compliance/services-in-scope/)\. \ No newline at end of file diff --git a/v1/doc-history.md b/v1/doc-history.md new file mode 100644 index 00000000..35f54e6e --- /dev/null +++ b/v1/doc-history.md @@ -0,0 +1,43 @@ +# AWS CDK Developer Guide history<a name="doc-history"></a> + +See [Releases](https://github.com/awslabs/aws-cdk/releases) for information about AWS CDK releases\. The AWS CDK is updated approximately once a week\. Maintenance versions may be released between weekly releases to address critical issues\. Each release includes a matched AWS CDK Toolkit \(CDK CLI\), AWS Construct Library, and API Reference\. Updates to this Guide generally do not synchronize with AWS CDK releases\. + +**Note** +The table below represents significant documentation milestones\. We fix errors and improve content on an ongoing basis\. + +| Change | Description | Date | +| --- |--- |--- | +| [Document `cdk.json`](#doc-history) | Add documentation of `cdk.json` configuration values\. | April 20, 2022 | +| [Dependency management](#doc-history) | Add topic on managing dependencies with the AWS CDK\. | April 7, 2022 | +| [Remove double\-braces from Java examples](#doc-history) | Replace this anti\-pattern with Java 9 `Map.of` throughout\. | March 9, 2022 | +| [AWS CDK v2 release](#doc-history) | Improvements to CDK v1 Developer Guide to coincide with the release of CDK v2 and its documentation\. | December 4, 2021 | +| [`cdk watch`](#doc-history) | Add description of `cdk watch` command for incremental deployments\. | November 19, 2021 | +| [Testing with `assertions`](#doc-history) | Revise testing topic to use new `assertions` library\. | November 17, 2021 | +| [Experimental modules](#doc-history) | Explain how experimental modules work with CDK v2\. | October 28, 2021 | +| [Faster local development](#doc-history) | Add information on `--no-rollback` and `--hotswap` options for accelerated local development\. | October 7, 2021 | +| [Add local tooling information](#doc-history) | Update TypeScript and JavaScript topics with information on using locally\-installed tools \(`cdk`, `tsc`\)\. | September 28, 2021 | +| [Update CDK Pipelines API](#doc-history) | Update CDK Pipelines topic to use new API\. | August 24, 2021 | +| [CloudFormation Public Registry](#doc-history) | Add topic about using resource definitions from the CloudFormation Public Registry with the AWS CDK\. | June 24, 2021 | +| [Best Practices topic](#doc-history) | Add topic about best practices for developing CDK apps\. | June 10, 2021 | +| [Go developer preview](#doc-history) | Add information about Go language support \(in developer preview\) including a "Working with the CDK in Go" topic\. | April 19, 2021 | +| [Import or migrate AWS CloudFormation template](#doc-history) | Add description of the new `cloudformation-include.CfnInclude` class, a powerful way to import and migrate AWS CloudFormation templates, or to vend them as AWS CDK constructs\. | October 15, 2020 | +| [Add construct tree section](#doc-history) | Information about the construct tree and its relation to the constructs you define in your AWS CDK app\. | October 5, 2020 | +| [Add Bootstrapping topic](#doc-history) | A complete explanation of why and how to bootstrap AWS environments for the CDK, including a comprehensive discussion of how to customize the process\. | September 8, 2020 | +| [Add CDK Pipelines how\-to](#doc-history) | CDK Pipelines let you easily automate the deployment of your AWS CDK apps from source control whenever they're updated\. | July 17, 2020 | +| [Improve CDK Toolkit topic](#doc-history) | Include more information and examples around performing common tasks with the CLI \(and the relevant flags\) rather than just including a copy of the help\. | July 9, 2020 | +| [Improve CodePipeline example](#doc-history) | Update pipeline stack to build in proper language and add more material dealing with the CodeCommit repository\. | July 6, 2020 | +| [Improve Getting Started](#doc-history) | Remove extraneous material from Getting Started, use a more conversational tone, incorporate current best practices\. Break out Hello World into its own topic\. | June 17, 2020 | +| [Update stability index](#doc-history) | Incorporate the latest definitions of the stability levels for AWS Construct Library modules\. | June 11, 2020 | +| [CDK Toolkit versioning](#doc-history) | Add information about cloud assembly versioning and compatibility of the CDK Toolkit \(CLI\) with the AWS Construct Library | April 22, 2020 | +| [Translating from TypeScript](#doc-history) | Updated "CDK in Other Languages" topic to also include JavaScript, Java, and C\# and renamed it "Translating from TypeScript\." | April 10, 2020 | +| [Parameters topic](#doc-history) | Add Concepts topic on using parameters with the AWS CDK\. | April 8, 2020 | +| [JavaScript code snippets](#doc-history) | Reinstate JavaScript code snippets throughout \(automated translation via Babel\)\. | April 3, 2020 | +| [Working with the CDK](#doc-history) | Add "Working with the CDK" articles for the five supported languages\. Various other improvements and fixes\. | February 4, 2020 | +| [Java code snippets](#doc-history) | Add Java code snippets throughout\. Designate Java and C\# bindings stable\. | November 25, 2019 | +| [C\# code snippets](#doc-history) | Add C\# code snippets throughout\. | November 19, 2019 | +| [Python code snippets](#doc-history) | Add Python code snippets throughout\. Add Troubleshooting and Testing topics\. | November 14, 2019 | +| [Troubleshooting topic](#doc-history) | Add Troubleshooting topic to AWS CDK Developer Guide\. | October 30, 2019 | +| [Improve Environments topic](#doc-history) | Add Troubleshooting topic to AWS CDK Developer Guide\. | October 10, 2019 | +| [ECS Patterns improvements](#doc-history) | Updates to reflect improvements to ECS Patterns module\. | September 17, 2019 | +| [New tagging API](#doc-history) | Update tagging topic to use new API\. | August 13, 2019 | +| [General availability](#doc-history) | The AWS CDK Developer Guide is released\. | July 11, 2019 | \ No newline at end of file diff --git a/v1/ecs_example.md b/v1/ecs_example.md new file mode 100644 index 00000000..0ad3cd64 --- /dev/null +++ b/v1/ecs_example.md @@ -0,0 +1,416 @@ +# Creating an AWS Fargate service using the AWS CDK<a name="ecs_example"></a> + +This example walks you through how to create an AWS Fargate service running on an Amazon Elastic Container Service \(Amazon ECS\) cluster that's fronted by an internet\-facing Application Load Balancer from an image on Amazon ECR\. + +Amazon ECS is a highly scalable, fast, container management service that makes it easy to run, stop, and manage Docker containers on a cluster\. You can host your cluster on a serverless infrastructure that's managed by Amazon ECS by launching your services or tasks using the Fargate launch type\. For more control, you can host your tasks on a cluster of Amazon Elastic Compute Cloud \(Amazon EC2\) instances that you manage by using the Amazon EC2 launch type\. + +This tutorial shows you how to launch some services using the Fargate launch type\. If you've used the AWS Management Console to create a Fargate service, you know that there are many steps to follow to accomplish that task\. AWS has several tutorials and documentation topics that walk you through creating a Fargate service, including: ++ [How to Deploy Docker Containers \- AWS](https://aws.amazon.com/getting-started/tutorials/deploy-docker-containers) ++ [Setting Up with Amazon ECS](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/get-set-up-for-amazon-ecs.html) ++ [Getting Started with Amazon ECS Using Fargate](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ECS_GetStarted.html) + +This example creates a similar Fargate service in AWS CDK code\. + +The Amazon ECS construct used in this tutorial helps you use AWS services by providing the following benefits: ++ Automatically configures a load balancer\. ++ Automatically opens a security group for load balancers\. This enables load balancers to communicate with instances without you explicitly creating a security group\. ++ Automatically orders dependency between the service and the load balancer attaching to a target group, where the AWS CDK enforces the correct order of creating the listener before an instance is created\. ++ Automatically configures user data on automatically scaling groups\. This creates the correct configuration to associate a cluster to AMIs\. ++ Validates parameter combinations early\. This exposes AWS CloudFormation issues earlier, thus saving you deployment time\. For example, depending on the task, it's easy to misconfigure the memory settings\. Previously, you would not encounter an error until you deployed your app\. But now the AWS CDK can detect a misconfiguration and emit an error when you synthesize your app\. ++ Automatically adds permissions for Amazon Elastic Container Registry \(Amazon ECR\) if you use an image from Amazon ECR\. ++ Automatically scales\. The AWS CDK supplies a method so you can autoscalinginstances when you use an Amazon EC2 cluster\. This happens automatically when you use an instance in a Fargate cluster\. + + In addition, the AWS CDK prevents an instance from being deleted when automatic scaling tries to kill an instance, but either a task is running or is scheduled on that instance\. + + Previously, you had to create a Lambda function to have this functionality\. ++ Provides asset support, so that you can deploy a source from your machine to Amazon ECS in one step\. Previously, to use an application source you had to perform several manual steps, such as uploading to Amazon ECR and creating a Docker image\. + +See [ECS](https://docs.aws.amazon.com/cdk/api/v1/docs/aws-ecs-readme.html) for details\. + +**Important** +The `ApplicationLoadBalancedFargateService` constructs we'll be using includes numerous AWS components, some of which have non\-trivial costs if left provisioned in your AWS account, even if you don't use them\. Be sure to clean up \(cdk destroy\) after completing this example\. + +## Creating the directory and initializing the AWS CDK<a name="ecs_example_initialize"></a> + +Let's start by creating a directory to hold the AWS CDK code, and then creating a AWS CDK app in that directory\. + +------ +#### [ TypeScript ] + +``` +mkdir MyEcsConstruct +cd MyEcsConstruct +cdk init --language typescript +``` + +------ +#### [ JavaScript ] + +``` +mkdir MyEcsConstruct +cd MyEcsConstruct +cdk init --language javascript +``` + +------ +#### [ Python ] + +``` +mkdir MyEcsConstruct +cd MyEcsConstruct +cdk init --language python +source .venv/bin/activate +pip install -r requirements.txt +``` + +------ +#### [ Java ] + +``` +mkdir MyEcsConstruct +cd MyEcsConstruct +cdk init --language java +``` + +You may now import the Maven project into your IDE\. + +------ +#### [ C\# ] + +``` +mkdir MyEcsConstruct +cd MyEcsConstruct +cdk init --language csharp +``` + +You may now open `src/MyEcsConstruct.sln` in Visual Studio\. + +------ + +Run the app and confirm that it creates an empty stack\. + +``` +cdk synth +``` + +You should see a stack like the following, where *CDK\-VERSION* is the version of the CDK and *NODE\-VERSION* is the version of Node\.js\. \(Your output may differ slightly from what's shown here\.\) + +``` +Resources: + CDKMetadata: + Type: AWS::CDK::Metadata + Properties: + Modules: aws-cdk=CDK-VERSION,@aws-cdk/core=CDK-VERSION,@aws-cdk/cx-api=CDK-VERSION,jsii-runtime=node.js/NODE-VERSION +``` + +## Add the Amazon EC2 and Amazon ECS packages<a name="ecs_example_add_packages"></a> + +Install the AWS construct library modules for Amazon EC2 and Amazon ECS\. + +------ +#### [ TypeScript ] + +``` +npm install @aws-cdk/aws-ec2 @aws-cdk/aws-ecs @aws-cdk/aws-ecs-patterns +``` + +------ +#### [ JavaScript ] + +``` +npm install @aws-cdk/aws-ec2 @aws-cdk/aws-ecs @aws-cdk/aws-ecs-patterns +``` + +------ +#### [ Python ] + +``` +pip install aws_cdk.aws_ec2 aws_cdk.aws_ecs aws_cdk.aws_ecs_patterns +``` + +------ +#### [ Java ] + +Using your IDE's Maven integration \(e\.g\., in Eclipse, right\-click your project and choose **Maven** > **Add Dependency**\), install the following artifacts from the group `software.amazon.awscdk`: + +``` +ec2 +ecs +ecs-patterns +``` + +------ +#### [ C\# ] + +Choose **Tools** > **NuGet Package Manager** > **Manage NuGet Packages for Solution** in Visual Studio and add the following packages\. + +``` +Amazon.CDK.AWS.EC2 +Amazon.CDK.AWS.ECS +Amazon.CDK.AWS.ECS.Patterns +``` + +**Tip** +If you don't see these packages in the **Browse** tab of the **Manage Packages for Solution** page, make sure the **Include prerelease** checkbox is ticked\. +For a better experience, also add the `Amazon.Jsii.Analyzers` package to provide compile\-time checks for missing required properties\. + +------ + +## Create a Fargate service<a name="ecs_example_create_fargate_service"></a> + +There are two different ways to run your container tasks with Amazon ECS: ++ Use the `Fargate` launch type, where Amazon ECS manages the physical machines that your containers are running on for you\. ++ Use the `EC2` launch type, where you do the managing, such as specifying automatic scaling\. + +For this example, we'll create a Fargate service running on an ECS cluster fronted by an internet\-facing Application Load Balancer\. + +Add the following AWS Construct Library module imports to the indicated file\. + +------ +#### [ TypeScript ] + +File: `lib/my_ecs_construct-stack.ts` + +``` +import * as ec2 from "@aws-cdk/aws-ec2"; +import * as ecs from "@aws-cdk/aws-ecs"; +import * as ecs_patterns from "@aws-cdk/aws-ecs-patterns"; +``` + +------ +#### [ JavaScript ] + +File: `lib/my_ecs_construct-stack.js` + +``` +const ec2 = require("@aws-cdk/aws-ec2"); +const ecs = require("@aws-cdk/aws-ecs"); +const ecs_patterns = require("@aws-cdk/aws-ecs-patterns"); +``` + +------ +#### [ Python ] + +File: `my_ecs_construct/my_ecs_construct_stack.py` + +``` +from aws_cdk import (core, aws_ec2 as ec2, aws_ecs as ecs, + aws_ecs_patterns as ecs_patterns) +``` + +------ +#### [ Java ] + +File: `src/main/java/com/myorg/MyEcsConstructStack.java` + +``` +import software.amazon.awscdk.services.ec2.*; +import software.amazon.awscdk.services.ecs.*; +import software.amazon.awscdk.services.ecs.patterns.*; +``` + +------ +#### [ C\# ] + +File: `src/MyEcsConstruct/MyEcsConstructStack.cs` + +``` +using Amazon.CDK.AWS.EC2; +using Amazon.CDK.AWS.ECS; +using Amazon.CDK.AWS.ECS.Patterns; +``` + +------ + +Replace the comment at the end of the constructor with the following code\. + +------ +#### [ TypeScript ] + +``` +// Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// +// This file is licensed under the Apache License, Version 2.0 (the "License"). +// You may not use this file except in compliance with the License. A copy of the +// License is located at +// +// http://aws.amazon.com/apache2.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. +import * as core from "@aws-cdk/core"; +import * as ec2 from "@aws-cdk/aws-ec2"; +import * as ecs from "@aws-cdk/aws-ecs"; +import * as ecs_patterns from "@aws-cdk/aws-ecs-patterns"; + +export class MyEcsConstructStack extends core.Stack { + constructor(scope: core.App, id: string, props?: core.StackProps) { + super(scope, id, props); + + const vpc = new ec2.Vpc(this, "MyVpc", { + maxAzs: 3 // Default is all AZs in region + }); + + const cluster = new ecs.Cluster(this, "MyCluster", { + vpc: vpc + }); + + // Create a load-balanced Fargate service and make it public + new ecs_patterns.ApplicationLoadBalancedFargateService(this, "MyFargateService", { + cluster: cluster, // Required + cpu: 512, // Default is 256 + desiredCount: 6, // Default is 1 + taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample") }, + memoryLimitMiB: 2048, // Default is 512 + publicLoadBalancer: true // Default is true + }); + } +} +``` + +------ +#### [ JavaScript ] + +``` +// Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// +// This file is licensed under the Apache License, Version 2.0 (the "License"). +// You may not use this file except in compliance with the License. A copy of the +// License is located at +// +// http://aws.amazon.com/apache2.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. +import * as core from "@aws-cdk/core"; +import * as ec2 from "@aws-cdk/aws-ec2"; +import * as ecs from "@aws-cdk/aws-ecs"; +import * as ecs_patterns from "@aws-cdk/aws-ecs-patterns"; + +export class MyEcsConstructStack extends core.Stack { + constructor(scope: core.App, id: string, props?: core.StackProps) { + super(scope, id, props); + + const vpc = new ec2.Vpc(this, "MyVpc", { + maxAzs: 3 // Default is all AZs in region + }); + + const cluster = new ecs.Cluster(this, "MyCluster", { + vpc: vpc + }); + + // Create a load-balanced Fargate service and make it public + new ecs_patterns.ApplicationLoadBalancedFargateService(this, "MyFargateService", { + cluster: cluster, // Required + cpu: 512, // Default is 256 + desiredCount: 6, // Default is 1 + taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample") }, + memoryLimitMiB: 2048, // Default is 512 + publicLoadBalancer: true // Default is true + }); + } +} +``` + +------ +#### [ Python ] + +``` + vpc = ec2.Vpc(self, "MyVpc", max_azs=3) # default is all AZs in region + + cluster = ecs.Cluster(self, "MyCluster", vpc=vpc) + + ecs_patterns.ApplicationLoadBalancedFargateService(self, "MyFargateService", + cluster=cluster, # Required + cpu=512, # Default is 256 + desired_count=6, # Default is 1 + task_image_options=ecs_patterns.ApplicationLoadBalancedTaskImageOptions( + image=ecs.ContainerImage.from_registry("amazon/amazon-ecs-sample")), + memory_limit_mib=2048, # Default is 512 + public_load_balancer=True) # Default is True +``` + +------ +#### [ Java ] + +``` + Vpc vpc = Vpc.Builder.create(this, "MyVpc") + .maxAzs(3) // Default is all AZs in region + .build(); + + Cluster cluster = Cluster.Builder.create(this, "MyCluster") + .vpc(vpc).build(); + + // Create a load-balanced Fargate service and make it public + ApplicationLoadBalancedFargateService.Builder.create(this, "MyFargateService") + .cluster(cluster) // Required + .cpu(512) // Default is 256 + .desiredCount(6) // Default is 1 + .taskImageOptions( + ApplicationLoadBalancedTaskImageOptions.builder() + .image(ContainerImage.fromRegistry("amazon/amazon-ecs-sample")) + .build()) + .memoryLimitMiB(2048) // Default is 512 + .publicLoadBalancer(true) // Default is true + .build(); +``` + +------ +#### [ C\# ] + +``` + var vpc = new Vpc(this, "MyVpc", new VpcProps + { + MaxAzs = 3 // Default is all AZs in region + }); + + var cluster = new Cluster(this, "MyCluster", new ClusterProps + { + Vpc = vpc + }); + + // Create a load-balanced Fargate service and make it public + new ApplicationLoadBalancedFargateService(this, "MyFargateService", + new ApplicationLoadBalancedFargateServiceProps + { + Cluster = cluster, // Required + DesiredCount = 6, // Default is 1 + TaskImageOptions = new ApplicationLoadBalancedTaskImageOptions + { + Image = ContainerImage.FromRegistry("amazon/amazon-ecs-sample") + }, + MemoryLimitMiB = 2048, // Default is 256 + PublicLoadBalancer = true // Default is true + } + ); +``` + +------ + +Save it and make sure it runs and creates a stack\. + +``` +cdk synth +``` + +The stack is hundreds of lines, so we don't show it here\. The stack should contain one default instance, a private subnet and a public subnet for the three Availability Zones, and a security group\. + +Deploy the stack\. + +``` +cdk deploy +``` + +AWS CloudFormation displays information about the dozens of steps that it takes as it deploys your app\. + +That's how easy it is to create a Fargate\-powered Amazon ECS service to run a Docker image\. + +## Clean up<a name="ecs_example_destroy"></a> + +To avoid unexpected AWS charges, destroy your AWS CDK stack after you're done with this exercise\. + +``` +cdk destroy +``` \ No newline at end of file diff --git a/v1/environments.md b/v1/environments.md new file mode 100644 index 00000000..60ccb67f --- /dev/null +++ b/v1/environments.md @@ -0,0 +1,397 @@ +# Environments<a name="environments"></a> + +Each `Stack` instance in your AWS CDK app is explicitly or implicitly associated with an environment \(`env`\)\. An environment is the target AWS account and region into which the stack is intended to be deployed\. The region is specified using a region code; see [Regional endpoints](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints) for a list\. + +**Note** +For all but the simplest deployments, you will need to [bootstrap](bootstrapping.md) each environment you will deploy into\. Deployment requires certain AWS resources to be available, and these resources are provisioned by bootstrapping\. + +If you don't specify an environment when you instantiate a stack, the stack is said to be *environment\-agnostic*\. AWS CloudFormation templates synthesized from such a stack will try to use deploy\-time resolution on environment\-related attributes such as `stack.account`, `stack.region`, and `stack.availabilityZones` \(Python: `availability_zones`\)\. + +**Tip** +If you're using the standard AWS CDK development template, your stacks are instantiated in the same file where you instantiate the `App` object\. +The file named after your project \(for example, `hello-cdk.ts`\) in your project's `bin` folder\. +The file named after your project \(for example, `hello-cdk.js`\) in your project's `bin` folder\. +The file `app.py` in your project's main directory\. +The file named `ProjectNameApp.java`, for example `HelloCdkApp.java`, nested deep under the `src/main` directory\. +The file named `Program.cs` under `src\ProjectName`, for example `src\HelloCdk\Program.cs`\. + +In an environment\-agnostic stack, any constructs that use availability zones will see two AZs, allowing the stack to be deployed to any region\. + +When using cdk deploy to deploy environment\-agnostic stacks, the AWS CDK CLI uses the specified AWS CLI profile \(or the default profile, if none is specified\) to determine where to deploy\. The AWS CDK CLI follows a protocol similar to the AWS CLI to determine which AWS credentials to use when performing operations in your AWS account\. See [AWS CDK Toolkit \(`cdk` command\)](cli.md) for details\. + +For production stacks, we recommend that you explicitly specify the environment for each stack in your app using the `env` property\. The following example specifies different environments for its two different stacks\. + +------ +#### [ TypeScript ] + +``` +const envEU = { account: '2383838383', region: 'eu-west-1' }; +const envUSA = { account: '8373873873', region: 'us-west-2' }; + +new MyFirstStack(app, 'first-stack-us', { env: envUSA }); +new MyFirstStack(app, 'first-stack-eu', { env: envEU }); +``` + +------ +#### [ JavaScript ] + +``` +const envEU = { account: '2383838383', region: 'eu-west-1' }; +const envUSA = { account: '8373873873', region: 'us-west-2' }; + +new MyFirstStack(app, 'first-stack-us', { env: envUSA }); +new MyFirstStack(app, 'first-stack-eu', { env: envEU }); +``` + +------ +#### [ Python ] + +``` +env_EU = core.Environment(account="8373873873", region="eu-west-1") +env_USA = core.Environment(account="2383838383", region="us-west-2") + +MyFirstStack(app, "first-stack-us", env=env_USA) +MyFirstStack(app, "first-stack-eu", env=env_EU) +``` + +------ +#### [ Java ] + +``` +public class MyApp { + + // Helper method to build an environment + static Environment makeEnv(String account, String region) { + return Environment.builder() + .account(account) + .region(region) + .build(); + } + + public static void main(final String argv[]) { + App app = new App(); + + Environment envEU = makeEnv("8373873873", "eu-west-1"); + Environment envUSA = makeEnv("2383838383", "us-west-2"); + + new MyFirstStack(app, "first-stack-us", StackProps.builder() + .env(envUSA).build()); + new MyFirstStack(app, "first-stack-eu", StackProps.builder() + .env(envEU).build()); + + app.synth(); + } +} +``` + +------ +#### [ C\# ] + +``` +Amazon.CDK.Environment makeEnv(string account, string region) +{ + return new Amazon.CDK.Environment + { + Account = account, + Region = region + }; +} + +var envEU = makeEnv(account: "8373873873", region: "eu-west-1"); +var envUSA = makeEnv(account: "2383838383", region: "us-west-2"); + +new MyFirstStack(app, "first-stack-us", new StackProps { Env=envUSA }); +new MyFirstStack(app, "first-stack-eu", new StackProps { Env=envEU }); +``` + +------ + +When you hard\-code the target account and region as above, the stack will always be deployed to that specific account and region\. To make the stack deployable to a different target, but to determine the target at synthesis time, your stack can use two environment variables provided by the AWS CDK CLI: `CDK_DEFAULT_ACCOUNT` and `CDK_DEFAULT_REGION`\. These variables are set based on the AWS profile specified using the \-\-profile option, or the default AWS profile if you don't specify one\. + +The following code fragment shows how to access the account and region passed from the AWS CDK CLI in your stack\. + +------ +#### [ TypeScript ] + +Access environment variables via Node's `process` object\. + +**Note** + You need the DefinitelyTyped module to use `process` in TypeScript\. `cdk init` installs this module for you, but if you are working with a project created before it was added, or didn't set up your project using `cdk init`, install it manually\. + +``` +npm install @types/node +``` + +``` +new MyDevStack(app, 'dev', { + env: { + account: process.env.CDK_DEFAULT_ACCOUNT, + region: process.env.CDK_DEFAULT_REGION +}}); +``` + +------ +#### [ JavaScript ] + +Access environment variables via Node's `process` object\. + +``` +new MyDevStack(app, 'dev', { + env: { + account: process.env.CDK_DEFAULT_ACCOUNT, + region: process.env.CDK_DEFAULT_REGION +}}); +``` + +------ +#### [ Python ] + +Use the `os` module's `environ` dictionary to access environment variables\. + +``` +import os +MyDevStack(app, "dev", env=core.Environment( + account=os.environ["CDK_DEFAULT_ACCOUNT"], + region=os.environ["CDK_DEFAULT_REGION"])) +``` + +------ +#### [ Java ] + +Use `System.getenv()` to get the value of an environment variable\. + +``` +public class MyApp { + + // Helper method to build an environment + static Environment makeEnv(String account, String region) { + account = (account == null) ? System.getenv("CDK_DEFAULT_ACCOUNT") : account; + region = (region == null) ? System.getenv("CDK_DEFAULT_REGION") : region; + + return Environment.builder() + .account(account) + .region(region) + .build(); + } + + public static void main(final String argv[]) { + App app = new App(); + + Environment envEU = makeEnv(null, null); + Environment envUSA = makeEnv(null, null); + + new MyDevStack(app, "first-stack-us", StackProps.builder() + .env(envUSA).build()); + new MyDevStack(app, "first-stack-eu", StackProps.builder() + .env(envEU).build()); + + app.synth(); + } +} +``` + +------ +#### [ C\# ] + +Use `System.Environment.GetEnvironmentVariable()` to get the value of an environment variable\. + +``` +Amazon.CDK.Environment makeEnv(string account=null, string region=null) +{ + return new Amazon.CDK.Environment + { + Account = account ?? System.Environment.GetEnvironmentVariable("CDK_DEFAULT_ACCOUNT"), + Region = region ?? System.Environment.GetEnvironmentVariable("CDK_DEFAULT_REGION") + }; +} + +new MyDevStack(app, "dev", new StackProps { Env = makeEnv() }); +``` + +------ + +The AWS CDK distinguishes between not specifying the `env` property at all and specifying it using `CDK_DEFAULT_ACCOUNT` and `CDK_DEFAULT_REGION`\. The former implies that the stack should synthesize an environment\-agnostic template\. Constructs that are defined in such a stack cannot use any information about their environment\. For example, you can't write code like `if (stack.region === 'us-east-1')` or use framework facilities like [Vpc\.fromLookup](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-ec2.Vpc.html#static-from-wbr-lookupscope-id-options) \(Python: `from_lookup`\), which need to query your AWS account\. These features do not work at all without an explicit environment specified; to use them, you must specify `env`\. + +When you pass in your environment using `CDK_DEFAULT_ACCOUNT` and `CDK_DEFAULT_REGION`, the stack will be deployed in the account and Region determined by the AWS CDK CLI at the time of synthesis\. This allows environment\-dependent code to work, but it also means that the synthesized template could be different based on the machine, user, or session under which it is synthesized\. This behavior is often acceptable or even desirable during development, but it would probably be an anti\-pattern for production use\. + +You can set `env` however you like, using any valid expression\. For example, you might write your stack to support two additional environment variables to let you override the account and region at synthesis time\. We'll call these `CDK_DEPLOY_ACCOUNT` and `CDK_DEPLOY_REGION` here, but you could name them anything you like, as they are not set by the AWS CDK\. In the following stack's environment, we use our alternative environment variables if they're set, falling back to the default environment provided by the AWS CDK if they are not\. + +------ +#### [ TypeScript ] + +``` +new MyDevStack(app, 'dev', { + env: { + account: process.env.CDK_DEPLOY_ACCOUNT || process.env.CDK_DEFAULT_ACCOUNT, + region: process.env.CDK_DEPLOY_REGION || process.env.CDK_DEFAULT_REGION +}}); +``` + +------ +#### [ JavaScript ] + +``` +new MyDevStack(app, 'dev', { + env: { + account: process.env.CDK_DEPLOY_ACCOUNT || process.env.CDK_DEFAULT_ACCOUNT, + region: process.env.CDK_DEPLOY_REGION || process.env.CDK_DEFAULT_REGION +}}); +``` + +------ +#### [ Python ] + +``` +MyDevStack(app, "dev", env=core.Environment( + account=os.environ.get("CDK_DEPLOY_ACCOUNT", os.environ["CDK_DEFAULT_ACCOUNT"]), + region=os.environ.get("CDK_DEPLOY_REGION", os.environ["CDK_DEFAULT_REGION"]) +``` + +------ +#### [ Java ] + +``` +public class MyApp { + + // Helper method to build an environment + static Environment makeEnv(String account, String region) { + account = (account == null) ? System.getenv("CDK_DEPLOY_ACCOUNT") : account; + region = (region == null) ? System.getenv("CDK_DEPLOY_REGION") : region; + account = (account == null) ? System.getenv("CDK_DEFAULT_ACCOUNT") : account; + region = (region == null) ? System.getenv("CDK_DEFAULT_REGION") : region; + + return Environment.builder() + .account(account) + .region(region) + .build(); + } + + public static void main(final String argv[]) { + App app = new App(); + + Environment envEU = makeEnv(null, null); + Environment envUSA = makeEnv(null, null); + + new MyDevStack(app, "first-stack-us", StackProps.builder() + .env(envUSA).build()); + new MyDevStack(app, "first-stack-eu", StackProps.builder() + .env(envEU).build()); + + app.synth(); + } +} +``` + +------ +#### [ C\# ] + +``` +Amazon.CDK.Environment makeEnv(string account=null, string region=null) +{ + return new Amazon.CDK.Environment + { + Account = account ?? + System.Environment.GetEnvironmentVariable("CDK_DEPLOY_ACCOUNT") ?? + System.Environment.GetEnvironmentVariable("CDK_DEFAULT_ACCOUNT"), + Region = region ?? + System.Environment.GetEnvironmentVariable("CDK_DEPLOY_REGION") ?? + System.Environment.GetEnvironmentVariable("CDK_DEFAULT_REGION") + }; +} + +new MyDevStack(app, "dev", new StackProps { Env = makeEnv() }); +``` + +------ + +With your stack's environment declared this way, you can now write a short script or batch file like the following to set the variables from command line arguments, then call `cdk deploy`\. Any arguments beyond the first two are passed through to `cdk deploy` and can be used to specify command\-line options or stacks\. + +------ +#### [ macOS/Linux ] + +``` +#!/usr/bin/env bash +if [[ $# -ge 2 ]]; then + export CDK_DEPLOY_ACCOUNT=$1 + export CDK_DEPLOY_REGION=$2 + shift; shift + npx cdk deploy "$@" + exit $? +else + echo 1>&2 "Provide account and region as first two args." + echo 1>&2 "Additional args are passed through to cdk deploy." + exit 1 +fi +``` + +Save the script as `cdk-deploy-to.sh`, then execute `chmod +x cdk-deploy-to.sh` to make it executable\. + +------ +#### [ Windows ] + +``` +@findstr /B /V @ %~dpnx0 > %~dpn0.ps1 && powershell -ExecutionPolicy Bypass %~dpn0.ps1 %* +@exit /B %ERRORLEVEL% +if ($args.length -ge 2) { + $env:CDK_DEPLOY_ACCOUNT, $args = $args + $env:CDK_DEPLOY_REGION, $args = $args + npx cdk deploy $args + exit $lastExitCode +} else { + [console]::error.writeline("Provide account and region as first two args.") + [console]::error.writeline("Additional args are passed through to cdk deploy.") + exit 1 +} +``` + +The Windows version of the script uses PowerShell to provide the same functionality as the macOS/Linux version\. It also contains instructions to allow it to be run as a batch file so it can be easily invoked from a command line\. It should be saved as `cdk-deploy-to.bat`\. The file `cdk-deploy-to.ps1` will be created when the batch file is invoked\. + +------ + +Then you can write additional scripts that call the "deploy\-to" script to deploy to specific environments \(even multiple environments per script\): + +------ +#### [ macOS/Linux ] + +``` +#!/usr/bin/env bash +# cdk-deploy-to-test.sh +./cdk-deploy-to.sh 123457689 us-east-1 "$@" +``` + +------ +#### [ Windows ] + +``` +@echo off +rem cdk-deploy-to-test.bat +cdk-deploy-to 135792469 us-east-1 %* +``` + +------ + +When deploying to multiple environments, consider whether you want to continue deploying to other environments after a deployment fails\. The following example avoids deploying to the second production environment if the first doesn't succeed\. + +------ +#### [ macOS/Linux ] + +``` +#!/usr/bin/env bash +# cdk-deploy-to-prod.sh +./cdk-deploy-to.sh 135792468 us-west-1 "$@" || exit +./cdk-deploy-to.sh 246813579 eu-west-1 "$@" +``` + +------ +#### [ Windows ] + +``` +@echo off +rem cdk-deploy-to-prod.bat +cdk-deploy-to 135792469 us-west-1 %* || exit /B +cdk-deploy-to 245813579 eu-west-1 %* +``` + +------ + +Developers could still use the normal `cdk deploy` command to deploy to their own AWS environments for development\. \ No newline at end of file diff --git a/v1/examples.md b/v1/examples.md new file mode 100644 index 00000000..873931c2 --- /dev/null +++ b/v1/examples.md @@ -0,0 +1,5 @@ +# Examples<a name="examples"></a> + +This topic contains the following examples: ++ [Creating a serverless application using the AWS CDK](serverless_example.md) Creates a serverless application using Lambda, API Gateway, and Amazon S3\. ++ [Creating an AWS Fargate service using the AWS CDK](ecs_example.md) Creates an Amazon ECS Fargate service from an image on DockerHub\. \ No newline at end of file diff --git a/v1/featureflags.md b/v1/featureflags.md new file mode 100644 index 00000000..38d506cb --- /dev/null +++ b/v1/featureflags.md @@ -0,0 +1,20 @@ +# Feature flags<a name="featureflags"></a> + +The AWS CDK uses *feature flags* to enable potentially breaking behaviors in a release\. Flags are stored as [Runtime context](context.md) values in `cdk.json` \(or `~/.cdk.json`\) as shown here\. + +``` +{ + "app": "npx ts-node bin/tscdk.ts", + "context": { + "@aws-cdk/core:enableStackNameDuplicates": true + } +} +``` + +The names of all feature flags begin with the NPM name of the package affected by the particular flag\. In the example above, this is `@aws-cdk/core`, the AWS CDK framework itself, since the flag affects stack naming rules, a core AWS CDK function\. AWS Construct Library modules can also use feature flags\. + +Feature flags are disabled by default, so existing projects that do not specify the flag will continue to work as expected with later AWS CDK releases\. New projects created using cdk init include flags enabling all features available in the release that created the project\. Edit `cdk.json` to disable any flags for which you prefer the old behavior, or to add flags to enable new behaviors after upgrading the AWS CDK\. + +See the `CHANGELOG` in a given release for a description of any new feature flags added in that release\. A list of all current feature flags can be found on the AWS CDK GitHub repository in [https://github.com/aws/aws-cdk/blob/main/packages/%40aws-cdk/cx-api/FEATURE_FLAGS.md](https://github.com/aws/aws-cdk/blob/main/packages/%40aws-cdk/cx-api/FEATURE_FLAGS.md)\. + +As feature flags are stored in `cdk.json`, they are not removed by the cdk context \-\-reset or cdk context \-\-clear commands\. \ No newline at end of file diff --git a/v1/get_cfn_param.md b/v1/get_cfn_param.md new file mode 100644 index 00000000..12e07b27 --- /dev/null +++ b/v1/get_cfn_param.md @@ -0,0 +1,5 @@ +# Use an AWS CloudFormation value<a name="get_cfn_param"></a> + +See [Parameters](parameters.md) for information about using AWS CloudFormation parameters with the AWS CDK\. + +To get a reference to a resource in an existing AWS CloudFormation template, see [Import or migrate an existing AWS CloudFormation template](use_cfn_template.md)\. \ No newline at end of file diff --git a/v1/get_context_var.md b/v1/get_context_var.md new file mode 100644 index 00000000..33a839cf --- /dev/null +++ b/v1/get_context_var.md @@ -0,0 +1,104 @@ +# Get a value from a context variable<a name="get_context_var"></a> + +You can specify a context variable either as part of an AWS CDK CLI command, or in `cdk.json`\. + +To create a command line context variable, use the **\-\-context** \(**\-c**\) option, as shown in the following example\. + +``` +cdk synth -c bucket_name=mygroovybucket +``` + +To specify the same context variable and value in the `cdk.json` file, use the following code\. + +``` +{ + "context": { + "bucket_name": "myotherbucket" + } +} +``` + +To get the value of a context variable in your app, use the `TryGetContext` method in the context of a construct \(that is, when `this`, or `self` in Python, is an instance of some construct\)\. The example gets the context value **bucket\_name**\. If the requested value is not defined, `TryGetContext` returns `undefined` \(`None` in Python; `null` in Java and C\#; `nil` in Go\) rather than raising an exception\. + +------ +#### [ TypeScript ] + +``` +const bucket_name = this.node.tryGetContext('bucket_name'); +``` + +------ +#### [ JavaScript ] + +``` +const bucket_name = this.node.tryGetContext('bucket_name'); +``` + +------ +#### [ Python ] + +``` +bucket_name = self.node.try_get_context("bucket_name") +``` + +------ +#### [ Java ] + +``` +String bucketName = (String)this.getNode().tryGetContext("bucket_name"); +``` + +------ +#### [ C\# ] + +``` +var bucketName = this.Node.TryGetContext("bucket_name"); +``` + +------ + +Outside the context of a construct, you can access the context variable from the app object, like this\. + +------ +#### [ TypeScript ] + +``` +const app = new cdk.App(); +const bucket_name = app.node.tryGetContext('bucket_name') +``` + +------ +#### [ JavaScript ] + +``` +const app = new cdk.App(); +const bucket_name = app.node.tryGetContext('bucket_name'); +``` + +------ +#### [ Python ] + +``` +app = cdk.App() +bucket_name = app.node.try_get_context("bucket_name") +``` + +------ +#### [ Java ] + +``` +App app = App(); +String bucketName = (String)app.getNode().tryGetContext("bucket_name"); +``` + +------ +#### [ C\# ] + +``` +app = App(); +var bucketName = app.Node.TryGetContext("bucket_name"); +``` + +------ + +For more details on working with context variables, see [Runtime context](context.md)\. \ No newline at end of file diff --git a/v1/get_env_var.md b/v1/get_env_var.md new file mode 100644 index 00000000..7d4439eb --- /dev/null +++ b/v1/get_env_var.md @@ -0,0 +1,68 @@ +# Get a value from an environment variable<a name="get_env_var"></a> + +To get the value of an environment variable, use code like the following\. This code gets the value of the environment variable `MYBUCKET`\. + +------ +#### [ TypeScript ] + +``` +// Sets bucket_name to undefined if environment variable not set +var bucket_name = process.env.MYBUCKET; + +// Sets bucket_name to a default if env var doesn't exist +var bucket_name = process.env.MYBUCKET || "DefaultName"; +``` + +------ +#### [ JavaScript ] + +``` +// Sets bucket_name to undefined if environment variable not set +var bucket_name = process.env.MYBUCKET; + +// Sets bucket_name to a default if env var doesn't exist +var bucket_name = process.env.MYBUCKET || "DefaultName"; +``` + +------ +#### [ Python ] + +``` +import os + +# Raises KeyError if environment variable doesn't exist +bucket_name = os.environ["MYBUCKET"] + +# Sets bucket_name to None if environment variable doesn't exist +bucket_name = os.getenv("MYBUCKET") + +# Sets bucket_name to a default if env var doesn't exist +bucket_name = os.getenv("MYBUCKET", "DefaultName") +``` + +------ +#### [ Java ] + +``` +// Sets bucketName to null if environment variable doesn't exist +String bucketName = System.getenv("MYBUCKET"); + +// Sets bucketName to a default if env var doesn't exist +String bucketName = System.getenv("MYBUCKET"); +if (bucketName == null) bucketName = "DefaultName"; +``` + +------ +#### [ C\# ] + +``` +using System; + +// Sets bucket name to null if environment variable doesn't exist +string bucketName = Environment.GetEnvironmentVariable("MYBUCKET"); + +// Sets bucket_name to a default if env var doesn't exist +string bucketName = Environment.GetEnvironmentVariable("MYBUCKET") ?? "DefaultName"; +``` + +------ \ No newline at end of file diff --git a/v1/get_secrets_manager_value.md b/v1/get_secrets_manager_value.md new file mode 100644 index 00000000..a975e114 --- /dev/null +++ b/v1/get_secrets_manager_value.md @@ -0,0 +1,114 @@ +# Get a value from AWS Secrets Manager<a name="get_secrets_manager_value"></a> + +To use values from AWS Secrets Manager in your AWS CDK app, use the [fromSecretAttributes](https://docs.aws.amazon.com/cdk/api/v1/docs/aws-secretsmanager/secret.html#aws_secretsmanager_Secret_fromSecretAttributes) method\. It represents a value that is retrieved from Secrets Manager and used at AWS CloudFormation deployment time\. + +------ +#### [ TypeScript ] + +``` +import * as sm from "@aws-cdk/aws-secretsmanager"; + +export class SecretsManagerStack extends core.Stack { + constructor(scope: core.App, id: string, props?: core.StackProps) { + super(scope, id, props); + + const secret = sm.Secret.fromSecretAttributes(this, "ImportedSecret", { + secretCompleteArn: + "arn:aws:secretsmanager:<region>:<account-id-number>:secret:<secret-name>-<random-6-characters>" + // If the secret is encrypted using a KMS-hosted CMK, either import or reference that key: + // encryptionKey: ... + }); +``` + +------ +#### [ JavaScript ] + +``` +const sm = require("@aws-cdk/aws-secretsmanager"); + +class SecretsManagerStack extends core.Stack { + constructor(scope, id, props) { + super(scope, id, props); + + const secret = sm.Secret.fromSecretAttributes(this, "ImportedSecret", { + secretCompleteArn: + "arn:aws:secretsmanager:<region>:<account-id-number>:secret:<secret-name>-<random-6-characters>" + // If the secret is encrypted using a KMS-hosted CMK, either import or reference that key: + // encryptionKey: ... + }); + } +} + +module.exports = { SecretsManagerStack } +``` + +------ +#### [ Python ] + +``` +import aws_cdk.aws_secretsmanager as sm + +class SecretsManagerStack(core.Stack): + def __init__(self, scope: core.App, id: str, **kwargs): + super().__init__(scope, name, **kwargs) + + secret = sm.Secret.from_secret_attributes(self, "ImportedSecret", + secret_complete_arn="arn:aws:secretsmanager:<region>:<account-id-number>:secret:<secret-name>-<random-6-characters>", + # If the secret is encrypted using a KMS-hosted CMK, either import or reference that key: + # encryption_key=.... + ) +``` + +------ +#### [ Java ] + +``` +import software.amazon.awscdk.services.secretsmanager.Secret; +import software.amazon.awscdk.services.secretsmanager.SecretAttributes; + +public class SecretsManagerStack extends Stack { + public SecretsManagerStack(App scope, String id) { + this(scope, id, null); + } + + public SecretsManagerStack(App scope, String id, StackProps props) { + super(scope, id, props); + + Secret secret = (Secret)Secret.fromSecretAttributes(this, "ImportedSecret", SecretAttributes.builder() + .secretCompleteArn("arn:aws:secretsmanager:<region>:<account-id-number>:secret:<secret-name>-<random-6-characters>") + // If the secret is encrypted using a KMS-hosted CMK, either import or reference that key: + // .encryptionKey(...) + .build()); + } +} +``` + +------ +#### [ C\# ] + +``` +using Amazon.CDK.AWS.SecretsManager; + +public class SecretsManagerStack : Stack +{ + public SecretsManagerStack(App scope, string id, StackProps props) : base(scope, id, props) { + + var secret = Secret.FromSecretAttributes(this, "ImportedSecret", new SecretAttributes { + SecretCompleteArn = "arn:aws:secretsmanager:<region>:<account-id-number>:secret:<secret-name>-<random-6-characters>" + // If the secret is encrypted using a KMS-hosted CMK, either import or reference that key: + // encryptionKey = ..., + }); + } +``` + +------ + +**Tip** +Use the [create\-secret](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_secretsmanager.Secret.html) CLI command to create a secret from the command\-line, such as when testing: + +``` +aws secretsmanager create-secret --name ImportedSecret --secret-string mygroovybucket +``` +The command returns an ARN you can use with the above example\. + +Once you have created a `Secret` instance, you can get the secret's value from the instance's `secretValue` attribute\. The value is represented by a `[SecretValue](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.SecretValue.html)` instance, a special type of [Tokens](tokens.md)\. As it is a token, it has meaning only after resolution; your CDK app does not need to access its actual value, but can instead pass the `SecretValue` instance \(or its string or numeric representation\) to whatever CDK method needs the value\. \ No newline at end of file diff --git a/v1/get_ssm_value.md b/v1/get_ssm_value.md new file mode 100644 index 00000000..33903694 --- /dev/null +++ b/v1/get_ssm_value.md @@ -0,0 +1,175 @@ +# Get a value from the Systems Manager Parameter Store<a name="get_ssm_value"></a> + +The AWS CDK can retrieve the value of AWS Systems Manager Parameter Store attributes\. During synthesis, the AWS CDK produces a [token](tokens.md) that is resolved by AWS CloudFormation during deployment\. + +The AWS CDK supports retrieving both plain and secure values\. You may request a specific version of either kind of value\. For plain values only, you may omit the version from your request to receive the latest version\. You must always specify the version when requesting the value of a secure attribute\. + +**Note** +This topic shows how to read attributes from the AWS Systems Manager Parameter Store\. You can also read secrets from the AWS Secrets Manager \(see [Get a value from AWS Secrets Manager](get_secrets_manager_value.md)\)\. + +## Reading Systems Manager values at deployment time<a name="ssm_read_at_deploy"></a> + +To read values from the Systems Manager Parameter Store, use the [valueForStringParameter](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-ssm.StringParameter.html#static-value-for-string-parameterscope-parametername-version) and [valueForSecureStringParameter](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-ssm.StringParameter.html#static-value-for-secure-string-parameterscope-parametername-version) methods, depending on whether the attribute you want is a plain string or a secure string value\. These methods return [tokens](tokens.md), not the actual value\. The value is resolved by AWS CloudFormation during deployment\. + +A [limited number of AWS services](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/dynamic-references.html#template-parameters-dynamic-patterns-resources) currently support this feature\. + +------ +#### [ TypeScript ] + +``` +import * as ssm from '@aws-cdk/aws-ssm'; + +// Get latest version or specified version of plain string attribute +const latestStringToken = ssm.StringParameter.valueForStringParameter( + this, 'my-plain-parameter-name'); // latest version +const versionOfStringToken = ssm.StringParameter.valueForStringParameter( + this, 'my-plain-parameter-name', 1); // version 1 + +// Get specified version of secure string attribute +const secureStringToken = ssm.StringParameter.valueForSecureStringParameter( + this, 'my-secure-parameter-name', 1); // must specify version +``` + +------ +#### [ JavaScript ] + +``` +const ssm = require('@aws-cdk/aws-ssm'); + +// Get latest version or specified version of plain string attribute +const latestStringToken = ssm.StringParameter.valueForStringParameter( + this, 'my-plain-parameter-name'); // latest version +const versionOfStringToken = ssm.StringParameter.valueForStringParameter( + this, 'my-plain-parameter-name', 1); // version 1 + +// Get specified version of secure string attribute +const secureStringToken = ssm.StringParameter.valueForSecureStringParameter( + this, 'my-secure-parameter-name', 1); // must specify version +``` + +------ +#### [ Python ] + +``` +import aws_cdk.aws_ssm as ssm + +# Get latest version or specified version of plain string attribute +latest_string_token = ssm.StringParameter.value_for_string_parameter( + self, "my-plain-parameter-name") +latest_string_token = ssm.StringParameter.value_for_string_parameter( + self, "my-plain-parameter-name", 1) + +# Get specified version of secure string attribute +secure_string_token = ssm.StringParameter.value_for_secure_string_parameter( + self, "my-secure-parameter-name", 1) # must specify version +``` + +------ +#### [ Java ] + +``` +import software.amazon.awscdk.services.ssm.StringParameter; + +//Get latest version or specified version of plain string attribute +String latestStringToken = StringParameter.valueForStringParameter( + this, "my-plain-parameter-name"); // latest version +String versionOfStringToken = StringParameter.valueForStringParameter( + this, "my-plain-parameter-name", 1); // version 1 + +//Get specified version of secure string attribute +String secureStringToken = StringParameter.valueForSecureStringParameter( + this, "my-secure-parameter-name", 1); // must specify version +``` + +------ +#### [ C\# ] + +``` +using Amazon.CDK.AWS.SSM; + +// Get latest version or specified version of plain string attribute +var latestStringToken = StringParameter.ValueForStringParameter( + this, "my-plain-parameter-name"); // latest version +var versionOfStringToken = StringParameter.ValueForStringParameter( + this, "my-plain-parameter-name", 1); // version 1 + +// Get specified version of secure string attribute +var secureStringToken = StringParameter.ValueForSecureStringParameter( + this, "my-secure-parameter-name", 1); // must specify version +``` + +------ + +## Reading Systems Manager values at synthesis time<a name="ssm_read_at_synth"></a> + +It is sometimes useful to "bake in" a parameter at synthesis time, so that the resulting AWS CloudFormation template always uses the same value, rather than resolving the value during deployment\. + +To read a value from the Systems Manager parameter store at synthesis time, use the [valueFromLookup](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-ssm.StringParameter.html#static-value-wbr-from-wbr-lookupscope-parametername) method \(Python: `value_from_lookup`\)\. This method returns the actual value of the parameter as a [Runtime context](context.md) value\. If the value is not already cached in `cdk.json` or passed on the command line, it will be retrieved from the current AWS account\. For this reason, the stack *must* be synthesized with explicit account and region information\. + +Only plain Systems Manager strings may be retrieved, not secure strings\. It is not possible to request a specific version; the latest version is always returned\. + +**Important** +The retrieved value will end up in your synthesized AWS CloudFormation template, which may be a security risk depending on who has access to your AWS CloudFormation templates and what kind of value it is\. Generally, don't use this feature for passwords, keys, or other values you want to keep private\. + +------ +#### [ TypeScript ] + +``` +import * as ssm from '@aws-cdk/aws-ssm'; + +const stringValue = ssm.StringParameter.valueFromLookup(this, 'my-plain-parameter-name'); +``` + +------ +#### [ JavaScript ] + +``` +const ssm = require('@aws-cdk/aws-ssm'); + +const stringValue = ssm.StringParameter.valueFromLookup(this, 'my-plain-parameter-name'); +``` + +------ +#### [ Python ] + +``` +import aws_cdk.aws_ssm as ssm + +string_value = ssm.StringParameter.value_from_lookup(self, "my-plain-parameter-name") +``` + +------ +#### [ Java ] + +``` +import software.amazon.awscdk.services.ssm.StringParameter; + +String stringValue = StringParameter.valueFromLookup(this, "my-plain-parameter-name"); +``` + +------ +#### [ C\# ] + +``` +using Amazon.CDK.AWS.SSM; + +var stringValue = StringParameter.ValueFromLookup(this, "my-plain-parameter-name"); +``` + +------ + +## Writing values to Systems Manager<a name="ssm_write"></a> + +You can use the AWS CLI, the AWS Management Console, or an AWS SDK to set Systems Manager parameter values\. The following examples use the [ssm put\-parameter](https://docs.aws.amazon.com/cli/latest/reference/ssm/put-parameter.html) CLI command\. + +``` +aws ssm put-parameter --name "parameter-name" --type "String" --value "parameter-value" +aws ssm put-parameter --name "secure-parameter-name" --type "SecureString" --value "secure-parameter-value" +``` + +When updating an SSM value that already exists, also include the `--overwrite` option\. + +``` +aws ssm put-parameter --overwrite --name "parameter-name" --type "String" --value "parameter-value" +aws ssm put-parameter --overwrite --name "secure-parameter-name" --type "SecureString" --value "secure-parameter-value" +``` \ No newline at end of file diff --git a/v1/getting_started.md b/v1/getting_started.md new file mode 100644 index 00000000..a6839166 --- /dev/null +++ b/v1/getting_started.md @@ -0,0 +1,247 @@ +# Getting started with the AWS CDK<a name="getting_started"></a> + +This topic introduces you to important AWS CDK concepts and describes how to install and configure the AWS CDK\. When you're done, you'll be ready to create [your first AWS CDK app](hello_world.md)\. + +## Your background<a name="getting_started_background"></a> + +The AWS Cloud Development Kit \(AWS CDK\) lets you define your cloud infrastructure as code in one of its supported programming languages\. It is intended for moderately to highly experienced AWS users\. + +Ideally, you already have experience with popular AWS services, particularly [AWS Identity and Access Management](https://aws.amazon.com/iam/) \(IAM\)\. You might already have AWS credentials on your workstation for use with an AWS SDK or the AWS CLI and experience working with AWS resources programmatically\. + +Familiarity with [AWS CloudFormation](https://aws.amazon.com/cloudformation/) is also useful, as the output of an AWS CDK program is an AWS CloudFormation template\. + +Finally, you should be proficient in the programming language you intend to use with the AWS CDK\. + +## Key concepts<a name="getting_started_concepts"></a> + +The AWS CDK is designed around a handful of important concepts\. We will introduce a few of these here briefly\. Follow the links to learn more, or see the Concepts topics in this guide's Table of Contents\. + +An AWS CDK [app](apps.md) is an application written in TypeScript, JavaScript, Python, Java, C\#, or Go that uses the AWS CDK to define AWS infrastructure\. An app defines one or more [stacks](stacks.md)\. Stacks \(equivalent to AWS CloudFormation stacks\) contain [constructs](constructs.md), each of which defines one or more concrete AWS resources, such as Amazon S3 buckets, Lambda functions, Amazon DynamoDB tables, and so on\. + +Constructs \(as well as stacks and apps\) are represented as classes \(types\) in your programming language of choice\. You instantiate constructs within a stack to declare them to AWS, and connect them to each other using well\-defined interfaces\. + +The AWS CDK includes the AWS CDK Toolkit \(also called the CLI\), a command\-line tool for working with your AWS CDK apps and stacks\. Among other functions, the Toolkit provides the ability to convert one or more AWS CDK stacks to AWS CloudFormation templates and related assets \(a process called *synthesis*\) and to deploy your stacks to an AWS account\. + +The AWS CDK includes a library of AWS constructs called the AWS Construct Library\. Each AWS service has at least one corresponding module in the library containing the constructs that represent that service's resources\. + +Constructs come in three fundamental flavors: ++ **AWS CloudFormation\-only** or L1 \(short for "layer 1"\)\. These constructs correspond directly to resource types defined by AWS CloudFormation\. In fact, these constructs are automatically generated from the AWS CloudFormation specification, so when a new AWS service is launched, the AWS CDK supports it a short time after AWS CloudFormation does\. + + AWS CloudFormation resources always have names that begin with `Cfn`\. For example, in the Amazon S3 module, `CfnBucket` is the L1 construct for an Amazon S3 bucket\. ++ **Curated** or L2\. These constructs are carefully developed by the AWS CDK team to address specific use cases and simplify infrastructure development\. For the most part, they encapsulate L1 resources, providing sensible defaults and best\-practice security policies\. For example, in the Amazon S3 module, `Bucket` is the L2 construct for an Amazon S3 bucket\. + + Modules may also define supporting resources needed by the primary resource\. Some services have more than one L2 module in the Construct Library for organizational purposes\. ++ **Patterns** or L3\. Patterns declare multiple resources to create entire AWS architectures for particular use cases\. All the plumbing is already hooked up, and configuration is boiled down to a few important parameters\. In the AWS Construct Library, patterns are in separate modules from L1 and L2 constructs\. + +The AWS CDK's core module \(usually imported into code as `core` or `cdk`\) contains constructs used by the AWS CDK itself as well as base classes for apps, stacks, and other AWS CDK objects\. + +Numerous third parties have also published constructs compatible with the AWS CDK\. Visit [Construct Hub](https://constructs.dev/search?q=&cdk=aws-cdk&cdkver=1&offset=0) to explore the AWS CDK construct ecosystem\. + +## Supported programming languages<a name="getting_started_languages"></a> + +The AWS CDK has first\-class support for TypeScript, JavaScript, Python, Java, C\#, and Go\. Other JVM and \.NET CLR languages may also be used, at least in theory, but we are unable to offer support for them at this time\. + +To facilitate supporting so many languages, the AWS CDK is developed in one language \(TypeScript\) and language bindings are generated for the other languages through the use of a tool called [JSII](https://github.com/aws/jsii)\. + +We have taken pains to make AWS CDK app development in each language follow that language's usual conventions, so writing AWS CDK apps feels natural, not like writing TypeScript in Python \(for example\)\. Take a look: + +------ +#### [ TypeScript ] + +``` +const bucket = new s3.Bucket(this, 'MyBucket', { + bucketName: 'my-bucket', + versioned: true, + websiteRedirect: {hostName: 'aws.amazon.com'}}); +``` + +------ +#### [ JavaScript ] + +``` +const bucket = new s3.Bucket(this, 'MyBucket', { + bucketName: 'my-bucket', + versioned: true, + websiteRedirect: {hostName: 'aws.amazon.com'}}); +``` + +------ +#### [ Python ] + +``` +bucket = s3.Bucket("MyBucket", bucket_name="my-bucket", versioned=True, + website_redirect=s3.RedirectTarget(host_name="aws.amazon.com")) +``` + +------ +#### [ Java ] + +``` +Bucket bucket = Bucket.Builder.create(self, "MyBucket") + .bucketName("my-bucket") + .versioned(true) + .websiteRedirect(new RedirectTarget.Builder() + .hostName("aws.amazon.com").build()) + .build(); +``` + +------ +#### [ C\# ] + +``` +var bucket = new Bucket(this, "MyBucket", new BucketProps { + BucketName = "my-bucket", + Versioned = true, + WebsiteRedirect = new RedirectTarget { + HostName = "aws.amazon.com" + }}); +``` + +------ + +**Note** +These code snippets are intended for illustration only\. They are incomplete and won't run as they are\. + +The AWS Construct Library is distributed using each language's standard package management tools, including NPM, PyPi, Maven, and NuGet\. There's even a version of the [AWS CDK API Reference](https://docs.aws.amazon.com/cdk/api/v1/docs/aws-construct-library.html) for each language\. + +To help you use the AWS CDK in your favorite language, this Guide includes topics that explain how to use the AWS CDK in all supported languages\. ++ [Working with the AWS CDK in TypeScript](work-with-cdk-typescript.md) ++ [Working with the AWS CDK in JavaScript](work-with-cdk-javascript.md) ++ [Working with the AWS CDK in Python](work-with-cdk-python.md) ++ [Working with the AWS CDK in Java](work-with-cdk-java.md) ++ [Working with the AWS CDK in C\#](work-with-cdk-csharp.md) + +TypeScript was the first language supported by the AWS CDK, and much AWS CDK example code is written in TypeScript\. This Guide includes a topic specifically to show how to adapt TypeScript AWS CDK code for use with the other supported languages\. See [Translating TypeScript AWS CDK code to other languages](multiple_languages.md)\. + +## Prerequisites<a name="getting_started_prerequisites"></a> + +Here's what you need to install to use the AWS CDK\. + +All AWS CDK developers, even those working in Python, Java, C\#, or Go, need [Node\.js](https://nodejs.org/en/download/) 10\.13\.0 or later\. All supported languages use the same back end, which runs on Node\.js\. We recommend a version in [active long\-term support](https://nodejs.org/en/about/releases/), which, at this writing, is the latest 16\.x release\. Your organization may have a different recommendation\. + +**Important** +Node\.js versions 13\.0\.0 through 13\.6\.0 are not compatible with the AWS CDK due to compatibility issues with its dependencies\. + +You must configure your workstation with your credentials and an AWS region, if you have not already done so\. If you have the AWS CLI installed, the easiest way to satisfy this requirement is issue the following command: + +``` +aws configure +``` + +Provide your AWS access key ID, secret access key, and default region when prompted\. + +You may also manually create or edit the `~/.aws/config` and `~/.aws/credentials` \(macOS/Linux\) or `%USERPROFILE%\.aws\config` and `%USERPROFILE%\.aws\credentials` \(Windows\) files to contain credentials and a default region, in the following format\. ++ In `~/.aws/config` or `%USERPROFILE%\.aws\config` + + ``` + [default] + region=us-west-2 + ``` ++ In `~/.aws/credentials` or `%USERPROFILE%\.aws\credentials` + + ``` + [default] + aws_access_key_id=AKIAI44QH8DHBEXAMPLE + aws_secret_access_key=je7MtGbClwBF/2Zp9Utk/h3yCo8nvbEXAMPLEKEY + ``` + +**Note** +Although the AWS CDK uses credentials from the same configuration files as other AWS tools and SDKs, including the [AWS Command Line Interface](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html), it may behave slightly differently from these tools\. In particular, if you use a named profile from the `credentials` file, the `config` must have a profile of the same name specifying the region\. The AWS CDK does not fall back to reading the region from the `[default]` section in `config`\. Also, do not use a profile named "default" \(e\.g\. `[profile default]`\)\. See [Setting credentials](https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/setting-credentials.html) for complete details on setting up credentials for the AWS SDK for JavaScript, which the AWS CDK uses under the hood\. +The AWS CDK natively supports AWS IAM Identity Center \(successor to AWS Single Sign\-On\)\. To use IAM Identity Center with the CDK, first create a profile using aws configure sso\. Then log in using aws sso login\. Finally, specify this profile when issuing cdk commands using the \-\-profile option or the `AWS_PROFILE` environment variable\. + +Alternatively, you can set the environment variables `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, and `AWS_DEFAULT_REGION` to appropriate values\. + +**Important** +We strongly recommend against using your AWS root account for day\-to\-day tasks\. Instead, create a user in IAM and use its credentials with the CDK\. Best practices are to change this account's access key regularly and to use a least\-privileges role \(specifying `--role-arn`\) when deploying\. + +Other prerequisites depend on the language in which you develop AWS CDK applications and are as follows\. + +------ +#### [ TypeScript ] ++ TypeScript 3\.8 or later \(`npm -g install typescript`\) + +------ +#### [ JavaScript ] + +No additional requirements + +------ +#### [ Python ] ++ Python 3\.6 or later including `pip` and `virtualenv` + +------ +#### [ Java ] ++ Java Development Kit \(JDK\) 8 \(a\.k\.a\. 1\.8\) or later ++ Apache Maven 3\.5 or later + +Java IDE recommended \(we use Eclipse in some examples in this Developer Guide\)\. IDE must be able to import Maven projects\. Check to make sure your project is set to use Java 1\.8\. Set the JAVA\_HOME environment variable to the path where you have installed the JDK\. + +------ +#### [ C\# ] + +\.NET Core 3\.1 or later\. + +Visual Studio 2019 \(any edition\) or Visual Studio Code recommended\. + +------ + +**Note** +Third\-party Language Deprecation: language version is only supported until its EOL \(End Of Life\) shared by the vendor or community and is subject to change with prior notice\. + +## Install the AWS CDK<a name="getting_started_install"></a> + +Install the AWS CDK Toolkit globally using the following Node Package Manager command\. + +``` +npm install -g aws-cdk@1.x +``` + +Run the following command to verify correct installation and print the version number of the AWS CDK\. + +``` +cdk --version +``` + +## Bootstrapping<a name="getting_started_bootstrap"></a> + +Many AWS CDK stacks that you write will include [assets](assets.md): external files that are deployed with the stack, such as AWS Lambda functions or Docker images\. The AWS CDK uploads these to an Amazon S3 bucket or other container so they are available to AWS CloudFormation during deployment\. Deployment requires that these containers already exist in the account and region you are deploying into\. Creating them is called [bootstrapping](bootstrapping.md)\. To bootstrap, issue: + +``` +cdk bootstrap aws://ACCOUNT-NUMBER/REGION +``` + +**Tip** +If you don't have your AWS account number handy, you can get it from the AWS Management Console\. Or, if you have the AWS CLI installed, the following command displays your default account information, including the account number\. + +``` +aws sts get-caller-identity +``` +If you have created named profiles in your local AWS configuration, you can use the `--profile` option to display the account information for a specific profile's account, such as the *prod* profile as shown here\. + +``` +aws sts get-caller-identity --profile prod +``` +To display the default region, use `aws configure get`\. + +``` +aws configure get region +aws configure get region --profile prod +``` + +## AWS CDK tools<a name="getting_started_tools"></a> + +The AWS CDK Toolkit, also known as the Command Line Interface \(CLI\), is the main tool you use to interact with your AWS CDK app\. It executes your code and produces and deploys the AWS CloudFormation templates it generates\. It also has deployment, diff, deletion, and troubleshooting capabilities\. For more information, see cdk \-\-help or [AWS CDK Toolkit \(`cdk` command\)](cli.md)\. + +The [AWS Toolkit for Visual Studio Code](https://aws.amazon.com/visualstudiocode/) is an open\-source plug\-in for Visual Studio Code that makes it easier to create, debug, and deploy applications on AWS\. The toolkit provides an integrated experience for developing AWS CDK applications, including the AWS CDK Explorer feature to list your AWS CDK projects and browse the various components of the CDK application\. [Install the plug\-in](https://docs.aws.amazon.com/toolkit-for-vscode/latest/userguide/setup-toolkit.html) and learn more about [using the AWS CDK Explorer](https://docs.aws.amazon.com/toolkit-for-vscode/latest/userguide/cdk-explorer.html)\. + +## Next steps<a name="getting_started_next_steps"></a> + +Where do you go now that you've dipped your toes in the AWS CDK? ++ Come on in; the water's fine\! Build [your first AWS CDK app](hello_world.md)\. ++ Try the [CDK Workshop](https://cdkworkshop.com/) for a more in\-depth tour involving a more complex project\. ++ See the [API reference](https://docs.aws.amazon.com/cdk/api/v1/docs/aws-construct-library.html) to begin exploring the provided constructs available for your favorite AWS services\. ++ Visit the [Construct Hub](https://constructs.dev/search?q=&cdk=aws-cdk&cdkver=1&sort=downloadsDesc&offset=0) to find constructs from the CDK community as well as from AWS\. ++ Dig deeper into concepts like [Environments](environments.md), [Assets](assets.md), [Bootstrapping](bootstrapping.md), [Permissions](permissions.md), [Runtime context](context.md), [Parameters](parameters.md), and [Abstractions and escape hatches](cfn_layer.md)\. ++ Explore [Examples](https://github.com/aws-samples/aws-cdk-examples/tree/CDKv1) of using the AWS CDK\. + +The AWS CDK is an open\-source project\. Want to [contribute](https://github.com/aws/aws-cdk)? \ No newline at end of file diff --git a/v1/hello_world.md b/v1/hello_world.md new file mode 100644 index 00000000..e942bb86 --- /dev/null +++ b/v1/hello_world.md @@ -0,0 +1,592 @@ +# Your first AWS CDK app<a name="hello_world"></a> + +You've read [Getting started with the AWS CDK](getting_started.md) and set up your development environment for writing AWS CDK apps? Great\! Now let's see how it feels to work with the AWS CDK by building the simplest possible AWS CDK app\. + +**Note** +This tutorial does not currently include instructions or code examples for Go\. + +In this tutorial, you'll learn about the structure of a AWS CDK project, how to use the AWS Construct Library to define AWS resources using code, and how to synthesize, diff, and deploy collections of resources using the AWS CDK Toolkit command\-line tool\. + +The standard AWS CDK development workflow is similar to the workflow you're already familiar with as a developer, just with a few extra steps\. + +1. Create the app from a template provided by the AWS CDK + +1. Add code to the app to create resources within stacks + +1. Build the app \(optional; the AWS CDK Toolkit will do it for you if you forget\) + +1. Synthesize one or more stacks in the app to create an AWS CloudFormation template + +1. Deploy one or more stacks to your AWS account + +The build step catches syntax and type errors\. The synthesis step catches logical errors in defining your AWS resources\. The deployment may find permission issues\. As always, you go back to the code, find the problem, fix it, then build, synthesize and deploy again\. + +**Tip** +Don't forget to keep your AWS CDK code under version control\! + +This tutorial walks you through creating and deploying a simple AWS CDK app, from initializing the project to deploying the resulting AWS CloudFormation template\. The app contains one stack, which contains one resource: an Amazon S3 bucket\. + +We'll also show what happens when you make a change and re\-deploy, and how to clean up when you're done\. + +## Create the app<a name="hello_world_tutorial_create_app"></a> + +Each AWS CDK app should be in its own directory, with its own local module dependencies\. Create a new directory for your app\. Starting in your home directory, or another directory if you prefer, issue the following commands\. + +**Important** +Be sure to name your project directory `hello-cdk`, *exactly as shown here\.* The AWS CDK project template uses the directory name to name things in the generated code, so if you use a different name, the code in this tutorial won't work\. + +``` +mkdir hello-cdk +cd hello-cdk +``` + +Now initialize the app using the cdk init command, specifying the desired template \("app"\) and programming language\. That is: + +------ +#### [ TypeScript ] + +``` +cdk init app --language typescript +``` + +------ +#### [ JavaScript ] + +``` +cdk init app --language javascript +``` + +------ +#### [ Python ] + +``` +cdk init app --language python +``` + +After the app has been created, also enter the following two commands to activate the app's Python virtual environment and install the AWS CDK core dependencies\. + +``` +source .venv/bin/activate +python -m pip install -r requirements.txt +``` + +------ +#### [ Java ] + +``` +cdk init app --language java +``` + +If you are using an IDE, you can now open or import the project\. In Eclipse, for example, choose **File** > **Import** > **Maven** > **Existing Maven Projects**\. Make sure that the project settings are set to use Java 8 \(1\.8\)\. + +------ +#### [ C\# ] + +``` +cdk init app --language csharp +``` + +If you are using Visual Studio, open the solution file in the `src` directory\. + +------ + +**Tip** +If you don't specify a template, the default is "app," which is the one we wanted anyway, so technically you can leave it out and save four keystrokes\. + +The cdk init command creates a number of files and folders inside the `hello-cdk` directory to help you organize the source code for your AWS CDK app\. Take a moment to explore\. The structure of a basic app is all there; you'll fill in the details in this tutorial\. + +If you have Git installed, each project you create using cdk init is also initialized as a Git repository\. We'll ignore that for now, but it's there when you need it\. + +## Build the app<a name="hello_world_tutorial_build"></a> + +In most programming environments, after making changes to your code, you'd build \(compile\) it\. This isn't strictly necessary with the AWS CDK—the Toolkit does it for you so you can't forget\. But you can still build manually whenever you want to catch syntax and type errors\. For reference, here's how\. + +------ +#### [ TypeScript ] + +``` +npm run build +``` + +------ +#### [ JavaScript ] + +No build step is necessary\. + +------ +#### [ Python ] + +No build step is necessary\. + +------ +#### [ Java ] + +``` +mvn compile -q +``` + +Or press Control\-B in Eclipse \(other Java IDEs may vary\) + +------ +#### [ C\# ] + +``` +dotnet build src +``` + +Or press F6 in Visual Studio + +------ + +**Note** +If your project was created with an older version of the AWS CDK Toolkit, it may not automatically build when you run it\. If changes you make in your code fail to be reflected in the synthesized template, try a manual build\. Make sure you are using the latest available version of the AWS CDK for this tutorial\. + +## List the stacks in the app<a name="hello_world_tutorial_list_stacks"></a> + +Just to verify everything is working correctly, list the stacks in your app\. + +``` +cdk ls +``` + +If you don't see `HelloCdkStack`, make sure you named your app's directory `hello-cdk`\. If you didn't, go back to [Create the app](#hello_world_tutorial_create_app) and try again\. + +## Add an Amazon S3 bucket<a name="hello_world_tutorial_add_bucket"></a> + +At this point, your app doesn't do anything because the stack it contains doesn't define any resources\. Let's add an Amazon S3 bucket\. + +Install the Amazon S3 package from the AWS Construct Library\. + +------ +#### [ TypeScript ] + +``` +npm install @aws-cdk/aws-s3 +``` + +------ +#### [ JavaScript ] + +``` +npm install @aws-cdk/aws-s3 +``` + +------ +#### [ Python ] + +``` +pip install aws-cdk.aws-s3 +``` + +------ +#### [ Java ] + +Add the following to the `<dependencies>` container of `pom.xml`\. + +``` +<dependency> + <groupId>software.amazon.awscdk</groupId> + <artifactId>s3</artifactId> + <version>${cdk.version}</version> +</dependency> +``` + +**Tip** +If you are using a Java IDE, it probably has a simpler way to add this dependency to your project, such as a GUI for editing the POM\. We recommend editing `pom.xml` by hand because of the use of the `cdk.version` variable, which helps keep the versions of installed modules consistent\. + +------ +#### [ C\# ] + +Run the following command in the `src/HelloCdk` directory\. + +``` +dotnet add package Amazon.CDK.AWS.S3 +``` + +Or **Tools** > **NuGet Package Manager** > **Manage NuGet Packages for Solution** in Visual Studio, then locate and install the `Amazon.CDK.AWS.S3` package + +------ + +Next, define an Amazon S3 bucket in the stack using the [Bucket](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-s3.Bucket.html) construct\. + +------ +#### [ TypeScript ] + +In `lib/hello-cdk-stack.ts`: + +``` +import * as cdk from '@aws-cdk/core'; +import * as s3 from '@aws-cdk/aws-s3'; + +export class HelloCdkStack extends cdk.Stack { + constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { + super(scope, id, props); + + new s3.Bucket(this, 'MyFirstBucket', { + versioned: true + }); + } +} +``` + +------ +#### [ JavaScript ] + +In `lib/hello-cdk-stack.js`: + +``` +const cdk = require('@aws-cdk/core'); +const s3 = require('@aws-cdk/aws-s3'); + +class HelloCdkStack extends cdk.Stack { + constructor(scope, id, props) { + super(scope, id, props); + + new s3.Bucket(this, 'MyFirstBucket', { + versioned: true + }); + } +} + +module.exports = { HelloCdkStack } +``` + +------ +#### [ Python ] + +Add the following import statement in `hello_cdk/hello_cdk_stack.py` in the `hello_cdk` directory below the existing imports\. + +``` +from aws_cdk import aws_s3 as s3 +``` + +Replace the comment with the following code\. + +``` +bucket = s3.Bucket(self, + "MyFirstBucket", + versioned=True,) +``` + +------ +#### [ Java ] + +In `src/main/java/com/myorg/HelloCdkStack.java`: + +``` +package com.myorg; + +import software.amazon.awscdk.core.*; +import software.amazon.awscdk.services.s3.Bucket; + +public class HelloCdkStack extends Stack { + public HelloCdkStack(final Construct scope, final String id) { + this(scope, id, null); + } + + public HelloCdkStack(final Construct scope, final String id, final StackProps props) { + super(scope, id, props); + + Bucket.Builder.create(this, "MyFirstBucket") + .versioned(true).build(); + } +} +``` + +------ +#### [ C\# ] + +In `src/HelloCdk/HelloCdkStack.cs`: + +``` +using Amazon.CDK; +using Amazon.CDK.AWS.S3; + +namespace HelloCdk +{ + public class HelloCdkStack : Stack + { + public HelloCdkStack(Construct scope, string id, IStackProps props=null) : base(scope, id, props) + { + new Bucket(this, "MyFirstBucket", new BucketProps + { + Versioned = true + }); + } + } +} +``` + +------ + +`Bucket` is the first construct we've seen, so let's take a closer look\. Like all constructs, the `Bucket` class takes three parameters\. ++ **scope:** Tells the bucket that the stack is its parent: it is defined within the scope of the stack\. You can define constructs inside of constructs, creating a hierarchy \(tree\)\. Here, and in most cases, the scope is `this` \(`self` in Python\), meaning the construct that contains the bucket: the stack\. ++ **Id:** The logical ID of the Bucket within your AWS CDK app\. This \(plus a hash based on the bucket's location within the stack\) uniquely identifies the bucket across deployments so the AWS CDK can update it if you change how it's defined in your app\. Here it is "MyFirstBucket\." Buckets can also have a name, which is separate from this ID \(it's the `bucketName` property\)\. ++ **props:** A bundle of values that define properties of the bucket\. Here we've defined only one property: `versioned`, which enables versioning for the files in the bucket\. + +All constructs take these same three arguments, so it's easy to stay oriented as you learn about new ones\. And as you might expect, you can subclass any construct to extend it to suit your needs, or just to change its defaults\. + +**Tip** +If a construct's props are all optional, you can omit the `props` parameter entirely\. + +Props are represented differently in the languages supported by the AWS CDK\. ++ In TypeScript and JavaScript, `props` is a single argument and you pass in an object containing the desired properties\. ++ In Python, props are passed as keyword arguments\. ++ In Java, a Builder is provided to pass the props\. Two, actually; one for `BucketProps`, and a second for `Bucket` to let you build the construct and its props object in one step\. This code uses the latter\. ++ In C\#, you instantiate a `BucketProps` object using an object initializer and pass it as the third parameter\. + +## Synthesize an AWS CloudFormation template<a name="hello_world_tutorial_synth"></a> + +Synthesize an AWS CloudFormation template for the app, as follows\. + +``` +cdk synth +``` + +If your app contained more than one stack, you'd need to specify which stack\(s\) to synthesize\. But since it only contains one, the CDK Toolkit knows you must mean that one\. + +**Tip** +If you received an error like `--app is required...`, it's probably because you are running the command from a subdirectory\. Navigate to the main app directory and try again\. + +The `cdk synth` command executes your app, which causes the resources defined in it to be translated into an AWS CloudFormation template\. The displayed output of `cdk synth` is a YAML\-format template; the beginning of our app's output is shown below\. The template is also saved in the `cdk.out` directory in JSON format\. + +``` +Resources: + MyFirstBucketB8884501: + Type: AWS::S3::Bucket + Properties: + VersioningConfiguration: + Status: Enabled + UpdateReplacePolicy: Retain + DeletionPolicy: Retain + Metadata:... +``` + +Even if you aren't very familiar with AWS CloudFormation, you should be able to find the definition for the bucket and see how the `versioned` property was translated\. + +**Note** +Every generated template contains a `AWS::CDK::Metadata` resource by default\. \(We haven't shown it here\.\) The AWS CDK team uses this metadata to gain insight into how the AWS CDK is used, so we can continue to improve it\. For details, including how to opt out of version reporting, see [Version reporting](cli.md#version_reporting)\. + +The `cdk synth` generates a perfectly valid AWS CloudFormation template\. You could take it and deploy it using the AWS CloudFormation console or another tool\. But the AWS CDK Toolkit can also do that\. + +## Deploying the stack<a name="hello_world_tutorial_deploy"></a> + +To deploy the stack using AWS CloudFormation, issue: + +``` +cdk deploy +``` + +As with `cdk synth`, you don't need to specify the name of the stack since there's only one in the app\. + +It is optional \(though good practice\) to synthesize before deploying\. The AWS CDK synthesizes your stack before each deployment\. + +If your code has security implications, you'll see a summary of these and need to confirm them before deployment proceeds\. This isn't the case in our stack\. + +`cdk deploy` displays progress information as your stack is deployed\. When it's done, the command prompt reappears\. You can go to the [AWS CloudFormation console](https://console.aws.amazon.com/cloudformation/home) and see that it now lists `HelloCdkStack`\. You'll also find `MyFirstBucket` in the Amazon S3 console\. + +You've deployed your first stack using the AWS CDK—congratulations\! But that's not all there is to the AWS CDK\. + +## Modifying the app<a name="hello_world_tutorial_modify"></a> + +The AWS CDK can update your deployed resources after you modify your app\. Let's change our bucket so it can be automatically deleted when we delete the stack, which involves changing its `RemovalPolicy`\. Also, because AWS CloudFormation won't delete Amazon S3 buckets that contain any objects, we'll ask the AWS CDK to delete the objects from our bucket before destroying the bucket, via the `autoDeleteObjects` property\. + +------ +#### [ TypeScript ] + +Update `lib/hello-cdk-stack.ts`\. + +``` +new s3.Bucket(this, 'MyFirstBucket', { + versioned: true, + removalPolicy: cdk.RemovalPolicy.DESTROY, + autoDeleteObjects: true +}); +``` + +------ +#### [ JavaScript ] + +Update `lib/hello-cdk-stack.js`\. + +``` +new s3.Bucket(this, 'MyFirstBucket', { + versioned: true, + removalPolicy: cdk.RemovalPolicy.DESTROY, + autoDeleteObjects: true +}); +``` + +------ +#### [ Python ] + +Update `hello_cdk/hello_cdk_stack.py`\. + +``` +bucket = s3.Bucket(self, "MyFirstBucket", + versioned=True, + removal_policy=core.RemovalPolicy.DESTROY, + auto_delete_objects=True) +``` + +------ +#### [ Java ] + +Update `src/main/java/com/myorg/HelloCdkStack.java`, adding the new import and updating the bucket definition in the appropriate places\. + +``` +import software.amazon.awscdk.core.RemovalPolicy; +``` + +``` +Bucket.Builder.create(this, "MyFirstBucket") + .versioned(true) + .removalPolicy(RemovalPolicy.DESTROY) + .autoDeleteObjects(true) + .build(); +``` + +------ +#### [ C\# ] + +Update `src/HelloCdk/HelloCdkStack.cs`\. + +``` +new Bucket(this, "MyFirstBucket", new BucketProps +{ + Versioned = true, + RemovalPolicy = RemovalPolicy.DESTROY, + AutoDeleteObjects = true +}); +``` + +------ + +Here, we haven't written any code that, in itself, changes our Amazon S3 bucket\. Instead, our code defines the desired state of the bucket\. The AWS CDK synthesizes that state to a new AWS CloudFormation template and deploys a changeset that makes only the changes necessary to reach that state\. + +To see these changes, we'll use the `cdk diff` command \. + +``` +cdk diff +``` + +The AWS CDK Toolkit queries your AWS account for the last\-deployed AWS CloudFormation template for the `HelloCdkStack` and compares it with the template it just synthesized from your app\. The output should look like the following\. + +``` +Stack HelloCdkStack +IAM Statement Changes +┌───┬──────────────────────────────┬────────┬──────────────────────────────┬──────────────────────────────┬───────────┐ +│ │ Resource │ Effect │ Action │ Principal │ Condition │ +├───┼──────────────────────────────┼────────┼──────────────────────────────┼──────────────────────────────┼───────────┤ +│ + │ ${Custom::S3AutoDeleteObject │ Allow │ sts:AssumeRole │ Service:lambda.amazonaws.com │ │ +│ │ sCustomResourceProvider/Role │ │ │ │ │ +│ │ .Arn} │ │ │ │ │ +├───┼──────────────────────────────┼────────┼──────────────────────────────┼──────────────────────────────┼───────────┤ +│ + │ ${MyFirstBucket.Arn} │ Allow │ s3:DeleteObject* │ AWS:${Custom::S3AutoDeleteOb │ │ +│ │ ${MyFirstBucket.Arn}/* │ │ s3:GetBucket* │ jectsCustomResourceProvider/ │ │ +│ │ │ │ s3:GetObject* │ Role.Arn} │ │ +│ │ │ │ s3:List* │ │ │ +└───┴──────────────────────────────┴────────┴──────────────────────────────┴──────────────────────────────┴───────────┘ +IAM Policy Changes +┌───┬────────────────────────────────────────────────────────┬────────────────────────────────────────────────────────┐ +│ │ Resource │ Managed Policy ARN │ +├───┼────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────┤ +│ + │ ${Custom::S3AutoDeleteObjectsCustomResourceProvider/Ro │ {"Fn::Sub":"arn:${AWS::Partition}:iam::aws:policy/serv │ +│ │ le} │ ice-role/AWSLambdaBasicExecutionRole"} │ +└───┴────────────────────────────────────────────────────────┴────────────────────────────────────────────────────────┘ +(NOTE: There may be security-related changes not in this list. See https://github.com/aws/aws-cdk/issues/1299) + +Parameters +[+] Parameter AssetParameters/4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392/S3Bucket AssetParameters4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392S3BucketBF7A7F3F: {"Type":"String","Description":"S3 bucket for asset \"4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392\""} +[+] Parameter AssetParameters/4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392/S3VersionKey AssetParameters4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392S3VersionKeyFAF93626: {"Type":"String","Description":"S3 key for asset version \"4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392\""} +[+] Parameter AssetParameters/4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392/ArtifactHash AssetParameters4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392ArtifactHashE56CD69A: {"Type":"String","Description":"Artifact hash for asset \"4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392\""} + +Resources +[+] AWS::S3::BucketPolicy MyFirstBucket/Policy MyFirstBucketPolicy3243DEFD +[+] Custom::S3AutoDeleteObjects MyFirstBucket/AutoDeleteObjectsCustomResource MyFirstBucketAutoDeleteObjectsCustomResourceC52FCF6E +[+] AWS::IAM::Role Custom::S3AutoDeleteObjectsCustomResourceProvider/Role CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092 +[+] AWS::Lambda::Function Custom::S3AutoDeleteObjectsCustomResourceProvider/Handler CustomS3AutoDeleteObjectsCustomResourceProviderHandler9D90184F +[~] AWS::S3::Bucket MyFirstBucket MyFirstBucketB8884501 + ├─ [~] DeletionPolicy + │ ├─ [-] Retain + │ └─ [+] Delete + └─ [~] UpdateReplacePolicy + ├─ [-] Retain + └─ [+] Delete +``` + +This diff has four sections\. ++ **IAM Statement Changes** and **IAM Policy Changes** \- These permission changes are there because we set the `AutoDeleteObjects` property on our Amazon S3 bucket\. The auto\-delete feature uses a custom resource to delete the objects in the bucket before the bucket itself is deleted\. The IAM objects grant the custom resource's code access to the bucket\. ++ **Parameters** \- The AWS CDK uses these entries to locate the Lambda function asset for the custom resource\. ++ **Resources** \- The new and changed resources in this stack\. We can see the aforementioned IAM objects, the custom resource, and its associated Lambda function being added\. We can also see that the bucket's `DeletionPolicy` and `UpdateReplacePolicy` attributes are being updated\. These allow the bucket to be deleted along with the stack, and to be replaced with a new one\. + +You may be curious about why we specified `RemovalPolicy` in our AWS CDK app but got a `DeletionPolicy` property in the resulting AWS CloudFormation template\. The AWS CDK uses a different name for the property because the AWS CDK default is to retain the bucket when the stack is deleted, while AWS CloudFormation's default is to delete it\. See [Removal policies](resources.md#resources_removal) for further details\. + +It's informative to compare the output of cdk synth here with the previous output and see the many additional lines of AWS CloudFormation template that the AWS CDK generated for us based on these relatively small changes\. + +**Important** +Since the `autoDeleteObjects` property is implemented using a AWS CloudFormation custom resource, which is implemented using an AWS Lambda function, our stack contains an [asset](assets.md)\. This fact requires that our AWS account and region be [bootstrapped](bootstrapping.md) so that there's an Amazon S3 bucket to hold the asset during deployment\. If you haven't already bootstrapped, issue: + +``` +cdk bootstrap aws://ACCOUNT-NUMBER/REGION +``` + +Now let's deploy\. + +``` +cdk deploy +``` + +The AWS CDK warns you about the security policy changes we've already seen in the diff\. Enter y to approve the changes and deploy the updated stack\. The CDK Toolkit updates the bucket configuration as you requested\. + +``` +HelloCdkStack: deploying... +[0%] start: Publishing 4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392:current +[100%] success: Published 4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392:current +HelloCdkStack: creating CloudFormation changeset... + 0/5 | 4:32:31 PM | UPDATE_IN_PROGRESS | AWS::CloudFormation::Stack | HelloCdkStack User Initiated + 0/5 | 4:32:36 PM | CREATE_IN_PROGRESS | AWS::IAM::Role | Custom::S3AutoDeleteObjectsCustomResourceProvider/Role (CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092) + 1/5 | 4:32:36 PM | UPDATE_COMPLETE | AWS::S3::Bucket | MyFirstBucket (MyFirstBucketB8884501) + 1/5 | 4:32:36 PM | CREATE_IN_PROGRESS | AWS::IAM::Role | Custom::S3AutoDeleteObjectsCustomResourceProvider/Role (CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092) Resource creation Initiated + 3/5 | 4:32:54 PM | CREATE_COMPLETE | AWS::IAM::Role | Custom::S3AutoDeleteObjectsCustomResourceProvider/Role (CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092) + 3/5 | 4:32:56 PM | CREATE_IN_PROGRESS | AWS::Lambda::Function | Custom::S3AutoDeleteObjectsCustomResourceProvider/Handler (CustomS3AutoDeleteObjectsCustomResourceProviderHandler9D90184F) + 3/5 | 4:32:56 PM | CREATE_IN_PROGRESS | AWS::S3::BucketPolicy | MyFirstBucket/Policy (MyFirstBucketPolicy3243DEFD) + 3/5 | 4:32:56 PM | CREATE_IN_PROGRESS | AWS::Lambda::Function | Custom::S3AutoDeleteObjectsCustomResourceProvider/Handler (CustomS3AutoDeleteObjectsCustomResourceProviderHandler9D90184F) Resource creation Initiated + 3/5 | 4:32:57 PM | CREATE_COMPLETE | AWS::Lambda::Function | Custom::S3AutoDeleteObjectsCustomResourceProvider/Handler (CustomS3AutoDeleteObjectsCustomResourceProviderHandler9D90184F) + 3/5 | 4:32:57 PM | CREATE_IN_PROGRESS | AWS::S3::BucketPolicy | MyFirstBucket/Policy (MyFirstBucketPolicy3243DEFD) Resource creation Initiated + 4/5 | 4:32:57 PM | CREATE_COMPLETE | AWS::S3::BucketPolicy | MyFirstBucket/Policy (MyFirstBucketPolicy3243DEFD) + 4/5 | 4:32:59 PM | CREATE_IN_PROGRESS | Custom::S3AutoDeleteObjects | MyFirstBucket/AutoDeleteObjectsCustomResource/Default (MyFirstBucketAutoDeleteObjectsCustomResourceC52FCF6E) + 5/5 | 4:33:06 PM | CREATE_IN_PROGRESS | Custom::S3AutoDeleteObjects | MyFirstBucket/AutoDeleteObjectsCustomResource/Default (MyFirstBucketAutoDeleteObjectsCustomResourceC52FCF6E) Resource creation Initiated + 5/5 | 4:33:06 PM | CREATE_COMPLETE | Custom::S3AutoDeleteObjects | MyFirstBucket/AutoDeleteObjectsCustomResource/Default (MyFirstBucketAutoDeleteObjectsCustomResourceC52FCF6E) + 5/5 | 4:33:08 PM | UPDATE_COMPLETE_CLEA | AWS::CloudFormation::Stack | HelloCdkStack + 6/5 | 4:33:09 PM | UPDATE_COMPLETE | AWS::CloudFormation::Stack | HelloCdkStack + + ✅ HelloCdkStack + +Stack ARN: +arn:aws:cloudformation:REGION:ACCOUNT:stack/HelloCdkStack/UNIQUE-ID +``` + +## Destroying the app's resources<a name="hello_world_tutorial_destroy"></a> + +Now that you're done with the quick tour, destroy your app's resources to avoid incurring any costs from the bucket you created, as follows\. + +``` +cdk destroy +``` + +Enter y to approve the changes and delete any stack resources\. + +**Note** +If we hadn't changed the bucket's `RemovalPolicy`, the stack deletion would complete successfully, but the bucket would become orphaned \(no longer associated with the stack\)\. + +## Next steps<a name="hello_world_next_steps"></a> + +Where do you go now that you've dipped your toes in the AWS CDK? ++ Try the [CDK Workshop](https://cdkworkshop.com/) for a more in\-depth tour involving a more complex project\. ++ Dig deeper into concepts like [Environments](environments.md), [Assets](assets.md), [Permissions](permissions.md), [Runtime context](context.md), [Parameters](parameters.md), and [Abstractions and escape hatches](cfn_layer.md)\. ++ See the [API reference](https://docs.aws.amazon.com/cdk/api/v1/docs/aws-construct-library.html) to begin exploring the CDK constructs available for your favorite AWS services\. ++ Visit [Construct Hub](https://constructs.dev/search?q=&cdk=aws-cdk&cdkver=1&sort=downloadsDesc&offset=0) to discover constructs created by AWS and others\. ++ Explore [Examples](https://github.com/aws-samples/aws-cdk-examples/tree/CDKv1) of using the AWS CDK\. + +The AWS CDK is an open\-source project\. Want to [contribute](https://github.com/aws/aws-cdk)? \ No newline at end of file diff --git a/v1/home.md b/v1/home.md new file mode 100644 index 00000000..080098c5 --- /dev/null +++ b/v1/home.md @@ -0,0 +1,265 @@ +# What is the AWS CDK?<a name="home"></a> + +Welcome to the *AWS Cloud Development Kit \(AWS CDK\) Developer Guide*\. This document provides information about the AWS CDK, a framework for defining cloud infrastructure in code and provisioning it through AWS CloudFormation\. + +**Important** +The CDK has been released in two major versions, v1 and v2\. This is the Developer Guide for the older AWS CDK v1\. +CDK v1 entered maintenance on June 1, 2022\. During the maintenance phase, CDK v1 will receive critical bug fixes and security patches only\. New features will be developed exclusively for CDK v2 during the v1 maintenance phase\. On June 1, 2023, support will end for AWS CDK v1\. For more details, see [AWS CDK Maintenance Policy](https://github.com/aws/aws-cdk-rfcs/blob/master/text/0079-cdk-2.0.md#aws-cdk-maintenance-policy)\. + +The AWS CDK lets you build reliable, scalable, cost\-effective applications in the cloud with the considerable expressive power of a programming language\. This approach yields many benefits, including: ++ Build with high\-level constructs that automatically provide sensible, secure defaults for your AWS resources, defining more infrastructure with less code\. ++ Use programming idioms like parameters, conditionals, loops, composition, and inheritance to model your system design from building blocks provided by AWS and others\. ++ Put your infrastructure, application code, and configuration all in one place, ensuring that at every milestone you have a complete, cloud\-deployable system\. ++ Employ software engineering practices such as code reviews, unit tests, and source control to make your infrastructure more robust\. ++ Connect your AWS resources together \(even across stacks\) and grant permissions using simple, intent\-oriented APIs\. ++ Import existing AWS CloudFormation templates to give your resources a CDK API\. ++ Use the power of AWS CloudFormation to perform infrastructure deployments predictably and repeatedly, with rollback on error\. ++ Easily share infrastructure design patterns among teams within your organization or even with the public\. + +The AWS CDK supports TypeScript, JavaScript, Python, Java, C\#/\.Net, and Go\. Developers can use one of these supported programming languages to define reusable cloud components known as [Constructs](constructs.md)\. You compose these together into [Stacks](stacks.md) and [Apps](apps.md)\. + +![\[Image NOT FOUND\]](http://docs.aws.amazon.com/cdk/v1/guide/images/AppStacks.png) + +## Why use the AWS CDK?<a name="why_use_cdk"></a> + +It's easier to show than to explain\! Here's some CDK code that creates an Amazon ECS service with AWS Fargate launch type \(this is the code we use in the [Creating an AWS Fargate service using the AWS CDK](ecs_example.md)\)\. + +------ +#### [ TypeScript ] + +``` +export class MyEcsConstructStack extends core.Stack { + constructor(scope: core.App, id: string, props?: core.StackProps) { + super(scope, id, props); + + const vpc = new ec2.Vpc(this, "MyVpc", { + maxAzs: 3 // Default is all AZs in region + }); + + const cluster = new ecs.Cluster(this, "MyCluster", { + vpc: vpc + }); + + // Create a load-balanced Fargate service and make it public + new ecs_patterns.ApplicationLoadBalancedFargateService(this, "MyFargateService", { + cluster: cluster, // Required + cpu: 512, // Default is 256 + desiredCount: 6, // Default is 1 + taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample") }, + memoryLimitMiB: 2048, // Default is 512 + publicLoadBalancer: true // Default is false + }); + } +} +``` + +------ +#### [ JavaScript ] + +``` +class MyEcsConstructStack extends core.Stack { + constructor(scope, id, props) { + super(scope, id, props); + + const vpc = new ec2.Vpc(this, "MyVpc", { + maxAzs: 3 // Default is all AZs in region + }); + + const cluster = new ecs.Cluster(this, "MyCluster", { + vpc: vpc + }); + + // Create a load-balanced Fargate service and make it public + new ecs_patterns.ApplicationLoadBalancedFargateService(this, "MyFargateService", { + cluster: cluster, // Required + cpu: 512, // Default is 256 + desiredCount: 6, // Default is 1 + taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample") }, + memoryLimitMiB: 2048, // Default is 512 + publicLoadBalancer: true // Default is false + }); + } +} + +module.exports = { MyEcsConstructStack } +``` + +------ +#### [ Python ] + +``` +class MyEcsConstructStack(core.Stack): + + def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + vpc = ec2.Vpc(self, "MyVpc", max_azs=3) # default is all AZs in region + + cluster = ecs.Cluster(self, "MyCluster", vpc=vpc) + + ecs_patterns.ApplicationLoadBalancedFargateService(self, "MyFargateService", + cluster=cluster, # Required + cpu=512, # Default is 256 + desired_count=6, # Default is 1 + task_image_options=ecs_patterns.ApplicationLoadBalancedTaskImageOptions( + image=ecs.ContainerImage.from_registry("amazon/amazon-ecs-sample")), + memory_limit_mib=2048, # Default is 512 + public_load_balancer=True) # Default is False +``` + +------ +#### [ Java ] + +``` +public class MyEcsConstructStack extends Stack { + + public MyEcsConstructStack(final Construct scope, final String id) { + this(scope, id, null); + } + + public MyEcsConstructStack(final Construct scope, final String id, + StackProps props) { + super(scope, id, props); + + Vpc vpc = Vpc.Builder.create(this, "MyVpc").maxAzs(3).build(); + + Cluster cluster = Cluster.Builder.create(this, "MyCluster") + .vpc(vpc).build(); + + ApplicationLoadBalancedFargateService.Builder.create(this, "MyFargateService") + .cluster(cluster) + .cpu(512) + .desiredCount(6) + .taskImageOptions( + ApplicationLoadBalancedTaskImageOptions.builder() + .image(ContainerImage + .fromRegistry("amazon/amazon-ecs-sample")) + .build()).memoryLimitMiB(2048) + .publicLoadBalancer(true).build(); + } +} +``` + +------ +#### [ C\# ] + +``` +public class MyEcsConstructStack : Stack +{ + public MyEcsConstructStack(Construct scope, string id, IStackProps props=null) : base(scope, id, props) + { + var vpc = new Vpc(this, "MyVpc", new VpcProps + { + MaxAzs = 3 + }); + + var cluster = new Cluster(this, "MyCluster", new ClusterProps + { + Vpc = vpc + }); + + new ApplicationLoadBalancedFargateService(this, "MyFargateService", + new ApplicationLoadBalancedFargateServiceProps + { + Cluster = cluster, + Cpu = 512, + DesiredCount = 6, + TaskImageOptions = new ApplicationLoadBalancedTaskImageOptions + { + Image = ContainerImage.FromRegistry("amazon/amazon-ecs-sample") + }, + MemoryLimitMiB = 2048, + PublicLoadBalancer = true, + }); + } +} +``` + +------ + +This class produces an AWS CloudFormation [template of more than 500 lines](https://github.com/awsdocs/aws-cdk-guide/blob/main/doc_source/my_ecs_construct-stack.yaml); deploying the AWS CDK app produces more than 50 resources of the following types\. ++ [AWS::EC2::EIP](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-eip.html) ++ [AWS::EC2::InternetGateway](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-internetgateway.html) ++ [AWS::EC2::NatGateway](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-natgateway.html) ++ [AWS::EC2::Route](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-route.html) ++ [AWS::EC2::RouteTable](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-routetable.html) ++ [AWS::EC2::SecurityGroup](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-security-group.html) ++ [AWS::EC2::Subnet](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-subnet.html) ++ [AWS::EC2::SubnetRouteTableAssociation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-subnet-route-table-assoc.html) ++ [AWS::EC2::VPCGatewayAttachment](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpc-gateway-attachment.html) ++ [AWS::EC2::VPC](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpc.html) ++ [AWS::ECS::Cluster](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ecs-cluster.html) ++ [AWS::ECS::Service](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ecs-service.html) ++ [AWS::ECS::TaskDefinition](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ecs-taskdefinition.html) ++ [AWS::ElasticLoadBalancingV2::Listener](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticloadbalancingv2-listener.html) ++ [AWS::ElasticLoadBalancingV2::LoadBalancer](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticloadbalancingv2-loadbalancer.html) ++ [AWS::ElasticLoadBalancingV2::TargetGroup](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticloadbalancingv2-targetgroup.html) ++ [AWS::IAM::Policy](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-policy.html) ++ [AWS::IAM::Role](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html) ++ [AWS::Logs::LogGroup](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-logs-loggroup.html) + +And let's not forget\.\.\. code completion within your IDE or editor\! + +![\[Image NOT FOUND\]](http://docs.aws.amazon.com/cdk/v1/guide/images/CodeCompletion.png) + +## Developing with the AWS CDK<a name="developing"></a> + +It's easy to [get set up](getting_started.md) and [write your first CDK app](hello_world.md)\. Short code examples are available throughout this Guide in the AWS CDK's supported programming languages: TypeScript, JavaScript, Python, Java, and C\#\. Longer examples are available [in our GitHub repository](https://github.com/aws-samples/aws-cdk-examples/tree/CDKv1)\. + +The [AWS CDK Toolkit](cli.md) is a command line tool for interacting with CDK apps\. It enables developers to synthesize artifacts such as AWS CloudFormation templates, deploy stacks to development AWS accounts, and diff against a deployed stack to understand the impact of a code change\. + +The [AWS Construct Library](constructs.md) offers constructs for each AWS service, many with "rich" APIs that provide high\-level abstractions\. The aim of the AWS Construct Library is to reduce the complexity and glue logic required when integrating various AWS services to achieve your goals on AWS\. + +**Note** +There is no charge for using the AWS CDK, but you might incur AWS charges for creating or using AWS [chargeable resources](https://docs.aws.amazon.com/general/latest/gr/glos-chap.html#chargeable-resources), such as running Amazon EC2 instances or using Amazon S3 storage\. Use the [AWS Pricing Calculator](https://calculator.aws/#/) to estimate charges for the use of various AWS resources\. + +## The Construct Programming Model<a name="cpm"></a> + +The Construct Programming Model \(CPM\) extends the concepts behind the AWS CDK into additional domains\. Other tools using the CPM include: ++ [CDK for Terraform](https://www.terraform.io/docs/cdktf/index.html) \(CDKtf\) ++ [CDK for Kubernetes](https://cdk8s.io/) \(CDK8s\) ++ [Projen](https://github.com/projen/projen), for building project configurations + +[Construct Hub](https://constructs.dev/) is an online registry where you can find and publish construct libraries for CDKs like the AWS CDK\. + +## Additional documentation and resources<a name="additional_docs"></a> + +In addition to this guide, the following other resources are available to AWS CDK users: ++ [API Reference](https://docs.aws.amazon.com/cdk/api/v1) ++ [AWS CDK Workshop](https://cdkworkshop.com/) ++ [cdk\.dev](https://cdk.dev/) community hub, including a Slack channel ++ [AWS CDK Examples](https://github.com/aws-samples/aws-cdk-examples/tree/CDKv1) ++ [CDK Patterns](https://cdkpatterns.com/) ++ [Awesome CDK](https://github.com/kolomied/awesome-cdk) ++ [AWS Solutions Constructs](http://aws.amazon.com/solutions/constructs/) ++ [AWS Developer Blog](https://aws.amazon.com/blogs/developer/category/developer-tools/aws-cloud-development-kit) CDK category ++ [Stack Overflow](https://stackoverflow.com/questions/tagged/aws-cdk) ++ [GitHub Repository](https://github.com/awslabs/aws-cdk) + + [Issues](https://github.com/awslabs/aws-cdk/issues) + + [Examples](https://github.com/aws-samples/aws-cdk-examples) + + [Documentation Source](https://github.com/awsdocs/aws-cdk-guide) + + [License](https://github.com/awslabs/aws-cdk/blob/master/LICENSE) + + [Releases](https://github.com/awslabs/aws-cdk/releases) + + [AWS CDK OpenPGP key](pgp-keys.md#cdk_pgp_key) + + [jsii OpenPGP key](pgp-keys.md#jsii_pgp_key) ++ [AWS CDK Sample for Cloud9](https://docs.aws.amazon.com/cloud9/latest/user-guide/sample-cdk.html) ++ [AWS CloudFormation Concepts](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-whatis-concepts.html) ++ [AWS Glossary](https://docs.aws.amazon.com/general/latest/gr/glos-chap.html) + +### Resources for serverless apps with CDK<a name="additional_serverless"></a> + +These tools can work with the AWS CDK to simplify serverless application development and deployment\. ++ [AWS Serverless Application Model](http://aws.amazon.com/serverless/sam/) ++ [AWS Chalice](https://github.com/aws/chalice), a Python serverless microframework + +## Contributing to the AWS CDK<a name="contributing"></a> + +Because the AWS CDK is open source, the team encourages you to contribute to make it an even better tool\. For details, see [Contributing](https://github.com/awslabs/aws-cdk/blob/master/CONTRIBUTING.md)\. + +## About Amazon Web Services<a name="about_aws"></a> + +Amazon Web Services \(AWS\) is a collection of digital infrastructure services that developers can use when developing their applications\. The services include computing, storage, database, and application synchronization \(messaging and queueing\)\. + +AWS uses a pay\-as\-you\-go service model\. You are charged only for the services that you — or your applications — use\. Also, to make AWS useful as a platform for prototyping and experimentation, AWS offers a free usage tier, in which services are free below a certain level of usage\. For more information about AWS costs and the free usage tier, see [Test\-Driving AWS in the Free Usage Tier](https://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/billing-free-tier.html)\. + +To obtain an AWS account, go to [aws\.amazon\.com](https://aws.amazon.com), and then choose **Create an AWS Account**\. \ No newline at end of file diff --git a/v1/how_to_set_cw_alarm.md b/v1/how_to_set_cw_alarm.md new file mode 100644 index 00000000..284fcaab --- /dev/null +++ b/v1/how_to_set_cw_alarm.md @@ -0,0 +1,239 @@ +# Set a CloudWatch alarm<a name="how_to_set_cw_alarm"></a> + +The [aws\-cloudwatch](https://docs.aws.amazon.com/cdk/api/v1/docs/aws-cloudwatch-readme.html) package supports setting CloudWatch alarms on CloudWatch metrics\. So the first thing you need is a metric\. You can use a predefined metric or you can create your own\. + +## Using an existing metric<a name="how_to_set_cw_alarm_use_metric"></a> + +Many AWS Construct Library modules let you set an alarm on an existing metric by passing the metric's name to a convenience method on an instance of an object that has metrics\. For example, given an Amazon SQS queue, you can get the metric **ApproximateNumberOfMessagesVisible** from the queue's [metric\(\)](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-sqs.Queue.html#metricmetricname-props) method\. + +------ +#### [ TypeScript ] + +``` +const metric = queue.metric("ApproximateNumberOfMessagesVisible"); +``` + +------ +#### [ JavaScript ] + +``` +const metric = queue.metric("ApproximateNumberOfMessagesVisible"); +``` + +------ +#### [ Python ] + +``` +metric = queue.metric("ApproximateNumberOfMessagesVisible") +``` + +------ +#### [ Java ] + +``` +Metric metric = queue.metric("ApproximateNumberOfMessagesVisible"); +``` + +------ +#### [ C\# ] + +``` +var metric = queue.Metric("ApproximateNumberOfMessagesVisible"); +``` + +------ + +## Creating your own metric<a name="how_to_set_cw_alarm_new_metric"></a> + +Create your own [metric](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-cloudwatch.Metric.html) as follows, where the *namespace* value should be something like **AWS/SQS** for an Amazon SQS queue\. You also need to specify your metric's name and dimension\. + +------ +#### [ TypeScript ] + +``` +const metric = new cloudwatch.Metric({ + namespace: 'MyNamespace', + metricName: 'MyMetric', + dimensions: { MyDimension: 'MyDimensionValue' } +}); +``` + +------ +#### [ JavaScript ] + +``` +const metric = new cloudwatch.Metric({ + namespace: 'MyNamespace', + metricName: 'MyMetric', + dimensions: { MyDimension: 'MyDimensionValue' } +}); +``` + +------ +#### [ Python ] + +``` +metric = cloudwatch.Metric( + namespace="MyNamespace", + metric_name="MyMetric", + dimensions=dict(MyDimension="MyDimensionValue") +) +``` + +------ +#### [ Java ] + +``` +Metric metric = Metric.Builder.create() + .namespace("MyNamespace") + .metricName("MyMetric") + .dimensionsMap(java.util.Map.of( // Java 9 or later + "MyDimension", "MyDimensionValue")) + .build(); +``` + +------ +#### [ C\# ] + +``` +var metric = new Metric(this, "Metric", new MetricProps +{ + Namespace = "MyNamespace", + MetricName = "MyMetric", + Dimensions = new Dictionary<string, object> + { + { "MyDimension", "MyDimensionValue" } + } +}); +``` + +------ + +## Creating the alarm<a name="how_to_set_cw_alarm_create"></a> + +Once you have a metric, either an existing one or one you defined, you can create an alarm\. In this example, the alarm is raised when there are more than 100 of your metric in two of the last three evaluation periods\. You can use comparisons such as less\-than in your alarms via the `comparisonOperator` property; greater\-than\-or\-equal\-to is the AWS CDK default, so we don't need to specify it\. + +------ +#### [ TypeScript ] + +``` +const alarm = new cloudwatch.Alarm(this, 'Alarm', { + metric: metric, + threshold: 100, + evaluationPeriods: 3, + datapointsToAlarm: 2, +}); +``` + +------ +#### [ JavaScript ] + +``` +const alarm = new cloudwatch.Alarm(this, 'Alarm', { + metric: metric, + threshold: 100, + evaluationPeriods: 3, + datapointsToAlarm: 2 +}); +``` + +------ +#### [ Python ] + +``` +alarm = cloudwatch.Alarm(self, "Alarm", + metric=metric, + threshold=100, + evaluation_periods=3, + datapoints_to_alarm=2 +) +``` + +------ +#### [ Java ] + +``` +import software.amazon.awscdk.services.cloudwatch.Alarm; +import software.amazon.awscdk.services.cloudwatch.Metric; + +Alarm alarm = Alarm.Builder.create(this, "Alarm") + .metric(metric) + .threshold(100) + .evaluationPeriods(3) + .datapointsToAlarm(2).build(); +``` + +------ +#### [ C\# ] + +``` +var alarm = new Alarm(this, "Alarm", new AlarmProps +{ + Metric = metric, + Threshold = 100, + EvaluationPeriods = 3, + DatapointsToAlarm = 2 +}); +``` + +------ + +An alternative way to create an alarm is using the metric's [createAlarm\(\)](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-cloudwatch.Metric.html#create-wbr-alarmscope-id-props) method, which takes essentially the same properties as the `Alarm` constructor; you just don't need to pass in the metric, since it's already known\. + +------ +#### [ TypeScript ] + +``` +metric.createAlarm(this, 'Alarm', { + threshold: 100, + evaluationPeriods: 3, + datapointsToAlarm: 2, +}); +``` + +------ +#### [ JavaScript ] + +``` +metric.createAlarm(this, 'Alarm', { + threshold: 100, + evaluationPeriods: 3, + datapointsToAlarm: 2, +}); +``` + +------ +#### [ Python ] + +``` +metric.create_alarm(self, "Alarm", + threshold=100, + evaluation_periods=3, + datapoints_to_alarm=2 +) +``` + +------ +#### [ Java ] + +``` +metric.createAlarm(this, "Alarm", new CreateAlarmOptions.Builder() + .threshold(100) + .evaluationPeriods(3) + .datapointsToAlarm(2) + .build()); +``` + +------ +#### [ C\# ] + +``` +metric.CreateAlarm(this, "Alarm", new CreateAlarmOptions +{ + Threshold = 100, + EvaluationPeriods = 3, + DatapointsToAlarm = 2 +}); +``` + +------ \ No newline at end of file diff --git a/v1/how_tos.md b/v1/how_tos.md new file mode 100644 index 00000000..229bd4c7 --- /dev/null +++ b/v1/how_tos.md @@ -0,0 +1,3 @@ +# AWS CDK how\-tos<a name="how_tos"></a> + +This section contains short code examples that show you how to accomplish a task using the AWS CDK\. \ No newline at end of file diff --git a/v1/identifiers.md b/v1/identifiers.md new file mode 100644 index 00000000..3a99daaa --- /dev/null +++ b/v1/identifiers.md @@ -0,0 +1,277 @@ +# Identifiers<a name="identifiers"></a> + +The AWS CDK deals with many types of identifiers and names\. To use the AWS CDK effectively and avoid errors, you need to understand the types of identifiers\. + +Identifiers must be unique within the scope in which they are created; they do not need to be globally unique in your AWS CDK application\. + +If you attempt to create an identifier with the same value within the same scope, the AWS CDK throws an exception\. + +## Construct IDs<a name="identifiers_construct_ids"></a> + +The most common identifier, `id`, is the identifier passed as the second argument when instantiating a construct object\. This identifier, like all identifiers, need only be unique within the scope in which it is created, which is the first argument when instantiating a construct object\. + +**Note** +The `id` of a stack is also the identifier you use to refer to it in the [AWS CDK Toolkit \(`cdk` command\)](cli.md)\. + +Let's look at an example where we have two constructs with the identifier `MyBucket` in our app\. However, since they are defined in different scopes, the first in the scope of the stack with the identifier `Stack1`, and the second in the scope of a stack with the identifier `Stack2`, that doesn't cause any sort of conflict, and they can coexist in the same app without any issues\. + +------ +#### [ TypeScript ] + +``` +import { App, Construct, Stack, StackProps } from '@aws-cdk/core'; +import * as s3 from '@aws-cdk/aws-s3'; + +class MyStack extends Stack { + constructor(scope: Construct, id: string, props: StackProps = {}) { + super(scope, id, props); + + new s3.Bucket(this, 'MyBucket'); + } +} + +const app = new App(); +new MyStack(app, 'Stack1'); +new MyStack(app, 'Stack2'); +``` + +------ +#### [ JavaScript ] + +``` +const { App , Stack } = require('@aws-cdk/core'); +const s3 = require('@aws-cdk/aws-s3'); + +class MyStack extends Stack { + constructor(scope, id, props = {}) { + super(scope, id, props); + + new s3.Bucket(this, 'MyBucket'); + } +} + +const app = new App(); +new MyStack(app, 'Stack1'); +new MyStack(app, 'Stack2'); +``` + +------ +#### [ Python ] + +``` +from aws_cdk.core import App, Construct, Stack, StackProps +from aws_cdk import aws_s3 as s3 + +class MyStack(Stack): + + def __init__(self, scope: Construct, id: str, **kwargs): + + super().__init__(scope, id, **kwargs) + s3.Bucket(self, "MyBucket") + +app = App() +MyStack(app, 'Stack1') +MyStack(app, 'Stack2') +``` + +------ +#### [ Java ] + +``` +// MyStack.java +package com.myorg; + +import software.amazon.awscdk.core.App; +import software.amazon.awscdk.core.Stack; +import software.amazon.awscdk.core.StackProps; +import software.amazon.awscdk.services.s3.Bucket; + +public class MyStack extends Stack { + public MyStack(final App scope, final String id) { + this(scope, id, null); + } + + public MyStack(final App scope, final String id, final StackProps props) { + super(scope, id, props); + new Bucket(this, "MyBucket"); + } +} + +// Main.java +package com.myorg; + +import software.amazon.awscdk.core.App; + +public class Main { + public static void main(String[] args) { + App app = new App(); + new MyStack(app, "Stack1"); + new MyStack(app, "Stack2"); + } +} +``` + +------ +#### [ C\# ] + +``` +using core = Amazon.CDK; +using s3 = Amazon.CDK.AWS.S3; + +public class MyStack : core.Stack +{ + public MyStack(core.App scope, string id, core.IStackProps props) : base(scope, id, props) + { + new s3.Bucket(this, "MyBucket"); + } +} + +class Program +{ + static void Main(string[] args) + { + var app = new core.App(); + new MyStack(app, "Stack1"); + new MyStack(app, "Stack2"); + } +} +``` + +------ + +## Paths<a name="identifiers_paths"></a> + +The constructs in an AWS CDK application form a hierarchy rooted in the `App` class\. We refer to the collection of IDs from a given construct, its parent construct, its grandparent, and so on to the root of the construct tree, as a *path*\. + +The AWS CDK typically displays paths in your templates as a string, with the IDs from the levels separated by slashes, starting at the node just below the root `App` instance, which is usually a stack\. For example, the paths of the two Amazon S3 bucket resources in the previous code example are `Stack1/MyBucket` and `Stack2/MyBucket`\. + +You can access the path of any construct programmatically, as shown in the following example, which gets the path of `myConstruct` \(or `my_construct`, as Python developers would write it\)\. Since IDs must be unique within the scope they are created, their paths are always unique within a AWS CDK application\. + +------ +#### [ TypeScript ] + +``` +const path: string = myConstruct.node.path; +``` + +------ +#### [ JavaScript ] + +``` +const path = myConstruct.node.path; +``` + +------ +#### [ Python ] + +``` +path = my_construct.node.path +``` + +------ +#### [ Java ] + +``` +String path = myConstruct.getNode().getPath(); +``` + +------ +#### [ C\# ] + +``` +string path = myConstruct.Node.Path; +``` + +------ + +## Unique IDs<a name="identifiers_unique_ids"></a> + +Since AWS CloudFormation requires that all logical IDs in a template are unique, the AWS CDK must be able to generate a unique identifier for each construct in an application\. Resources have paths that are globally unique \(the names of all scopes from the stack to a specific resource\) so the AWS CDK generates the necessary unique identifiers by concatenating the elements of the path and adding an 8\-digit hash\. \(The hash is necessary to distinguish distinct paths, such as `A/B/C` and `A/BC`, that would result in the same AWS CloudFormation identifier, since AWS CloudFormation identifiers are alphanumeric and cannot contain slashes or other separator characters\.\) The AWS CDK calls this string the *unique ID* of the construct\. + +In general, your AWS CDK app should not need to know about unique IDs\. You can, however, access the unique ID of any construct programmatically, as shown in the following example\. + +------ +#### [ TypeScript ] + +``` +const uid: string = Names.uniqueId(myConstruct); +``` + +------ +#### [ JavaScript ] + +``` +const uid = Names.uniqueId(myConstruct); +``` + +------ +#### [ Python ] + +``` +uid = Names.unique_id(my_construct) +``` + +------ +#### [ Java ] + +``` +String uid = Names.uniqueId(myConstruct); +``` + +------ +#### [ C\# ] + +``` +string uid = Names.Uniqueid(myConstruct); +``` + +------ + +The *address* is another kind of unique identifier that uniquely distinguishes CDK resources\. Derived from the SHA\-1 hash of the path, it is not human\-readable, but its constant, relatively short length \(always 42 hexadecimal characters\) makes it useful in situations where the "traditional" unique ID might be too long\. Some constructs may use the address in the synthesized AWS CloudFormation template instead of the unique ID\. Again, your app generally should not need to know about its constructs' addresses, but you can retrieve a construct's address as follows\. + +------ +#### [ TypeScript ] + +``` +const addr: string = myConstruct.node.addr; +``` + +------ +#### [ JavaScript ] + +``` +const addr = myConstruct.node.addr; +``` + +------ +#### [ Python ] + +``` +addr = my_construct.node.addr +``` + +------ +#### [ Java ] + +``` +String addr = myConstruct.getNode().getAddr(); +``` + +------ +#### [ C\# ] + +``` +string addr = myConstruct.Node.Addr; +``` + +------ + +## Logical IDs<a name="identifiers_logical_ids"></a> + +Unique IDs serve as the *logical identifiers*, which are sometimes called *logical names*, of resources in the generated AWS CloudFormation templates for those constructs that represent AWS resources\. + +For example, the Amazon S3 bucket in the previous example that is created within `Stack2` results in an `AWS::S3::Bucket` resource with the logical ID `Stack2MyBucket4DD88B4F` in the resulting AWS CloudFormation template\. + +### Logical ID stability<a name="identifiers_logical_id_stability"></a> + +Avoid changing the logical ID of a resource after it has been created\. Since AWS CloudFormation identifies resources by their logical ID, if you change the logical ID of a resource, AWS CloudFormation creates a new resource with the new logical ID, then deletes the existing one\. Depending on the type of resource, this may cause service interruption or data loss, or both\. \ No newline at end of file diff --git a/v1/index.md b/v1/index.md new file mode 100644 index 00000000..d25dbf17 --- /dev/null +++ b/v1/index.md @@ -0,0 +1,77 @@ +# AWS Cloud Development Kit (AWS CDK) v1 Developer Guide + +----- +*****Copyright © Amazon Web Services, Inc. and/or its affiliates. All rights reserved.***** + +----- +Amazon's trademarks and trade dress may not be used in +connection with any product or service that is not Amazon's, +in any manner that is likely to cause confusion among customers, +or in any manner that disparages or discredits Amazon. All other +trademarks not owned by Amazon are the property of their respective +owners, who may or may not be affiliated with, connected to, or +sponsored by Amazon. + +----- +## Contents ++ [What is the AWS CDK?](home.md) ++ [Getting started with the AWS CDK](getting_started.md) + + [Your first AWS CDK app](hello_world.md) ++ [Working with the AWS CDK](work-with.md) + + [Working with the AWS CDK in TypeScript](work-with-cdk-typescript.md) + + [Working with the AWS CDK in JavaScript](work-with-cdk-javascript.md) + + [Working with the AWS CDK in Python](work-with-cdk-python.md) + + [Working with the AWS CDK in Java](work-with-cdk-java.md) + + [Working with the AWS CDK in C#](work-with-cdk-csharp.md) + + [Working with the AWS CDK in Go](work-with-cdk-go.md) ++ [Managing dependencies](manage-dependencies.md) ++ [Migrating to AWS CDK v2](work-with-cdk-v2.md) ++ [Translating TypeScript AWS CDK code to other languages](multiple_languages.md) ++ [Concepts](core_concepts.md) + + [Constructs](constructs.md) + + [Apps](apps.md) + + [Stacks](stacks.md) + + [Environments](environments.md) + + [Resources](resources.md) + + [Identifiers](identifiers.md) + + [Tokens](tokens.md) + + [Parameters](parameters.md) + + [Tagging](tagging.md) + + [Assets](assets.md) + + [Permissions](permissions.md) + + [Runtime context](context.md) + + [Feature flags](featureflags.md) + + [Aspects](aspects.md) + + [Bootstrapping](bootstrapping.md) ++ [Abstractions and escape hatches](cfn_layer.md) ++ [Best practices for developing and deploying cloud infrastructure with the AWS CDK](best-practices.md) ++ [API reference](reference.md) ++ [Examples](examples.md) + + [Creating a serverless application using the AWS CDK](serverless_example.md) + + [Creating an AWS Fargate service using the AWS CDK](ecs_example.md) + + [AWS CDK examples](about_examples.md) ++ [AWS CDK how-tos](how_tos.md) + + [Get a value from an environment variable](get_env_var.md) + + [Use an AWS CloudFormation value](get_cfn_param.md) + + [Import or migrate an existing AWS CloudFormation template](use_cfn_template.md) + + [Using resources from the AWS CloudFormation Public Registry](use_cfn_public_registry.md) + + [Get a value from the Systems Manager Parameter Store](get_ssm_value.md) + + [Get a value from AWS Secrets Manager](get_secrets_manager_value.md) + + [Create an app with multiple stacks](stack_how_to_create_multiple_stacks.md) + + [Set a CloudWatch alarm](how_to_set_cw_alarm.md) + + [Get a value from a context variable](get_context_var.md) + + [Continuous integration and delivery (CI/CD) using CDK Pipelines](cdk_pipeline.md) ++ [AWS CDK tools](tools.md) + + [AWS CDK Toolkit (cdk command)](cli.md) + + [AWS Toolkit for Visual Studio Code](vscode.md) + + [AWS SAM integration](sam.md) ++ [Testing constructs](testing.md) ++ [Security for the AWS Cloud Development Kit (AWS CDK)](security.md) + + [Identity and access management for the AWS Cloud Development Kit (AWS CDK)](security-iam.md) + + [Compliance validation for the AWS Cloud Development Kit (AWS CDK)](compliance-validation.md) + + [Resilience for the AWS Cloud Development Kit (AWS CDK)](disaster-recovery-resiliency.md) + + [Infrastructure security for the AWS Cloud Development Kit (AWS CDK)](infrastructure-security.md) ++ [Troubleshooting common AWS CDK issues](troubleshooting.md) ++ [Videos](videos.md) ++ [OpenPGP keys for the AWS CDK and jsii](pgp-keys.md) ++ [AWS CDK Developer Guide history](doc-history.md) \ No newline at end of file diff --git a/v1/infrastructure-security.md b/v1/infrastructure-security.md new file mode 100644 index 00000000..e2052b67 --- /dev/null +++ b/v1/infrastructure-security.md @@ -0,0 +1,3 @@ +# Infrastructure security for the AWS Cloud Development Kit \(AWS CDK\)<a name="infrastructure-security"></a> + +The AWS CDK follows the [shared responsibility model](https://aws.amazon.com/compliance/shared-responsibility-model/) through the specific Amazon Web Services \(AWS\) services it supports\. For AWS service security information, see the [AWS service security documentation page](https://docs.aws.amazon.com/security/?id=docs_gateway#aws-security) and [AWS services that are in scope of AWS compliance efforts by compliance program](https://aws.amazon.com/compliance/services-in-scope/)\. \ No newline at end of file diff --git a/v1/manage-dependencies.md b/v1/manage-dependencies.md new file mode 100644 index 00000000..02de3280 --- /dev/null +++ b/v1/manage-dependencies.md @@ -0,0 +1,321 @@ +# Managing dependencies<a name="manage-dependencies"></a> + +Dependencies for your AWS CDK app or library are managed using package management tools commonly used with the programming language in which you develop your app\. Typically, the CDK supports the language's standard or official package management tool, if there is one, or its most popular or widely\-supported one if not\. You may also be able to use other tools, especially if they interoperate with the supported tools, although our ability to support alternatives is limited\. + +The CDK supports the following package managers\. + + +| Language | Supported package management tool | +| --- | --- | +| TypeScript/JavaScript | NPM \(Node Package Manager\) or Yarn | +| Python | PIP \(Package Installer for Python\) | +| Java | Maven | +| C\# | NuGet | +| Go | Go modules | + +**Note** +The projects generated by cdk init specify dependencies for the CDK core libraries and stable constructs\. + +The remainder of this topic provides details on using AWS CDK dependencies in each language\. + +## TypeScript and JavaScript<a name="manage-dependencies-ts-js"></a> + +In TypeScript and JavaScript CDK projects, dependencies are specified in `package.json` in the project's main directory\. Every AWS Construct Library module is a separate NPM package\. All versions of AWS CDK packages match and specify a single version, and the same version\. If the versions are different, NPM is likely to install multiple copies of CDK libraries, and you will see unpredictable compilation or runtime errors\. + +**Tip** +When you install a package using npm install, NPM records it in `package.json` for you\. + +If you prefer, you may use Yarn in place of NPM\. However, the CDK does not support Yarn's plug\-and\-play mode, which is default mode in Yarn 2\. Add the following to your project's `.yarnrc.yml` file to disable this feature\. + +``` +nodeLinker: node-modules +``` + +### Applications<a name="w55aac15c13c11"></a> + +The following is an example `package.json` generated by cdk init \-\-language typescript\. The file generated for JavaScript is similar, just without the TypeScript\-related entries\. + +``` +{ + "name": "my-package", + "version": "0.1.0", + "bin": { + "my-package": "bin/my-package.js" + }, + "scripts": { + "build": "tsc", + "watch": "tsc -w", + "test": "jest", + "cdk": "cdk" + }, + "devDependencies": { + "@aws-cdk/assert": "1.121.0", + "@types/jest": "^26.0.10", + "@types/node": "10.17.27", + "jest": "^26.4.2", + "ts-jest": "^26.2.0", + "aws-cdk": "1.121.0", + "ts-node": "^9.0.0", + "typescript": "~3.9.7" + }, + "dependencies": { + "@aws-cdk/core": "1.121.0", + "source-map-support": "^0.5.16" + } +} +``` + +All CDK apps use `@aws-cdk/core`, which must be specified in the `dependencies` section of `package.json` along with all other AWS Construct Library module your app uses\. + +**Note** +All AWS CDK dependencies must have the same version\. + +Specify versions of libraries and tools needed to test your app \(for example, the `jest` testing framework\) in the `devDependencies` section of `package.json`\. Optionally, use ^ to specify that later compatible versions are acceptable\. + +### Construct libraries<a name="w55aac15c13c13"></a> + +If you're developing a construct library, specify its dependencies via a combination of the `peerDependencies` and `devDependencies` sections, as shown in the following example `package.json` file\. + +``` +{ + "name": "my-package", + "version": "0.0.1", + "peerDependencies": { + "@aws-cdk/core": "1.140.0", + "@aws-cdk/aws-s3": "1.140.0", + "@aws-cdk/aws-iam": "1.140.0" + }, + "devDependencies": { + "jsii": "^1.50.0", + "aws-cdk": "^1.140.0" + } +} +``` + +In `peerDependencies`, use a caret \(^\) to specify the lowest version of the AWS CDK packages that your library works with, to maximize the compatibility of your library with a range of CDK versions\. Using `peerDependencies` makes sure there is only one copy of all CDK libraries in the `node_modules` tree\. + +In `devDependencies`, specify the tools and libraries you need for testing, optionally with ^ to indicate that later compatible versions are acceptable\. Specify exactly \(without ^ or \~\) the lowest version of the CDK packages that you advertise your library be compatible with\. This practice ensures that your tests run against those versions, so that if you inadvertently use a feature found only in newer versions, your tests can catch it\. + +**Warning** +`peerDependencies` are installed automatically only by NPM 7 and later\. If you are using NPM 6 or earlier, or if you are using Yarn, you must include the dependencies of your dependencies in `devDependencies`, or they will not be installed, and you will receive a warning about unresolved peer dependencies + +### Installing and updating dependencies<a name="w55aac15c13c17"></a> + +Run the following command to install your project's dependencies\. + +------ +#### [ NPM ] + +``` +# Install the latest version of everything that matches the ranges in 'package.json' +npm install + +# Install the same exact dependency versions as recorded in 'package-lock.json' +npm ci +``` + +------ +#### [ Yarn ] + +``` +# Install the latest version of everything that matches the ranges in 'package.json' +yarn upgrade + +# Install the same exact dependency versions as recorded in 'yarn.lock' +yarn install --frozen-lockfile +``` + +------ + +To update the installed modules, the npm install and yarn upgrade commands given above can be used\. Either command updates the packages in `node_modules` to the latest versions that satisfy the rules in `package.json`, but they do not update `package.json` itself, which you might want to do to set a new minimum version\. If you host your package on GitHub, you can configure [Dependabot version updates](https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuring-dependabot-version-updates) to automatically update `package.json`\. Alternatively, use [npm\-check\-updates](https://www.npmjs.com/package/npm-check-updates)\. + +**Important** +By design, when you install or update dependencies, NPM and Yarn choose the latest version of every package that satisfies the requirements specified in `package.json`\. There is always a risk that these versions may be broken \(either accidentally or intentionally\)\. Test thoroughly after updating your project's dependencies\. + +## Python<a name="manage-dependencies-python"></a> + +In Python, you specify dependencies by putting them in `requirements.txt` \(for applications\) or `setup.py` \(for construct libraries\)\. Dependencies are then managed with the PIP tool\. PIP is invoked in one of the following ways: + +``` +pip command options +python -m pip command options +``` + +The python \-m pip invocation works on most systems; pip requires that PIP's executable be on the system path\. If pip doesn't work, try replacing it with python \-m pip\. + +cdk init \-\-language python creates a virtual environment for your new project, which allows each project to have its own versions of dependencies, as well as a basic `requirements.txt` file\. You must activate this virtual environment \(source \.venv/bin/activate\) each time you begin working with the project\. + +### Applications<a name="w55aac15c15c11"></a> + +An example `requirements.txt` follows\. Because PIP does not have a dependency\-locking feature, we recommend that you use the == operator to specify exact versions for all dependencies, as shown here\. + +``` +aws-cdk.core==1.140.0 +aws-cdk.aws-s3==1.140.0 +aws-cdk.aws-iam==1.140.0 +``` + +**Note** +All AWS CDK dependencies must have the same version\. + +Installing a module with pip install does not add it to `requirements.txt`; you should do that yourself\. If you want to upgrade to a later version of a dependency, edit its version number in `requirements.txt`\. + +To install or update your project's dependencies after creating or editing `requirements.txt`, issue: + +``` +python -m pip install -r requirements.txt +``` + +**Tip** +The pip freeze command outputs the versions of all installed dependencies in a format that can be written to a text file and used as a requirements file with `pip install -r`\. This file is convenient for pinning all dependencies \(indluding transitive ones\) to the exact versions you tested with\. To avoid problems when upgrading packages later, use a separate file for this, e\.g\. `freeze.txt` not `requirements.txt`, and regenerate it when you upgrade your project's dependencies\. + +### Construct libraries<a name="w55aac15c15c13"></a> + +In libraries, dependencies are specified in `setup.py`, so that transitive dependencies are automatically downloaded when the package is consumed by an application\. Otherwise, every application that wants to use your package needs to copy your dependencies into their `requirements.txt`\. An example `setup.py` is shown here\. + +``` +from setuptools import setup + +setup( + name='my-package', + version='0.0.1', + install_requires=[ + 'aws-cdk.core==1.140.0', + 'aws-cdk.aws-s3==1.140.0', + 'aws-cdk.aws-iam==1.140.0', + ], + ... +) +``` + +**Note** +All AWS CDK dependencies must have the same version\. + +To work on the package for development, create or activate a virtual environment, then run the following command\. + +``` +python -m pip install -e . +``` + +Although PIP automatically installs transitive dependencies, there can only be one installed copy of any one package\. The version that is specified highest in the dependency tree is selected; applications always have the last word in what version of packages get installed\. + +## Java<a name="manage-dependencies-java"></a> + +In Java, dependencies are specified in `pom.xml` and installed using Maven\. The `<dependencies>` container includes a `<dependency>` element for each package\. Following is a section of `pom.xml` for a typical CDK Java app\. + +**Tip** +Many Java IDEs have integrated Maven support and visual `pom.xml` editors, which you may find convenient for managing dependencies\. + +``` +<properties> + <cdk.version>1.140.0</cdk.version> +</properties> + +<dependencies> + <dependency> + <groupId>software.amazon.awscdk</groupId> + <artifactId>core</artifactId> + <version>${cdk.version}</version> + </dependency> + <dependency> + <groupId>software.amazon.awscdk</groupId> + <artifactId>s3</artifactId> + <version>${cdk.version}</version> + </dependency> + <dependency> + <groupId>software.amazon.awscdk</groupId> + <artifactId>iam</artifactId> + <version>${cdk.version}</version> + </dependency> +</dependencies> +``` + +**Note** +All AWS CDK dependencies must have the same version\. To make it easier to update the versions of these packages while keeping them in sync, we define a propertywith the desired CDK version\. + +Maven does not support dependency locking, so while it is possible to specify version ranges in `pom.xml`, we recommend you always use exact versions to keep your builds repeatable\. + +Maven automatically installs transitive dependencies, but there can only be one installed copy of each package\. The version that is specified highest in the POM tree is selected; applications always have the last word in what version of packages get installed\. + +Maven automatically installs or updates your dependencies whenever you build \(mvn compile\) or package \(mvn package\) your project\. The CDK Toolkit does this automatically every time you run it, so generally there is no need to manually invoke Maven\. + +## C\#<a name="manage-dependencies-csharp"></a> + +In C\# AWS CDK apps, you manage dependencies using NuGet\. NuGet has four standard, mostly\-equivalent interfaces; you can use the one that suits your needs and working style\. You can also use compatible tools, such as [Paket](https://fsprojects.github.io/Paket/) or [MyGet](https://www.myget.org/) or even edit the `.csproj` file directly\. + +NuGet does not allow you to specify version ranges for dependencies\. Every dependency is pinned to a specific version\. + +**Note** +All AWS CDK dependencies must have the same version\. + +After updating your dependencies, Visual Studio will use NuGet to retrieve the specified versions of each package the next time you build\. If you are not using Visual Studio, use the dotnet restore command to update your dependencies\. + +### Editing the project file directly<a name="manage-dependencies-csharp-direct-edit"></a> + +Your project's `.csproj` file contains an `<ItemGroup>` container that lists your dependencies as `<PackageReference` elements\. + +``` +<ItemGroup> + <PackageReference Include="Amazon.CDK" Version="1.140.0" /> + <PackageReference Include="Amazon.CDK.AWS.S3" Version="1.140.0" /> + <PackageReference Include="Amazon.CDK.AWS.IAM" Version="1.140.0" /> +</ItemGroup> +``` + +### The Visual Studio NuGet GUI<a name="manage-dependencies-csharp-vs-nuget-gui"></a> + +Visual Studio's NuGet tools are accessible from **Tools** > **NuGet Package Manager** > **Manage NuGet Packages for Solution**\. Use the **Browse** tab to find the AWS Construct Library packages you want to install\. You can choose the desired version, including pre\-release versions of your modules and add them to any of the open projects\. + +![\[Image NOT FOUND\]](http://docs.aws.amazon.com/cdk/v1/guide/images/visual-studio-nuget.png) + +Look on the **Updates** page to install new versions of your packages\. + +### The NuGet console<a name="manage-dependencies-csharp-vs-nuget-console"></a> + +The NuGet console is a PowerShell\-based interface to NuGet that works in the context of a Visual Studio project\. You can open it in Visual Studio by choosing **Tools** > **NuGet Package Manager** > **Package Manager Console**\. For more information about using this tool, see [Install and Manage Packages with the Package Manager Console in Visual Studio](https://docs.microsoft.com/en-us/nuget/consume-packages/install-use-packages-powershell)\. + +### The `dotnet` command<a name="manage-dependencies-csharp-vs-dotnet-command"></a> + +The `dotnet` command is the primary command\-line tool for working with Visual Studio C\# projects\. You can invoke it from any Windows command prompt\. Among its many capabilities, `dotnet` can add NuGet dependencies to a Visual Studio project\. + +Assuming you're in the same directory as the Visual Studio project \(`.csproj`\) file, issue a command like the following to install a package\. Note that since the main CDK library is included when you create a project, you should ever only need to explictly install experimental modules\. Experimental modules require you to specify an explicit version number\. + +``` +dotnet add package Amazon.CDK.AWS.IoT -v VERSION-NUMBER +``` + +You may issue the command from another directory by including the path to the project file, or to the directory that contains it, after the `add` keyword\. The following example assumes that you are in your AWS CDK project's main directory\. + +To install a specific version of a package, include the `-v` flag and the desired version\. + +To update a package, issue the same `dotnet add` command you used to install it\. For experimental modules, again, you must specify an explicit version number\. + +For more information about managing packages using the `dotnet` command, see [Install and Manage Packages Using the dotnet CLI](https://docs.microsoft.com/en-us/nuget/consume-packages/install-use-packages-dotnet-cli)\. + +### The `nuget` command<a name="manage-dependencies-csharp-vs-nuget-command"></a> + +The `nuget` command line tool can install and update NuGet packages\. However, it requires your Visual Studio project to be set up differently from the way `cdk init` sets up projects\. \(Technical details: `nuget` works with `Packages.config` projects, while `cdk init` creates a newer\-style `PackageReference` project\.\) + +We do not recommend the use of the `nuget` tool with AWS CDK projects created by `cdk init`\. If you are using another type of project, and want to use `nuget`, see the [NuGet CLI Reference](https://docs.microsoft.com/en-us/nuget/reference/nuget-exe-cli-reference)\. + +## Go<a name="manage-dependencies-go"></a> + +In Go, dependencies versions are defined in `go.mod`\. The default `go.mod` is similar to the one shown here\. + +``` +module my-package + +go 1.16 + +require ( + github.com/aws/aws-cdk-go/awscdk/v2 v2.16.0 + github.com/aws/constructs-go/constructs/v10 v10.0.5 + github.com/aws/jsii-runtime-go v1.29.0 +) +``` + +Package names \(modules, in Go parlance\) are specified by URL with the version number appended\. Go's module system does not support version ranges, so all dependencies must be pinned to a specfic version\. + +Go automatically downloads dependencies whenever you build\. The CDK does this for you automatically whenever you run your app, so there is no need to do it manually\. + +You may use the go get command to install a module and update `go.mod`\. To see a list of available updates for your dependencies, issue go list \-m \-u all\. \ No newline at end of file diff --git a/v1/multiple_languages.md b/v1/multiple_languages.md new file mode 100644 index 00000000..cc1f89b4 --- /dev/null +++ b/v1/multiple_languages.md @@ -0,0 +1,341 @@ +# Translating TypeScript AWS CDK code to other languages<a name="multiple_languages"></a> + +TypeScript was the first language supported for developing AWS CDK applications, and for that reason, there is a substantial amount of example CDK code written in TypeScript\. If you are developing in another language, it may be useful to compare how AWS CDK code is implemented in TypeScript and your language of choice, so you can, with a little effort, make use of these examples\. + +For more details on working with the AWS CDK in its supported programming languages, see: ++ [Working with the AWS CDK in TypeScript](work-with-cdk-typescript.md) ++ [Working with the AWS CDK in JavaScript](work-with-cdk-javascript.md) ++ [Working with the AWS CDK in Python](work-with-cdk-python.md) ++ [Working with the AWS CDK in Java](work-with-cdk-java.md) ++ [Working with the AWS CDK in C\#](work-with-cdk-csharp.md) + +## Importing a module<a name="multiple_languages_import"></a> + +------ +#### [ TypeScript/JavaScript ] + +TypeScript supports importing either an entire namespace, or individual objects from a namespace\. Each namespace includes constructs and other classes for use with a given AWS service\. + +``` +// Import namespace as s3 into current namespace +import * as s3 from '@aws-cdk-lib/aws-s3'; + +// Import namespace using Node.js require() (import * as s3 generally preferred) +const s3 = require('@aws-cdk-lib/aws-s3'); + +// TypeScript version of require() (again, import * as s3 generally preferred) +import s3 = require('@aws-cdk/aws-s3'); + +// Now use s3 to access the S3 types +const bucket = s3.Bucket(...); + +// Selective import of s3.Bucket into current namespace +import { Bucket } from '@aws-cdk/aws-s3'; + +// Selective import of Bucket and EventType into current namespace +import { Bucket, EventType } from '@aws-cdk/aws-s3'; + +// Now use Bucket to instantiate an S3 bucket +const bucket = Bucket(...); +``` + +------ + +------ +#### [ Python ] + +Like TypeScript, Python supports namespaced module imports and selective imports\. Module names in Python look like **aws\_cdk\.***xxx*, where *xxx* represents an AWS service name, such as **s3** for Amazon S3 \(we'll use Amazon S3 for our examples\)\. + +``` +# Import entire module as s3 into current namespace +import aws_cdk.aws_s3 as s3 + +# s3 can now be used to access classes it contains +bucket = s3.Bucket(...) + +# Selective import of s3.Bucket into current namespace +from aws_cdk.s3 import Bucket + +# Selective import of Bucket and EventType into current namespace +from aws_cdk.s3 import Bucket, EventType + +# Bucket can now be used to instantiate a bucket +bucket = Bucket(...) +``` + +------ +#### [ Java ] + +Java's imports work differently from TypeScript's\. Each import statement imports either a single class name from a given package, or all classes defined in that package \(using `*`\)\. Classes may be accessed using either the class name by itself if it has been imported, or the *qualified* class name including its package\. + +Packages are named like `software.amazon.awscdk.services.xxx` for AWS Construct Library packages \(the core module is `software.amazon.awscdk.core`\)\. The Maven group ID for AWS CDK packages is `software.amazon.awscdk`\. + +``` +// Make all Amazon S3 construct library classes available +import software.amazon.awscdk.services.s3.*; + +// Make only Bucket and EventType classes available +import software.amazon.awscdk.services.s3.Bucket; +import software.amazon.awscdk.services.s3.EventType; + +// An imported class may now be accessed using the simple class name (assuming that name +// does not conflict with another class) +Bucket bucket = Bucket.Builder.create(...).build(); + +// We can always use the qualified name of a class (including its package) even without an +// import directive +software.amazon.awscdk.services.s3.Bucket bucket = + software.amazon.awscdk.services.s3.Bucket.Builder.create(...) + .build(); + +// Java 10 or later can use var keyword to avoid typing the type twice +var bucket = + software.amazon.awscdk.services.s3.Bucket.Builder.create(...) + .build(); +``` + +------ +#### [ C\# ] + +In C\#, you import types with the `using` directive\. There are two styles, which give you access either all the types in the specified namespace using their plain names, or let you refer to the namespace itself using an alias\. + +Packages are named like `Amazon.CDK.AWS.xxx` for AWS Construct Library packages \(the core module is `Amazon.CDK`\)\. + +``` +// Make all Amazon S3 construct library classes available +using Amazon.CDK.AWS.S3; + +// Now we can access any S3 type using its name +var bucket = new Bucket(...); + +// Import the S3 namespace under an alias +using s3 = Amazon.CDK.AWS.S3; + +// Now we can access an S3 type through the namespace alias +var bucket = new s3.Bucket(...); + +// We can always use the qualified name of a type (including its namespace) even without a +// using directive +var bucket = new Amazon.CDK.AWS.S3.Bucket(...) +``` + +------ + +## Instantiating a construct<a name="multiple_languages_class"></a> + +AWS CDK construct classes have the same name in all supported languages\. Most languages use the `new` keyword to instantiate a class \(Python is the only one that doesn't\)\. Also, in most languages, the keyword `this` refers to the current instance\. Python, again, is the exception \(it uses `self` by convention\)\. You should pass a reference to the current instance as the `scope` parameter to every construct you create\. + + The third argument to a AWS CDK construct is `props`, an object containing attributes needed to build the construct\. This argument may be optional, but when it is required, the supported languages handle it in idiomatic ways\. The names of the attributes are also adapted to the language's standard naming patterns\. + +------ +#### [ TypeScript/JavaScript ] + +``` +// Instantiate default Bucket +const bucket = new s3.Bucket(this, 'MyBucket'); + +// Instantiate Bucket with bucketName and versioned properties +const bucket = new s3.Bucket(this, 'MyBucket', { + bucketName: 'my-bucket', + versioned: true, +}); + +// Instantiate Bucket with websiteRedirect, which has its own sub-properties +const bucket = new s3.Bucket(this, 'MyBucket', { + websiteRedirect: {host: 'aws.amazon.com'}}); +``` + +------ + +------ +#### [ Python ] + +Python doesn't use a `new` keyword when instantiating a class\. The properties argument is represented using keyword arguments, and the arguments are named using `snake_case`\. + +If a props value is itself a bundle of attributes, it is represented by a class named after the property, which accepts keyword arguments for the sub\-properties\. + +In Python, the current instance is passed to methods as the first argument, which is named `self` by convention\. + +``` +# Instantiate default Bucket +bucket = s3.Bucket(self, "MyBucket") + +# Instantiate Bucket with bucket_name and versioned properties +bucket = s3.Bucket(self, "MyBucket", bucket_name="my-bucket", versioned=true) + +# Instantiate Bucket with website_redirect, which has its own sub-properties +bucket = s3.Bucket(self, "MyBucket", website_redirect=s3.WebsiteRedirect( + host_name="aws.amazon.com")) +``` + +------ +#### [ Java ] + +In Java, the props argument is represented by a class named `XxxxProps` \(for example, `BucketProps` for the `Bucket` construct's props\)\. You build the props argument using a builder pattern\. + +Each `XxxxProps` class has a builder, and there is also a convenient builder for each construct that builds the props and the construct in one step, as shown here\. + +Props are named the same as in TypeScript, using `camelCase`\. + +``` +// Instantiate default Bucket +Bucket bucket = Bucket(self, "MyBucket"); + +// Instantiate Bucket with bucketName and versioned properties +Bucket bucket = Bucket.Builder.create(self, "MyBucket") + .bucketName("my-bucket").versioned(true) + .build(); + +# Instantiate Bucket with websiteRedirect, which has its own sub-properties +Bucket bucket = Bucket.Builder.create(self, "MyBucket") + .websiteRedirect(new websiteRedirect.Builder() + .hostName("aws.amazon.com").build()) + .build(); +``` + +------ +#### [ C\# ] + +In C\#, props are specified using an object initializer to a class named `XxxxProps` \(for example, `BucketProps` for the `Bucket` construct's props\)\. + +Props are named similarly to TypeScript, except using `PascalCase`\. + +It is convenient to use the `var` keyword when instantiating a construct, so you don't need to type the class name twice\. However, your local code style guide may vary\. + +``` +// Instantiate default Bucket +var bucket = Bucket(self, "MyBucket"); + +// Instantiate Bucket with BucketName and versioned properties +var bucket = Bucket(self, "MyBucket", new BucketProps { + BucketName = "my-bucket", + Versioned = true}); + +// Instantiate Bucket with WebsiteRedirect, which has its own sub-properties +var bucket = Bucket(self, "MyBucket", new BucketProps { + WebsiteRedirect = new WebsiteRedirect { + HostName = "aws.amazon.com" + }}); +``` + +------ + +## Accessing members<a name="multiple_languages_members"></a> + +It is common to refer to attributes or properties of constructs and other AWS CDK classes and use these values as, for examples, inputs to build other constructs\. The naming differences described above for methods apply\. Furthermore, in Java, it is not possible to access members directly; instead, a getter method is provided\. + +------ +#### [ TypeScript/JavaScript ] + +Names are `camelCase`\. + +``` +bucket.bucketArn +``` + +------ + +------ +#### [ Python ] + +Names are `snake_case`\. + +``` +bucket.bucket_arn +``` + +------ +#### [ Java ] + +A getter method is provided for each property; these names are `camelCase`\. + +``` +bucket.getBucketArn() +``` + +------ +#### [ C\# ] + +Names are `PascalCase`\. + +``` +bucket.BucketArn +``` + +------ + +## Enum constants<a name="multiple_languages_enums"></a> + +Enum constants are scoped to a class, and have uppercase names with underscores in all languages \(sometimes referred to as `SCREAMING_SNAKE_CASE`\)\. Since class names also use the same casing in all supported languages, qualified enum names are also the same\. + +``` +s3.BucketEncryption.KMS_MANAGED +``` + +## Object interfaces<a name="multiple_languages_object"></a> + +The AWS CDK uses TypeScript object interfaces to indicate that a class implements an expected set of methods and properties\. You can recognize an object interface because its name starts with `I`\. A concrete class indicates the interface\(s\) it implements using the `implements` keyword\. + +------ +#### [ TypeScript/JavaScript ] + +**Note** +JavaScript doesn't have an interface feature\. You can ignore the `implements` keyword and the class names following it\. + +``` +import { IAspect, IConstruct } from '@aws-cdk/core'; + +class MyAspect implements IAspect { + public visit(node: IConstruct) { + console.log('Visited', node.node.path); + } +} +``` + +------ + +------ +#### [ Python ] + +Python doesn't have an interface feature\. However, for the AWS CDK you can indicate interface implementation by decorating your class with `@jsii.implements(interface)`\. + +``` +from aws_cdk.core import IAspect, IConstruct +import jsii + +@jsii.implements(IAspect) +class MyAspect(): + def visit(self, node: IConstruct) -> None: + print("Visited", node.node.path) +``` + +------ +#### [ Java ] + +``` +import software.amazon.awscdk.core.IAspect; +import software.amazon.awscdk.core.IConstruct; + +public class MyAspect implements IAspect { + public void visit(IConstruct node) { + System.out.format("Visited %s", node.getNode().getPath()); + } +} +``` + +------ +#### [ C\# ] + +``` +using Amazon.CDK; + +public class MyAspect : IAspect +{ + public void Visit(IConstruct node) + { + System.Console.WriteLine($"Visited ${node.Node.Path}"); + } +} +``` + +------ \ No newline at end of file diff --git a/v1/parameters.md b/v1/parameters.md new file mode 100644 index 00000000..19d7b76c --- /dev/null +++ b/v1/parameters.md @@ -0,0 +1,208 @@ +# Parameters<a name="parameters"></a> + +AWS CloudFormation templates can contain [parameters](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html)—custom values that are supplied at deployment time and incorporated into the template\. Since the AWS CDK synthesizes AWS CloudFormation templates, it too offers support for deployment\-time parameters\. + +Using the AWS CDK, you can both define parameters, which can then be used in the properties of constructs you create, and you can also deploy stacks containing parameters\. + +When deploying the AWS CloudFormation template using the AWS CDK Toolkit, you provide the parameter values on the command line\. If you deploy the template through the AWS CloudFormation console, you are prompted for the parameter values\. + +In general, we recommend against using AWS CloudFormation parameters with the AWS CDK\. The usual ways to pass values into AWS CDK apps are [context values](context.md) and environment variables\. Because they are not available at synthesis time, parameter values cannot be easily used for flow control and other purposes in your CDK app\. + +**Note** +To do control flow with parameters, you can use [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.CfnCondition.html](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.CfnCondition.html) constructs, although this is awkward compared to native `if` statements\. + +Using parameters requires you to be mindful of how the code you're writing behaves at deployment time, as well as at synthesis time\. This makes it harder to understand and reason about your AWS CDK application, in many cases for little benefit\. + +It is better, again in general, to have your CDK app accept any necessary information in some well\-defined way and use it directly to declare constructs in your CDK app\. An ideal AWS CDK\-generated AWS CloudFormation template is concrete, with no values remaining to be specified at deployment time\. + +There are, however, use cases to which AWS CloudFormation parameters are uniquely suited\. If you have separate teams defining and deploying infrastructure, for example, you can use parameters to make the generated templates more widely useful\. Additionally, the AWS CDK's support for AWS CloudFormation parameters lets you use the AWS CDK with AWS services that use AWS CloudFormation templates \(such as AWS Service Catalog\), which use parameters to configure the template being deployed\. + +## Defining parameters<a name="parameters_define"></a> + +Use the [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.CfnParameter.html](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.CfnParameter.html) class to define a parameter\. You'll want to specify at least a type and a description for most parameters, though both are technically optional\. The description appears when the user is prompted to enter the parameter's value in the AWS CloudFormation console\. For more information on the available types, see [Types](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html#parameters-section-structure-properties-type)\. + +**Note** +You can define parameters in any scope, but we recommend defining parameters at the stack level so that their logical ID does not change when you refactor your code\. + +------ +#### [ TypeScript ] + +``` +const uploadBucketName = new CfnParameter(this, "uploadBucketName", { + type: "String", + description: "The name of the Amazon S3 bucket where uploaded files will be stored."}); +``` + +------ +#### [ JavaScript ] + +``` +const uploadBucketName = new CfnParameter(this, "uploadBucketName", { + type: "String", + description: "The name of the Amazon S3 bucket where uploaded files will be stored."}); +``` + +------ +#### [ Python ] + +``` +upload_bucket_name = CfnParameter(self, "uploadBucketName", type="String", + description="The name of the Amazon S3 bucket where uploaded files will be stored.") +``` + +------ +#### [ Java ] + +``` +CfnParameter uploadBucketName = CfnParameter.Builder.create(this, "uploadBucketName") + .type("String") + .description("The name of the Amazon S3 bucket where uploaded files will be stored") + .build(); +``` + +------ +#### [ C\# ] + +``` +var uploadBucketName = new CfnParameter(this, "uploadBucketName", new CfnParameterProps +{ + Type = "String", + Description = "The name of the Amazon S3 bucket where uploaded files will be stored" +}); +``` + +------ + +## Using parameters<a name="parameters_use"></a> + +A `CfnParameter` instance exposes its value to your AWS CDK app via a [token](tokens.md)\. Like all tokens, the parameter's token is resolved at synthesis time, but it resolves to a reference to the parameter defined in the AWS CloudFormation template, which will be resolved at deploy time, rather than to a concrete value\. + +You can retrieve the token as an instance of the `Token` class, or in string, string list, or numeric encoding, depending on the type of value required by the class or method you want to use the parameter with\. + +------ +#### [ TypeScript ] + + +| Property | kind of value | +| --- |--- | +| value | Token class instance | +| valueAsList | The token represented as a string list | +| valueAsNumber | The token represented as a number | +| valueAsString | The token represented as a string | + +------ +#### [ JavaScript ] + + +| Property | kind of value | +| --- |--- | +| value | Token class instance | +| valueAsList | The token represented as a string list | +| valueAsNumber | The token represented as a number | +| valueAsString | The token represented as a string | + +------ +#### [ Python ] + + +| Property | kind of value | +| --- |--- | +| value | Token class instance | +| value\_as\_list | The token represented as a string list | +| value\_as\_number | The token represented as a number | +| value\_as\_string | The token represented as a string | + +------ +#### [ Java ] + + +| Property | kind of value | +| --- |--- | +| getValue\(\) | Token class instance | +| getValueAsList\(\) | The token represented as a string list | +| getValueAsNumber\(\) | The token represented as a number | +| getValueAsString\(\) | The token represented as a string | + +------ +#### [ C\# ] + + +| Property | kind of value | +| --- |--- | +| Value | Token class instance | +| ValueAsList | The token represented as a string list | +| ValueAsNumber | The token represented as a number | +| ValueAsString | The token represented as a string | + +------ + +For example, to use a parameter in a Bucket definition: + +------ +#### [ TypeScript ] + +``` +const bucket = new Bucket(this, "myBucket", + { bucketName: uploadBucketName.valueAsString}); +``` + +------ +#### [ JavaScript ] + +``` +const bucket = new Bucket(this, "myBucket", + { bucketName: uploadBucketName.valueAsString}); +``` + +------ +#### [ Python ] + +``` +bucket = Bucket(self, "myBucket", + bucket_name=upload_bucket_name.value_as_string) +``` + +------ +#### [ Java ] + +``` +Bucket bucket = Bucket.Builder.create(this, "myBucket") + .bucketName(uploadBucketName.getValueAsString()) + .build(); +``` + +------ +#### [ C\# ] + +``` +var bucket = new Bucket(this, "myBucket") +{ + BucketName = uploadBucketName.ValueAsString +}; +``` + +------ + +## Deploying with parameters<a name="parameters_deploy"></a> + +A generated template containing parameters can be deployed in the usual way through the AWS CloudFormation console; you are prompted for the values of each parameter\. + +The AWS CDK Toolkit \(`cdk` command\-line tool\) also supports specifying parameters at deployment\. You may provide these on the command line following the `--parameters` flag\. You might deploy a stack that uses the `uploadBucketName` parameter like this\. + +``` +cdk deploy MyStack --parameters uploadBucketName=uploadbucket +``` + +To define multiple parameters, use multiple `--parameters` flags\. + +``` +cdk deploy MyStack --parameters uploadBucketName=upbucket --parameters downloadBucketName=downbucket +``` + +If you are deploying multiple stacks, you can specify a different value of each parameter for each stack by prefixing the name of the parameter with the stack name and a colon\. + +``` +cdk deploy MyStack YourStack --parameters MyStack:uploadBucketName=uploadbucket --parameters YourStack:uploadBucketName=upbucket +``` + +By default, the AWS CDK retains values of parameters from previous deployments and uses them in subsequent deployments if they are not specified explicitly\. Use the `--no-previous-parameters` flag to require all parameters to be specified\. \ No newline at end of file diff --git a/v1/permissions.md b/v1/permissions.md new file mode 100644 index 00000000..e6cfc213 --- /dev/null +++ b/v1/permissions.md @@ -0,0 +1,510 @@ +# Permissions<a name="permissions"></a> + +The AWS Construct Library uses a few common, widely\-implemented idioms to manage access and permissions\. The IAM module provides you with the tools you need to use these idioms\. + +## Principals<a name="permissions_principals"></a> + +An IAM principal is an authenticated AWS entity representing a user, service, or application that can call AWS APIs\. The AWS Construct Library supports specifying principals in several flexible ways to grant them access your AWS resources\. + +In security contexts, the term "principal" refers specifically to authenticated entities such as users\. Objects like groups and roles do not *represent* users \(and other authenticated entities\) but rather *identify* them indirectly for the purpose of granting permissions\. For example, if you create an IAM group, you can grant the group \(i\.e\. its members\) write access to a Amazon RDS table, but the group itself is not a principal since it does not represent a single entity \(also, you cannot log in to a group\)\. + +In the CDK's IAM library, classes that directly or indirectly identify principals implement the [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-iam.IPrincipal.html](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-iam.IPrincipal.html) interface, allowing these objects to be used interchangeably in access policies\. However, not all of them are principals in the security sense\. These objects include: + +1. Traditional IAM resources such as `[Role](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-iam.Role.html)`, `[User](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-iam.User.html)`, and `[Group](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-iam.Group.html)` + +1. Service principals \(`new iam.[ServicePrincipal](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-iam.ServicePrincipal.html)('service.amazonaws.com')`\) + +1. Federated principals \(`new iam.[FederatedPrincipal](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-iam.FederatedPrincipal.html)('cognito-identity.amazonaws.com')`\) + +1. Account principals \(`new iam.[AccountPrincipal](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-iam.AccountPrincipal.html)('0123456789012'))` + +1. Canonical user principals \(`new iam.[CanonicalUserPrincipal](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-iam.CanonicalUserPrincipal.html)('79a59d[...]7ef2be')`\) + +1. AWS organizations principals \(`new iam.[OrganizationPrincipal](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-iam.OrganizationPrincipal.html)('org-id')`\) + +1. Arbitrary ARN principals \(`new iam.[ArnPrincipal](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-iam.ArnPrincipal.html)(res.arn)`\) + +1. An `iam.[CompositePrincipal](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-iam.CompositePrincipal.html)(principal1, principal2, ...)` to trust multiple principals + +## Grants<a name="permissions_grants"></a> + +Every construct that represents a resource that can be accessed, such as an Amazon S3 bucket or Amazon DynamoDB table, has methods that grant access to another entity\. All such methods have names starting with **grant**\. For example, Amazon S3 buckets have the methods `[grantRead](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-s3.Bucket.html#grant-readidentity-objectskeypattern)` and `[grantReadWrite](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-s3.Bucket.html#grant-read-writeidentity-objectskeypattern)` \(Python: `grant_read`, `grant_read_write`\) to enable read and read/write access, respectively, from an entity to the bucket without having to know exactly which Amazon S3 IAM permissions are required to perform these operations\. + +The first argument of a **grant** method is always of type [IGrantable](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-iam.IGrantable.html)\. This interface represents entities that can be granted permissions—that is, resources with roles, such as the IAM objects `[Role](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-iam.Role.html)`, `[User](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-iam.User.html)`, and `[Group](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-iam.Group.html)`\. + +Other entities can also be granted permissions\. For example, later in this topic, we show how to grant a CodeBuild project access to an Amazon S3 bucket\. Generally, the associated role is obtained via a `role` property on the entity being granted access\. + +Resources that use execution roles, such as `[lambda\.Function](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-lambda.Function.html)`, also implement `IGrantable`, so you can grant them access directly instead of granting access to their role\. For example, if `bucket` is an Amazon S3 bucket, and `function` is a Lambda function, the code below grants the function read access to the bucket\. + +------ +#### [ TypeScript ] + +``` +bucket.grantRead(function); +``` + +------ +#### [ JavaScript ] + +``` +bucket.grantRead(function); +``` + +------ +#### [ Python ] + +``` +bucket.grant_read(function) +``` + +------ +#### [ Java ] + +``` +bucket.grantRead(function); +``` + +------ +#### [ C\# ] + +``` +bucket.GrantRead(function); +``` + +------ + + Sometimes permissions must be applied while your stack is being deployed\. One such case is when you grant a AWS CloudFormation custom resource access to some other resource\. The custom resource will be invoked during deployment, so it must have the specified permissions at deployment time\. Another case is when a service verifies that the role you pass to it has the right policies applied \(a number of AWS services do this to make sure you didn't forget to set the policies\)\. In those cases, the deployment may fail if the permissions are applied too late\. + + To force the grant's permissions to be applied before another resource is created, you can add a dependency on the grant itself, as shown here\. Though the return value of grant methods is commonly discarded, every grant method in fact returns an `iam.Grant` object\. + +------ +#### [ TypeScript ] + +``` +const grant = bucket.grantRead(lambda); +const custom = new CustomResource(...); +custom.node.addDependency(grant); +``` + +------ +#### [ JavaScript ] + +``` +const grant = bucket.grantRead(lambda); +const custom = new CustomResource(...); +custom.node.addDependency(grant); +``` + +------ +#### [ Python ] + +``` +grant = bucket.grant_read(function) +custom = CustomResource(...) +custom.node.add_dependency(grant) +``` + +------ +#### [ Java ] + +``` +Grant grant = bucket.grantRead(function); +CustomResource custom = new CustomResource(...); +custom.node.addDependency(grant); +``` + +------ +#### [ C\# ] + +``` +var grant = bucket.GrantRead(function); +var custom = new CustomResource(...); +custom.node.AddDependency(grant); +``` + +------ + +## Roles<a name="permissions_roles"></a> + +The IAM package contains a `[Role](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-iam.Role.html)` construct that represents IAM roles\. The following code creates a new role, trusting the Amazon EC2 service\. + +------ +#### [ TypeScript ] + +``` +import * as iam from '@aws-cdk/aws-iam'; + +const role = new iam.Role(this, 'Role', { + assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com'), // required +}); +``` + +------ +#### [ JavaScript ] + +``` +const iam = require('@aws-cdk/aws-iam'); + +const role = new iam.Role(this, 'Role', { + assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com') // required +}); +``` + +------ +#### [ Python ] + +``` +import aws_cdk.aws_iam as iam + +role = iam.Role(self, "Role", + assumed_by=iam.ServicePrincipal("ec2.amazonaws.com")) # required +``` + +------ +#### [ Java ] + +``` +import software.amazon.awscdk.services.iam.Role; +import software.amazon.awscdk.services.iam.ServicePrincipal; + +Role role = Role.Builder.create(this, "Role") + .assumedBy(new ServicePrincipal("ec2.amazonaws.com")).build(); +``` + +------ +#### [ C\# ] + +``` +using Amazon.CDK.AWS.IAM; + +var role = new Role(this, "Role", new RoleProps +{ + AssumedBy = new ServicePrincipal("ec2.amazonaws.com"), // required +}); +``` + +------ + +You can add permissions to a role by calling the role's `[addToPolicy](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-iam.Role.html#add-to-policystatement)` method \(Python: `add_to_policy`\), passing in a `[PolicyStatement](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-iam.PolicyStatement.html)` that defines the rule to be added\. The statement is added to the role's default policy; if it has none, one is created\. + + The following example adds a `Deny` policy statement to the role for the actions `ec2:SomeAction` and `s3:AnotherAction` on the resources `bucket` and `otherRole` \(Python: `other_role`\), under the condition that the authorized service is AWS CodeBuild\. + +------ +#### [ TypeScript ] + +``` +role.addToPolicy(new iam.PolicyStatement({ + effect: iam.Effect.DENY, + resources: [bucket.bucketArn, otherRole.roleArn], + actions: ['ec2:SomeAction', 's3:AnotherAction'], + conditions: {StringEquals: { + 'ec2:AuthorizedService': 'codebuild.amazonaws.com', +}}})); +``` + +------ +#### [ JavaScript ] + +``` +role.addToPolicy(new iam.PolicyStatement({ + effect: iam.Effect.DENY, + resources: [bucket.bucketArn, otherRole.roleArn], + actions: ['ec2:SomeAction', 's3:AnotherAction'], + conditions: {StringEquals: { + 'ec2:AuthorizedService': 'codebuild.amazonaws.com' +}}})); +``` + +------ +#### [ Python ] + +``` +role.add_to_policy(iam.PolicyStatement( + effect=iam.Effect.DENY, + resources=[bucket.bucket_arn, other_role.role_arn], + actions=["ec2:SomeAction", "s3:AnotherAction"], + conditions={"StringEquals": { + "ec2:AuthorizedService": "codebuild.amazonaws.com"}} +)) +``` + +------ +#### [ Java ] + +``` +role.addToPolicy(PolicyStatement.Builder.create() + .effect(Effect.DENY) + .resources(Arrays.asList(bucket.getBucketArn(), otherRole.getRoleArn())) + .actions(Arrays.asList("ec2:SomeAction", "s3:AnotherAction")) + .conditions(java.util.Map.of( // Map.of requires Java 9 or later + "StringEquals", java.util.Map.of( + "ec2:AuthorizedService", "codebuild.amazonaws.com"))) + .build()); +``` + +------ +#### [ C\# ] + +``` +role.AddToPolicy(new PolicyStatement(new PolicyStatementProps +{ + Effect = Effect.DENY, + Resources = new string[] { bucket.BucketArn, otherRole.RoleArn }, + Actions = new string[] { "ec2:SomeAction", "s3:AnotherAction" }, + Conditions = new Dictionary<string, object> + { + ["StringEquals"] = new Dictionary<string, string> + { + ["ec2:AuthorizedService"] = "codebuild.amazonaws.com" + } + } +})); +``` + +------ + + In our example above, we've created a new `[PolicyStatement](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-iam.PolicyStatement.html)` inline with the `[addToPolicy](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-iam.Role.html#add-to-policystatement)` \(Python: `add_to_policy`\) call\. You can also pass in an existing policy statement or one you've modified\. The [PolicyStatement](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-iam.PolicyStatement.html) object has [numerous methods](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-iam.PolicyStatement.html#methods) for adding principals, resources, conditions, and actions\. + +If you're using a construct that requires a role to function correctly, you can either pass in an existing role when instantiating the construct object, or let the construct create a new role for you, trusting the appropriate service principal\. The following example uses such a construct: a CodeBuild project\. + +------ +#### [ TypeScript ] + +``` +import * as codebuild from '@aws-cdk/aws-codebuild'; + +// imagine roleOrUndefined is a function that might return a Role object +// under some conditions, and undefined under other conditions +const someRole: iam.IRole | undefined = roleOrUndefined(); + +const project = new codebuild.Project(this, 'Project', { + // if someRole is undefined, the Project creates a new default role, + // trusting the codebuild.amazonaws.com service principal + role: someRole, +}); +``` + +------ +#### [ JavaScript ] + +``` +const codebuild = require('@aws-cdk/aws-codebuild'); + +// imagine roleOrUndefined is a function that might return a Role object +// under some conditions, and undefined under other conditions +const someRole = roleOrUndefined(); + +const project = new codebuild.Project(this, 'Project', { + // if someRole is undefined, the Project creates a new default role, + // trusting the codebuild.amazonaws.com service principal + role: someRole +}); +``` + +------ +#### [ Python ] + +``` +import aws_cdk.aws_codebuild as codebuild + +# imagine role_or_none is a function that might return a Role object +# under some conditions, and None under other conditions +some_role = role_or_none(); + +project = codebuild.Project(self, "Project", +# if role is None, the Project creates a new default role, +# trusting the codebuild.amazonaws.com service principal +role=some_role) +``` + +------ +#### [ Java ] + +``` +import software.amazon.awscdk.services.iam.Role; +import software.amazon.awscdk.services.codebuild.Project; + +// imagine roleOrNull is a function that might return a Role object +// under some conditions, and null under other conditions +Role someRole = roleOrNull(); + +// if someRole is null, the Project creates a new default role, +// trusting the codebuild.amazonaws.com service principal +Project project = Project.Builder.create(this, "Project") + .role(someRole).build(); +``` + +------ +#### [ C\# ] + +``` +using Amazon.CDK.AWS.CodeBuild; + +// imagine roleOrNull is a function that might return a Role object +// under some conditions, and null under other conditions +var someRole = roleOrNull(); + +// if someRole is null, the Project creates a new default role, +// trusting the codebuild.amazonaws.com service principal +var project = new Project(this, "Project", new ProjectProps +{ + Role = someRole +}); +``` + +------ + +Once the object is created, the role \(whether the role passed in or the default one created by the construct\) is available as the property `role`\. This property is not available on external resources, however, so such constructs have an `addToRolePolicy` \(Python: `add_to_role_policy`\) method that does nothing if the construct is a reference to an external resource, and calls the `addToPolicy` \(Python: `add_to_policy`\) method of the `role` property otherwise, saving you the trouble of handling the undefined case explicitly\. The following example demonstrates: + +------ +#### [ TypeScript ] + +``` +// project is imported into the CDK application +const project = codebuild.Project.fromProjectName(this, 'Project', 'ProjectName'); + +// project is imported, so project.role is undefined, and this call has no effect +project.addToRolePolicy(new iam.PolicyStatement({ + effect: iam.Effect.ALLOW, // ... and so on defining the policy +})); +``` + +------ +#### [ JavaScript ] + +``` +// project is imported into the CDK application +const project = codebuild.Project.fromProjectName(this, 'Project', 'ProjectName'); + +// project is imported, so project.role is undefined, and this call has no effect +project.addToRolePolicy(new iam.PolicyStatement({ + effect: iam.Effect.ALLOW // ... and so on defining the policy +})); +``` + +------ +#### [ Python ] + +``` +# project is imported into the CDK application +project = codebuild.Project.from_project_name(self, 'Project', 'ProjectName') + +# project is imported, so project.role is undefined, and this call has no effect +project.add_to_role_policy(iam.PolicyStatement( + effect=iam.Effect.ALLOW, # ... and so on defining the policy +) +``` + +------ +#### [ Java ] + +``` +// project is imported into the CDK application +Project project = Project.fromProjectName(this, "Project", "ProjectName"); + +// project is imported, so project.getRole() is null, and this call has no effect +project.addToRolePolicy(PolicyStatement.Builder.create() + .effect(Effect.ALLOW) // .. and so on defining the policy + .build(); +``` + +------ +#### [ C\# ] + +``` +// project is imported into the CDK application +var project = Project.FromProjectName(this, "Project", "ProjectName"); + +// project is imported, so project.role is null, and this call has no effect +project.AddToRolePolicy(new PolicyStatement(new PolicyStatementProps +{ + Effect = Effect.ALLOW, // ... and so on defining the policy +})); +``` + +------ + +## Resource policies<a name="permissions_resource_policies"></a> + +A few resources in AWS, such as Amazon S3 buckets and IAM roles, also have a resource policy\. These constructs have an `addToResourcePolicy` method \(Python: `add_to_resource_policy`\), which takes a `[PolicyStatement](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-iam.PolicyStatement.html)` as its argument\. Every policy statement added to a resource policy must specify at least one principal\. + +In the following example, the [Amazon S3 bucket](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-s3.Bucket.html) `bucket` grants a role with the `s3:SomeAction` permission to itself\. + +------ +#### [ TypeScript ] + +``` +bucket.addToResourcePolicy(new iam.PolicyStatement({ + effect: iam.Effect.ALLOW, + actions: ['s3:SomeAction'], + resources: [bucket.bucketArn], + principals: [role] +})); +``` + +------ +#### [ JavaScript ] + +``` +bucket.addToResourcePolicy(new iam.PolicyStatement({ + effect: iam.Effect.ALLOW, + actions: ['s3:SomeAction'], + resources: [bucket.bucketArn], + principals: [role] +})); +``` + +------ +#### [ Python ] + +``` +bucket.add_to_resource_policy(iam.PolicyStatement( + effect=iam.Effect.ALLOW, + actions=["s3:SomeAction"], + resources=[bucket.bucket_arn], + principals=role)) +``` + +------ +#### [ Java ] + +``` +bucket.addToResourcePolicy(PolicyStatement.Builder.create() + .effect(Effect.ALLOW) + .actions(Arrays.asList("s3:SomeAction")) + .resources(Arrays.asList(bucket.getBucketArn())) + .principals(Arrays.asList(role)) + .build()); +``` + +------ +#### [ C\# ] + +``` +bucket.AddToResourcePolicy(new PolicyStatement(new PolicyStatementProps +{ + Effect = Effect.ALLOW, + Actions = new string[] { "s3:SomeAction" }, + Resources = new string[] { bucket.BucketArn }, + Principals = new IPrincipal[] { role } +})); +``` + +------ + +## Using external IAM objects<a name="permissions_existing"></a> + +If you have defined an IAM user, principal, group, or role outside your AWS CDK app, you can use that IAM object in your AWS CDK app by creating a reference to it using its ARN or \(for users, groups, and roles\) its name\. The returned reference can then be used to grant permissions or to construct policy statements as explained above\. ++ For users, call `[User\.fromUserArn\(\)](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-iam.User.html#static-fromwbruserwbrarnscope-id-userarn)` or `[User\.fromUserName\(\)](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-iam.User.html#static-fromwbruserwbrnamescope-id-username)`\. `User.fromUserAttributes()` is also available, but currently provides the same functionality as `User.fromUserArn()`\. ++ For principals, instantiate an `[ArnPrincipal](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-iam.ArnPrincipal.html)` object\. ++ For groups, call `[Group\.fromGroupArn\(\)](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-iam.Group.html#static-fromwbrgroupwbrarnscope-id-grouparn)` or `[Group\.fromGroupName\(\)](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-iam.Group.html#static-fromwbrgroupwbrnamescope-id-groupname)`\. ++ For roles, call `[Role\.fromRoleArn\(\)](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-iam.Role.html#static-fromwbrrolewbrarnscope-id-rolearn-options)` or `[Role\.fromRoleName\(\)](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-iam.Role.html#static-fromwbrrolewbrnamescope-id-rolename)`\. + +Policies \(including managed policies\) can be referenced in similar fashion using the methods listed below\. You can use references to these objects anywhere an IAM policy is required\. ++ `[Policy\.fromPolicyName](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-iam.Policy.html#static-fromwbrpolicywbrnamescope-id-policyname)` ++ `[ManagedPolicy\.fromManagedPolicyArn](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-iam.ManagedPolicy.html#static-fromwbrmanagedwbrpolicywbrarnscope-id-managedpolicyarn)` ++ `[ManagedPolicy\.fromManagedPolicyName](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-iam.ManagedPolicy.html#static-fromwbrmanagedwbrpolicywbrnamescope-id-managedpolicyname)` ++ `[ManagedPolicy\.fromAwsManagedPolicyName](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-iam.ManagedPolicy.html#static-fromwbrawswbrmanagedwbrpolicywbrnamemanagedpolicyname)` + +**Note** +As with all references to external AWS resources, you cannot modify IAM references returned by the above methods in your CDK app\. \ No newline at end of file diff --git a/v2/guide/pgp-keys.adoc b/v1/pgp-keys.md similarity index 76% rename from v2/guide/pgp-keys.adoc rename to v1/pgp-keys.md index b8ba167f..05c1957b 100644 --- a/v2/guide/pgp-keys.adoc +++ b/v1/pgp-keys.md @@ -1,58 +1,27 @@ -include::attributes.txt[] +# OpenPGP keys for the AWS CDK and jsii<a name="pgp-keys"></a> -// Attributes +This topic contains current and historical OpenPGP keys for the AWS CDK and jsii\. -[#pgp-keys] -= OpenPGP keys for the {aws} CDK and jsii -:doctype: book -:info_titleabbrev: OpenPGP keys +## Current keys<a name="pgp-keys-current"></a> -[abstract] --- -Current and historical OpenPGP keys for the {aws} CDK and jsii. --- +These keys should be used to validate current releases of the AWS CDK and jsii\. -// Content start +### AWS CDK OpenPGP key<a name="cdk_pgp_key"></a> -This topic contains current and historical OpenPGP keys for the {aws} CDK and jsii. -[#pgp-keys-current,] -== Current keys - -These keys should be used to validate current releases of the {aws} CDK and jsii. - -[#cdk-pgp-key] -=== {aws} CDK OpenPGP key - -[cols="1,1"] -|=== - -|Key ID: -|0x42B9CF2286CD987A - -|Type: -|RSA - -|Size: -|4096/4096 - -|Created: -|2022-07-05 - -|Expires: -|2026-07-04 - -|User ID: -|{aws} Cloud Development Kit <aws-cdk@amazon.com> - -|Key fingerprint: -|69B5 2D5B A295 1D11 FA65 413B 42B9 CF22 86CD 987A -|=== +| | | +| --- |--- | +| Key ID: | 0x42B9CF2286CD987A | +| Type: | RSA | +| Size: | 4096/4096 | +| Created: | 2022\-07\-05 | +| Expires: | 2026\-07\-04 | +| User ID: | AWS Cloud Development Kit <aws\-cdk@amazon\.com> | +| Key fingerprint: | 69B5 2D5B A295 1D11 FA65 413B 42B9 CF22 86CD 987A | Select the "Copy" icon to copy the following OpenPGP key: -[source,none,subs="verbatim,attributes"] ----- +``` -----BEGIN PGP PUBLIC KEY BLOCK----- mQINBGLEgOsBEADCoAMwvnszMLybJ+AD9cHhVyX6+rYIUEXYSgVnfkl6Z7qawIwv @@ -82,40 +51,24 @@ Y4U1nCPCdTK5/C7JCKzR2gVnCpe6uaxAWkkM2feQhjqJZkTC4cFVgBT+4M6WcT1r yq4= =ahbs -----END PGP PUBLIC KEY BLOCK----- ----- - -[#jsii-pgp-key] -=== jsii OpenPGP key - -[cols="1,1"] -|=== +``` -|Key ID: -|0x056C4E15DAE3D8D9 +### jsii OpenPGP key<a name="jsii_pgp_key"></a> -|Type: -|RSA -|Size: -|4096/4096 - -|Created: -|2022-07-05 - -|Expires: -|2026-07-04 - -|User ID: -|{aws} JSII Team <aws-jsii@amazon.com> - -|Key fingerprint: -|1E07 31D4 57E5 FE87 87E5 530A 056C 4E15 DAE3 D8D9 -|=== +| | | +| --- |--- | +| Key ID: | 0x056C4E15DAE3D8D9 | +| Type: | RSA | +| Size: | 4096/4096 | +| Created: | 2022\-07\-05 | +| Expires: | 2026\-07\-04 | +| User ID: | AWS JSII Team <aws\-jsii@amazon\.com> | +| Key fingerprint: | 1E07 31D4 57E5 FE87 87E5 530A 056C 4E15 DAE3 D8D9 | Select the "Copy" icon to copy the following OpenPGP key: -[source,none,subs="verbatim,attributes"] ----- +``` -----BEGIN PGP PUBLIC KEY BLOCK----- mQINBGLEgOkBEAD27EPVG9g2mHQ3+M6tF6le+tfhARJ2EV7m7NKIrTdSlCZATLWn @@ -144,59 +97,34 @@ OCZJKrydluIIwR8vvONNqO+QwZ1xDEhO7MaSZlOm1AuUZIXFPgaWQkPZHKiiwFA/ QWnL/+shuRtMH2geTjkev198Jgb5HyXFm4SyYtZferQROyliEhik =BuGv -----END PGP PUBLIC KEY BLOCK----- ----- - -[#pgp-keys-expired] -== Historical keys - -These keys may be used to validate releases of the {aws} CDK and jsii before 2022-07-05. - -[IMPORTANT] -==== - -New keys are created before the previous ones expire. As a result, at any given moment in time, more than one key may be valid. Keys are used to sign artifacts starting the day they are created, so use the more recently-issued key where keys' validity overlaps. - -==== - -[#cdk-pgp-key-2022-04-07] -=== {aws} CDK OpenPGP key (2022-04-07) - -[NOTE] -==== - -This key was not used to sign {aws} CDK artifacts after 2022-07-05. +``` -==== +## Historical keys<a name="pgp-keys-expired"></a> -[cols="1,1"] -|=== +These keys may be used to validate releases of the AWS CDK and jsii before 2022\-07\-05\. -|Key ID: -|0x015584281F44A3C3 +**Important** +New keys are created before the previous ones expire\. As a result, at any given moment in time, more than one key may be valid\. Keys are used to sign artifacts starting the day they are created, so use the more recently\-issued key where keys' validity overlaps\. -|Type: -|RSA +### AWS CDK OpenPGP key \(2022\-04\-07\)<a name="cdk_pgp_key-2022-04-07-"></a> -|Size: -|4096/4096 +**Note** +This key was not used to sign AWS CDK artifacts after 2022\-07\-05\. -|Created: -|2022-04-07 -|Expires: -|2026-04-06 - -|User ID: -|{aws} Cloud Development Kit <aws-cdk@amazon.com> - -|Key fingerprint: -|EAE1 1A24 82B0 AA86 456E 6C67 0155 8428 1F44 A3C3 -|=== +| | | +| --- |--- | +| Key ID: | 0x015584281F44A3C3 | +| Type: | RSA | +| Size: | 4096/4096 | +| Created: | 2022\-04\-07 | +| Expires: | 2026\-04\-06 | +| User ID: | AWS Cloud Development Kit <aws\-cdk@amazon\.com> | +| Key fingerprint: | EAE1 1A24 82B0 AA86 456E 6C67 0155 8428 1F44 A3C3 | Select the "Copy" icon to copy the following OpenPGP key: -[source,none,subs="verbatim,attributes"] ----- +``` -----BEGIN PGP PUBLIC KEY BLOCK----- mQINBGJPLgUBEADtlR5jQtxtBmROQvmWlPOViqqnJNhk0dULc3tXnq8NS/l6X81r @@ -226,48 +154,27 @@ pVAtyCtTJdD3eZbQPVaL3T8cf1VGqt6++pnLGnWJ0+X3TyvfmTohdJvN3TE+tq7A l6U= =MQI4 -----END PGP PUBLIC KEY BLOCK----- ----- - - -[#jsii-pgp-key-2022-04-07] -=== jsii OpenPGP key (2022-04-07) - -[NOTE] -==== - -This key was not used to sign jsii artifacts after 2022-07-05. +``` -==== +### jsii OpenPGP key \(2022\-04\-07\)<a name="jsii_pgp_key-2022-04-07"></a> -[cols="1,1"] -|=== +**Note** +This key was not used to sign jsii artifacts after 2022\-07\-05\. -|Key ID: -|0x985F5BC974B79356 -|Type: -|RSA - -|Size: -|4096/4096 - -|Created: -|2022-04-07 - -|Expires: -|2026-04-06 - -|User ID: -|{aws} JSII Team <aws-jsii@amazon.com> - -|Key fingerprint: -|35A7 1785 8FA6 282D C5AC CD95 985F 5BC9 74B7 9356 -|=== +| | | +| --- |--- | +| Key ID: | 0x985F5BC974B79356 | +| Type: | RSA | +| Size: | 4096/4096 | +| Created: | 2022\-04\-07 | +| Expires: | 2026\-04\-06 | +| User ID: | AWS JSII Team <aws\-jsii@amazon\.com> | +| Key fingerprint: | 35A7 1785 8FA6 282D C5AC CD95 985F 5BC9 74B7 9356 | Select the "Copy" icon to copy the following OpenPGP key: -[source,none,subs="verbatim,attributes"] ----- +``` -----BEGIN PGP PUBLIC KEY BLOCK----- mQINBGJPLewBEADHH4TXup/gOlHrKDZRbj8MvsMTdM6eDteA6/c32UYV/YsK9rDA @@ -296,40 +203,24 @@ mhPUvXZj/I9rgsEq3L/sm2Xjy09nra4o3oe3bhEL8nOj11wkIodi17VaGP0y+H3s I5zB5UztS6dy+cH+J7DoRaxzVzq7qtH/ZY2quClt30wwqDHUX1ef =+iYX -----END PGP PUBLIC KEY BLOCK----- ----- - -[#cdk-pgp-key-2018-06-19] -=== {aws} CDK OpenPGP key (2018-06-19) +``` -[cols="1,1"] -|=== +### AWS CDK OpenPGP key \(2018\-06\-19\)<a name="cdk_pgp_key-2018-06-19-"></a> -|Key ID: -|0x0566A784E17F3870 -|Type: -|RSA - -|Size: -|4096/4096 - -|Created: -|2018-06-19 - -|Expires: -|2022-06-18 - -|User ID: -|{aws} CDK Team <aws-cdk@amazon.com> - -|Key fingerprint: -|E88B E3B6 F0B1 E350 9E36 4F96 0566 A784 E17F 3870 -|=== +| | | +| --- |--- | +| Key ID: | 0x0566A784E17F3870 | +| Type: | RSA | +| Size: | 4096/4096 | +| Created: | 2018\-06\-19 | +| Expires: | 2022\-06\-18 | +| User ID: | AWS CDK Team <aws\-cdk@amazon\.com> | +| Key fingerprint: | E88B E3B6 F0B1 E350 9E36 4F96 0566 A784 E17F 3870 | Select the "Copy" icon to copy the following OpenPGP key: -[source,none,subs="verbatim,attributes"] ----- +``` -----BEGIN PGP PUBLIC KEY BLOCK----- mQINBFsovE8BEADEFVCHeAVPvoQgsjVu9FPUczxy9P+2zGIT/MLI3/vPLiULQwRy @@ -358,40 +249,24 @@ EkSlc/RoDqZCpBGgcoy1FFWvV/ZLgNU6OTQlYH6oYOWiylSJnaTDyurrktsxJI6d 80RE7ayn7BsiaLzFBVux/zz/WgvudsZX18r8tDiVQBL51ORmqw== =0wuQ -----END PGP PUBLIC KEY BLOCK----- ----- - -[#jsii-pgp-key-2018-08-06] -=== jsii OpenPGP key (2018-08-06) - -[cols="1,1"] -|=== - -|Key ID: -|0x1C7ACE4CB2A1B93A - -|Type: -|RSA - -|Size: -|4096/4096 - -|Created: -|2018-08-06 +``` -|Expires: -|2022-08-05 +### jsii OpenPGP key \(2018\-08\-06\)<a name="jsii_pgp_key-2018-08-06"></a> -|User ID: -|{aws} JSII Team <aws-jsii@amazon.com> -|Key fingerprint: -|85EF 6522 4CE2 1E8C 72DB 28EC 1C7A CE4C B2A1 B93A -|=== +| | | +| --- |--- | +| Key ID: | 0x1C7ACE4CB2A1B93A | +| Type: | RSA | +| Size: | 4096/4096 | +| Created: | 2018\-08\-06 | +| Expires: | 2022\-08\-05 | +| User ID: | AWS JSII Team <aws\-jsii@amazon\.com> | +| Key fingerprint: | 85EF 6522 4CE2 1E8C 72DB 28EC 1C7A CE4C B2A1 B93A | Select the "Copy" icon to copy the following OpenPGP key: -[source,none,subs="verbatim,attributes"] ----- +``` -----BEGIN PGP PUBLIC KEY BLOCK----- mQINBFtoSs0BEAD6WweLD0B26h0F7Jo9iR6tVQ4PgQBK1Va5H/eP+A2Iqw79UyxZ @@ -420,4 +295,4 @@ ZsLa398LMteQ8UMxwJ3t06jwDWAd7mbr2tatIilLHtWWBFoCwBh1XLe/03ENCpDp njZ7OsBsBK2nVVcN0H2v5ey0T1yE93o6r7xOwCwBiVp5skTCRUob =2Tag -----END PGP PUBLIC KEY BLOCK----- ----- \ No newline at end of file +``` \ No newline at end of file diff --git a/v1/reference.md b/v1/reference.md new file mode 100644 index 00000000..3489ad05 --- /dev/null +++ b/v1/reference.md @@ -0,0 +1,71 @@ +# API reference<a name="reference"></a> + +The [API Reference](https://docs.aws.amazon.com/cdk/api/v1) contains information about the AWS Construct Library and other APIs provided by the AWS CDK\. It is organized by module\. + +Each module has an overview that includes information about how to use its APIs\. For example, the [S3](https://docs.aws.amazon.com/cdk/api/v1/docs/aws-s3-readme.html) overview demonstrates how to set default encryption on an Amazon S3 bucket\. + +Separate versions of the API Reference are provided for TypeScript/JavaScript, Python, Java, C\#/\.NET\., and Go\. + +## Versioning<a name="versioning"></a> + +Version numbers consist of three numeric version parts: *major*\.*minor*\.*patch*, and generally adhere to the [semantic versioning](https://semver.org) model\. This means that breaking changes to stable APIs are limited to major releases\. Minor and patch releases are backward compatible, meaning that the code written in a previous version with the same major version can be upgraded to a newer version and be expected to continue to build and run, producing the same output\. + +**Note** +This compatibility promise does not apply to APIs under active development, which are designated as experimental\. See [AWS CDK stability index](#aws_construct_lib_stability) for more details\. + +### AWS CDK Toolkit \(CLI\) compatibility<a name="cdk_toolkit_versioning"></a> + +The AWS CDK Toolkit \(that is, the `cdk` command line command\) is *always* compatible with construct libraries of a semantically *lower* or *equal* version number\. It is, therefore, always safe to upgrade the AWS CDK Toolkit within the same major version\. + +The AWS CDK Toolkit may be, but is *not always*, compatible with construct libraries of a semantically *higher* version, depending on whether the same cloud assembly schema version is employed by the two components\. The AWS CDK framework generates a cloud assembly during synthesis; the AWS CDK Toolkit consumes it for deployment\. The schema that defines the format of the cloud assembly is strictly specified and versioned\. AWS construct libraries using a given cloud assembly schema version are compatible with AWS CDK toolkit versions using that schema version or later, which may include releases of the AWS CDK Toolkit *older than* a given construct library release\. + +When the cloud assembly version required by the construct library is not compatible with the version supported by the AWS CDK Toolkit, you receive an error message like this one\. + +``` +Cloud assembly schema version mismatch: Maximum schema version supported is 3.0.0, but found 4.0.0. + Please upgrade your CLI in order to interact with this app. +``` + +To resolve this error, update the AWS CDK Toolkit to a version compatible with the required cloud assembly version, or simply to the latest available version\. The alternative \(downgrading the construct library modules your app uses\) is generally not desirable\. + +**Note** +For more details on the cloud assembly schema, see [Cloud Assembly Versioning](https://github.com/aws/aws-cdk/tree/master/packages/%40aws-cdk/cloud-assembly-schema#versioning)\. + +### AWS CDK stability index<a name="aws_construct_lib_stability"></a> + +The modules in the AWS Construct Library move through various stages as they are developed from concept to mature API\. Different stages imply different promises for API stability in subsequent versions of the AWS CDK\. + +Stage 0: CFN resources +All construct library modules start in stage 0 when they are auto\-generated from the AWS CloudFormation resource specification\. The goal of stage 0 is to make new AWS CloudFormation resources/properties available to AWS CDK customers as quickly as possible\. We capture feedback from customers to better understand what L2 resources to add\. +AWS CloudFormation resources themselves are considered stable APIs, regardless of whether other constructs in the module are under active development\. + +Stage 1: Experimental +The goal of the experimental stage is to retain the freedom to make breaking changes to APIs while we design and build a module\. During this stage, the primary use cases and the set of L2 constructs required to support them are incrementally identified, implemented, and validated\. +Development of L2 constructs is community\-oriented and transparent\. For large and/or complex changes, we author a Request for Comments \(RFC\) that outlines our intended design and publish it for feedback\. We also use pull requests to conduct API design reviews\. +At this stage, individual APIs may be in flux, and breaking changes may occur from release to release if we deem these necessary to support customer use cases\. + +Stage 2: Developer preview \(DP\) +At the developer preview stage, our aim is to deliver a release candidate with a stable API with which to conduct user acceptance testing\. When the API passes acceptance, it is deemed suitable for general availability\. +We make breaking changes at this stage only when required to address unforeseen customer use cases or issues\. Since breaking changes are still possible, the package itself retains the "experimental" label while in developer preview\. + +Stage 3: General availability \(GA\) +The module is generally available with a compatibility guarantee across minor versions\. We will only make backward\-compatible changes to the API, so that your existing apps will continue to work until the next major AWS CDK release\. +In some cases, we may use [feature flags](featureflags.md) to optionally enable new behavior while retaining the previous behavior to support existing apps\. + +Each module's Overview in the [API Reference](https://docs.aws.amazon.com/cdk/api/v1/docs/aws-construct-library.html) describes its stability level\. + +For more information about these maturity stages, see [AWS Construct Library Module Lifecycle](https://github.com/aws/aws-cdk-rfcs/blob/master/text/0107-construct-library-module-lifecycle.md)\. + +### Language binding stability<a name="aws_construct_lib_versioning_binding"></a> + +From time to time, we may add support to the AWS CDK for additional programming languages\. Although the API described in all the languages is the same, the way that API is expressed varies by language and may change as the language support evolves\. For this reason, language bindings are deemed experimental for a time until they are considered ready for production use\. + + +| Language | Stability | +| --- |--- | +| TypeScript | Stable | +| JavaScript | Stable | +| Python | Stable | +| Java | Stable | +| C\#/\.NET | Stable | +| Go | Experimental | \ No newline at end of file diff --git a/v1/resources.md b/v1/resources.md new file mode 100644 index 00000000..f1865ffe --- /dev/null +++ b/v1/resources.md @@ -0,0 +1,1283 @@ +# Resources<a name="resources"></a> + +As described in [Constructs](constructs.md), the AWS CDK provides a rich class library of constructs, called *AWS constructs*, that represent all AWS resources\. + +To create an instance of a resource using its corresponding construct, pass in the scope as the first argument, the logical ID of the construct, and a set of configuration properties \(props\)\. For example, here's how to create an Amazon SQS queue with KMS encryption using the [sqs\.Queue](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-sqs.Queue.html) construct from the AWS Construct Library\. + +------ +#### [ TypeScript ] + +``` +import * as sqs from '@aws-cdk/aws-sqs'; + +new sqs.Queue(this, 'MyQueue', { + encryption: sqs.QueueEncryption.KMS_MANAGED +}); +``` + +------ +#### [ JavaScript ] + +``` +const sqs = require('@aws-cdk/aws-sqs'); + +new sqs.Queue(this, 'MyQueue', { + encryption: sqs.QueueEncryption.KMS_MANAGED +}); +``` + +------ +#### [ Python ] + +``` +import aws_cdk.aws_sqs as sqs + +sqs.Queue(self, "MyQueue", encryption=sqs.QueueEncryption.KMS_MANAGED) +``` + +------ +#### [ Java ] + +``` +import software.amazon.awscdk.services.sqs.*; + +Queue.Builder.create(this, "MyQueue").encryption( + QueueEncryption.KMS_MANAGED).build(); +``` + +------ +#### [ C\# ] + +``` +using Amazon.CDK.AWS.SQS; + +new Queue(this, "MyQueue", new QueueProps +{ + Encryption = QueueEncryption.KMS_MANAGED +}); +``` + +------ + +Some configuration props are optional, and in many cases have default values\. In some cases, all props are optional, and the last argument can be omitted entirely\. + +## Resource attributes<a name="resources_attributes"></a> + +Most resources in the AWS Construct Library expose attributes, which are resolved at deployment time by AWS CloudFormation\. Attributes are exposed in the form of properties on the resource classes with the type name as a prefix\. The following example shows how to get the URL of an Amazon SQS queue using the `queueUrl` \(Python: `queue_url`\) property\. + +------ +#### [ TypeScript ] + +``` +import * as sqs from '@aws-cdk/aws-sqs'; + +const queue = new sqs.Queue(this, 'MyQueue'); +const url = queue.queueUrl; // => A string representing a deploy-time value +``` + +------ +#### [ JavaScript ] + +``` +const sqs = require('@aws-cdk/aws-sqs'); + +const queue = new sqs.Queue(this, 'MyQueue'); +const url = queue.queueUrl; // => A string representing a deploy-time value +``` + +------ +#### [ Python ] + +``` +import aws_cdk.aws_sqs as sqs + +queue = sqs.Queue(self, "MyQueue") +url = queue.queue_url # => A string representing a deploy-time value +``` + +------ +#### [ Java ] + +``` +Queue queue = new Queue(this, "MyQueue"); +String url = queue.getQueueUrl(); // => A string representing a deploy-time value +``` + +------ +#### [ C\# ] + +``` +var queue = new Queue(this, "MyQueue"); +var url = queue.QueueUrl; // => A string representing a deploy-time value +``` + +------ + +See [Tokens](tokens.md) for information about how the AWS CDK encodes deploy\-time attributes as strings\. + +## Referencing resources<a name="resources_referencing"></a> + +Many AWS CDK classes require properties that are AWS CDK resource objects \(resources\)\. For example, an Amazon ECS resource requires a reference to the cluster on which it runs; an Amazon CloudFront distribution requires a reference to the bucket containing source code\. To satisfy these requirements, you can refer to a resource in one of two ways: ++ By passing a resource defined in your CDK app, either in the same stack or in a different one ++ By passing a proxy object referencing a resource defined in your AWS account, created from a unique identifier of the resource \(such as an ARN\) + +If a construct property represents another AWS construct, its type is that of the interface type of that construct\. For example, the Amazon ECS service takes a property `cluster` of type `ecs.ICluster`; the CloudFront distribution takes a property `sourceBucket` \(Python: `source_bucket`\) of type `s3.IBucket`\. + +You can directly pass any resource object of the proper type defined in the same AWS CDK app\. The following example defines an Amazon ECS cluster and then uses it to define an Amazon ECS service\. + +------ +#### [ TypeScript ] + +``` +const cluster = new ecs.Cluster(this, 'Cluster', { /*...*/ }); + +const service = new ecs.Ec2Service(this, 'Service', { cluster: cluster }); +``` + +------ +#### [ JavaScript ] + +``` +const cluster = new ecs.Cluster(this, 'Cluster', { /*...*/ }); + +const service = new ecs.Ec2Service(this, 'Service', { cluster: cluster }); +``` + +------ +#### [ Python ] + +``` +cluster = ecs.Cluster(self, "Cluster") + +service = ecs.Ec2Service(self, "Service", cluster=cluster) +``` + +------ +#### [ Java ] + +``` +Cluster cluster = new Cluster(this, "Cluster"); +Ec2Service service = new Ec2Service(this, "Service", + new Ec2ServiceProps.Builder().cluster(cluster).build()); +``` + +------ +#### [ C\# ] + +``` +var cluster = new Cluster(this, "Cluster"); +var service = new Ec2Service(this, "Service", new Ec2ServiceProps { Cluster = cluster }); +``` + +------ + +## Referencing resources in a different stack<a name="resource_stack"></a> + +You can refer to resources in a different stack as long as they are defined in the same app and are in the same AWS account and region\. The pattern generally used is: ++ Store a reference to the construct as an attribute of the stack that produces the resource\. \(To get a reference to the current construct's stack, use `Stack.of(this)`\.\) ++ Pass this reference to the constructor of the stack that consumes the resource as a parameter or a property\. The consuming stack then passes it as a property to any construct that needs it\. + +The following example defines a stack `stack1`\. This stack defines an Amazon S3 bucket and stores a reference to the bucket construct as an attribute of the stack\. Then the app defines a second stack, `stack2`, which accepts a bucket at instantiation\. `stack2` might, for example, define an AWS Glue Table that uses the bucket for data storage\. + +------ +#### [ TypeScript ] + +``` +const prod = { account: '123456789012', region: 'us-east-1' }; + +const stack1 = new StackThatProvidesABucket(app, 'Stack1', { env: prod }); + +// stack2 will take a property { bucket: IBucket } +const stack2 = new StackThatExpectsABucket(app, 'Stack2', { + bucket: stack1.bucket, + env: prod +}); +``` + +------ +#### [ JavaScript ] + +``` +const prod = { account: '123456789012', region: 'us-east-1' }; + +const stack1 = new StackThatProvidesABucket(app, 'Stack1', { env: prod }); + +// stack2 will take a property { bucket } +const stack2 = new StackThatExpectsABucket(app, 'Stack2', { + bucket: stack1.bucket, + env: prod +}); +``` + +------ +#### [ Python ] + +``` +prod = core.Environment(account="123456789012", region="us-east-1") + +stack1 = StackThatProvidesABucket(app, "Stack1", env=prod) + +# stack2 will take a property "bucket" +stack2 = StackThatExpectsABucket(app, "Stack2", bucket=stack1.bucket, env=prod) +``` + +------ +#### [ Java ] + +``` +// Helper method to build an environment +static Environment makeEnv(String account, String region) { + return Environment.builder().account(account).region(region) + .build(); +} + +App app = new App(); + +Environment prod = makeEnv("123456789012", "us-east-1"); + +StackThatProvidesABucket stack1 = new StackThatProvidesABucket(app, "Stack1", + StackProps.builder().env(prod).build()); + +// stack2 will take an argument "bucket" +StackThatExpectsABucket stack2 = new StackThatExpectsABucket(app, "Stack,", + StackProps.builder().env(prod).build(), stack1.bucket); +``` + +------ +#### [ C\# ] + +``` +Amazon.CDK.Environment makeEnv(string account, string region) +{ + return new Amazon.CDK.Environment { Account = account, Region = region }; +} + +var prod = makeEnv(account: "123456789012", region: "us-east-1"); + +var stack1 = new StackThatProvidesABucket(app, "Stack1", new StackProps { Env = prod }); + +// stack2 will take a property "bucket" +var stack2 = new StackThatExpectsABucket(app, "Stack2", new StackProps { Env = prod, + bucket = stack1.Bucket}); +``` + +------ + +If the AWS CDK determines that the resource is in the same account and region, but in a different stack, it automatically synthesizes AWS CloudFormation [exports](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-stack-exports.html) in the producing stack and an [Fn::ImportValue](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-importvalue.html) in the consuming stack to transfer that information from one stack to the other\. + +### Resolving dependency deadlocks<a name="resources_deadlock"></a> + +Referencing a resource from one stack in a different stack creates a dependency between the two stacks to ensure that they are deployed in the right order\. Once this dependency has been made concrete by deploying the stacks, removing the use of the shared resource from the consuming stack can cause an unexpected deployment failure\. This happens if there is another dependency between the two stacks that force them to be deployed in the same order, but it can also happen without a dependency if the producing stack is simply chosen by the CDK Toolkit to be deployed first\. The AWS CloudFormation export is removed from the producing stack because it is no longer needed, but the exported resource is still being used in the consuming stack because its update has not yet been deployed, so deploying the producer stack fails\. + +To break this deadlock, remove the use of the shared resource from the consuming stack \(which will remove the automatic export from the producing stack\), then manually add the same export to the producing stack using exactly the same logical ID as the automatically\-generated export\. Remove the use of the shared resource in the consuming stack and deploy both stacks\. Then remove the manual export \(and the shared resource if it is no longer needed\), and deploy both stacks again\. The stack's `[exportValue\(\)](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.Stack.html#exportwbrvalueexportedvalue-options)` method is a convenient way to create the manual export for this purpose \(see the example in the linked method reference\)\. + +## Referencing resources in your AWS account<a name="resources_external"></a> + +Suppose you want to use a resource already available in your AWS account in your AWS CDK app: for example, a resource that was defined through the console, an AWS SDK, directly with AWS CloudFormation, or in a different AWS CDK application\. You can turn the resource's ARN \(or another identifying attribute, or group of attributes\) into a proxy object that serves as a reference to the resource by calling a static factory method on the resource's class\. + +When you create such a proxy, the external resource **does not** become a part of your AWS CDK app, and therefore, changes you make to the proxy in your AWS CDK app do not affect the deployed resource\. The proxy can, however, be passed to any AWS CDK method that requires a resource of that type\. + +The following example shows how to reference a bucket based on an existing bucket with the ARN **arn:aws:s3:::my\-bucket\-name**, and a Amazon Virtual Private Cloud based on an existing VPC having a specific ID\. + +------ +#### [ TypeScript ] + +``` +// Construct a proxy for a bucket by its name (must be same account) +s3.Bucket.fromBucketName(this, 'MyBucket', 'my-bucket-name'); + +// Construct a proxy for a bucket by its full ARN (can be another account) +s3.Bucket.fromBucketArn(this, 'MyBucket', 'arn:aws:s3:::my-bucket-name'); + +// Construct a proxy for an existing VPC from its attribute(s) +ec2.Vpc.fromVpcAttributes(this, 'MyVpc', { + vpcId: 'vpc-1234567890abcde', +}); +``` + +------ +#### [ JavaScript ] + +``` +// Construct a proxy for a bucket by its name (must be same account) +s3.Bucket.fromBucketName(this, 'MyBucket', 'my-bucket-name'); + +// Construct a proxy for a bucket by its full ARN (can be another account) +s3.Bucket.fromBucketArn(this, 'MyBucket', 'arn:aws:s3:::my-bucket-name'); + +// Construct a proxy for an existing VPC from its attribute(s) +ec2.Vpc.fromVpcAttributes(this, 'MyVpc', { + vpcId: 'vpc-1234567890abcde' +}); +``` + +------ +#### [ Python ] + +``` +# Construct a proxy for a bucket by its name (must be same account) +s3.Bucket.from_bucket_name(self, "MyBucket", "my-bucket-name") + +# Construct a proxy for a bucket by its full ARN (can be another account) +s3.Bucket.from_bucket_arn(self, "MyBucket", "arn:aws:s3:::my-bucket-name") + +# Construct a proxy for an existing VPC from its attribute(s) +ec2.Vpc.from_vpc_attributes(self, "MyVpc", vpc_id="vpc-1234567890abcdef") +``` + +------ +#### [ Java ] + +``` +// Construct a proxy for a bucket by its name (must be same account) +Bucket.fromBucketName(this, "MyBucket", "my-bucket-name"); + +// Construct a proxy for a bucket by its full ARN (can be another account) +Bucket.fromBucketArn(this, "MyBucket", + "arn:aws:s3:::my-bucket-name"); + +// Construct a proxy for an existing VPC from its attribute(s) +Vpc.fromVpcAttributes(this, "MyVpc", VpcAttributes.builder() + .vpcId("vpc-1234567890abcdef").build()); +``` + +------ +#### [ C\# ] + +``` +// Construct a proxy for a bucket by its name (must be same account) +Bucket.FromBucketName(this, "MyBucket", "my-bucket-name"); + +// Construct a proxy for a bucket by its full ARN (can be another account) +Bucket.FromBucketArn(this, "MyBucket", "arn:aws:s3:::my-bucket-name"); + +// Construct a proxy for an existing VPC from its attribute(s) +Vpc.FromVpcAttributes(this, "MyVpc", new VpcAttributes +{ + VpcId = "vpc-1234567890abcdef" +}); +``` + +------ + +Let's take a closer look at the [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-ec2.Vpc.html#static-fromwbrlookupscope-id-options](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-ec2.Vpc.html#static-fromwbrlookupscope-id-options) method\. Because the `ec2.Vpc` construct is complex, there are many ways you might want to select the VPC to be used with your CDK app\. To address this, the VPC construct has a `fromLookup` static method \(Python: `from_lookup`\) that lets you look up the desired Amazon VPC by querying your AWS account at synthesis time\. + +To use `Vpc.fromLookup()`, the system that synthesizes the stack must have access to the account that owns the Amazon VPC, since the CDK Toolkit queries the account to find the right Amazon VPC at synthesis time\. + +Furthermore, `Vpc.fromLookup()` works only in stacks that are defined with an explicit **account** and **region** \(see [Environments](environments.md)\)\. If the AWS CDK attempts to look up an Amazon VPC from an [environment\-agnostic stack](stacks.md#stack_api), the CDK Toolkit does not know which environment to query to find the VPC\. + +You must provide `Vpc.fromLookup()` attributes sufficient to uniquely identify a VPC in your AWS account\. For example, there can only ever be one default VPC, so specifying that you want the VPC marked as the default is sufficient\. + +------ +#### [ TypeScript ] + +``` +ec2.Vpc.fromLookup(this, 'DefaultVpc', { + isDefault: true +}); +``` + +------ +#### [ JavaScript ] + +``` +ec2.Vpc.fromLookup(this, 'DefaultVpc', { + isDefault: true +}); +``` + +------ +#### [ Python ] + +``` +ec2.Vpc.from_lookup(self, "DefaultVpc", is_default=True) +``` + +------ +#### [ Java ] + +``` +Vpc.fromLookup(this, "DefaultVpc", VpcLookupOptions.builder() + .isDefault(true).build()); +``` + +------ +#### [ C\# ] + +``` +Vpc.FromLookup(this, id = "DefaultVpc", new VpcLookupOptions { IsDefault = true }); +``` + +------ + +You can also use the `tags` property to query for VPCs by tag\. Tags may be added to the Amazon VPC at the time of its creation using AWS CloudFormation or the AWS CDK, and they may be edited at any time after creation using the AWS Management Console, the AWS CLI, or an AWS SDK\. In addition to any tags you have added yourself, the AWS CDK automatically adds the following tags to all VPCs it creates\. ++ *Name* – The name of the VPC\. ++ *aws\-cdk:subnet\-name* – The name of the subnet\. ++ *aws\-cdk:subnet\-type* – The type of the subnet: Public, Private, or Isolated\. + +------ +#### [ TypeScript ] + +``` +ec2.Vpc.fromLookup(this, 'PublicVpc', + {tags: {'aws-cdk:subnet-type': "Public"}}); +``` + +------ +#### [ JavaScript ] + +``` +ec2.Vpc.fromLookup(this, 'PublicVpc', + {tags: {'aws-cdk:subnet-type': "Public"}}); +``` + +------ +#### [ Python ] + +``` +ec2.Vpc.from_lookup(self, "PublicVpc", + tags={"aws-cdk:subnet-type": "Public"}) +``` + +------ +#### [ Java ] + +``` +Vpc.fromLookup(this, "PublicVpc", VpcLookupOptions.builder() + .tags(java.util.Map.of("aws-cdk:subnet-type", "Public")) // Java 9 or later + .build()); +``` + +------ +#### [ C\# ] + +``` +Vpc.FromLookup(this, id = "PublicVpc", new VpcLookupOptions + { Tags = new Dictionary<string, string> { ["aws-cdk:subnet-type"] = "Public" }); +``` + +------ + +Results of `Vpc.fromLookup()` are cached in the project's `cdk.context.json` file\. \(See [Runtime context](context.md)\.\) Commit this file to version control so that your app will continue to refer to the same Amazon VPC even if you later change the attributes of your VPCs in a way that would result in a different VPC being selected\. This is particularly important if you will be deploying the stack in an environment that does not have access to the AWS account that defines the VPC, such as [CDK Pipelines](cdk_pipeline.md)\. + +Although you can use an external resource anywhere you'd use a similar resource defined in your AWS CDK app, you cannot modify it\. For example, calling `addToResourcePolicy` \(Python: `add_to_resource_policy`\) on an external `s3.Bucket` does nothing\. + +## Physical names<a name="resources_physical_names"></a> + +The logical names of resources in AWS CloudFormation are different from the names of resources that are shown in the AWS Management Console after AWS CloudFormation has deployed the resources\. The AWS CDK calls these final names *physical names*\. + +For example, AWS CloudFormation might create the Amazon S3 bucket with the logical ID **Stack2MyBucket4DD88B4F** from the previous example with the physical name **stack2mybucket4dd88b4f\-iuv1rbv9z3to**\. + +You can specify a physical name when creating constructs that represent resources by using the property <resourceType>Name\. The following example creates an Amazon S3 bucket with the physical name **my\-bucket\-name**\. + +------ +#### [ TypeScript ] + +``` +const bucket = new s3.Bucket(this, 'MyBucket', { + bucketName: 'my-bucket-name', +}); +``` + +------ +#### [ JavaScript ] + +``` +const bucket = new s3.Bucket(this, 'MyBucket', { + bucketName: 'my-bucket-name' +}); +``` + +------ +#### [ Python ] + +``` +bucket = s3.Bucket(self, "MyBucket", bucket_name="my-bucket-name") +``` + +------ +#### [ Java ] + +``` +Bucket bucket = Bucket.Builder.create(this, "MyBucket") + .bucketName("my-bucket-name").build(); +``` + +------ +#### [ C\# ] + +``` +var bucket = new Bucket(this, "MyBucket", new BucketProps { BucketName = "my-bucket-name" }); +``` + +------ + +Assigning physical names to resources has some disadvantages in AWS CloudFormation\. Most importantly, any changes to deployed resources that require a resource replacement, such as changes to a resource's properties that are immutable after creation, will fail if a resource has a physical name assigned\. If you end up in that state, the only solution is to delete the AWS CloudFormation stack, then deploy the AWS CDK app again\. See the [AWS CloudFormation documentation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-name.html) for details\. + +In some cases, such as when creating an AWS CDK app with cross\-environment references, physical names are required for the AWS CDK to function correctly\. In those cases, if you don't want to bother with coming up with a physical name yourself, you can let the AWS CDK name it for you by using the special value `PhysicalName.GENERATE_IF_NEEDED`, as follows\. + +------ +#### [ TypeScript ] + +``` +const bucket = new s3.Bucket(this, 'MyBucket', { + bucketName: core.PhysicalName.GENERATE_IF_NEEDED, +}); +``` + +------ +#### [ JavaScript ] + +``` +const bucket = new s3.Bucket(this, 'MyBucket', { + bucketName: core.PhysicalName.GENERATE_IF_NEEDED +}); +``` + +------ +#### [ Python ] + +``` +bucket = s3.Bucket(self, "MyBucket", + bucket_name=core.PhysicalName.GENERATE_IF_NEEDED) +``` + +------ +#### [ Java ] + +``` +Bucket bucket = Bucket.Builder.create(this, "MyBucket") + .bucketName(PhysicalName.GENERATE_IF_NEEDED).build(); +``` + +------ +#### [ C\# ] + +``` +var bucket = new Bucket(this, "MyBucket", new BucketProps + { BucketName = PhysicalName.GENERATE_IF_NEEDED }); +``` + +------ + +## Passing unique identifiers<a name="resources_identifiers"></a> + +Whenever possible, you should pass resources by reference, as described in the previous section\. However, there are cases where you have no other choice but to refer to a resource by one of its attributes\. For example, when you are using the low\-level AWS CloudFormation resources, or need to expose resources to the runtime components of an AWS CDK application, such as when referring to Lambda functions through environment variables\. + +These identifiers are available as attributes on the resources, such as the following\. + +------ +#### [ TypeScript ] + +``` +bucket.bucketName +lambdaFunc.functionArn +securityGroup.groupArn +``` + +------ +#### [ JavaScript ] + +``` +bucket.bucketName +lambdaFunc.functionArn +securityGroup.groupArn +``` + +------ +#### [ Python ] + +``` +bucket.bucket_name +lambda_func.function_arn +security_group_arn +``` + +------ +#### [ Java ] + +The Java AWS CDK binding uses getter methods for attributes\. + +``` +bucket.getBucketName() +lambdaFunc.getFunctionArn() +securityGroup.getGroupArn() +``` + +------ +#### [ C\# ] + +``` +bucket.BucketName +lambdaFunc.FunctionArn +securityGroup.GroupArn +``` + +------ + +The following example shows how to pass a generated bucket name to an AWS Lambda function\. + +------ +#### [ TypeScript ] + +``` +const bucket = new s3.Bucket(this, 'Bucket'); + +new lambda.Function(this, 'MyLambda', { + // ... + environment: { + BUCKET_NAME: bucket.bucketName, + }, +}); +``` + +------ +#### [ JavaScript ] + +``` +const bucket = new s3.Bucket(this, 'Bucket'); + +new lambda.Function(this, 'MyLambda', { + // ... + environment: { + BUCKET_NAME: bucket.bucketName + } +}); +``` + +------ +#### [ Python ] + +``` +bucket = s3.Bucket(self, "Bucket") + +lambda.Function(self, "MyLambda", environment=dict(BUCKET_NAME=bucket.bucket_name)) +``` + +------ +#### [ Java ] + +``` +final Bucket bucket = new Bucket(this, "Bucket"); + +Function.Builder.create(this, "MyLambda") + .environment(java.util.Map.of( // Java 9 or later + "BUCKET_NAME", bucket.getBucketName())) + .build(); +``` + +------ +#### [ C\# ] + +``` +var bucket = new Bucket(this, "Bucket"); + +new Function(this, "MyLambda", new FunctionProps +{ + Environment = new Dictionary<string, string> + { + ["BUCKET_NAME"] = bucket.BucketName + } +}); +``` + +------ + +## Permission grants<a name="resources_grants"></a> + +AWS constructs make least\-privilege permissions easy to achieve by offering simple, intent\-based APIs to express permission requirements\. Many AWS constructs offer grant methods that enable you to easily grant an entity, such as an IAM role or a user, permission to work with the resource without having to manually craft one or more IAM permission statements\. + +The following example creates the permissions to allow a Lambda function's execution role to read and write objects to a particular Amazon S3 bucket\. If the Amazon S3 bucket is encrypted using an AWS KMS key, this method also grants the Lambda function's execution role permissions to decrypt using this key\. + +------ +#### [ TypeScript ] + +``` +if (bucket.grantReadWrite(func).success) { + // ... +} +``` + +------ +#### [ JavaScript ] + +``` +if ( bucket.grantReadWrite(func).success) { + // ... +} +``` + +------ +#### [ Python ] + +``` +if bucket.grant_read_write(func).success: + # ... +``` + +------ +#### [ Java ] + +``` +if (bucket.grantReadWrite(func).getSuccess()) { + // ... +} +``` + +------ +#### [ C\# ] + +``` +if (bucket.GrantReadWrite(func).Success) +{ + // ... +} +``` + +------ + +The grant methods return an `iam.Grant` object\. Use the `success` attribute of the `Grant` object to determine whether the grant was effectively applied \(for example, it may not have been applied on [external resources](#resources_referencing)\)\. You can also use the `assertSuccess` \(Python: `assert_success`\) method of the `Grant` object to enforce that the grant was successfully applied\. + +If a specific grant method isn't available for the particular use case, you can use a generic grant method to define a new grant with a specified list of actions\. + +The following example shows how to grant a Lambda function access to the Amazon DynamoDB `CreateBackup` action\. + +------ +#### [ TypeScript ] + +``` +table.grant(func, 'dynamodb:CreateBackup'); +``` + +------ +#### [ JavaScript ] + +``` +table.grant(func, 'dynamodb:CreateBackup'); +``` + +------ +#### [ Python ] + +``` +table.grant(func, "dynamodb:CreateBackup") +``` + +------ +#### [ Java ] + +``` +table.grant(func, "dynamodb:CreateBackup"); +``` + +------ +#### [ C\# ] + +``` +table.Grant(func, "dynamodb:CreateBackup"); +``` + +------ + +Many resources, such as Lambda functions, require a role to be assumed when executing code\. A configuration property enables you to specify an `iam.IRole`\. If no role is specified, the function automatically creates a role specifically for this use\. You can then use grant methods on the resources to add statements to the role\. + +The grant methods are built using lower\-level APIs for handling with IAM policies\. Policies are modeled as [PolicyDocument](https://docs.aws.amazon.com/cdk/api/v1/docs/aws-iam-readme.html) objects\. Add statements directly to roles \(or a construct's attached role\) using the `addToRolePolicy` method \(Python: `add_to_role_policy`\), or to a resource's policy \(such as a `Bucket` policy\) using the `addToResourcePolicy` \(Python: `add_to_resource_policy`\) method\. + +## Metrics and alarms<a name="resources_metrics"></a> + +Many resources emit CloudWatch metrics that can be used to set up monitoring dashboards and alarms\. AWS constructs have metric methods that allow easy access to the metrics without having to look up the correct name to use\. + +The following example shows how to define an alarm when the `ApproximateNumberOfMessagesNotVisible` of an Amazon SQS queue exceeds 100\. + +------ +#### [ TypeScript ] + +``` +import * as cw from '@aws-cdk/aws-cloudwatch'; +import * as sqs from '@aws-cdk/aws-sqs'; +import { Duration } from '@aws-cdk/core'; + +const queue = new sqs.Queue(this, 'MyQueue'); + +const metric = queue.metricApproximateNumberOfMessagesNotVisible({ + label: 'Messages Visible (Approx)', + period: Duration.minutes(5), + // ... +}); +metric.createAlarm(this, 'TooManyMessagesAlarm', { + comparisonOperator: cw.ComparisonOperator.GREATER_THAN_THRESHOLD, + threshold: 100, + // ... +}); +``` + +------ +#### [ JavaScript ] + +``` +const cw = require('@aws-cdk/aws-cloudwatch'); +const sqs = require('@aws-cdk/aws-sqs'); +const { Duration } = require('@aws-cdk/core'); + +const queue = new sqs.Queue(this, 'MyQueue'); + +const metric = queue.metricApproximateNumberOfMessagesNotVisible({ + label: 'Messages Visible (Approx)', + period: Duration.minutes(5) + // ... +}); +metric.createAlarm(this, 'TooManyMessagesAlarm', { + comparisonOperator: cw.ComparisonOperator.GREATER_THAN_THRESHOLD, + threshold: 100 + // ... +}); +``` + +------ +#### [ Python ] + +``` +import aws_cdk.aws_cloudwatch as cw +import aws_cdk.aws_sqs as sqs +from aws_cdk.core import Duration + +queue = sqs.Queue(self, "MyQueue") +metric = queue.metric_approximate_number_of_messages_not_visible( + label="Messages Visible (Approx)", + period=Duration.minutes(5), + # ... +) +metric.create_alarm(self, "TooManyMessagesAlarm", + comparison_operator=cw.ComparisonOperator.GREATER_THAN_THRESHOLD, + threshold=100, + # ... +) +``` + +------ +#### [ Java ] + +``` +import software.amazon.awscdk.core.Duration; +import software.amazon.awscdk.services.sqs.Queue; +import software.amazon.awscdk.services.cloudwatch.Metric; +import software.amazon.awscdk.services.cloudwatch.MetricOptions; +import software.amazon.awscdk.services.cloudwatch.CreateAlarmOptions; +import software.amazon.awscdk.services.cloudwatch.ComparisonOperator; + +Queue queue = new Queue(this, "MyQueue"); + +Metric metric = queue + .metricApproximateNumberOfMessagesNotVisible(MetricOptions.builder() + .label("Messages Visible (Approx)") + .period(Duration.minutes(5)).build()); + +metric.createAlarm(this, "TooManyMessagesAlarm", CreateAlarmOptions.builder() + .comparisonOperator(ComparisonOperator.GREATER_THAN_THRESHOLD) + .threshold(100) + // ... + .build()); +``` + +------ +#### [ C\# ] + +``` +using cdk = Amazon.CDK; +using cw = Amazon.CDK.AWS.CloudWatch; +using sqs = Amazon.CDK.AWS.SQS; + +var queue = new sqs.Queue(this, "MyQueue"); +var metric = queue.MetricApproximateNumberOfMessagesNotVisible(new cw.MetricOptions +{ + Label = "Messages Visible (Approx)", + Period = cdk.Duration.Minutes(5), + // ... +}); +metric.CreateAlarm(this, "TooManyMessagesAlarm", new cw.CreateAlarmOptions +{ + ComparisonOperator = cw.ComparisonOperator.GREATER_THAN_THRESHOLD, + Threshold = 100, + // .. +}); +``` + +------ + +If there is no method for a particular metric, you can use the general metric method to specify the metric name manually\. + +Metrics can also be added to CloudWatch dashboards\. See [CloudWatch](https://docs.aws.amazon.com/cdk/api/v1/docs/aws-cloudwatch-readme.html)\. + +## Network traffic<a name="resources_traffic"></a> + +In many cases, you must enable permissions on a network for an application to work, such as when the compute infrastructure needs to access the persistence layer\. Resources that establish or listen for connections expose methods that enable traffic flows, including setting security group rules or network ACLs\. + +[IConnectable](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-ec2.IConnectable.html) resources have a `connections` property that is the gateway to network traffic rules configuration\. + +You enable data to flow on a given network path by using `allow` methods\. The following example enables HTTPS connections to the web and incoming connections from the Amazon EC2 Auto Scaling group `fleet2`\. + +------ +#### [ TypeScript ] + +``` +import * as asg from '@aws-cdk/aws-autoscaling'; +import * as ec2 from '@aws-cdk/aws-ec2'; + +const fleet1: asg.AutoScalingGroup = asg.AutoScalingGroup(/*...*/); + +// Allow surfing the (secure) web +fleet1.connections.allowTo(new ec2.Peer.anyIpv4(), new ec2.Port({ fromPort: 443, toPort: 443 })); + +const fleet2: asg.AutoScalingGroup = asg.AutoScalingGroup(/*...*/); +fleet1.connections.allowFrom(fleet2, ec2.Port.AllTraffic()); +``` + +------ +#### [ JavaScript ] + +``` +const asg = require('@aws-cdk/aws-autoscaling'); +const ec2 = require('@aws-cdk/aws-ec2'); + +const fleet1 = asg.AutoScalingGroup(); + +// Allow surfing the (secure) web +fleet1.connections.allowTo(new ec2.Peer.anyIpv4(), new ec2.Port({ fromPort: 443, toPort: 443 })); + +const fleet2 = asg.AutoScalingGroup(); +fleet1.connections.allowFrom(fleet2, ec2.Port.AllTraffic()); +``` + +------ +#### [ Python ] + +``` +import aws_cdk.aws_autoscaling as asg +import aws_cdk.aws_ec2 as ec2 + +fleet1 = asg.AutoScalingGroup( ... ) + +# Allow surfing the (secure) web +fleet1.connections.allow_to(ec2.Peer.any_ipv4(), + ec2.Port(PortProps(from_port=443, to_port=443))) + +fleet2 = asg.AutoScalingGroup( ... ) +fleet1.connections.allow_from(fleet2, ec2.Port.all_traffic()) +``` + +------ +#### [ Java ] + +``` +import software.amazon.awscdk.services.autoscaling.AutoScalingGroup; +import software.amazon.awscdk.services.ec2.Peer; +import software.amazon.awscdk.services.ec2.Port; + +AutoScalingGroup fleet1 = AutoScalingGroup.Builder.create(this, "MyFleet") + /* ... */.build(); + +// Allow surfing the (secure) Web +fleet1.getConnections().allowTo(Peer.anyIpv4(), + Port.Builder.create().fromPort(443).toPort(443).build()); + +AutoScalingGroup fleet2 = AutoScalingGroup.Builder.create(this, "MyFleet2") + /* ... */.build(); +fleet1.getConnections().allowFrom(fleet2, Port.allTraffic()); +``` + +------ +#### [ C\# ] + +``` +using cdk = Amazon.CDK; +using asg = Amazon.CDK.AWS.AutoScaling; +using ec2 = Amazon.CDK.AWS.EC2; + +// Allow surfing the (secure) Web +var fleet1 = new asg.AutoScalingGroup(this, "MyFleet", new asg.AutoScalingGroupProps { /* ... */ }); +fleet1.Connections.AllowTo(ec2.Peer.AnyIpv4(), new ec2.Port(new ec2.PortProps + { FromPort = 443, ToPort = 443 }); + +var fleet2 = new asg.AutoScalingGroup(this, "MyFleet2", new asg.AutoScalingGroupProps { /* ... */ }); +fleet1.Connections.AllowFrom(fleet2, ec2.Port.AllTraffic()); +``` + +------ + +Certain resources have default ports associated with them, for example, the listener of a load balancer on the public port, and the ports on which the database engine accepts connections for instances of an Amazon RDS database\. In such cases, you can enforce tight network control without having to manually specify the port by using the `allowDefaultPortFrom` and `allowToDefaultPort` methods \(Python: `allow_default_port_from`, `allow_to_default_port`\)\. + +The following example shows how to enable connections from any IPV4 address, and a connection from an Auto Scaling group to access a database\. + +------ +#### [ TypeScript ] + +``` +listener.connections.allowDefaultPortFromAnyIpv4('Allow public access'); + +fleet.connections.allowToDefaultPort(rdsDatabase, 'Fleet can access database'); +``` + +------ +#### [ JavaScript ] + +``` +listener.connections.allowDefaultPortFromAnyIpv4('Allow public access'); + +fleet.connections.allowToDefaultPort(rdsDatabase, 'Fleet can access database'); +``` + +------ +#### [ Python ] + +``` +listener.connections.allow_default_port_from_any_ipv4("Allow public access") + +fleet.connections.allow_to_default_port(rds_database, "Fleet can access database") +``` + +------ +#### [ Java ] + +``` +listener.getConnections().allowDefaultPortFromAnyIpv4("Allow public access"); + +fleet.getConnections().AllowToDefaultPort(rdsDatabase, "Fleet can access database"); +``` + +------ +#### [ C\# ] + +``` +listener.Connections.AllowDefaultPortFromAnyIpv4("Allow public access"); + +fleet.Connections.AllowToDefaultPort(rdsDatabase, "Fleet can access database"); +``` + +------ + +## Event handling<a name="resources_events"></a> + +Some resources can act as event sources\. Use the `addEventNotification` method \(Python: `add_event_notification`\) to register an event target to a particular event type emitted by the resource\. In addition to this, `addXxxNotification` methods offer a simple way to register a handler for common event types\. + +The following example shows how to trigger a Lambda function when an object is added to an Amazon S3 bucket\. + +------ +#### [ TypeScript ] + +``` +import * as s3nots from '@aws-cdk/aws-s3-notifications'; + +const handler = new lambda.Function(this, 'Handler', { /*…*/ }); +const bucket = new s3.Bucket(this, 'Bucket'); +bucket.addObjectCreatedNotification(new s3nots.LambdaDestination(handler)); +``` + +------ +#### [ JavaScript ] + +``` +const s3nots = require('@aws-cdk/aws-s3-notifications'); + +const handler = new lambda.Function(this, 'Handler', { /*…*/ }); +const bucket = new s3.Bucket(this, 'Bucket'); +bucket.addObjectCreatedNotification(new s3nots.LambdaDestination(handler)); +``` + +------ +#### [ Python ] + +``` +import aws_cdk.aws_s3_notifications as s3_nots + +handler = lambda_.Function(self, "Handler", ...) +bucket = s3.Bucket(self, "Bucket") +bucket.add_object_created_notification(s3_nots.LambdaDestination(handler)) +``` + +------ +#### [ Java ] + +``` +import software.amazon.awscdk.services.s3.Bucket; +import software.amazon.awscdk.services.lambda.Function; +import software.amazon.awscdk.services.s3.notifications.LambdaDestination; + +Function handler = Function.Builder.create(this, "Handler")/* ... */.build(); +Bucket bucket = new Bucket(this, "Bucket"); +bucket.addObjectCreatedNotification(new LambdaDestination(handler)); +``` + +------ +#### [ C\# ] + +``` +using lambda = Amazon.CDK.AWS.Lambda; +using s3 = Amazon.CDK.AWS.S3; +using s3Nots = Amazon.CDK.AWS.S3.Notifications; + +var handler = new lambda.Function(this, "Handler", new lambda.FunctionProps { .. }); +var bucket = new s3.Bucket(this, "Bucket"); +bucket.AddObjectCreatedNotification(new s3Nots.LambdaDestination(handler)); +``` + +------ + +## Removal policies<a name="resources_removal"></a> + +Resources that maintain persistent data, such as databases and Amazon S3 buckets and even Amazon ECR registries, have a *removal policy* that indicates whether to delete persistent objects when the AWS CDK stack that contains them is destroyed\. The values specifying the removal policy are available through the `RemovalPolicy` enumeration in the AWS CDK `core` module\. + +**Note** +Resources besides those that store data persistently may also have a `removalPolicy` that is used for a different purpose\. For example, a Lambda function version uses a `removalPolicy` attribute to determine whether a given version is retained when a new version is deployed\. These have different meanings and defaults compared to the removal policy on an Amazon S3 bucket or DynamoDB table\. + + +| Value | meaning | +| --- |--- | +| RemovalPolicy\.RETAIN | Keep the contents of the resource when destroying the stack \(default\)\. The resource is orphaned from the stack and must be deleted manually\. If you attempt to re\-deploy the stack while the resource still exists, you will receive an error message due to a name conflict\. | +| RemovalPolicy\.DESTROY | The resource will be destroyed along with the stack\. | + +AWS CloudFormation does not remove Amazon S3 buckets that contain files even if their removal policy is set to `DESTROY`\. Attempting to do so is a AWS CloudFormation error\. To have the AWS CDK delete all files from the bucket before destroying it, set the bucket's `autoDeleteObjects` property to `true`\. + +Following is an example of creating an Amazon S3 bucket with `RemovalPolicy` of `DESTROY` and `autoDeleteOjbects` set to `true`\. + +------ +#### [ TypeScript ] + +``` +import * as cdk from '@aws-cdk/core'; +import * as s3 from '@aws-cdk/aws-s3'; + +export class CdkTestStack extends cdk.Stack { + constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { + super(scope, id, props); + + const bucket = new s3.Bucket(this, 'Bucket', { + removalPolicy: cdk.RemovalPolicy.DESTROY, + autoDeleteObjects: true + }); + } +} +``` + +------ +#### [ JavaScript ] + +``` +const cdk = require('@aws-cdk/core'); +const s3 = require('@aws-cdk/aws-s3'); + +class CdkTestStack extends cdk.Stack { + constructor(scope, id, props) { + super(scope, id, props); + + const bucket = new s3.Bucket(this, 'Bucket', { + removalPolicy: cdk.RemovalPolicy.DESTROY, + autoDeleteObjects: true + }); + } +} + +module.exports = { CdkTestStack } +``` + +------ +#### [ Python ] + +``` +import aws_cdk.core as cdk +import aws_cdk.aws_s3 as s3 + +class CdkTestStack(cdk.stack): + def __init__(self, scope: cdk.Construct, id: str, **kwargs): + super().__init__(scope, id, **kwargs) + + bucket = s3.Bucket(self, "Bucket", + removal_policy=cdk.RemovalPolicy.DESTROY, + auto_delete_objects=True) +``` + +------ +#### [ Java ] + +``` +software.amazon.awscdk.core.*; +import software.amazon.awscdk.services.s3.*; + +public class CdkTestStack extends Stack { + public CdkTestStack(final Construct scope, final String id) { + this(scope, id, null); + } + + public CdkTestStack(final Construct scope, final String id, final StackProps props) { + super(scope, id, props); + + Bucket.Builder.create(this, "Bucket") + .removalPolicy(RemovalPolicy.DESTROY) + .autoDeleteObjects(true).build(); + } +} +``` + +------ +#### [ C\# ] + +``` +using Amazon.CDK; +using Amazon.CDK.AWS.S3; + +public CdkTestStack(Construct scope, string id, IStackProps props) : base(scope, id, props) +{ + new Bucket(this, "Bucket", new BucketProps { + RemovalPolicy = RemovalPolicy.DESTROY, + AutoDeleteObjects = true + }); +} +``` + +------ + +You can also apply a removal policy directly to the underlying AWS CloudFormation resource via the `applyRemovalPolicy()` method\. This method is available on some stateful resources that do not have a `removalPolicy` property in their L2 resource's props, including AWS CloudFormation stacks, Amazon Cognito user pools, Amazon DocumentDB database instances, Amazon EC2 volumes, Amazon OpenSearch Service domains, Amazon FSx file systems, and Amazon SQS queues\. + +------ +#### [ TypeScript ] + +``` +const resource = bucket.node.findChild('Resource') as cdk.CfnResource; +resource.applyRemovalPolicy(cdk.RemovalPolicy.DESTROY); +``` + +------ +#### [ JavaScript ] + +``` +const resource = bucket.node.findChild('Resource'); +resource.applyRemovalPolicy(cdk.RemovalPolicy.DESTROY); +``` + +------ +#### [ Python ] + +``` +resource = bucket.node.find_child('Resource') +resource.apply_removal_policy(cdk.RemovalPolicy.DESTROY); +``` + +------ +#### [ Java ] + +``` +CfnResource resource = (CfnResource)bucket.node.findChild("Resource"); +resource.applyRemovalPolicy(cdk.RemovalPolicy.DESTROY); +``` + +------ +#### [ C\# ] + +``` +var resource = (CfnResource)bucket.node.findChild('Resource'); +resource.ApplyRemovalPolicy(cdk.RemovalPolicy.DESTROY); +``` + +------ + +**Note** +The AWS CDK's `RemovalPolicy` translates to AWS CloudFormation's `DeletionPolicy`, but the default in AWS CDK is to retain the data, which is the opposite of the AWS CloudFormation default\. \ No newline at end of file diff --git a/v1/sam.md b/v1/sam.md new file mode 100644 index 00000000..e61e0367 --- /dev/null +++ b/v1/sam.md @@ -0,0 +1,3 @@ +# AWS SAM integration<a name="sam"></a> + +The AWS CDK and the AWS Serverless Application Model \(AWS SAM\) can work together to let you to locally build and test serverless applications defined in the CDK\. For complete information, see [AWS Cloud Development Kit \(AWS CDK\)](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-cdk.html) in the AWS SAM Developer Guide\. To install the SAM CLI, see [Installing the AWS SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html)\. \ No newline at end of file diff --git a/v1/security-iam.md b/v1/security-iam.md new file mode 100644 index 00000000..55f220ba --- /dev/null +++ b/v1/security-iam.md @@ -0,0 +1,11 @@ +# Identity and access management for the AWS Cloud Development Kit \(AWS CDK\)<a name="security-iam"></a> + +AWS Identity and Access Management \(IAM\) is an Amazon Web Services \(AWS\) service that helps an administrator securely control access to AWS resources\. IAM administrators control who can be *authenticated* \(signed in\) and *authorized* \(have permissions\) to use resources in AWS services\. IAM is an AWS service that you can use with no additional charge\. + +To use the AWS CDK to access AWS, you need an AWS account and AWS credentials\. To increase the security of your AWS account, we recommend that you use an *IAM user* to provide access credentials instead of using your AWS account credentials\. + +For details about working with IAM, see [AWS Identity and Access Management](https://aws.amazon.com/iam/)\. + +For an overview of IAM users and why they are important for the security of your account, see [AWS Security Credentials](https://docs.aws.amazon.com/general/latest/gr/aws-security-credentials.html) in the [Amazon Web Services General Reference](https://docs.aws.amazon.com/general/latest/gr/)\. + +The AWS CDK follows the [shared responsibility model](https://aws.amazon.com/compliance/shared-responsibility-model/) through the specific Amazon Web Services \(AWS\) services it supports\. For AWS service security information, see the [AWS service security documentation page](https://docs.aws.amazon.com/security/?id=docs_gateway#aws-security) and [AWS services that are in scope of AWS compliance efforts by compliance program](https://aws.amazon.com/compliance/services-in-scope/)\. \ No newline at end of file diff --git a/v1/security.md b/v1/security.md new file mode 100644 index 00000000..bf319928 --- /dev/null +++ b/v1/security.md @@ -0,0 +1,15 @@ +# Security for the AWS Cloud Development Kit \(AWS CDK\)<a name="security"></a> + +Cloud security at Amazon Web Services \(AWS\) is the highest priority\. As an AWS customer, you benefit from a data center and network architecture that is built to meet the requirements of the most security\-sensitive organizations\. Security is a shared responsibility between AWS and you\. The [Shared Responsibility Model](https://aws.amazon.com/compliance/shared-responsibility-model/) describes this as Security of the Cloud and Security in the Cloud\. + +**Security of the Cloud** – AWS is responsible for protecting the infrastructure that runs all of the services offered in the AWS Cloud and providing you with services that you can use securely\. Our security responsibility is the highest priority at AWS, and the effectiveness of our security is regularly tested and verified by third\-party auditors as part of the [AWS Compliance Programs](https://aws.amazon.com/compliance/programs/)\. + +**Security in the Cloud** – Your responsibility is determined by the AWS service you are using, and other factors including the sensitivity of your data, your organization's requirements, and applicable laws and regulations\. + +The AWS CDK follows the [shared responsibility model](https://aws.amazon.com/compliance/shared-responsibility-model/) through the specific Amazon Web Services \(AWS\) services it supports\. For AWS service security information, see the [AWS service security documentation page](https://docs.aws.amazon.com/security/?id=docs_gateway#aws-security) and [AWS services that are in scope of AWS compliance efforts by compliance program](https://aws.amazon.com/compliance/services-in-scope/)\. + +**Topics** ++ [Identity and access management](security-iam.md) ++ [Compliance validation](compliance-validation.md) ++ [Resilience](disaster-recovery-resiliency.md) ++ [Infrastructure security](infrastructure-security.md) \ No newline at end of file diff --git a/v1/serverless_example.md b/v1/serverless_example.md new file mode 100644 index 00000000..0a536f1b --- /dev/null +++ b/v1/serverless_example.md @@ -0,0 +1,866 @@ +# Creating a serverless application using the AWS CDK<a name="serverless_example"></a> + +This example walks you through creating the resources for a simple widget dispensing service\. \(For the purpose of this example, a widget is just a name or identifier that can be added to, retrieved from, and deleted from a collection\.\) The example includes: ++ An AWS Lambda function\. ++ An Amazon API Gateway API to call the Lambda function\. ++ An Amazon S3 bucket that holds the widgets\. + +This tutorial contains the following steps\. + +1. Create an AWS CDK app + +1. Create a Lambda function that gets a list of widgets with HTTP GET / + +1. Create the service that calls the Lambda function + +1. Add the service to the AWS CDK app + +1. Test the app + +1. Add Lambda functions to do the following: + + Create a widget with POST /\{name\} + + Get a widget by name with GET /\{name\} + + Delete a widget by name with DELETE /\{name\} + +1. Tear everything down when you're finished + +## Create an AWS CDK app<a name="serverless_example_create_app"></a> + +Create the app **MyWidgetService** in the current folder\. + +------ +#### [ TypeScript ] + +``` +mkdir MyWidgetService +cd MyWidgetService +cdk init --language typescript +``` + +------ +#### [ JavaScript ] + +``` +mkdir MyWidgetService +cd MyWidgetService +cdk init --language javascript +``` + +------ +#### [ Python ] + +``` +mkdir MyWidgetService +cd MyWidgetService +cdk init --language python +source .venv/bin/activate +pip install -r requirements.txt +``` + +------ +#### [ Java ] + +``` +mkdir MyWidgetService +cd MyWidgetService +cdk init --language java +``` + +You may now import the Maven project into your IDE\. + +------ +#### [ C\# ] + +``` +mkdir MyWidgetService +cd MyWidgetService +cdk init --language csharp +``` + +You may now open `src/MyWidgetService.sln` in Visual Studio\. + +------ + +**Note** +The CDK names source files and classes based on the name of the project directory\. If you don't use the name `MyWidgetService` as shown above, you'll have trouble following the rest of the steps because some of the files the instructions tell you to modify aren't there \(they'll have different names\)\. + +The important files in the blank project are as follows\. \(We will also be adding a couple of new files\.\) + +------ +#### [ TypeScript ] ++ `bin/my_widget_service.ts` – Main entry point for the application ++ `lib/my_widget_service-stack.ts` – Defines the widget service stack + +------ +#### [ JavaScript ] ++ `bin/my_widget_service.js` – Main entry point for the application ++ `lib/my_widget_service-stack.js` – Defines the widget service stack + +------ +#### [ Python ] ++ `app.py` – Main entry point for the application ++ `my_widget_service/my_widget_service_stack.py` – Defines the widget service stack + +------ +#### [ Java ] ++ `src/main/java/com/myorg/MyWidgetServiceApp.java` – Main entry point for the application ++ `src/main/java/com/myorg/MyWidgetServiceStack.java` – Defines the widget service stack + +------ +#### [ C\# ] ++ `src/MyWidgetService/Program.cs` – Main entry point for the application ++ `src/MyWidgetService/MyWidgetServiceStack.cs` – Defines the widget service stack + +------ + +Run the app and note that it synthesizes an empty stack\. + +``` +cdk synth +``` + +You should see output beginning with YAML code like the following\. + +``` +Resources: + CDKMetadata: + Type: AWS::CDK::Metadata + Properties: + ..." +``` + +## Create a Lambda function to list all widgets<a name="serverless_example_create_iam_function"></a> + +The next step is to create a Lambda function to list all of the widgets in our Amazon S3 bucket\. We will provide the Lambda function's code in JavaScript\. + +Create the `resources` directory in the project's main directory\. + +``` +mkdir resources +``` + +Create the following JavaScript file, `widgets.js`, in the `resources` directory\. + +``` +/* +This code uses callbacks to handle asynchronous function responses. +It currently demonstrates using an async-await pattern. +AWS supports both the async-await and promises patterns. +For more information, see the following: +https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function +https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises +https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/calling-services-asynchronously.html +https://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-handler.html +*/ +const AWS = require('aws-sdk'); +const S3 = new AWS.S3(); + +const bucketName = process.env.BUCKET; + +exports.main = async function(event, context) { + try { + var method = event.httpMethod; + + if (method === "GET") { + if (event.path === "/") { + const data = await S3.listObjectsV2({ Bucket: bucketName }).promise(); + var body = { + widgets: data.Contents.map(function(e) { return e.Key }) + }; + return { + statusCode: 200, + headers: {}, + body: JSON.stringify(body) + }; + } + } + + // We only accept GET for now + return { + statusCode: 400, + headers: {}, + body: "We only accept GET /" + }; + } catch(error) { + var body = error.stack || JSON.stringify(error, null, 2); + return { + statusCode: 400, + headers: {}, + body: JSON.stringify(body) + } + } +} +``` + +Save it and be sure the project still results in an empty stack\. We haven't yet wired the Lambda function to the AWS CDK app, so the Lambda asset doesn't appear in the output\. + +``` +cdk synth +``` + +## Create a widget service<a name="serverless_example_create_widget_service"></a> + +Add the API Gateway, Lambda, and Amazon S3 packages to the app\. + +------ +#### [ TypeScript ] + +``` +npm install @aws-cdk/aws-apigateway @aws-cdk/aws-lambda @aws-cdk/aws-s3 +``` + +------ +#### [ JavaScript ] + +``` +npm install @aws-cdk/aws-apigateway @aws-cdk/aws-lambda @aws-cdk/aws-s3 +``` + +------ +#### [ Python ] + +``` +pip install aws_cdk.aws_apigateway aws_cdk.aws_lambda aws_cdk.aws_s3 +``` + +------ +#### [ Java ] + +Add the following dependencies in the `dependencies` element of your project's `pom.xml` file\. + +``` +<dependency> + <groupId>software.amazon.awscdk</groupId> + <artifactId>apigateway</artifactId> + <version>${cdk.version}</version> +</dependency> +<dependency> + <groupId>software.amazon.awscdk</groupId> + <artifactId>lambda</artifactId> + <version>${cdk.version}</version> +</dependency> +<dependency> + <groupId>software.amazon.awscdk</groupId> + <artifactId>s3</artifactId> + <version>${cdk.version}</version> +</dependency> +``` + +We recommend editing `pom.xml` directory rather than using your IDE's dependency management tools to make sure the versions of all AWS CDK libraries are synchronized using the `$cdk.version` variable\. + +------ +#### [ C\# ] + +Choose **Tools** > **NuGet Package Manager** > **Manage NuGet Packages for Solution** in Visual Studio and add the following packages\. + +``` +Amazon.CDK.AWS.ApiGateway +Amazon.CDK.AWS.Lambda +Amazon.CDK.AWS.S3 +``` + +**Tip** +If you don't see these packages in the **Browse** tab of the **Manage Packages for Solution** page, make sure the **Include prerelease** checkbox is ticked\. +For a better experience, also add the `Amazon.Jsii.Analyzers` package to provide compile\-time checks for missing required properties\. + +------ + +Create a new source file to define the widget service with the source code shown below\. + +------ +#### [ TypeScript ] + +File: `lib/widget_service.ts` + +``` +import * as core from "@aws-cdk/core"; +import * as apigateway from "@aws-cdk/aws-apigateway"; +import * as lambda from "@aws-cdk/aws-lambda"; +import * as s3 from "@aws-cdk/aws-s3"; + +export class WidgetService extends core.Construct { + constructor(scope: core.Construct, id: string) { + super(scope, id); + + const bucket = new s3.Bucket(this, "WidgetStore"); + + const handler = new lambda.Function(this, "WidgetHandler", { + runtime: lambda.Runtime.NODEJS_14_X, // So we can use async in widget.js + code: lambda.Code.fromAsset("resources"), + handler: "widgets.main", + environment: { + BUCKET: bucket.bucketName + } + }); + + bucket.grantReadWrite(handler); // was: handler.role); + + const api = new apigateway.RestApi(this, "widgets-api", { + restApiName: "Widget Service", + description: "This service serves widgets." + }); + + const getWidgetsIntegration = new apigateway.LambdaIntegration(handler, { + requestTemplates: { "application/json": '{ "statusCode": "200" }' } + }); + + api.root.addMethod("GET", getWidgetsIntegration); // GET / + } +} +``` + +------ +#### [ JavaScript ] + +File: `lib/widget_service.js` + +``` +const core = require("@aws-cdk/core"); +const apigateway = require("@aws-cdk/aws-apigateway"); +const lambda = require("@aws-cdk/aws-lambda"); +const s3 = require("@aws-cdk/aws-s3"); + +class WidgetService extends core.Construct { + constructor(scope, id) { + super(scope, id); + + const bucket = new s3.Bucket(this, "WidgetStore"); + + const handler = new lambda.Function(this, "WidgetHandler", { + runtime: lambda.Runtime.NODEJS_14_X, // So we can use async in widget.js + code: lambda.Code.fromAsset("resources"), + handler: "widgets.main", + environment: { + BUCKET: bucket.bucketName + } + }); + + bucket.grantReadWrite(handler); // was: handler.role); + + const api = new apigateway.RestApi(this, "widgets-api", { + restApiName: "Widget Service", + description: "This service serves widgets." + }); + + const getWidgetsIntegration = new apigateway.LambdaIntegration(handler, { + requestTemplates: { "application/json": '{ "statusCode": "200" }' } + }); + + api.root.addMethod("GET", getWidgetsIntegration); // GET / + } +} + +module.exports = { WidgetService } +``` + +------ +#### [ Python ] + +File: `my_widget_service/widget_service.py` + +``` +from aws_cdk import (core, + aws_apigateway as apigateway, + aws_s3 as s3, + aws_lambda as lambda_) + +class WidgetService(core.Construct): + def __init__(self, scope: core.Construct, id: str): + super().__init__(scope, id) + + bucket = s3.Bucket(self, "WidgetStore") + + handler = lambda_.Function(self, "WidgetHandler", + runtime=lambda_.Runtime.NODEJS_14_X, + code=lambda_.Code.from_asset("resources"), + handler="widgets.main", + environment=dict( + BUCKET=bucket.bucket_name) + ) + + bucket.grant_read_write(handler) + + api = apigateway.RestApi(self, "widgets-api", + rest_api_name="Widget Service", + description="This service serves widgets.") + + get_widgets_integration = apigateway.LambdaIntegration(handler, + request_templates={"application/json": '{ "statusCode": "200" }'}) + + api.root.add_method("GET", get_widgets_integration) # GET / +``` + +------ +#### [ Java ] + +File: `src/src/main/java/com/myorg/WidgetService.java` + +``` +package com.myorg; + +import java.util.HashMap; + +import software.amazon.awscdk.core.Construct; +import software.amazon.awscdk.services.apigateway.LambdaIntegration; +import software.amazon.awscdk.services.apigateway.Resource; +import software.amazon.awscdk.services.apigateway.RestApi; +import software.amazon.awscdk.services.lambda.Code; +import software.amazon.awscdk.services.lambda.Function; +import software.amazon.awscdk.services.lambda.Runtime; +import software.amazon.awscdk.services.s3.Bucket; + +public class WidgetService extends Construct { + + @SuppressWarnings("serial") + public WidgetService(Construct scope, String id) { + super(scope, id); + + Bucket bucket = new Bucket(this, "WidgetStore"); + + Function handler = Function.Builder.create(this, "WidgetHandler") + .runtime(Runtime.NODEJS_14_X) + .code(Code.fromAsset("resources")) + .handler("widgets.main") + .environment(java.util.Map.of( // Java 9 or later + "BUCKET", bucket.getBucketName()) + .build(); + + bucket.grantReadWrite(handler); + + RestApi api = RestApi.Builder.create(this, "Widgets-API") + .restApiName("Widget Service").description("This service services widgets.") + .build(); + + LambdaIntegration getWidgetsIntegration = LambdaIntegration.Builder.create(handler) + .requestTemplates(java.util.Map.of( // Map.of is Java 9 or later + "application/json", "{ \"statusCode\": \"200\" }")) + .build(); + + api.getRoot().addMethod("GET", getWidgetsIntegration); + } +} +``` + +------ +#### [ C\# ] + +File: `src/MyWidgetService/WidgetService.cs` + +``` +using Amazon.CDK; +using Amazon.CDK.AWS.APIGateway; +using Amazon.CDK.AWS.Lambda; +using Amazon.CDK.AWS.S3; +using System.Collections.Generic; + +namespace MyWidgetService +{ + + public class WidgetService : Construct + { + public WidgetService(Construct scope, string id) : base(scope, id) + { + var bucket = new Bucket(this, "WidgetStore"); + + var handler = new Function(this, "WidgetHandler", new FunctionProps + { + Runtime = Runtime.NODEJS_14_X, + Code = Code.FromAsset("resources"), + Handler = "widgets.main", + Environment = new Dictionary<string, string> + { + ["BUCKET"] = bucket.BucketName + } + }); + + bucket.GrantReadWrite(handler); + + var api = new RestApi(this, "Widgets-API", new RestApiProps + { + RestApiName = "Widget Service", + Description = "This service services widgets." + }); + + var getWidgetsIntegration = new LambdaIntegration(handler, new LambdaIntegrationOptions + { + RequestTemplates = new Dictionary<string, string> + { + ["application/json"] = "{ \"statusCode\": \"200\" }" + } + }); + + api.Root.AddMethod("GET", getWidgetsIntegration); + + } + } +} +``` + +------ + +**Tip** +We're using a `[lambda\.Function](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-lambda.Function.html)` in to deploy this function because it supports a wide variety of programming languages\. For JavaScript and TypeScript specifically, you might consider a `[lambda\-nodejs\.NodejsFunction](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-lambda-nodejs.NodejsFunction.html)`\. The latter uses esbuild to bundle up the script and converts code written in TypeScript automatically\. + +Save the app and make sure it still synthesizes an empty stack\. + +``` +cdk synth +``` + +## Add the service to the app<a name="serverless_example_add_service"></a> + +To add the widget service to our AWS CDK app, we'll need to modify the source file that defines the stack to instantiate the service construct\. + +------ +#### [ TypeScript ] + +File: `lib/my_widget_service-stack.ts` + +Add the following line of code after the existing `import` statement\. + +``` +import * as widget_service from '../lib/widget_service'; +``` + +Replace the comment in the constructor with the following line of code\. + +``` + new widget_service.WidgetService(this, 'Widgets'); +``` + +------ +#### [ JavaScript ] + +File: `lib/my_widget_service-stack.js` + +Add the following line of code after the existing `require()` line\. + +``` +const widget_service = require('../lib/widget_service'); +``` + +Replace the comment in the constructor with the following line of code\. + +``` + new widget_service.WidgetService(this, 'Widgets'); +``` + +------ +#### [ Python ] + +File: `my_widget_service/my_widget_service_stack.py` + +Add the following line of code after the existing `import` statement\. + +``` +from . import widget_service +``` + +Replace the comment in the constructor with the following line of code\. + +``` + widget_service.WidgetService(self, "Widgets") +``` + +------ +#### [ Java ] + +File: `src/src/main/java/com/myorg/MyWidgetServiceStack.java` + +Replace the comment in the constructor with the following line of code\. + +``` +new WidgetService(this, "Widgets"); +``` + +------ +#### [ C\# ] + +File: `src/MyWidgetService/MyWidgetServiceStack.cs` + +Replace the comment in the constructor with the following line of code\. + +``` +new WidgetService(this, "Widgets"); +``` + +------ + +Be sure the app runs and synthesizes a stack \(we won't show the stack here: it's over 250 lines\)\. + +``` +cdk synth +``` + +## Deploy and test the app<a name="serverless_example_deploy_and_test"></a> + +Before you can deploy your first AWS CDK app containing a lambda function, you must bootstrap your AWS environment\. This creates a staging bucket that the AWS CDK uses to deploy stacks containing assets\. For details, see [Bootstrapping your AWS environment](cli.md#cli-bootstrap)\. If you've already bootstrapped, you'll get a warning and nothing will change\. + +``` +cdk bootstrap aws://ACCOUNT-NUMBER/REGION +``` + +Now we're ready to deploy the app as follows\. + +``` +cdk deploy +``` + +If the deployment succeeds, save the URL for your server\. This URL appears in one of the last lines in the window, where *GUID* is an alphanumeric GUID and *REGION* is your AWS Region\. + +``` +https://GUID.execute-api-REGION.amazonaws.com/prod/ +``` + +Test your app by getting the list of widgets \(currently empty\) by navigating to this URL in a browser, or use the following command\. + +``` +curl -X GET 'https://GUID.execute-api.REGION.amazonaws.com/prod' +``` + +You can also test the app by: + +1. Opening the AWS Management Console\. + +1. Navigating to the API Gateway service\. + +1. Finding **Widget Service** in the list\. + +1. Selecting **GET** and **Test** to test the function\. + +Because we haven't stored any widgets yet, the output should be similar to the following\. + +``` +{ "widgets": [] } +``` + +## Add the individual widget functions<a name="serverless_example_add_widget_functions"></a> + +The next step is to create Lambda functions to create, show, and delete individual widgets\. + +Replace the code in `widgets.js` \(in `resources`\) with the following\. + +``` +const AWS = require('aws-sdk'); +const S3 = new AWS.S3(); + +const bucketName = process.env.BUCKET; + +/* +This code uses callbacks to handle asynchronous function responses. +It currently demonstrates using an async-await pattern. +AWS supports both the async-await and promises patterns. +For more information, see the following: +https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function +https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises +https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/calling-services-asynchronously.html +https://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-handler.html +*/ +exports.main = async function(event, context) { + try { + var method = event.httpMethod; + // Get name, if present + var widgetName = event.path.startsWith('/') ? event.path.substring(1) : event.path; + + if (method === "GET") { + // GET / to get the names of all widgets + if (event.path === "/") { + const data = await S3.listObjectsV2({ Bucket: bucketName }).promise(); + var body = { + widgets: data.Contents.map(function(e) { return e.Key }) + }; + return { + statusCode: 200, + headers: {}, + body: JSON.stringify(body) + }; + } + + if (widgetName) { + // GET /name to get info on widget name + const data = await S3.getObject({ Bucket: bucketName, Key: widgetName}).promise(); + var body = data.Body.toString('utf-8'); + + return { + statusCode: 200, + headers: {}, + body: JSON.stringify(body) + }; + } + } + + if (method === "POST") { + // POST /name + // Return error if we do not have a name + if (!widgetName) { + return { + statusCode: 400, + headers: {}, + body: "Widget name missing" + }; + } + + // Create some dummy data to populate object + const now = new Date(); + var data = widgetName + " created: " + now; + + var base64data = new Buffer(data, 'binary'); + + await S3.putObject({ + Bucket: bucketName, + Key: widgetName, + Body: base64data, + ContentType: 'application/json' + }).promise(); + + return { + statusCode: 200, + headers: {}, + body: data + }; + } + + if (method === "DELETE") { + // DELETE /name + // Return an error if we do not have a name + if (!widgetName) { + return { + statusCode: 400, + headers: {}, + body: "Widget name missing" + }; + } + + await S3.deleteObject({ + Bucket: bucketName, Key: widgetName + }).promise(); + + return { + statusCode: 200, + headers: {}, + body: "Successfully deleted widget " + widgetName + }; + } + + // We got something besides a GET, POST, or DELETE + return { + statusCode: 400, + headers: {}, + body: "We only accept GET, POST, and DELETE, not " + method + }; + } catch(error) { + var body = error.stack || JSON.stringify(error, null, 2); + return { + statusCode: 400, + headers: {}, + body: body + } + } +} +``` + +Wire up these functions to your API Gateway code at the end of the `WidgetService` constructor\. + +------ +#### [ TypeScript ] + +File: `lib/widget_service.ts` + +``` + const widget = api.root.addResource("{id}"); + + const widgetIntegration = new apigateway.LambdaIntegration(handler); + + widget.addMethod("POST", widgetIntegration); // POST /{id} + widget.addMethod("GET", widgetIntegration); // GET /{id} + widget.addMethod("DELETE", widgetIntegration); // DELETE /{id} +``` + +------ +#### [ JavaScript ] + +File: `lib/widget_service.js` + +``` + const widget = api.root.addResource("{id}"); + + const widgetIntegration = new apigateway.LambdaIntegration(handler); + + widget.addMethod("POST", widgetIntegration); // POST /{id} + widget.addMethod("GET", widgetIntegration); // GET /{id} + widget.addMethod("DELETE", widgetIntegration); // DELETE /{id} +``` + +------ +#### [ Python ] + +File: `my_widget_service/widget_service.py` + +``` + widget = api.root.add_resource("{id}") + + widget_integration = apigateway.LambdaIntegration(handler) + + widget.add_method("POST", widget_integration); # POST /{id} + widget.add_method("GET", widget_integration); # GET /{id} + widget.add_method("DELETE", widget_integration); # DELETE /{id} +``` + +------ +#### [ Java ] + +File: `src/src/main/java/com/myorg/WidgetService.java` + +``` + Resource widget = api.getRoot().addResource("{id}"); + + LambdaIntegration widgetIntegration = new LambdaIntegration(handler); + + widget.addMethod("POST", widgetIntegration); // POST /{id} + widget.addMethod("GET", widgetIntegration); // GET /{id} + widget.addMethod("DELETE", widgetIntegration); // DELETE /{id} +``` + +------ +#### [ C\# ] + +File: `src/MyWidgetService/WidgetService.cs` + +``` + var widget = api.Root.AddResource("{id}"); + + var widgetIntegration = new LambdaIntegration(handler); + + widget.AddMethod("POST", widgetIntegration); // POST /{id} + widget.AddMethod("GET", widgetIntegration); // GET /{id} + widget.AdMethod("DELETE", widgetIntegration); // DELETE /{id} +``` + +------ + +Save and deploy the app\. + +``` +cdk deploy +``` + +We can now store, show, or delete an individual widget\. Use the following commands to list the widgets, create the widget **example**, list all of the widgets, show the contents of **example** \(it should show today's date\), delete **example**, and then show the list of widgets again\. + +``` +curl -X GET 'https://GUID.execute-api.REGION.amazonaws.com/prod' +curl -X POST 'https://GUID.execute-api.REGION.amazonaws.com/prod/example' +curl -X GET 'https://GUID.execute-api.REGION.amazonaws.com/prod' +curl -X GET 'https://GUID.execute-api.REGION.amazonaws.com/prod/example' +curl -X DELETE 'https://GUID.execute-api.REGION.amazonaws.com/prod/example' +curl -X GET 'https://GUID.execute-api.REGION.amazonaws.com/prod' +``` + +You can also use the API Gateway console to test these functions\. Set the **name** value to the name of a widget, such as **example**\. + +## Clean up<a name="serverless_example_destroy"></a> + +To avoid unexpected AWS charges, destroy your AWS CDK stack after you're done with this exercise\. + +``` +cdk destroy +``` \ No newline at end of file diff --git a/v1/stack_how_to_create_multiple_stacks.md b/v1/stack_how_to_create_multiple_stacks.md new file mode 100644 index 00000000..9c291a45 --- /dev/null +++ b/v1/stack_how_to_create_multiple_stacks.md @@ -0,0 +1,641 @@ +# Create an app with multiple stacks<a name="stack_how_to_create_multiple_stacks"></a> + +Most of the other code examples in the *AWS CDK Developer Guide* involve only a single stack\. However, you can create apps containing any number of stacks\. Each stack results in its own AWS CloudFormation template\. Stacks are the *unit of deployment:* each stack in an app can be synthesized and deployed individually using the `cdk deploy` command\. + +This topic illustrates how to extend the `Stack` class to accept new properties or arguments, how to use these properties to affect what resources the stack contains and their configuration, and how to instantiate multiple stacks from this class\. The example uses a Boolean property, named `encryptBucket` \(Python: `encrypt_bucket`\), to indicate whether an Amazon S3 bucket should be encrypted\. If so, the stack enables encryption using a key managed by AWS Key Management Service \(AWS KMS\)\. The app creates two instances of this stack, one with encryption and one without\. + +## Before you begin<a name="cdk-how-to-create-multiple-stacks-prereqs"></a> + +First, install Node\.js and the AWS CDK command line tools, if you haven't already\. See [Getting started with the AWS CDK](getting_started.md) for details\. + +Next, create an AWS CDK project by entering the following commands at the command line\. + +------ +#### [ TypeScript ] + +``` +mkdir multistack +cd multistack +cdk init --language=typescript +``` + +------ +#### [ JavaScript ] + +``` +mkdir multistack +cd multistack +cdk init --language=javascript +``` + +------ +#### [ Python ] + +``` +mkdir multistack +cd multistack +cdk init --language=python +source .venv/bin/activate +pip install -r requirements.txt +``` + +------ +#### [ Java ] + +``` +mkdir multistack +cd multistack +cdk init --language=java +``` + +You can import the resulting Maven project into your Java IDE\. + +------ +#### [ C\# ] + +``` +mkdir multistack +cd multistack +cdk init --language=csharp +``` + +You can open the file `src/Pipeline.sln` in Visual Studio\. + +------ + +Finally, install the `core` and `s3` AWS Construct Library modules\. We use these modules in our app\. + +------ +#### [ TypeScript ] + +``` +npm install @aws-cdk/core @aws-cdk/aws-s3 +``` + +------ +#### [ JavaScript ] + +``` +npm install @aws-cdk/core @aws-cdk/aws-s3 +``` + +------ +#### [ Python ] + +``` +pip install aws_cdk.core aws_cdk.aws_s3 +``` + +------ +#### [ Java ] + +Using the Maven integration in your IDE \(for example, in Eclipse, right\-click the project and choose **Maven** > **Add Dependency**\), add the following packages in the group `software.amazon.awscdk`\. + +``` +core +s3 +``` + +------ +#### [ C\# ] + +``` +nuget install Amazon.CDK +nuget install Amazon.CDK.AWS.S3 +``` + +Or **Tools** > **NuGet Package Manager** > **Manage NuGet Packages for Solution** in Visual Studio + +**Tip** +If you don't see these packages in the **Browse** tab of the **Manage Packages for Solution** page, make sure the **Include prerelease** checkbox is ticked\. +For a better experience, also add the `Amazon.Jsii.Analyzers` package to provide compile\-time checks for missing required properties\. + +------ + +## Add optional parameter<a name="cdk-how-to-create-multiple-stacks-extend-stackprops"></a> + +The `props` argument of the `Stack` constructor fulfills the interface `StackProps`\. Because we want our stack to accept an additional property to tell us whether to encrypt the Amazon S3 bucket, we should create an interface or class that includes that property\. This allows the compiler to make sure the property has a Boolean value and enables autocompletion for it in your IDE\. + +So open the indicated source file in your IDE or editor and add the new interface, class, or argument\. The code should look like this after the changes\. The lines we added are shown in boldface\. + +------ +#### [ TypeScript ] + +File: `lib/multistack-stack.ts` + +``` +import * as cdk from '@aws-cdk/core'; +import * as s3 from '@aws-cdk/aws-s3'; + +interface MultiStackProps extends cdk.StackProps { + encryptBucket?: boolean; +} + +export class MultistackStack extends cdk.Stack { + constructor(scope: cdk.Construct, id: string, props?: MultiStackProps) { + super(scope, id, props); + + // The code that defines your stack goes here + } +} +``` + +------ +#### [ JavaScript ] + +File: `lib/multistack-stack.js` + +JavaScript doesn't have an interface feature; we don't need to add any code\. + +``` +const cdk = require('@aws-cdk/core'); + +class MultistackStack extends cdk.Stack { + constructor(scope, id, props) { + super(scope, id, props); + + // The code that defines your stack goes here + } +} + +module.exports = { MultistackStack } +``` + +------ +#### [ Python ] + +File: `multistack/multistack_stack.py` + +Python does not have an interface feature, so we'll extend our stack to accept the new property by adding a keyword argument\. + +``` +from aws_cdk import aws_s3 as s3 + +class MultistackStack(core.Stack): + + # The Stack class doesn't know about our encrypt_bucket parameter, + # so accept it separately and pass along any other keyword arguments. + def __init__(self, scope: core.Construct, id: str, *, encrypt_bucket=False, + **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + # The code that defines your stack goes here +``` + +------ +#### [ Java ] + +File: `src/main/java/com/myorg/MultistackStack.java` + +It's more complicated than we really want to get into to extend a props type in Java, so we'll simply write our stack's constructor to accept an optional Boolean parameter\. Since `props` is an optional argument, we'll write an additional constructor that allows you to skip it\. It will default to `false`\. + +``` +package com.myorg; + +import software.amazon.awscdk.core.Stack; +import software.amazon.awscdk.core.StackProps; +import software.amazon.awscdk.core.Construct; + +import software.amazon.awscdk.services.s3.Bucket; + +public class MultistackStack extends Stack { + // additional constructors to allow props and/or encryptBucket to be omitted + public MultistackStack(final Construct scope, final String id, boolean encryptBucket) { + this(scope, id, null, encryptBucket); + } + + public MultistackStack(final Construct scope, final String id) { + this(scope, id, null, false); + } + + public MultistackStack(final Construct scope, final String id, final StackProps props, + final boolean encryptBucket) { + super(scope, id, props); + + // The code that defines your stack goes here + } +} +``` + +------ +#### [ C\# ] + +File: `src/Multistack/MultistackStack.cs` + +``` +using Amazon.CDK; +using Amazon.CDK.AWS.S3; +namespace Multistack +{ + + + public class MultiStackProps : StackProps + { + public bool? EncryptBucket { get; set; } + } + + + public class MultistackStack : Stack + { + public MultistackStack(Construct scope, string id, MultiStackProps props) : base(scope, id, props) + { + // The code that defines your stack goes here + } + } +} +``` + +------ + +The new property is optional\. If `encryptBucket` \(Python: `encrypt_bucket`\) is not present, its value is `undefined`, or the local equivalent\. The bucket will be unencrypted by default\. + +## Define the stack class<a name="cdk-how-to-create-multiple-stacks-define-stack"></a> + + Now let's define our stack class, using our new property\. Make the code look like the following\. The code you need to add or change is shown in boldface\. + +------ +#### [ TypeScript ] + +File: `lib/multistack-stack.ts` + +``` +import * as cdk from '@aws-cdk/core'; +import * as s3 from '@aws-cdk/aws-s3'; + +interface MultistackProps extends cdk.StackProps { + encryptBucket?: boolean; +} + +export class MultistackStack extends cdk.Stack { + constructor(scope: cdk.Construct, id: string, props?: MultistackProps) { + super(scope, id, props); + + // Add a Boolean property "encryptBucket" to the stack constructor. + // If true, creates an encrypted bucket. Otherwise, the bucket is unencrypted. + // Encrypted bucket uses KMS-managed keys (SSE-KMS). + if (props && props.encryptBucket) { + new s3.Bucket(this, "MyGroovyBucket", { + encryption: s3.BucketEncryption.KMS_MANAGED, + removalPolicy: cdk.RemovalPolicy.DESTROY + }); + } else { + new s3.Bucket(this, "MyGroovyBucket", { + removalPolicy: cdk.RemovalPolicy.DESTROY}); + } + } +} +``` + +------ +#### [ JavaScript ] + +File: `lib/multistack-stack.js` + +``` +const cdk = require('@aws-cdk/core'); +const s3 = require('@aws-cdk/aws-s3'); + +class MultistackStack extends cdk.Stack { + constructor(scope, id, props) { + super(scope, id, props); + + // Add a Boolean property "encryptBucket" to the stack constructor. + // If true, creates an encrypted bucket. Otherwise, the bucket is unencrypted. + // Encrypted bucket uses KMS-managed keys (SSE-KMS). + if ( props && props.encryptBucket) { + new s3.Bucket(this, "MyGroovyBucket", { + encryption: s3.BucketEncryption.KMS_MANAGED, + removalPolicy: cdk.RemovalPolicy.DESTROY + }); + } else { + new s3.Bucket(this, "MyGroovyBucket", { + removalPolicy: cdk.RemovalPolicy.DESTROY}); + } + } +} + +module.exports = { MultistackStack } +``` + +------ +#### [ Python ] + +File: `multistack/multistack_stack.py` + +``` +from aws_cdk import core +from aws_cdk import aws_s3 as s3 + +class MultistackStack(core.Stack): + + # The Stack class doesn't know about our encrypt_bucket parameter, + # so accept it separately and pass along any other keyword arguments. + def __init__(self, scope: core.Construct, id: str, *, encrypt_bucket=False, + **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + # Add a Boolean property "encryptBucket" to the stack constructor. + # If true, creates an encrypted bucket. Otherwise, the bucket is unencrypted. + # Encrypted bucket uses KMS-managed keys (SSE-KMS). + if encrypt_bucket: + s3.Bucket(self, "MyGroovyBucket", + encryption=s3.BucketEncryption.KMS_MANAGED, + removal_policy=core.RemovalPolicy.DESTROY) + else: + s3.Bucket(self, "MyGroovyBucket", + removal_policy=core.RemovalPolicy.DESTROY) +``` + +------ +#### [ Java ] + +File: `src/main/java/com/myorg/MultistackStack.java` + +``` +package com.myorg; + +import software.amazon.awscdk.core.Stack; +import software.amazon.awscdk.core.StackProps; +import software.amazon.awscdk.core.Construct; +import software.amazon.awscdk.core.RemovalPolicy; + +import software.amazon.awscdk.services.s3.Bucket; +import software.amazon.awscdk.services.s3.BucketEncryption; + +public class MultistackStack extends Stack { + // additional constructors to allow props and/or encryptBucket to be omitted + public MultistackStack(final Construct scope, final String id, + boolean encryptBucket) { + this(scope, id, null, encryptBucket); + } + + public MultistackStack(final Construct scope, final String id) { + this(scope, id, null, false); + } + + // main constructor + public MultistackStack(final Construct scope, final String id, + final StackProps props, final boolean encryptBucket) { + super(scope, id, props); + + // Add a Boolean property "encryptBucket" to the stack constructor. + // If true, creates an encrypted bucket. Otherwise, the bucket is + // unencrypted. Encrypted bucket uses KMS-managed keys (SSE-KMS). + if (encryptBucket) { + Bucket.Builder.create(this, "MyGroovyBucket") + .encryption(BucketEncryption.KMS_MANAGED) + .removalPolicy(RemovalPolicy.DESTROY).build(); + } else { + Bucket.Builder.create(this, "MyGroovyBucket") + .removalPolicy(RemovalPolicy.DESTROY).build(); + } + } +} +``` + +------ +#### [ C\# ] + +File: `src/Multistack/MultistackStack.cs` + +``` +using Amazon.CDK; +using Amazon.CDK.AWS.S3; + +namespace Multistack +{ + + public class MultiStackProps : StackProps + { + public bool? EncryptBucket { get; set; } + } + + public class MultistackStack : Stack + { + public MultistackStack(Construct scope, string id, IMultiStackProps props = null) : base(scope, id, props) + { + // Add a Boolean property "EncryptBucket" to the stack constructor. + // If true, creates an encrypted bucket. Otherwise, the bucket is unencrypted. + // Encrypted bucket uses KMS-managed keys (SSE-KMS). + if (props?.EncryptBucket ?? false) + { + new Bucket(this, "MyGroovyBucket", new BucketProps + { + Encryption = BucketEncryption.KMS_MANAGED, + RemovalPolicy = RemovalPolicy.DESTROY + }); + } + else + { + new Bucket(this, "MyGroovyBucket", new BucketProps + { + RemovalPolicy = RemovalPolicy.DESTROY + }); + } + } + } +} +``` + +------ + +## Create two stack instances<a name="stack_how_to_create_multiple_stacks-create-stacks"></a> + +Now we'll add the code to instantiate two separate stacks\. As before, the lines of code shown in boldface are the ones you need to add\. Delete the existing `MultistackStack` definition\. + +------ +#### [ TypeScript ] + +File: `bin/multistack.ts` + +``` +#!/usr/bin/env node +import 'source-map-support/register'; +import * as cdk from '@aws-cdk/core'; +import { MultistackStack } from '../lib/multistack-stack'; + +const app = new cdk.App(); + +new MultistackStack(app, "MyWestCdkStack", { + env: {region: "us-west-1"}, + encryptBucket: false +}); + +new MultistackStack(app, "MyEastCdkStack", { + env: {region: "us-east-1"}, + encryptBucket: true +}); + +app.synth(); +``` + +------ +#### [ JavaScript ] + +File: `bin/multistack.js` + +``` +#!/usr/bin/env node +const cdk = require('@aws-cdk/core'); +const { MultistackStack } = require('../lib/multistack-stack'); + +const app = new cdk.App(); + +new MultistackStack(app, "MyWestCdkStack", { + env: {region: "us-west-1"}, + encryptBucket: false +}); + +new MultistackStack(app, "MyEastCdkStack", { + env: {region: "us-east-1"}, + encryptBucket: true +}); + +app.synth(); +``` + +------ +#### [ Python ] + +File: `./app.py` + +``` +#!/usr/bin/env python3 + +from aws_cdk import core + +from multistack.multistack_stack import MultistackStack + +app = core.App() +MultistackStack(app, "MyWestCdkStack", + env=core.Environment(region="us-west-1"), + encrypt_bucket=False) + +MultistackStack(app, "MyEastCdkStack", + env=core.Environment(region="us-east-1"), + encrypt_bucket=True) + +app.synth() +``` + +------ +#### [ Java ] + +File: `src/main/java/com/myorg/MultistackApp.java` + +``` +package com.myorg; + +import software.amazon.awscdk.core.App; +import software.amazon.awscdk.core.Environment; +import software.amazon.awscdk.core.StackProps; + +public class MultistackApp { + public static void main(final String argv[]) { + App app = new App(); + + new MultistackStack(app, "MyWestCdkStack", StackProps.builder() + .env(Environment.builder() + .region("us-west-1") + .build()) + .build(), false); + + new MultistackStack(app, "MyEastCdkStack", StackProps.builder() + .env(Environment.builder() + .region("us-east-1") + .build()) + .build(), true); + + app.synth(); + } +} +``` + +------ +#### [ C\# ] + +File: src/Multistack/Program\.cs + +``` +using Amazon.CDK; + +namespace Multistack +{ + class Program + { + static void Main(string[] args) + { + var app = new App(); + + new MultistackStack(app, "MyWestCdkStack", new MultiStackProps + { + Env = new Environment { Region = "us-west-1" }, + EncryptBucket = false + }); + + new MultistackStack(app, "MyEastCdkStack", new MultiStackProps + { + Env = new Environment { Region = "us-east-1" }, + EncryptBucket = true + }); + + app.Synth(); + } + } +} +``` + +------ + + This code uses the new `encryptBucket` \(Python: `encrypt_bucket`\) property on the `MultistackStack` class to instantiate the following: ++ One stack with an encrypted Amazon S3 bucket in the `us-east-1` AWS Region\. ++ One stack with an unencrypted Amazon S3 bucket in the `us-west-1` AWS Region\. + +## Synthesize and deploy the stack<a name="cdk-how-to-create-multiple-stacks-synth-deploy"></a> + +Now you can deploy stacks from the app\. First, synthesize a AWS CloudFormation template for `MyEastCdkStack`—the stack in `us-east-1`\. This is the stack with the encrypted S3 bucket\. + +``` +$ cdk synth MyEastCdkStack +``` + +The output should look similar to the following AWS CloudFormation template \(there might be slight differences\)\. + +``` +Resources: + MyGroovyBucketFD9882AC: + Type: AWS::S3::Bucket + Properties: + BucketEncryption: + ServerSideEncryptionConfiguration: + - ServerSideEncryptionByDefault: + SSEAlgorithm: aws:kms + UpdateReplacePolicy: Retain + DeletionPolicy: Retain + Metadata: + aws:cdk:path: MyEastCdkStack/MyGroovyBucket/Resource + CDKMetadata: + Type: AWS::CDK::Metadata + Properties: + Modules: aws-cdk=1.10.0,@aws-cdk/aws-events=1.10.0,@aws-cdk/aws-iam=1.10.0,@aws-cdk/aws-kms=1.10.0,@aws-cdk/aws-s3=1.10.0,@aws-cdk/core=1.10.0,@aws-cdk/cx-api=1.10.0,@aws-cdk/region-info=1.10.0,jsii-runtime=node.js/v10.16.2 +``` + +To deploy this stack to your AWS account, issue one of the following commands\. The first command uses your default AWS profile to obtain the credentials to deploy the stack\. The second uses a profile you specify: for *PROFILE\_NAME*, substitute the name of an AWS CLI profile that contains appropriate credentials for deploying to the `us-east-1` AWS Region\. + +``` +cdk deploy MyEastCdkStack +``` + +``` +cdk deploy MyEastCdkStack --profile=PROFILE_NAME +``` + +## Clean up<a name="cdk-how-to-create-multiple-stacks-destroy-stack"></a> + +To avoid charges for resources that you deployed, destroy the stack using the following command\. + +``` +cdk destroy MyEastCdkStack +``` + +The destroy operation fails if there is anything stored in the stack's bucket\. There shouldn't be if you've only followed the instructions in this topic\. But if you did put something in the bucket, you must delete the bucket's contents, but not the bucket itself, using the AWS Management Console or the AWS CLI before destroying the stack\. \ No newline at end of file diff --git a/v1/stacks.md b/v1/stacks.md new file mode 100644 index 00000000..aff226d1 --- /dev/null +++ b/v1/stacks.md @@ -0,0 +1,373 @@ +# Stacks<a name="stacks"></a> + +The unit of deployment in the AWS CDK is called a *stack*\. All AWS resources defined within the scope of a stack, either directly or indirectly, are provisioned as a single unit\. + +Because AWS CDK stacks are implemented through AWS CloudFormation stacks, they have the same limitations as in [AWS CloudFormation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cloudformation-limits.html)\. + +You can define any number of stacks in your AWS CDK app\. Any instance of the `Stack` construct represents a stack, and can be either defined directly within the scope of the app, like the `MyFirstStack` example shown previously, or indirectly by any construct within the tree\. + +For example, the following code defines an AWS CDK app with two stacks\. + +------ +#### [ TypeScript ] + +``` +const app = new App(); + +new MyFirstStack(app, 'stack1'); +new MySecondStack(app, 'stack2'); + +app.synth(); +``` + +------ +#### [ JavaScript ] + +``` +const app = new App(); + +new MyFirstStack(app, 'stack1'); +new MySecondStack(app, 'stack2'); + +app.synth(); +``` + +------ +#### [ Python ] + +``` +app = App() + +MyFirstStack(app, 'stack1') +MySecondStack(app, 'stack2') + +app.synth() +``` + +------ +#### [ Java ] + +``` +App app = new App(); + +new MyFirstStack(app, "stack1"); +new MySecondStack(app, "stack2"); + +app.synth(); +``` + +------ +#### [ C\# ] + +``` +var app = new App(); + +new MyFirstStack(app, "stack1"); +new MySecondStack(app, "stack2"); + +app.Synth(); +``` + +------ + +To list all the stacks in an AWS CDK app, run the cdk ls command, which for the previous AWS CDK app would have the following output\. + +``` +stack1 +stack2 +``` + +When you run the cdk synth command for an app with multiple stacks, the cloud assembly includes a separate template for each stack instance\. Even if the two stacks are instances of the same class, the AWS CDK emits them as two individual templates\. + +You can synthesize each template by specifying the stack name in the cdk synth command\. The following example synthesizes the template for **stack1**\. + +``` +cdk synth stack1 +``` + +This approach is conceptually different from how AWS CloudFormation templates are normally used, where a template can be deployed multiple times and parameterized through [AWS CloudFormation parameters](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html)\. Although AWS CloudFormation parameters can be defined in the AWS CDK, they are generally discouraged because AWS CloudFormation parameters are resolved only during deployment\. This means that you cannot determine their value in your code\. For example, to conditionally include a resource in your app based on the value of a parameter, you must set up an [AWS CloudFormation condition](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/conditions-section-structure.html) and tag the resource with this condition\. Because the AWS CDK takes an approach where concrete templates are resolved at synthesis time, you can use an **if** statement to check the value to determine whether a resource should be defined or some behavior should be applied\. + +**Note** +The AWS CDK provides as much resolution as possible during synthesis time to enable idiomatic and natural usage of your programming language\. + +Like any other construct, stacks can be composed together into groups\. The following code shows an example of a service that consists of three stacks: a control plane, a data plane, and monitoring stacks\. The service construct is defined twice: once for the beta environment and once for the production environment\. + +------ +#### [ TypeScript ] + +``` +import { App, Construct, Stack } from "@aws-cdk/core"; + +interface EnvProps { + prod: boolean; +} + +// imagine these stacks declare a bunch of related resources +class ControlPlane extends Stack {} +class DataPlane extends Stack {} +class Monitoring extends Stack {} + +class MyService extends Construct { + + constructor(scope: Construct, id: string, props?: EnvProps) { + + super(scope, id); + + // we might use the prod argument to change how the service is configured + new ControlPlane(this, "cp"); + new DataPlane(this, "data"); + new Monitoring(this, "mon"); } +} + +const app = new App(); +new MyService(app, "beta"); +new MyService(app, "prod", { prod: true }); + +app.synth(); +``` + +------ +#### [ JavaScript ] + +``` +const { App , Construct , Stack } = require("@aws-cdk/core"); + +// imagine these stacks declare a bunch of related resources +class ControlPlane extends Stack {} +class DataPlane extends Stack {} +class Monitoring extends Stack {} + +class MyService extends Construct { + + constructor(scope, id, props) { + + super(scope, id); + + // we might use the prod argument to change how the service is configured + new ControlPlane(this, "cp"); + new DataPlane(this, "data"); + new Monitoring(this, "mon"); + } +} + +const app = new App(); +new MyService(app, "beta"); +new MyService(app, "prod", { prod: true }); + +app.synth(); +``` + +------ +#### [ Python ] + +``` +from aws_cdk.core import App, Construct, Stack + +# imagine these stacks declare a bunch of related resources +class ControlPlane(Stack): pass +class DataPlane(Stack): pass +class Monitoring(Stack): pass + +class MyService(Construct): + + def __init__(self, scope: Construct, id: str, *, prod=False): + + super().__init__(scope, id) + + # we might use the prod argument to change how the service is configured + ControlPlane(self, "cp") + DataPlane(self, "data") + Monitoring(self, "mon") + +app = App(); +MyService(app, "beta") +MyService(app, "prod", prod=True) + +app.synth() +``` + +------ +#### [ Java ] + +``` +package com.myorg; + +import software.amazon.awscdk.core.App; +import software.amazon.awscdk.core.Stack; +import software.amazon.awscdk.core.Construct; + +public class MyApp { + + // imagine these stacks declare a bunch of related resources + static class ControlPlane extends Stack { + ControlPlane(Construct scope, String id) { + super(scope, id); + } + } + + static class DataPlane extends Stack { + DataPlane(Construct scope, String id) { + super(scope, id); + } + } + + static class Monitoring extends Stack { + Monitoring(Construct scope, String id) { + super(scope, id); + } + } + + static class MyService extends Construct { + MyService(Construct scope, String id) { + this(scope, id, false); + } + + MyService(Construct scope, String id, boolean prod) { + super(scope, id); + + // we might use the prod argument to change how the service is configured + new ControlPlane(this, "cp"); + new DataPlane(this, "data"); + new Monitoring(this, "mon"); + } + } + + public static void main(final String argv[]) { + App app = new App(); + + new MyService(app, "beta"); + new MyService(app, "prod", true); + + app.synth(); + } +} +``` + +------ +#### [ C\# ] + +``` +using Amazon.CDK; + +// imagine these stacks declare a bunch of related resources +public class ControlPlane : Stack { + public ControlPlane(Construct scope, string id=null) : base(scope, id) { } +} + +public class DataPlane : Stack { + public DataPlane(Construct scope, string id=null) : base(scope, id) { } +} + +public class Monitoring : Stack +{ + public Monitoring(Construct scope, string id=null) : base(scope, id) { } +} + +public class MyService : Construct +{ + public MyService(Construct scope, string id, Boolean prod=false) : base(scope, id) + { + // we might use the prod argument to change how the service is configured + new ControlPlane(this, "cp"); + new DataPlane(this, "data"); + new Monitoring(this, "mon"); + } +} + +class Program +{ + static void Main(string[] args) + { + + var app = new App(); + new MyService(app, "beta"); + new MyService(app, "prod", prod: true); + app.Synth(); + } +} +``` + +------ + +This AWS CDK app eventually consists of six stacks, three for each environment: + +``` +$ cdk ls + +betacpDA8372D3 +betadataE23DB2BA +betamon632BD457 +prodcp187264CE +proddataF7378CE5 +prodmon631A1083 +``` + +The physical names of the AWS CloudFormation stacks are automatically determined by the AWS CDK based on the stack's construct path in the tree\. By default, a stack's name is derived from the construct ID of the `Stack` object, but you can specify an explicit name using the `stackName` prop \(in Python, `stack_name`\), as follows\. + +------ +#### [ TypeScript ] + +``` +new MyStack(this, 'not:a:stack:name', { stackName: 'this-is-stack-name' }); +``` + +------ +#### [ JavaScript ] + +``` +new MyStack(this, 'not:a:stack:name', { stackName: 'this-is-stack-name' }); +``` + +------ +#### [ Python ] + +``` +MyStack(self, "not:a:stack:name", stack_name="this-is-stack-name") +``` + +------ +#### [ Java ] + +``` +new MyStack(this, "not:a:stack:name", StackProps.builder() + .StackName("this-is-stack-name").build()); +``` + +------ +#### [ C\# ] + +``` +new MyStack(this, "not:a:stack:name", new StackProps +{ + StackName = "this-is-stack-name" +}); +``` + +------ + +## Stack API<a name="stack_api"></a> + +The [Stack](https://docs.aws.amazon.com/cdk/api/v1/docs/core/stack.html) object provides a rich API, including the following: ++ `Stack.of(construct)` – A static method that returns the **Stack** in which a construct is defined\. This is useful if you need to interact with a stack from within a reusable construct\. The call fails if a stack cannot be found in scope\. ++ `stack.stackName` \(Python: `stack_name`\) – Returns the physical name of the stack\. As mentioned previously, all AWS CDK stacks have a physical name that the AWS CDK can resolve during synthesis\. ++ `stack.region` and `stack.account` – Return the AWS Region and account, respectively, into which this stack will be deployed\. These properties return either the account or Region explicitly specified when the stack was defined, or a string\-encoded token that resolves to the AWS CloudFormation pseudo\-parameters for account and Region to indicate that this stack is environment agnostic\. See [Environments](environments.md) for information about how environments are determined for stacks\. ++ `stack.addDependency(stack)` \(Python: `stack.add_dependency(stack)` – Can be used to explicitly define dependency order between two stacks\. This order is respected by the cdk deploy command when deploying multiple stacks at once\. ++ `stack.tags` – Returns a [TagManager](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.TagManager.html) that you can use to add or remove stack\-level tags\. This tag manager tags all resources within the stack, and also tags the stack itself when it's created through AWS CloudFormation\. ++ `stack.partition`, `stack.urlSuffix` \(Python: `url_suffix`\), `stack.stackId` \(Python: `stack_id`\), and `stack.notificationArn` \(Python: `notification_arn`\) – Return tokens that resolve to the respective AWS CloudFormation pseudo\-parameters, such as `{ "Ref": "AWS::Partition" }`\. These tokens are associated with the specific stack object so that the AWS CDK framework can identify cross\-stack references\. ++ `stack.availabilityZones` \(Python: `availability_zones`\) – Returns the set of Availability Zones available in the environment in which this stack is deployed\. For environment\-agnostic stacks, this always returns an array with two Availability Zones, but for environment\-specific stacks, the AWS CDK queries the environment and returns the exact set of Availability Zones available in the region you specified\. ++ `stack.parseArn(arn)` and `stack.formatArn(comps)` \(Python: `parse_arn`, `format_arn`\) – Can be used to work with Amazon Resource Names \(ARNs\)\. ++ `stack.toJsonString(obj)` \(Python: `to_json_string`\) – Can be used to format an arbitrary object as a JSON string that can be embedded in an AWS CloudFormation template\. The object can include tokens, attributes, and references, which are only resolved during deployment\. ++ `stack.templateOptions` \(Python: `template_options`\) – Enables you to specify AWS CloudFormation template options, such as Transform, Description, and Metadata, for your stack\. + +## Nested stacks<a name="stack_nesting"></a> + +The [NestedStack](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.NestedStack.html) construct offers a way around the AWS CloudFormation 500\-resource limit for stacks\. A nested stack counts as only one resource in the stack that contains it, but can itself contain up to 500 resources, including additional nested stacks\. + +The scope of a nested stack must be a `Stack` or `NestedStack` construct\. The nested stack needn't be declared lexically inside its parent stack; it is necessary only to pass the parent stack as the first parameter \(`scope`\) when instantiating the nested stack\. Aside from this restriction, defining constructs in a nested stack works exactly the same as in an ordinary stack\. + +At synthesis time, the nested stack is synthesized to its own AWS CloudFormation template, which is uploaded to the AWS CDK staging bucket at deployment\. Nested stacks are bound to their parent stack and are not treated as independent deployment artifacts; they are not listed by `cdk list` nor can they be deployed by `cdk deploy`\. + +References between parent stacks and nested stacks are automatically translated to stack parameters and outputs in the generated AWS CloudFormation templates, as with any [cross\-stack reference](resources.md#resource_stack)\. + +**Warning** +Changes in security posture are not displayed before deployment for nested stacks\. This information is displayed only for top\-level stacks\. \ No newline at end of file diff --git a/v1/tagging.md b/v1/tagging.md new file mode 100644 index 00000000..7d837a72 --- /dev/null +++ b/v1/tagging.md @@ -0,0 +1,540 @@ +# Tagging<a name="tagging"></a> + +Tags are informational key\-value elements that you can add to constructs in your AWS CDK app\. A tag applied to a given construct also applies to all of its taggable children\. Tags are included in the AWS CloudFormation template synthesized from your app and are applied to the AWS resources it deploys\. You can use tags to identify and categorize resources to simplify management, in cost allocation, and for access control, as well as for any other purposes you devise\. + +**Tip** +For more information about how you can use tags with your AWS resources, see the white paper [Tagging Best Practices](https://d1.awsstatic.com/whitepapers/aws-tagging-best-practices.pdf) \(PDF\)\. + +The [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.Tags.html](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.Tags.html) class includes the static method `of()`, through which you can add tags to, or remove tags from, the specified construct\. ++ [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.Tags.html#addkey-value-props](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.Tags.html#addkey-value-props) applies a new tag to the given construct and all of its children\. ++ [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.Tags.html#removekey-props](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.Tags.html#removekey-props) removes a tag from the given construct and any of its children, including tags a child construct may have applied to itself\. + +**Note** +Tagging is implemented using [Aspects](aspects.md)\. Aspects are a way to apply an operation \(such as tagging\) to all constructs in a given scope\. + +The following example applies the tag **key** with the value **value** to a construct\. + +------ +#### [ TypeScript ] + +``` +Tags.of(myConstruct).add('key', 'value'); +``` + +------ +#### [ JavaScript ] + +``` +Tags.of(myConstruct).add('key', 'value'); +``` + +------ +#### [ Python ] + +``` +Tags.of(my_construct).add("key", "value") +``` + +------ +#### [ Java ] + +``` +Tags.of(myConstruct).add("key", "value"); +``` + +------ +#### [ C\# ] + +``` +Tags.Of(myConstruct).Add("key", "value"); +``` + +------ + +The following example deletes the tag **key** from a construct\. + +------ +#### [ TypeScript ] + +``` +Tags.of(myConstruct).remove('key'); +``` + +------ +#### [ JavaScript ] + +``` +Tags.of(myConstruct).remove('key'); +``` + +------ +#### [ Python ] + +``` +Tags.of(my_construct).remove("key") +``` + +------ +#### [ Java ] + +``` +Tags.of(myConstruct).remove("key"); +``` + +------ +#### [ C\# ] + +``` +Tags.Of(myConstruct).Remove("key"); +``` + +------ + +If you are using `Stage` constructs, apply the tag at the `Stage` level or below\. Tags are not applied across `Stage` boundaries\. + +## Tag priorities<a name="w55aac21c23c23"></a> + +The AWS CDK applies and removes tags recursively\. If there are conflicts, the tagging operation with the highest priority wins\. \(Priorities are set using the optional `priority` property\.\) If the priorities of two operations are the same, the tagging operation closest to the bottom of the construct tree wins\. By default, applying a tag has a priority of 100 \(except for tags added directly to an AWS CloudFormation resource, which has a priority of 50\) and removing a tag has a priority of 200\. + +The following applies a tag with a priority of 300 to a construct\. + +------ +#### [ TypeScript ] + +``` +Tags.of(myConstruct).add('key', 'value', { + priority: 300 +}); +``` + +------ +#### [ JavaScript ] + +``` +Tags.of(myConstruct).add('key', 'value', { + priority: 300 +}); +``` + +------ +#### [ Python ] + +``` +Tags.of(my_construct).add("key", "value", priority=300) +``` + +------ +#### [ Java ] + +``` +Tags.of(myConstruct).add("key", "value", TagProps.builder() + .priority(300).build()); +``` + +------ +#### [ C\# ] + +``` +Tags.Of(myConstruct).Add("key", "value", new TagProps { Priority = 300 }); +``` + +------ + +## Optional properties<a name="tagging_props"></a> + +Tags support [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.TagProps.html](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.TagProps.html) that fine\-tune how tags are applied to, or removed from, resources\. All properties are optional\. + +`applyToLaunchedInstances` \(Python: `apply_to_launched_instances`\) +Available for add\(\) only\. By default, tags are applied to instances launched in an Auto Scaling group\. Set this property to **false** to ignore instances launched in an Auto Scaling group\. + +`includeResourceTypes`/`excludeResourceTypes` \(Python: `include_resource_types`/`exclude_resource_types`\) +Use these to manipulate tags only on a subset of resources, based on AWS CloudFormation resource types\. By default, the operation is applied to all resources in the construct subtree, but this can be changed by including or excluding certain resource types\. Exclude takes precedence over include, if both are specified\. + +`priority` +Use this to set the priority of this operation with respect to other `Tags.add()` and `Tags.remove()` operations\. Higher values take precedence over lower values\. The default is 100 for add operations \(50 for tags applied directly to AWS CloudFormation resources\) and 200 for remove operations\. + +The following example applies the tag **tagname** with the value **value** and priority **100** to resources of type **AWS::Xxx::Yyy** in the construct, but not to instances launched in an Amazon EC2 Auto Scaling group or to resources of type **AWS::Xxx::Zzz**\. \(These are placeholders for two arbitrary but different AWS CloudFormation resource types\.\) + +------ +#### [ TypeScript ] + +``` +Tags.of(myConstruct).add('tagname', 'value', { + applyToLaunchedInstances: false, + includeResourceTypes: ['AWS::Xxx::Yyy'], + excludeResourceTypes: ['AWS::Xxx::Zzz'], + priority: 100, +}); +``` + +------ +#### [ JavaScript ] + +``` +Tags.of(myConstruct).add('tagname', 'value', { + applyToLaunchedInstances: false, + includeResourceTypes: ['AWS::Xxx::Yyy'], + excludeResourceTypes: ['AWS::Xxx::Zzz'], + priority: 100 +}); +``` + +------ +#### [ Python ] + +``` +Tags.of(my_construct).add("tagname", "value", + apply_to_launched_instances=False, + include_resource_types=["AWS::Xxx::Yyy"], + exclude_resource_types=["AWS::Xxx::Zzz"], + priority=100) +``` + +------ +#### [ Java ] + +``` +Tags.of(myConstruct).add("key", "value", TagProps.builder() + .applyToLaunchedInstances(false) + .includeResourceTypes(Arrays.asList("AWS::Xxx::Yyy")) + .excludeResourceTypes(Arrays.asList("AWS::Xxx::Zzz")) + .priority(100).build()); +``` + +------ +#### [ C\# ] + +``` +Tags.Of(myConstruct).Add("tagname", "value", new TagProps +{ + ApplyToLaunchedInstances = false, + IncludeResourceTypes = ["AWS::Xxx::Yyy"], + ExcludeResourceTypes = ["AWS::Xxx::Zzz"], + Priority = 100 +}); +``` + +------ + +The following example removes the tag **tagname** with priority **200** from resources of type **AWS::Xxx::Yyy** in the construct, but not from resources of type **AWS::Xxx::Zzz**\. + +------ +#### [ TypeScript ] + +``` +Tags.of(myConstruct).remove('tagname', { + includeResourceTypes: ['AWS::Xxx::Yyy'], + excludeResourceTypes: ['AWS::Xxx::Zzz'], + priority: 200, +}); +``` + +------ +#### [ JavaScript ] + +``` +Tags.of(myConstruct).remove('tagname', { + includeResourceTypes: ['AWS::Xxx::Yyy'], + excludeResourceTypes: ['AWS::Xxx::Zzz'], + priority: 200 +}); +``` + +------ +#### [ Python ] + +``` +Tags.of(my_construct).remove("tagname", + include_resource_types=["AWS::Xxx::Yyy"], + exclude_resource_types=["AWS::Xxx::Zzz"], + priority=200,) +``` + +------ +#### [ Java ] + +``` +Tags.of((myConstruct).remove("tagname", TagProps.builder() + .includeResourceTypes(Arrays.asList("AWS::Xxx::Yyy")) + .excludeResourceTypes(Arrays.asList("AWS::Xxx::Zzz")) + .priority(100).build()); +``` + +------ +#### [ C\# ] + +``` +Tags.Of(myConstruct).Remove("tagname", new TagProps +{ + IncludeResourceTypes = ["AWS::Xxx::Yyy"], + ExcludeResourceTypes = ["AWS::Xxx::Zzz"], + Priority = 100 +}); +``` + +------ + +## Example<a name="tagging_example"></a> + +The following example adds the tag key **StackType** with value **TheBest** to any resource created within the Stack named `MarketingSystem`\. Then it removes it again from all resources except Amazon EC2 VPC subnets\. The result is that only the subnets have the tag applied\. + +------ +#### [ TypeScript ] + +``` +import { App, Stack, Tags } from '@aws-cdk/core'; + +const app = new App(); +const theBestStack = new Stack(app, 'MarketingSystem'); + +// Add a tag to all constructs in the stack +Tags.of(theBestStack).add('StackType', 'TheBest'); + +// Remove the tag from all resources except subnet resources +Tags.of(theBestStack).remove('StackType', { + excludeResourceTypes: ['AWS::EC2::Subnet'] +}); +``` + +------ +#### [ JavaScript ] + +``` +const { App , Stack , Tags } = require('@aws-cdk/core'); + +const app = new App(); +const theBestStack = new Stack(app, 'MarketingSystem'); + +// Add a tag to all constructs in the stack +Tags.of(theBestStack).add('StackType', 'TheBest'); + +// Remove the tag from all resources except subnet resources +Tags.of(theBestStack).remove('StackType', { + excludeResourceTypes: ['AWS::EC2::Subnet'] +}); +``` + +------ +#### [ Python ] + +``` +from aws_cdk.core import App, Stack, Tags + +app = App(); +the_best_stack = Stack(app, 'MarketingSystem') + +# Add a tag to all constructs in the stack +Tags.of(the_best_stack).add("StackType", "TheBest") + +# Remove the tag from all resources except subnet resources +Tags.of(the_best_stack).remove("StackType", + exclude_resource_types=["AWS::EC2::Subnet"]) +``` + +------ +#### [ Java ] + +``` +import software.amazon.awscdk.core.App; +import software.amazon.awscdk.core.Tags; + +// Add a tag to all constructs in the stack +Tags.of(theBestStack).add("StackType", "TheBest"); + +// Remove the tag from all resources except subnet resources +Tags.of(theBestStack).remove("StackType", TagProps.builder() + .excludeResourceTypes(Arrays.asList("AWS::EC2::Subnet")) + .build()); +``` + +------ +#### [ C\# ] + +``` +using Amazon.CDK; + +var app = new App(); +var theBestStack = new Stack(app, 'MarketingSystem'); + +// Add a tag to all constructs in the stack +Tags.Of(theBestStack).Add("StackType", "TheBest"); + +// Remove the tag from all resources except subnet resources +Tags.Of(theBestStack).Remove("StackType", new TagProps +{ + ExcludeResourceTypes = ["AWS::EC2::Subnet"] +}); +``` + +------ + +The following code achieves the same result\. Consider which approach \(inclusion or exclusion\) makes your intent clearer\. + +------ +#### [ TypeScript ] + +``` +Tags.of(theBestStack).add('StackType', 'TheBest', + { includeResourceTypes: ['AWS::EC2::Subnet']}); +``` + +------ +#### [ JavaScript ] + +``` +Tags.of(theBestStack).add('StackType', 'TheBest', + { includeResourceTypes: ['AWS::EC2::Subnet']}); +``` + +------ +#### [ Python ] + +``` +Tags.of(the_best_stack).add("StackType", "TheBest", + include_resource_types=["AWS::EC2::Subnet"]) +``` + +------ +#### [ Java ] + +``` +Tags.of(theBestStack).add("StackType", "TheBest", TagProps.builder() + .includeResourceTypes(Arrays.asList("AWS::EC2::Subnet")) + .build()); +``` + +------ +#### [ C\# ] + +``` +Tags.Of(theBestStack).Add("StackType", "TheBest", new TagProps { + IncludeResourceTypes = ["AWS::EC2::Subnet"] +}); +``` + +------ + +## Tagging single constructs<a name="tagging_single"></a> + +`Tags.of(scope).add(key, value)` is the standard way to add tags to constructs in the AWS CDK\. Its tree\-walking behavior, which recursively tags all taggable resources under the given scope, is almost always what you want\. Sometimes, however, you need to tag a specific, arbitrary construct \(or constructs\)\. + +One such case involves applying tags whose value is derived from some property of the construct being tagged\. The standard tagging approach recursively applies the same key and value to all matching resources in the scope, but here, the value could be different for each tagged construct\. + +Tags are implemented using [aspects](aspects.md), and the CDK calls the tag's `visit()` method for each construct under the scope you specified using `Tags.of(scope)`\. We can call `Tag.visit()` directly to apply a tag to a single construct\. + +------ +#### [ TypeScript ] + +``` +new cdk.Tag(key, value).visit(construct); +``` + +------ +#### [ JavaScript ] + +``` +new cdk.Tag(key, value).visit(construct); +``` + +------ +#### [ Python ] + +``` +cdk.Tag(key, value).visit(construct) +``` + +------ +#### [ Java ] + +``` +Tag.Builder.create(key, value).build().visit(construct); +``` + +------ +#### [ C\# ] + +``` +new Tag(key, value).Visit(construct); +``` + +------ + +To tag all constructs under a scope but allow the values of the tags to be derived from properties of each construct, write an aspect, apply the tag in the aspect's `visit()` method as shown above, and add the aspect to the desired scope using `Aspects.of(scope).add(aspect)`\. + +The example below applies a tag to each resource in a stack containing the resource's path\. + +------ +#### [ TypeScript ] + +``` +class PathTagger implements cdk.IAspect { + visit(node: IConstruct) { + new cdk.Tag("aws-cdk-path", node.node.path).visit(node); + } +} + +stack = new MyStack(app); +cdk.Aspects.of(stack).add(new PathTagger()) +``` + +------ +#### [ JavaScript ] + +``` +class PathTagger { + visit(node) { + new cdk.Tag("aws-cdk-path", node.node.path).visit(node); + } +} + +stack = new MyStack(app); +cdk.Aspects.of(stack).add(new PathTagger()) +``` + +------ +#### [ Python ] + +``` +@jsii.implements(cdk.IAspect) +class PathTagger: + def visit(self, node: IConstruct): + cdk.Tag("aws-cdk-path", node.node.path).visit(node) + +stack = MyStack(app) +cdk.Aspects.of(stack).add(PathTagger()) +``` + +------ +#### [ Java ] + +``` +final class PathTagger implements IAspect { + public void visit(IConstruct node) { + Tag.Builder.create("aws-cdk-path", node.getNode().getPath()).build().visit(node); + } +} + +stack stack = new MyStack(app); +Aspects.of(stack).add(new PathTagger()); +``` + +------ +#### [ C\# ] + +``` +public class PathTagger : IAspect +{ + public void Visit(IConstruct node) + { + new Tag("aws-cdk-path", node.Node.Path).Visit(node); + } +} + +var stack = new MyStack(app); +Aspects.Of(stack).Add(new PathTagger()); +``` + +------ + +**Tip** +The logic of conditional tagging, including priorities, resource types, and so on, is built into the `Tag` class, so you can use these features when applying tags to arbitrary resources\. Also, the `Tag` class only tags taggble resources, so you don't need to test whether a construct is taggable before applying a tag\. \ No newline at end of file diff --git a/v1/testing.md b/v1/testing.md new file mode 100644 index 00000000..2f389906 --- /dev/null +++ b/v1/testing.md @@ -0,0 +1,1591 @@ +# Testing constructs<a name="testing"></a> + +With the AWS CDK, your infrastructure can be as testable as any other code you write\. This article illustrates the standard approach to testing AWS CDK apps using the AWS CDK's [assertions](https://docs.aws.amazon.com/cdk/api/v1/docs/assertions-readme.html) module and popular test frameworks such as [Jest](https://jestjs.io/) for TypeScript and JavaScript or [Pytest](https://docs.pytest.org/en/6.2.x/) for Python\. + +There are two categories of tests you can write for AWS CDK apps\. ++ **Fine\-grained assertions** test specific aspects of the generated AWS CloudFormation template, such as "this resource has this property with this value\." These tests can detect regressions, and are also useful when you're developing new features using test\-driven development \(write a test first, then make it pass by writing a correct implementation\)\. Fine\-grained assertions are the tests you'll write the most of\. ++ **Snapshot tests** test the synthesized AWS CloudFormation template against a previously\-stored baseline template\. Snapshot tests let you refactor freely, since you can be sure that the refactored code works exactly the same way as the original\. If the changes were intentional, you can accept a new baseline for future tests\. However, CDK upgrades can also cause synthesized templates to change, so you can't rely only on snapshots to make sure your implementation is correct\. + +**Note** +Complete versions of the TypeScript, Python, and Java apps used as examples in this topic are [available on GitHub](https://github.com/cdklabs/aws-cdk-testing-examples/)\. + +## Getting started<a name="testing_getting_started"></a> + +To illustrate how to write these tests, we'll create a stack that contains an AWS Step Functions state machine and a AWS Lambda function\. The Lambda function is subscribed to an Amazon SNS topic and simply forwards the message to the state machine\. + +First, create an empty CDK application project using the CDK Toolkit and installing the construct libraries we'll need\. \(We'll also use the Amazon SNS module and the core AWS CDK library; there's no need to install these separately because they're dependencies of the ones we installed explicitly\.\) Don't forget to add your testing framework and the `assertions` module\! + +------ +#### [ TypeScript ] + +``` +mkdir state-machine && cd state-machine +cdk init --language=typescript +npm install @aws-cdk/aws-lambda @aws-cdk/aws-sns-subscriptions @aws-cdk/aws-stepfunctions +npm install --save-dev jest @types/jest @aws-cdk/assertions +``` + +Create a directory for your tests\. + +``` +mkdir test +``` + +Edit the project's `package.json` to tell NPM how to run Jest, and to tell Jest what kinds of files to collect\. The necessary changes are as follows\. ++ Add a new `test` key to the `scripts` section ++ Add Jest and its types to the `devDependencies` section ++ Add a new `jest` top\-level key with a `moduleFileExtensions` declaration + +These changes are shown in outline below\. Place the new text where indicated in `package.json`\. The "\.\.\." placeholders indicate existing parts of the file that should not be changed\. + +``` +{ + ... + "scripts": { + ... + "test": "jest" + }, + "devDependencies": { + ... + "@types/jest": "^24.0.18", + "jest": "^24.9.0" + }, + "jest": { + "moduleFileExtensions": ["js"] + } +} +``` + +------ +#### [ JavaScript ] + +``` +mkdir state-machine && cd state-machine +cdk init --language=javascript +npm install @aws-cdk/aws-lambda @aws-cdk/aws-sns-subscriptions @aws-cdk/aws-stepfunctions +npm install --save-dev jest @aws-cdk/assertions +``` + +Create a directory for your tests\. + +``` +mkdir test +``` + +Edit the project's `package.json` to tell NPM how to run Jest, and to tell Jest what kinds of files to collect\. The necessary changes are as follows\. ++ Add a new `test` key to the `scripts` section ++ Add Jest to the `devDependencies` section ++ Add a new `jest` top\-level key with a `moduleFileExtensions` declaration + +These changes are shown in outline below\. Place the new text where indicated in `package.json`\. The "\.\.\." placeholders indicate existing parts of the file that should not be changed\. + +``` +{ + ... + "scripts": { + ... + "test": "jest" + }, + "devDependencies": { + ... + "jest": "^24.9.0" + }, + "jest": { + "moduleFileExtensions": ["js"] + } +} +``` + +------ +#### [ Python ] + +``` +mkdir state-machine && cd state-machine +cdk init --language=python +source .venv/bin/activate +python -m pip install -r requirements.txt +python -m pip install -r requirements-dev.txt +python -m pip install aws_cdk.aws_lambda aws_cdk.aws_sns_subscriptions aws_cdk.aws_stepfunctions +python -m pip install pytest aws_cdk.assertions +``` + +------ +#### [ Java ] + +``` +mkdir state-machine && cd-state-machine +cdk init --language=java +``` + +Open the project in your preferred Java IDE\. \(In Eclipse, use **File** > **Import** > Existing Maven Projects\.\) + +Edit `pom.xml` to include the following dependencies\. + +``` + <dependency> + <groupId>software.amazon.awscdk</groupId> + <artifactId>assertions</artifactId> + <version>${cdk.version}</version> + </dependency> + <dependency> + <groupId>software.amazon.awscdk</groupId> + <artifactId>cloudwatch</artifactId> + <version>${cdk.version}</version> + </dependency> + <dependency> + <groupId>software.amazon.awscdk</groupId> + <artifactId>lambda</artifactId> + <version>${cdk.version}</version> + </dependency> + <dependency> + <groupId>software.amazon.awscdk</groupId> + <artifactId>sns</artifactId> + <version>${cdk.version}</version> + </dependency> + <dependency> + <groupId>software.amazon.awscdk</groupId> + <artifactId>sns-subscriptions</artifactId> + <version>${cdk.version}</version> + </dependency> + <dependency> + <groupId>software.amazon.awscdk</groupId> + <artifactId>sqs</artifactId> + <version>${cdk.version}</version> + </dependency> + <dependency> + <groupId>software.amazon.awscdk</groupId> + <artifactId>stepfunctions</artifactId> + <version>${cdk.version}</version> + </dependency> +``` + +Also add the following JUnit dependencies\. + +``` +><dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-api</artifactId> + <version>${junit.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-engine</artifactId> + <version>${junit.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.assertj</groupId> + <artifactId>assertj-core</artifactId> + <version>3.21.0</version> + <scope>test</scope> + </dependency> +``` + +------ +#### [ C\# ] + +``` +mkdir state-machine && cd-state-machine +cdk init --language=csharp +``` + +Open `src\StateMachine.sln` in Visual Studio\. + +Right\-click the solution in Solution Explorer and choose **Add** > **New Project**\. Search for MSTest C\# and add an **MSTest Test Project** for C\#\. \(The default name `TestProject1`is fine\.\) + +Right\-click `TestProject1` and choose **Add** > **Project Reference**, and add the `StateMachine` project as a reference\. + +Choose **Tools** > **NuGet Package Manager** > **Manage NuGet Packages for Solution** and add the following packages to both projects in the solution: ++ `AWS.CDK.Assertions` ++ `AWS.CDK.AWS.Lambda` ++ `AWS.CDK.AWS.SQL` ++ `AWS.CDK.AWS.SNS` ++ `AWS.CDK.AWS.SNS.Subscriptions` ++ `AWS.CDK.AWS.StepFunctions` + +------ + +## The example stack<a name="testing_app"></a> + +Here's the stack we'll be testing in this topic\. As we've previously described, it contains a Lambda function and a Step Functions state machine, and accepts one or more Amazon SNS topics\. The Lambda function is subscribed to the Amazon SNS topics and forwards them to the state machine\. + +You don't have to do anything special to make the app testable\. In fact, this CDK stack is not different in any important way from the other example stacks in this Guide\. + +------ +#### [ TypeScript ] + +Place the following code in `lib/state-machine-stack.ts`: + +``` +import * as cdk from "@aws-cdk/core"; +import * as sns from "@aws-cdk/aws-sns"; +import * as sns_subscriptions from "@aws-cdk/aws-sns-subscriptions"; +import * as lambda from "@aws-cdk/aws-lambda"; +import * as sfn from "@aws-cdk/aws-stepfunctions"; + +export interface ProcessorStackProps extends cdk.StackProps { + readonly topics: sns.Topic[]; +} + +export class ProcessorStack extends cdk.Stack { + constructor(scope: cdk.Construct, id: string, props: ProcessorStackProps) { + super(scope, id, props); + + // In the future this state machine will do some work... + const stateMachine = new sfn.StateMachine(this, "StateMachine", { + definition: new sfn.Pass(this, "StartState"), + }); + + // This Lambda function starts the state machine. + const func = new lambda.Function(this, "LambdaFunction", { + runtime: lambda.Runtime.NODEJS_14_X, + handler: "handler", + code: lambda.Code.fromAsset("./start-state-machine"), + environment: { + STATE_MACHINE_ARN: stateMachine.stateMachineArn, + }, + }); + stateMachine.grantStartExecution(func); + + const subscription = new sns_subscriptions.LambdaSubscription(func); + for (const topic of props.topics) { + topic.addSubscription(subscription); + } + } +} +``` + +------ +#### [ JavaScript ] + +Place the following code in `lib/state-machine-stack.js`: + +``` +const cdk = require("@aws-cdk/core"); +const sns = require("@aws-cdk/aws-sns"); +const sns_subscriptions = require("@aws-cdk/aws-sns-subscriptions"); +const lambda = require("@aws-cdk/aws-lambda"); +const sfn = require("@aws-cdk/aws-stepfunctions"); + +class ProcessorStack extends cdk.Stack { + constructor(scope, id, props) { + super(scope, id, props); + + // In the future this state machine will do some work... + const stateMachine = new sfn.StateMachine(this, "StateMachine", { + definition: new sfn.Pass(this, "StartState"), + }); + + // This Lambda function starts the state machine. + const func = new lambda.Function(this, "LambdaFunction", { + runtime: lambda.Runtime.NODEJS_14_X, + handler: "handler", + code: lambda.Code.fromAsset("./start-state-machine"), + environment: { + STATE_MACHINE_ARN: stateMachine.stateMachineArn, + }, + }); + stateMachine.grantStartExecution(func); + + const subscription = new sns_subscriptions.LambdaSubscription(func); + for (const topic of props.topics) { + topic.addSubscription(subscription); + } + } +} + +module.exports = { ProcessorStack } +``` + +------ +#### [ Python ] + +Place the following code in `state_machine/state_machine_stack.py`: + +``` +from typing import List + +from aws_cdk import aws_lambda as lambda_ +from aws_cdk import aws_sns as sns +from aws_cdk import aws_sns_subscriptions as sns_subscriptions +from aws_cdk import aws_stepfunctions as sfn +from aws_cdk import core as cdk + +class ProcessorStack(cdk.Stack): + def __init__( + self, + scope: cdk.Construct, + construct_id: str, + *, + topics: List[sns.Topic], + **kwargs + ) -> None: + super().__init__(scope, construct_id, **kwargs) + + # In the future this state machine will do some work... + state_machine = sfn.StateMachine( + self, "StateMachine", definition=sfn.Pass(self, "StartState") + ) + + # This Lambda function starts the state machine. + func = lambda_.Function( + self, + "LambdaFunction", + runtime=lambda_.Runtime.NODEJS_14_X, + handler="handler", + code=lambda_.Code.from_asset("./start-state-machine"), + environment={ + "STATE_MACHINE_ARN": state_machine.state_machine_arn, + }, + ) + state_machine.grant_start_execution(func) + + subscription = sns_subscriptions.LambdaSubscription(func) + for topic in topics: + topic.add_subscription(subscription) +``` + +------ +#### [ Java ] + +``` +package software.amazon.samples.awscdkassertionssamples; + +import software.amazon.awscdk.core.Construct; +import software.amazon.awscdk.core.Stack; +import software.amazon.awscdk.core.StackProps; +import software.amazon.awscdk.services.lambda.Code; +import software.amazon.awscdk.services.lambda.Function; +import software.amazon.awscdk.services.lambda.Runtime; +import software.amazon.awscdk.services.sns.ITopicSubscription; +import software.amazon.awscdk.services.sns.Topic; +import software.amazon.awscdk.services.sns.subscriptions.LambdaSubscription; +import software.amazon.awscdk.services.stepfunctions.Pass; +import software.amazon.awscdk.services.stepfunctions.StateMachine; + +import java.util.Collections; +import java.util.List; + +public class ProcessorStack extends Stack { + public ProcessorStack(final Construct scope, final String id, final List<Topic> topics) { + this(scope, id, null, topics); + } + + public ProcessorStack(final Construct scope, final String id, final StackProps props, final List<Topic> topics) { + super(scope, id, props); + + // In the future this state machine will do some work... + final StateMachine stateMachine = StateMachine.Builder.create(this, "StateMachine") + .definition(new Pass(this, "StartState")) + .build(); + + // This Lambda function starts the state machine. + final Function func = Function.Builder.create(this, "LambdaFunction") + .runtime(Runtime.NODEJS_14_X) + .handler("handler") + .code(Code.fromAsset("./start-state-machine")) + .environment(Collections.singletonMap("STATE_MACHINE_ARN", stateMachine.getStateMachineArn())) + .build(); + stateMachine.grantStartExecution(func); + + final ITopicSubscription subscription = new LambdaSubscription(func); + for (final Topic topic : topics) { + topic.addSubscription(subscription); + } + } +} +``` + +------ +#### [ C\# ] + +``` +using Amazon.CDK; +using Amazon.CDK.AWS.Lambda; +using Amazon.CDK.AWS.StepFunctions; +using Amazon.CDK.AWS.SNS; +using Amazon.CDK.AWS.SNS.Subscriptions; + +using System.Collections.Generic; + +namespace AwsCdkAssertionSamples +{ + public class StateMachineStackProps : StackProps + { + public Topic[] Topics; + } + + public class StateMachineStack : Stack + { + + internal StateMachineStack(Construct scope, string id, StateMachineStackProps props = null) : base(scope, id, props) + { + // In the future this state machine will do some work... + var stateMachine = new StateMachine(this, "StateMachine", new StateMachineProps + { + Definition = new Pass(this, "StartState") + }); + + // This Lambda function starts the state machine. + var func = new Function(this, "LambdaFunction", new FunctionProps + { + Runtime = Runtime.NODEJS_14_X, + Handler = "handler", + Code = Code.FromAsset("./start-state-machine"), + Environment = new Dictionary<string, string> + { + { "STATE_MACHINE_ARN", stateMachine.StateMachineArn } + } + }); + stateMachine.GrantStartExecution(func); + + foreach (Topic topic in props?.Topics ?? new Topic[0]) + { + var subscription = new LambdaSubscription(func); + } + + } + } +} +``` + +------ + +We'll modify the app's main entry point to not actually instantiate our stack, since we don't want to accidentally deploy it\. Our tests will create an app and an instance of the stack for testing\. This is a useful tactic when combined with test\-driven development: make sure the stack passes all tests before you enable deployment\. + +------ +#### [ TypeScript ] + +In `bin/state-machine.ts`: + +``` +#!/usr/bin/env node +import * as cdk from "@aws-cdk/core"; + +const app = new cdk.App(); + +// Stacks are intentionally not created here -- this application isn't meant to +// be deployed. +``` + +------ +#### [ JavaScript ] + +In `bin/state-machine.js`: + +``` +#!/usr/bin/env node +const cdk = require("@aws-cdk/core"); + +const app = new cdk.App(); + +// Stacks are intentionally not created here -- this application isn't meant to +// be deployed. +``` + +------ +#### [ Python ] + +In `app.py`: + +``` +#!/usr/bin/env python3 +import os + +from aws_cdk import core as cdk + +app = cdk.App() + +# Stacks are intentionally not created here -- this application isn't meant to +# be deployed. + +app.synth() +``` + +------ +#### [ Java ] + +``` +package software.amazon.samples.awscdkassertionssamples; + +import software.amazon.awscdk.core.App; + + +public class SampleApp { + public static void main(final String[] args) { + App app = new App(); + + // Stacks are intentionally not created here -- this application isn't meant to be deployed. + + app.synth(); + } +} +``` + +------ +#### [ C\# ] + +``` +using Amazon.CDK; + +namespace AwsCdkAssertionSamples +{ + sealed class Program + { + public static void Main(string[] args) + { + var app = new App(); + + // Stacks are intentionally not created here -- this application isn't meant to be deployed. + + app.Synth(); + } + } +} +``` + +------ + +## The Lambda function<a name="testing_lambda"></a> + +Our example stack includes a Lambda function that starts our state machine\. We must provide the source code for this function so the CDK can bundle it up and deploy it as part of creating the Lambda function resource\. ++ Create the folder `start-state-machine` in the app's main directory\. ++ In this folder, create at least one file\. For example, you can save the code below in `start-state-machines/index.js`\. + + ``` + exports.handler = async function (event, context) { + return 'hello world'; + }; + ``` + + However, any file will work, since we won't actually be deploying the stack\. + +## Running tests<a name="testing_running_tests"></a> + +For reference, here are the commands you use to run tests in your AWS CDK app\. These are the same commands you'd use to run the tests in any project using the same testing framework\. For languages that require a build step, include that to make sure your tests have been compiled\. + +------ +#### [ TypeScript ] + +``` +tsc && npm test +``` + +------ +#### [ JavaScript ] + +``` +npm test +``` + +------ +#### [ Python ] + +``` +python -m pytest +``` + +------ +#### [ Java ] + +``` +mvn compile && mvn test +``` + +------ +#### [ C\# ] + +Build your solution \(F6\) to discover the tests, then run the tests \(**Test** > **Run All Tests**\)\. To choose which tests to run, open Test Explorer \(**Test** > **Test Explorer**\)\. + +Or: + +``` +dotnet test src +``` + +------ + +## Fine\-grained assertions<a name="testing_fine_grained"></a> + +The first step for testing a stack with fine\-grained assertions is to synthesize the stack, because we're writing assertions against the generated AWS CloudFormation template\. + +Our `ProcessorStack` requires that we pass it the Amazon SNS topic to be forwarded to the state machine\. So in our test, we'll create a separate stack to contain the topic\. + +Ordinarily, if you were writing a CDK app, you'd subclass `Stack` and instantiate the Amazon SNS topic in the stack's constructor\. In our test, we instantiate `Stack` directly, then pass this stack as the `Topic`'s scope, attaching it to the stack\. This is functionally equivalent, less verbose, and helps make stacks used only in tests "look different" from stacks you intend to deploy\. + +------ +#### [ TypeScript ] + +``` +import { Capture, Match, Template } from "@aws-cdk/assertions"; +import * as cdk from "@aws-cdk/core"; +import * as sns from "@aws-cdk/aws-sns"; +import { ProcessorStack } from "../lib/processor-stack"; + +describe("ProcessorStack", () => { + test("synthesizes the way we expect", () => { + const app = new cdk.App(); + + // Since the ProcessorStack consumes resources from a separate stack + // (cross-stack references), we create a stack for our SNS topics to live + // in here. These topics can then be passed to the ProcessorStack later, + // creating a cross-stack reference. + const topicsStack = new cdk.Stack(app, "TopicsStack"); + + // Create the topic the stack we're testing will reference. + const topics = [new sns.Topic(topicsStack, "Topic1", {})]; + + // Create the ProcessorStack. + const processorStack = new ProcessorStack(app, "ProcessorStack", { + topics: topics, // Cross-stack reference + }); + + // Prepare the stack for assertions. + const template = Template.fromStack(processorStack); + + +} +``` + +------ +#### [ JavaScript ] + +``` +const { Capture, Match, Template } = require("@aws-cdk/assertions"); +const cdk = require("@aws-cdk/core"); +const sns = require("@aws-cdk/aws-sns"); +const { ProcessorStack } = require("../lib/processor-stack"); + +describe("ProcessorStack", () => { + test("synthesizes the way we expect", () => { + const app = new cdk.App(); + + // Since the ProcessorStack consumes resources from a separate stack + // (cross-stack references), we create a stack for our SNS topics to live + // in here. These topics can then be passed to the ProcessorStack later, + // creating a cross-stack reference. + const topicsStack = new cdk.Stack(app, "TopicsStack"); + + // Create the topic the stack we're testing will reference. + const topics = [new sns.Topic(topicsStack, "Topic1", {})]; + + // Create the ProcessorStack. + const processorStack = new ProcessorStack(app, "ProcessorStack", { + topics: topics, // Cross-stack reference + }); + + // Prepare the stack for assertions. + const template = Template.fromStack(processorStack); +``` + +------ +#### [ Python ] + +``` +from aws_cdk import aws_sns as sns +from aws_cdk import core as cdk +from aws_cdk.assertions import Template + +from app.processor_stack import ProcessorStack + +def test_synthesizes_properly(): + app = cdk.App() + + # Since the ProcessorStack consumes resources from a separate stack + # (cross-stack references), we create a stack for our SNS topics to live + # in here. These topics can then be passed to the ProcessorStack later, + # creating a cross-stack reference. + topics_stack = cdk.Stack(app, "TopicsStack") + + # Create the topic the stack we're testing will reference. + topics = [sns.Topic(topics_stack, "Topic1")] + + # Create the ProcessorStack. + processor_stack = ProcessorStack( + app, "ProcessorStack", topics=topics # Cross-stack reference + ) + + # Prepare the stack for assertions. + template = Template.from_stack(processor_stack) +``` + +------ +#### [ Java ] + +``` +package software.amazon.samples.awscdkassertionssamples; + +import org.junit.jupiter.api.Test; +import software.amazon.awscdk.assertions.Capture; +import software.amazon.awscdk.assertions.Match; +import software.amazon.awscdk.assertions.Template; +import software.amazon.awscdk.core.App; +import software.amazon.awscdk.core.Stack; +import software.amazon.awscdk.services.sns.Topic; + +import java.util.*; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ProcessorStackTest { + @Test + public void testSynthesizesProperly() { + final App app = new App(); + + // Since the ProcessorStack consumes resources from a separate stack (cross-stack references), we create a stack + // for our SNS topics to live in here. These topics can then be passed to the ProcessorStack later, creating a + // cross-stack reference. + final Stack topicsStack = new Stack(app, "TopicsStack"); + + // Create the topic the stack we're testing will reference. + final List<Topic> topics = Collections.singletonList(Topic.Builder.create(topicsStack, "Topic1").build()); + + // Create the ProcessorStack. + final ProcessorStack processorStack = new ProcessorStack( + app, + "ProcessorStack", + topics // Cross-stack reference + ); + + // Prepare the stack for assertions. + final Template template = Template.fromStack(processorStack) +``` + +------ +#### [ C\# ] + +``` +using Microsoft.VisualStudio.TestTools.UnitTesting; + +using Amazon.CDK; +using Amazon.CDK.AWS.SNS; +using Amazon.CDK.Assertions; +using AwsCdkAssertionSamples; + +using ObjectDict = System.Collections.Generic.Dictionary<string, object>; +using StringDict = System.Collections.Generic.Dictionary<string, string>; + +namespace TestProject1 +{ + [TestClass] + public class ProcessorStackTest + { + [TestMethod] + public void TestMethod1() + { + var app = new App(); + + // Since the ProcessorStack consumes resources from a separate stack (cross-stack references), we create a stack + // for our SNS topics to live in here. These topics can then be passed to the ProcessorStack later, creating a + // cross-stack reference. + var topicsStack = new Stack(app, "TopicsStack"); + + // Create the topic the stack we're testing will reference. + var topics = new Topic[] { new Topic(topicsStack, "Topic1") }; + + // Create the ProcessorStack. + var processorStack = new StateMachineStack(app, "ProcessorStack", new StateMachineStackProps + { + Topics = topics + }); + + // Prepare the stack for assertions. + var template = Template.FromStack(processorStack); + + // test will go here + } + } +} +``` + +------ + +Now we can assert that the Lambda function and the Amazon SNS subscription were created\. + +------ +#### [ TypeScript ] + +``` + // Assert it creates the function with the correct properties... + template.hasResourceProperties("AWS::Lambda::Function", { + Handler: "handler", + Runtime: "nodejs14.x", + }); + + // Creates the subscription... + template.resourceCountIs("AWS::SNS::Subscription", 1); +``` + +------ +#### [ JavaScript ] + +``` + // Assert it creates the function with the correct properties... + template.hasResourceProperties("AWS::Lambda::Function", { + Handler: "handler", + Runtime: "nodejs14.x", + }); + + // Creates the subscription... + template.resourceCountIs("AWS::SNS::Subscription", 1); +``` + +------ +#### [ Python ] + +``` +# Assert that we have created the function with the correct properties + template.has_resource_properties( + "AWS::Lambda::Function", + { + "Handler": "handler", + "Runtime": "nodejs14.x", + }, + ) + + # Assert that we have created a subscription + template.resource_count_is("AWS::SNS::Subscription", 1) +``` + +------ +#### [ Java ] + +``` + // Assert it creates the function with the correct properties... + template.hasResourceProperties("AWS::Lambda::Function", Map.of( + "Handler", "handler", + "Runtime", "nodejs14.x" + )); + + // Creates the subscription... + template.resourceCountIs("AWS::SNS::Subscription", 1); +``` + +------ +#### [ C\# ] + +``` + // Prepare the stack for assertions. + var template = Template.FromStack(processorStack); + + // Assert it creates the function with the correct properties... + template.HasResourceProperties("AWS::Lambda::Function", new StringDict { + { "Handler", "handler"}, + { "Runtime", "nodejs14x" } + }); + + // Creates the subscription... + template.ResourceCountIs("AWS::SNS::Subscription", 1); +``` + +------ + +Our Lambda function test asserts that two particular properties of the function resource have specific values\. By default, the `hasResourceProperties` method performs a partial match on the resource's properties as given in the synthesized CloudFormation template\. This test requires that the provided properties exist and have the specified values, but the resource can also have other properties, and these are not tested\. + +Our Amazon SNS assertion asserts that the synthesized template contains a subscription, but nothing about the subscription itself\. We included this assertion mainly to illustrate how to assert on resource counts\. The `Template` class offers more specific methods to write assertions against the `Resources`, `Outputs`, and `Mapping` sections of the CloudFormation template\. + +### Matchers<a name="testing_fine_grained_matchers"></a> + +The default partial matching behavior of `hasResourceProperties` can be changed using *matchers* from the [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_assertions.Match.html#methods](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_assertions.Match.html#methods) class\. + +Matchers range from the very lenient \(`Match.anyValue`\) to the quite strict \(`Match.objectEquals`\), and can be nested to apply different matching methods to different parts of the resource properties\. Using `Match.objectEquals` and `Match.anyValue` together, for example, we can test the state machine's IAM role more fully, while not requiring specific values for properties that may change\. + +------ +#### [ TypeScript ] + +``` + // Fully assert on the state machine's IAM role with matchers. + template.hasResourceProperties( + "AWS::IAM::Role", + Match.objectEquals({ + AssumeRolePolicyDocument: { + Version: "2012-10-17", + Statement: [ + { + Action: "sts:AssumeRole", + Effect: "Allow", + Principal: { + Service: { + "Fn::Join": [ + "", + ["states.", Match.anyValue(), ".amazonaws.com"], + ], + }, + }, + }, + ], + }, + }) + ); +``` + +------ +#### [ JavaScript ] + +``` + // Fully assert on the state machine's IAM role with matchers. + template.hasResourceProperties( + "AWS::IAM::Role", + Match.objectEquals({ + AssumeRolePolicyDocument: { + Version: "2012-10-17", + Statement: [ + { + Action: "sts:AssumeRole", + Effect: "Allow", + Principal: { + Service: { + "Fn::Join": [ + "", + ["states.", Match.anyValue(), ".amazonaws.com"], + ], + }, + }, + }, + ], + }, + }) + ); +``` + +------ +#### [ Python ] + +``` +from aws_cdk.assertions import Match + + # Fully assert on the state machine's IAM role with matchers. + template.has_resource_properties( + "AWS::IAM::Role", + Match.object_equals( + { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": { + "Fn::Join": [ + "", + [ + "states.", + Match.any_value(), + ".amazonaws.com", + ], + ], + }, + }, + }, + ], + }, + } + ), + ) +``` + +------ +#### [ Java ] + +``` + // Fully assert on the state machine's IAM role with matchers. + template.hasResourceProperties("AWS::IAM::Role", Match.objectEquals( + Collections.singletonMap("AssumeRolePolicyDocument", Map.of( + "Version", "2012-10-17", + "Statement", Collections.singletonList(Map.of( + "Action", "sts:AssumeRole", + "Effect", "Allow", + "Principal", Collections.singletonMap( + "Service", Collections.singletonMap( + "Fn::Join", Arrays.asList( + "", + Arrays.asList("states.", Match.anyValue(), ".amazonaws.com") + ) + ) + ) + )) + )) + )); +``` + +------ +#### [ C\# ] + +``` + // Fully assert on the state machine's IAM role with matchers. + template.HasResource("AWS::IAM::Role", Match.ObjectEquals(new ObjectDict + { + { "AssumeRolePolicyDocument", new ObjectDict + { + { "Version", "2012-10-17" }, + { "Action", "sts:AssumeRole" }, + { "Principal", new ObjectDict + { + { "Version", "2012-10-17" }, + { "Statement", new object[] + { + new ObjectDict { + { "Action", "sts:AssumeRole" }, + { "Effect", "Allow" }, + { "Principal", new ObjectDict + { + { "Service", new ObjectDict + { + { "", new object[] + { "states", Match.AnyValue(), ".amazonaws.com" } + } + } + } + } + } + } + } + } + } + } + } + } + })); +``` + +------ + +Many CloudFormation resources include serialized JSON objects represented as strings\. The `Match.serializedJson()` matcher can be used to match properties inside this JSON\. For example, Step Functions state machines are defined using a string in the JSON\-based [Amazon States Language](https://docs.aws.amazon.com/step-functions/latest/dg/concepts-amazon-states-language.html)\. We'll use `Match.serializedJson()` to make sure our initial state is the only step, again using nested matchers to apply different kinds of matching to different parts of the object\. + +------ +#### [ TypeScript ] + +``` + // Assert on the state machine's definition with the Match.serializedJson() + // matcher. + template.hasResourceProperties("AWS::StepFunctions::StateMachine", { + DefinitionString: Match.serializedJson( + // Match.objectEquals() is used implicitly, but we use it explicitly + // here for extra clarity. + Match.objectEquals({ + StartAt: "StartState", + States: { + StartState: { + Type: "Pass", + End: true, + // Make sure this state doesn't provide a next state -- we can't + // provide both Next and set End to true. + Next: Match.absent(), + }, + }, + }) + ), + }); +``` + +------ +#### [ JavaScript ] + +``` + // Assert on the state machine's definition with the Match.serializedJson() + // matcher. + template.hasResourceProperties("AWS::StepFunctions::StateMachine", { + DefinitionString: Match.serializedJson( + // Match.objectEquals() is used implicitly, but we use it explicitly + // here for extra clarity. + Match.objectEquals({ + StartAt: "StartState", + States: { + StartState: { + Type: "Pass", + End: true, + // Make sure this state doesn't provide a next state -- we can't + // provide both Next and set End to true. + Next: Match.absent(), + }, + }, + }) + ), + }); +``` + +------ +#### [ Python ] + +``` + # Assert on the state machine's definition with the serialized_json matcher. + template.has_resource_properties( + "AWS::StepFunctions::StateMachine", + { + "DefinitionString": Match.serialized_json( + # Match.object_equals() is the default, but specify it here for clarity + Match.object_equals( + { + "StartAt": "StartState", + "States": { + "StartState": { + "Type": "Pass", + "End": True, + # Make sure this state doesn't provide a next state -- + # we can't provide both Next and set End to true. + "Next": Match.absent(), + }, + }, + } + ) + ), + }, + ) +``` + +------ +#### [ Java ] + +``` + // Assert on the state machine's definition with the Match.serializedJson() matcher. + template.hasResourceProperties("AWS::StepFunctions::StateMachine", Collections.singletonMap( + "DefinitionString", Match.serializedJson( + // Match.objectEquals() is used implicitly, but we use it explicitly here for extra clarity. + Match.objectEquals(Map.of( + "StartAt", "StartState", + "States", Collections.singletonMap( + "StartState", Map.of( + "Type", "Pass", + "End", true, + // Make sure this state doesn't provide a next state -- we can't provide + // both Next and set End to true. + "Next", Match.absent() + ) + ) + )) + ) + )); +``` + +------ +#### [ C\# ] + +``` + // Assert on the state machine's definition with the Match.serializedJson() matcher + template.HasResourceProperties("AWS::StepFunctions::StateMachine", new ObjectDict + { + { "DefinitionString", Match.SerializedJson( + // Match.objectEquals() is used implicitly, but we use it explicitly here for extra clarity. + Match.ObjectEquals(new ObjectDict { + { "StartAt", "StartState" }, + { "States", new ObjectDict + { + { "StartState", new ObjectDict { + { "Type", "Pass" }, + { "End", "True" }, + // Make sure this state doesn't provide a next state -- we can't provide + // both Next and set End to true. + { "Next", Match.Absent() } + }} + }} + }) + )}}); +``` + +------ + +### Capturing<a name="testing_fine_grained_capture"></a> + +It's often useful to test properties to make sure they follow specific formats, or have the same value as another property, without needing to know their exact values ahead of time\. The `assertions` module provides this capability in its [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_assertions.Capture.html](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_assertions.Capture.html) class\. + +By specifying a `Capture` instance in place of a value in `hasResourceProperties`, that value is retained in the `Capture` object\. The actual captured value can be retrieved using the object's `as` methods, including `asNumber()`, `asString()`, and `asObject`, and subjected to test\. Use `Capture` with a matcher to specify the exact location of the value to be captured within the resource's properties, including serialized JSON properties\. + +For example, this example tests to make sure that the starting state of our state machine has a name beginning with `Start` and also that this state is actually present within the list of states in the machine\. + +------ +#### [ TypeScript ] + +``` + // Capture some data from the state machine's definition. + const startAtCapture = new Capture(); + const statesCapture = new Capture(); + template.hasResourceProperties("AWS::StepFunctions::StateMachine", { + DefinitionString: Match.serializedJson( + Match.objectLike({ + StartAt: startAtCapture, + States: statesCapture, + }) + ), + }); + + // Assert that the start state starts with "Start". + expect(startAtCapture.asString()).toEqual(expect.stringMatching(/^Start/)); + + // Assert that the start state actually exists in the states object of the + // state machine definition. + expect(statesCapture.asObject()).toHaveProperty(startAtCapture.asString()); +``` + +------ +#### [ JavaScript ] + +``` + // Capture some data from the state machine's definition. + const startAtCapture = new Capture(); + const statesCapture = new Capture(); + template.hasResourceProperties("AWS::StepFunctions::StateMachine", { + DefinitionString: Match.serializedJson( + Match.objectLike({ + StartAt: startAtCapture, + States: statesCapture, + }) + ), + }); + + // Assert that the start state starts with "Start". + expect(startAtCapture.asString()).toEqual(expect.stringMatching(/^Start/)); + + // Assert that the start state actually exists in the states object of the + // state machine definition. + expect(statesCapture.asObject()).toHaveProperty(startAtCapture.asString()); +``` + +------ +#### [ Python ] + +``` +import re + + from aws_cdk.assertions import Capture + + # ... + + # Capture some data from the state machine's definition. + start_at_capture = Capture() + states_capture = Capture() + template.has_resource_properties( + "AWS::StepFunctions::StateMachine", + { + "DefinitionString": Match.serialized_json( + Match.object_like( + { + "StartAt": start_at_capture, + "States": states_capture, + } + ) + ), + }, + ) + + # Assert that the start state starts with "Start". + assert re.match("^Start", start_at_capture.as_string()) + + # Assert that the start state actually exists in the states object of the + # state machine definition. + assert start_at_capture.as_string() in states_capture.as_object() +``` + +------ +#### [ Java ] + +``` + // Capture some data from the state machine's definition. + final Capture startAtCapture = new Capture(); + final Capture statesCapture = new Capture(); + template.hasResourceProperties("AWS::StepFunctions::StateMachine", Collections.singletonMap( + "DefinitionString", Match.serializedJson( + Match.objectLike(Map.of( + "StartAt", startAtCapture, + "States", statesCapture + )) + ) + )); + + // Assert that the start state starts with "Start". + assertThat(startAtCapture.asString()).matches("^Start.+"); + + // Assert that the start state actually exists in the states object of the state machine definition. + assertThat(statesCapture.asObject()).containsKey(startAtCapture.asString()); +``` + +------ +#### [ C\# ] + +``` + // Capture some data from the state machine's definition. + var startAtCapture = new Capture(); + var statesCapture = new Capture(); + template.HasResourceProperties("AWS::StepFunctions::StateMachine", new ObjectDict + { + { "DefinitionString", Match.SerializedJson( + new ObjectDict + { + { "StartAt", startAtCapture }, + { "States", statesCapture } + } + )} + }); + + Assert.IsTrue(startAtCapture.ToString().StartsWith("Start")); + Assert.IsTrue(statesCapture.AsObject().ContainsKey(startAtCapture.ToString())); +``` + +------ + +## Snapshot tests<a name="testing_snapshot"></a> + +In *snapshot testing*, you compare the entire synthesized CloudFormation template against a previously\-stored master\. This isn't useful in catching regressions, as fine\-grained assertions are, because it applies to the entire template, and things besides code changes can cause small \(or not\-so\-small\) differences in synthesis results\. For example, we may update a CDK construct to incorporate a new best practice, which can cause changes to the synthesized resources or how they're organized, or we might update the CDK Toolkit to report additional metadata\. Changes to context values can also affect the synthesized template\. + +Snapshot tests can be of great help in refactoring, though, as long as you hold constant all other factors that might affect the synthesized template\. You will know immediately if a change you made has unintentionally changed the template\. If the change is intentional, simply accept a new master and proceed\. + +For example, if we have this `DeadLetterQueue` construct: + +------ +#### [ TypeScript ] + +``` +import * as cloudwatch from '@aws-cdk/aws-cloudwatch'; +import * as sqs from '@aws-cdk/aws-sqs'; +import { Construct, Duration } from '@aws-cdk/core'; + +export class DeadLetterQueue extends sqs.Queue { + public readonly messagesInQueueAlarm: cloudwatch.IAlarm; + + constructor(scope: Construct, id: string) { + super(scope, id); + + // Add the alarm + this.messagesInQueueAlarm = new cloudwatch.Alarm(this, 'Alarm', { + alarmDescription: 'There are messages in the Dead Letter Queue', + evaluationPeriods: 1, + threshold: 1, + metric: this.metricApproximateNumberOfMessagesVisible(), + }); + } +} +``` + +------ +#### [ JavaScript ] + +``` +const cloudwatch = require('@aws-cdk/aws-cloudwatch'); +const sqs = require('@aws-cdk/aws-sqs'); +const { Construct, Duration } = require('@aws-cdk/core'); + +class DeadLetterQueue extends sqs.Queue { + + constructor(scope, id) { + super(scope, id); + + // Add the alarm + this.messagesInQueueAlarm = new cloudwatch.Alarm(this, 'Alarm', { + alarmDescription: 'There are messages in the Dead Letter Queue', + evaluationPeriods: 1, + threshold: 1, + metric: this.metricApproximateNumberOfMessagesVisible(), + }); + } +} + +module.exports = { DeadLetterQueue } +``` + +------ +#### [ Python ] + +``` +class DeadLetterQueue(sqs.Queue): + def __init__(self, scope: cdk.Construct, id: str): + super().__init__(scope, id) + + self.messages_in_queue_alarm = cloudwatch.Alarm( + self, + "Alarm", + alarm_description="There are messages in the Dead Letter Queue.", + evaluation_periods=1, + threshold=1, + metric=self.metric_approximate_number_of_messages_visible(), + ) +``` + +------ +#### [ Java ] + +``` +package software.amazon.samples.awscdkassertionssamples; + +import org.jetbrains.annotations.NotNull; +import software.amazon.awscdk.services.cloudwatch.Alarm; +import software.amazon.awscdk.services.cloudwatch.IAlarm; +import software.amazon.awscdk.services.sqs.Queue; +import software.constructs.Construct; + +public class DeadLetterQueue extends Queue { + private final IAlarm messagesInQueueAlarm; + + public DeadLetterQueue(@NotNull Construct scope, @NotNull String id) { + super(scope, id); + + this.messagesInQueueAlarm = Alarm.Builder.create(this, "Alarm") + .alarmDescription("There are messages in the Dead Letter Queue.") + .evaluationPeriods(1) + .threshold(1) + .metric(this.metricApproximateNumberOfMessagesVisible()) + .build(); + } + + public IAlarm getMessagesInQueueAlarm() { + return messagesInQueueAlarm; + } +} +``` + +------ +#### [ C\# ] + +``` +using Amazon.CDK; +using Amazon.CDK.AWS.SQS; +using Amazon.CDK.AWS.CloudWatch; + +namespace AwsCdkAssertionSamples +{ + public class DeadLetterQueue : Queue + { + public IAlarm messagesInQueueAlarm; + + public DeadLetterQueue(Construct scope, string id) : base(scope, id) + { + messagesInQueueAlarm = new Alarm(this, "Alarm", new AlarmProps + { + AlarmDescription = "There are messages in the Dead Letter Queue.", + EvaluationPeriods = 1, + Threshold = 1, + Metric = this.MetricApproximateNumberOfMessagesVisible() + }); + } + } +} +``` + +------ + +We can test it like this: + +------ +#### [ TypeScript ] + +``` +import { Match, Template } from "@aws-cdk/assertions"; +import * as cdk from "@aws-cdk/core"; +import { DeadLetterQueue } from "../lib/dead-letter-queue"; + +describe("DeadLetterQueue", () => { + test("matches the snapshot", () => { + const stack = new cdk.Stack(); + new DeadLetterQueue(stack, "DeadLetterQueue"); + + const template = Template.fromStack(stack); + expect(template.toJSON()).toMatchSnapshot(); + }); +}); +``` + +------ +#### [ JavaScript ] + +``` +const { Match, Template } = require("@aws-cdk/assertions"); +const cdk = require("@aws-cdk/core"); +const { DeadLetterQueue } = require("../lib/dead-letter-queue"); + +describe("DeadLetterQueue", () => { + test("matches the snapshot", () => { + const stack = new cdk.Stack(); + new DeadLetterQueue(stack, "DeadLetterQueue"); + + const template = Template.fromStack(stack); + expect(template.toJSON()).toMatchSnapshot(); + }); +}); +``` + +------ +#### [ Python ] + +``` +from aws_cdk import core as cdk +from aws_cdk.assertions import Match, Template + +from app.dead_letter_queue import DeadLetterQueue + +def snapshot_test(): + stack = cdk.Stack() + DeadLetterQueue(stack, "DeadLetterQueue") + + template = Template.from_stack(stack) + assert template.to_json() == snapshot +``` + +------ +#### [ Java ] + +``` +package software.amazon.samples.awscdkassertionssamples; + +import org.junit.jupiter.api.Test; +import au.com.origin.snapshots.Expect; +import software.amazon.awscdk.assertions.Match; +import software.amazon.awscdk.assertions.Template; +import software.amazon.awscdk.core.Stack; + +import java.util.Collections; +import java.util.Map; + +public class DeadLetterQueueTest { + @Test + public void snapshotTest() { + final Stack stack = new Stack(); + new DeadLetterQueue(stack, "DeadLetterQueue"); + + final Template template = Template.fromStack(stack); + expect.toMatchSnapshot(template.toJSON()); + } +} +``` + +------ +#### [ C\# ] + +``` +using Microsoft.VisualStudio.TestTools.UnitTesting; + +using Amazon.CDK; +using Amazon.CDK.Assertions; +using AwsCdkAssertionSamples; + +using ObjectDict = System.Collections.Generic.Dictionary<string, object>; +using StringDict = System.Collections.Generic.Dictionary<string, string>; + +namespace TestProject1 +{ + [TestClass] + public class ProcessorStackTest + + [TestClass] + public class DeadLetterQueueTest + { + [TestMethod] + public void SnapshotTest() + { + var stack = new Stack(); + new DeadLetterQueue(stack, "DeadLetterQueue"); + + var template = Template.FromStack(stack); + + return Verifier.Verify(template.ToJSON()); + } + } +} +``` + +------ + +## Tips for tests<a name="testing_tips"></a> + +Remember, your tests will live just as long as the code they test, and be read and modified just as often, so it pays to take a moment to consider how best to write them\. Don't copy and paste setup lines or common assertions, for example; refactor this logic into fixtures or helper functions\. Use good names that reflect what each test actually tests\. + +Don't try to do too much in one test\. Preferably, a test should test one and only one behavior\. If you accidentally break that behavior, exactly one test should fail, and the name of the test should tell you exactly what failed\. This is more an ideal to be striven for, however; sometimes you will unavoidably \(or inadvertently\) write tests that test more than one behavior\. Snapshot tests are, for reasons we've already described, especially prone to this problem, so use them sparingly\. \ No newline at end of file diff --git a/v1/tokens.md b/v1/tokens.md new file mode 100644 index 00000000..419c2205 --- /dev/null +++ b/v1/tokens.md @@ -0,0 +1,426 @@ +# Tokens<a name="tokens"></a> + +Tokens represent values that can only be resolved at a later time in the lifecycle of an app \(see [App lifecycle](apps.md#lifecycle)\)\. For example, the name of an Amazon S3 bucket that you define in your AWS CDK app is only allocated when the AWS CloudFormation template is synthesized\. If you print the `bucket.bucketName` attribute, which is a string, you see it contains something like the following\. + +``` +${TOKEN[Bucket.Name.1234]} +``` + +This is how the AWS CDK encodes a token whose value is not yet known at construction time, but will become available later\. The AWS CDK calls these placeholders *tokens*\. In this case, it's a token encoded as a string\. + +You can pass this string around as if it was the name of the bucket, such as in the following example, where the bucket name is specified as an environment variable to an AWS Lambda function\. + +------ +#### [ TypeScript ] + +``` +const bucket = new s3.Bucket(this, 'MyBucket'); + +const fn = new lambda.Function(stack, 'MyLambda', { + // ... + environment: { + BUCKET_NAME: bucket.bucketName, + } +}); +``` + +------ +#### [ JavaScript ] + +``` +const bucket = new s3.Bucket(this, 'MyBucket'); + +const fn = new lambda.Function(stack, 'MyLambda', { + // ... + environment: { + BUCKET_NAME: bucket.bucketName + } +}); +``` + +------ +#### [ Python ] + +``` +bucket = s3.Bucket(self, "MyBucket") + +fn = lambda_.Function(stack, "MyLambda", + environment=dict(BUCKET_NAME=bucket.bucket_name)) +``` + +------ +#### [ Java ] + +``` +final Bucket bucket = new Bucket(this, "MyBucket"); + +Function fn = Function.Builder.create(this, "MyLambda") + .environment(java.util.Map.of( // Map.of requires Java 9+ + "BUCKET_NAME", bucket.getBucketName())) + .build(); +``` + +------ +#### [ C\# ] + +``` +var bucket = new s3.Bucket(this, "MyBucket"); + +var fn = new Function(this, "MyLambda", new FunctionProps { + Environment = new Dictionary<string, string> + { + ["BUCKET_NAME"] = bucket.BucketName + } +}); +``` + +------ + +When the AWS CloudFormation template is finally synthesized, the token is rendered as the AWS CloudFormation intrinsic `{ "Ref": "MyBucket" }`\. At deployment time, AWS CloudFormation replaces this intrinsic with the actual name of the bucket that was created\. + +## Tokens and token encodings<a name="tokens_encoding"></a> + +Tokens are objects that implement the [IResolvable](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.IResolvable.html) interface, which contains a single `resolve` method\. The AWS CDK calls this method during synthesis to produce the final value for the AWS CloudFormation template\. Tokens participate in the synthesis process to produce arbitrary values of any type\. + +**Note** +You'll hardly ever work directly with the `IResolvable` interface\. You will most likely only see string\-encoded versions of tokens\. + +Other functions typically only accept arguments of basic types, such as `string` or `number`\. To use tokens in these cases, you can encode them into one of three types using static methods on the [core\.Token](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.Token.html) class\. ++ [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.Token.html#static-as-stringvalue-options](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.Token.html#static-as-stringvalue-options) to generate a string encoding \(or call `.toString()` on the token object\) ++ [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.Token.html#static-as-listvalue-options](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.Token.html#static-as-listvalue-options) to generate a list encoding ++ [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.Token.html#static-as-numbervalue](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.Token.html#static-as-numbervalue) to generate a numeric encoding + +These take an arbitrary value, which can be an `IResolvable`, and encode them into a primitive value of the indicated type\. + +**Important** +Because any one of the previous types can potentially be an encoded token, be careful when you parse or try to read their contents\. For example, if you attempt to parse a string to extract a value from it, and the string is an encoded token, your parsing will fail\. Similarly, if you attempt to query the length of an array, or perform math operations with a number, you must first verify that they are not encoded tokens\. + +To check whether a value has an unresolved token in it, call the `Token.isUnresolved` \(Python: `is_unresolved`\) method\. + +The following example validates that a string value, which could be a token, is no more than 10 characters long\. + +------ +#### [ TypeScript ] + +``` +if (!Token.isUnresolved(name) && name.length > 10) { + throw new Error(`Maximum length for name is 10 characters`); +} +``` + +------ +#### [ JavaScript ] + +``` +if ( !Token.isUnresolved(name) && name.length > 10) { + throw ( new Error(`Maximum length for name is 10 characters`)); +} +``` + +------ +#### [ Python ] + +``` +if not Token.is_unresolved(name) and len(name) > 10: + raise ValueError("Maximum length for name is 10 characters") +``` + +------ +#### [ Java ] + +``` +if (!Token.isUnresolved(name) && name.length() > 10) + throw new IllegalArgumentException("Maximum length for name is 10 characters"); +``` + +------ +#### [ C\# ] + +``` +if (!Token.IsUnresolved(name) && name.Length > 10) + throw new ArgumentException("Maximum length for name is 10 characters"); +``` + +------ + +If **name** is a token, validation isn't performed, and an error could still occur in a later stage in the lifecycle, such as during deployment\. + +**Note** +You can use token encodings to escape the type system\. For example, you could string\-encode a token that produces a number value at synthesis time\. If you use these functions, it's your responsibility to ensure that your template resolves to a usable state after synthesis\. + +## String\-encoded tokens<a name="tokens_string"></a> + +String\-encoded tokens look like the following\. + +``` +${TOKEN[Bucket.Name.1234]} +``` + +They can be passed around like regular strings, and can be concatenated, as shown in the following example\. + +------ +#### [ TypeScript ] + +``` +const functionName = bucket.bucketName + 'Function'; +``` + +------ +#### [ JavaScript ] + +``` +const functionName = bucket.bucketName + 'Function'; +``` + +------ +#### [ Python ] + +``` +function_name = bucket.bucket_name + "Function" +``` + +------ +#### [ Java ] + +``` +String functionName = bucket.getBucketName().concat("Function"); +``` + +------ +#### [ C\# ] + +``` +string functionName = bucket.BucketName + "Function"; +``` + +------ + +You can also use string interpolation, if your language supports it, as shown in the following example\. + +------ +#### [ TypeScript ] + +``` +const functionName = `${bucket.bucketName}Function`; +``` + +------ +#### [ JavaScript ] + +``` +const functionName = `${bucket.bucketName}Function`; +``` + +------ +#### [ Python ] + +``` +function_name = f"{bucket.bucket_name}Function" +``` + +------ +#### [ Java ] + +``` +String functionName = String.format("%sFunction". bucket.getBucketName()); +``` + +------ +#### [ C\# ] + +``` +string functionName = $"${bucket.bucketName}Function"; +``` + +------ + +Avoid manipulating the string in other ways\. For example, taking a substring of a string is likely to break the string token\. + +## List\-encoded tokens<a name="tokens_list"></a> + +List\-encoded tokens look like the following + +``` +["#{TOKEN[Stack.NotificationArns.1234]}"] +``` + +The only safe thing to do with these lists is pass them directly to other constructs\. Tokens in string list form cannot be concatenated, nor can an element be taken from the token\. The only safe way to manipulate them is by using AWS CloudFormation intrinsic functions like [Fn\.select](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-select.html)\. + +## Number\-encoded tokens<a name="tokens_number"></a> + +Number\-encoded tokens are a set of tiny negative floating\-point numbers that look like the following\. + +``` +-1.8881545897087626e+289 +``` + +As with list tokens, you cannot modify the number value, as doing so is likely to break the number token\. The only allowed operation is to pass the value around to another construct\. + +## Lazy values<a name="tokens_lazy"></a> + +In addition to representing deploy\-time values, such as AWS CloudFormation [parameters](parameters.md), Tokens are also commonly used to represent synthesis\-time lazy values\. These are values for which the final value will be determined before synthesis has completed, just not at the point where the value is constructed\. Use tokens to pass a literal string or number value to another construct, while the actual value at synthesis time may depend on some calculation that has yet to occur\. + +You can construct tokens representing synth\-time lazy values using static methods on the `Lazy` class, such as [Lazy\.string](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.Lazy.html#static-stringproducer-options) and [Lazy\.number](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.Lazy.html#static-numberproducer)\. These methods accept an object whose `produce` property is a function that accepts a context argument and returns the final value when called\. + +The following example creates an Auto Scaling group whose capacity is determined after its creation\. + +------ +#### [ TypeScript ] + +``` +let actualValue: number; + +new AutoScalingGroup(this, 'Group', { + desiredCapacity: Lazy.numberValue({ + produce(context) { + return actualValue; + } + }) +}); + +// At some later point +actualValue = 10; +``` + +------ +#### [ JavaScript ] + +``` +let actualValue; + +new AutoScalingGroup(this, 'Group', { + desiredCapacity: Lazy.numberValue({ + produce(context) { + return (actualValue); + } + }) +}); + +// At some later point +actualValue = 10; +``` + +------ +#### [ Python ] + +``` +class Producer: + def __init__(self, func): + self.produce = func + +actual_value = None + +AutoScalingGroup(self, "Group", + desired_capacity=Lazy.number_value(Producer(lambda context: actual_value)) +) + +# At some later point +actual_value = 10 +``` + +------ +#### [ Java ] + +``` +double actualValue = 0; + +class ProduceActualValue implements INumberProducer { + + @Override + public Number produce(IResolveContext context) { + return actualValue; + } +} + +AutoScalingGroup.Builder.create(this, "Group") + .desiredCapacity(Lazy.numberValue(new ProduceActualValue())).build(); + +// At some later point +actualValue = 10; +``` + +------ +#### [ C\# ] + +``` +public class NumberProducer : INumberProducer +{ + Func<Double> function; + + public NumberProducer(Func<Double> function) + { + this.function = function; + } + + public Double Produce(IResolveContext context) + { + return function(); + } +} + +double actualValue = 0; + +new AutoScalingGroup(this, "Group", new AutoScalingGroupProps +{ + DesiredCapacity = Lazy.NumberValue(new NumberProducer(() => actualValue)) +}); + +// At some later point +actualValue = 10; +``` + +------ + +## Converting to JSON<a name="tokens_json"></a> + +Sometimes you want to produce a JSON string of arbitrary data, and you may not know whether the data contains tokens\. To properly JSON\-encode any data structure, regardless of whether it contains tokens, use the method [stack\.toJsonString](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.Stack.html#to-json-stringobj-space), as shown in the following example\. + +------ +#### [ TypeScript ] + +``` +const stack = Stack.of(this); +const str = stack.toJsonString({ + value: bucket.bucketName +}); +``` + +------ +#### [ JavaScript ] + +``` +const stack = Stack.of(this); +const str = stack.toJsonString({ + value: bucket.bucketName +}); +``` + +------ +#### [ Python ] + +``` +stack = Stack.of(self) +string = stack.to_json_string(dict(value=bucket.bucket_name)) +``` + +------ +#### [ Java ] + +``` +Stack stack = Stack.of(this); +String stringVal = stack.toJsonString(java.util.Map.of( // Map.of requires Java 9+ + "value", bucket.getBucketName())); +``` + +------ +#### [ C\# ] + +``` +var stack = Stack.Of(this); +var stringVal = stack.ToJsonString(new Dictionary<string, string> +{ + ["value"] = bucket.BucketName +}); +``` + +------ \ No newline at end of file diff --git a/v1/tools.md b/v1/tools.md new file mode 100644 index 00000000..4eef2d2e --- /dev/null +++ b/v1/tools.md @@ -0,0 +1,8 @@ +# AWS CDK tools<a name="tools"></a> + +This section contains information about the AWS CDK tools listed below\. + +**Topics** ++ [AWS CDK Toolkit \(`cdk` command\)](cli.md) ++ [AWS Toolkit for Visual Studio Code](vscode.md) ++ [AWS SAM integration](sam.md) \ No newline at end of file diff --git a/v1/troubleshooting.md b/v1/troubleshooting.md new file mode 100644 index 00000000..7e22f89e --- /dev/null +++ b/v1/troubleshooting.md @@ -0,0 +1,355 @@ +# Troubleshooting common AWS CDK issues<a name="troubleshooting"></a><a name="troubleshooting_top"></a> + +This topic describes how to troubleshoot the following issues with the AWS CDK\. ++ [After updating the AWS CDK, code that used to work fine now results in errors](#troubleshooting_modules) ++ [After updating the AWS CDK, the AWS CDK Toolkit \(CLI\) reports a mismatch with the AWS Construct Library](#troubleshooting_toolkit) ++ [When deploying my AWS CDK stack, I receive a `NoSuchBucket` error](#troubleshooting_nobucket) ++ [When deploying my AWS CDK stack, I receive a `forbidden: null` message](#troubleshooting_forbidden_null) ++ [When synthesizing an AWS CDK stack, I get the message `--app is required either in command-line, in cdk.json or in ~/.cdk.json`](#troubleshooting_app_required) ++ [When synthesizing an AWS CDK stack, I receive an error because the AWS CloudFormation template contains too many resources](#troubleshooting_resource_count) ++ [I specified three \(or more\) Availability Zones for my EC2 Auto\-Scaling Group or Virtual Private Cloud, but it was only deployed in two](#troubleshooting_availability_zones) ++ [My S3 bucket, DynamoDB table, or other resource is not deleted when I issue `cdk destroy`](#troubleshooting_resource_not_deleted)<a name="troubleshooting_modules"></a> + +**After updating the AWS CDK, code that used to work fine now results in errors** +Errors in code that used to work is typically a symptom of having mismatched versions of AWS Construct Library modules\. Make sure all library modules are the same version and up\-to\-date\. + +An error message commonly seen in this situation is `unable to determine cloud assembly output directory. Assets must be defined indirectly within a "Stage" or an "App" scope`\. + +The modules that make up the AWS Construct Library are a matched set\. They are released together and are intended to be used together\. Interfaces between modules are considered private; we may change them when necessary to implement new features in the library\. + +We also update the libraries that are used by the AWS Construct Library from time to time, and different versions of the library modules may have incompatible dependencies\. Synchronizing the versions of the library modules will also address this issue\. + +[JSII](https://github.com/aws/jsii) is an important AWS CDK dependency, especially if you are using the AWS CDK in a language other than TypeScript or JavaScript\. You do not ordinarily have to concern yourself with the JSII versions, since it is a declared dependency of all AWS CDK modules\. If a compatible version is not installed, however, you can see unexpected type\-related errors, such as `'undefined' is not a valid TargetType`\. Making sure all AWS CDK modules are the same version will resolve JSII compatibility issues, since they will all depend on the same JSII version\. + +Below, you'll find details on managing the versions of your installed AWS Construct Library modules in TypeScript, JavaScript, Python, Java, and C\#\. + +------ +#### [ TypeScript/JavaScript ] + +Install your project's AWS Construct Library modules locally \(the default\)\. Use `npm` to install the modules and keep them up to date\. + +To see what needs to be updated: + +``` +npm outdated +``` + +To actually update the modules to the latest version: + +``` +npm update +``` + +If you are working with a specific older version of the AWS Construct Library, rather than the latest, first uninstall all of your project's `@aws-cdk` modules, then reinstall the specific version you want to use\. For example, to install version 1\.9\.0 of the Amazon S3 module, use: + +``` +npm uninstall @aws-cdk/aws-s3 +npm install @aws-cdk/aws-s3@1.9.0 +``` + +Repeat these commands for each module your project uses\. + +You can edit your `package.json` file to lock the AWS Construct Library modules to a specific version, so `npm update` won't update them\. You can also specify a version using `~` or `^` to allow modules to be updated to versions that are API\-compatible with the current version, such as `^1.0.0` to accept any update API\-compatible with version 1\.x\. Use the same version specification for all AWS Construct Library modules within a project, including these special characters\. Otherwise, Node\.js may not resolve all these specifications to the same concrete version, resulting in a mismatch\. + +------ +#### [ Python ] + +Use a virtual environment to manage your project's AWS Construct Library modules\. For your convenience, `cdk init` creates a virtual environment for new Python projects in the project's `.venv` directory\. + +Add the AWS Construct Library modules your project uses to its `requirements.txt` file\. Use the `=` syntax to specify an exact version, or the `~=` syntax to constrain updates to versions without breaking API changes\. For example, the following specifies the latest version of the listed modules that are API\-compatible with version 1\.x: + +``` +aws-cdk.core~=1.0 +aws-cdk.aws-s3~=1.0 +``` + +If you wanted to accept only bug\-fix updates to, for example, version 1\.9\.0, you could instead specify `~=1.9.0`\. Use the same version specification for all AWS Construct Library modules within a single project\. + +Use `pip` to install and update the modules\. + +To see what needs to be updated: + +``` +pip list --local --outdated +``` + +To actually update the modules to the latest compatible version: + +``` +pip install --upgrade -r requirements.txt +``` + +If your project requires a specific older version of the AWS Construct Library, rather than the latest, first uninstall all of your project's `aws-cdk` modules\. Edit `requirements.txt` to specify the exact versions of the modules you want to use using `=`, then install from `requirements.txt`\. + +``` +pip install -r requirements.txt +``` + +------ +#### [ Java ] + +Add your project's AWS Construct Library modules as dependencies in your project's `pom.xml`\. You may specify an exact version, or use Maven's [range syntax](https://docs.oracle.com/middleware/1212/core/MAVEN/maven_version.htm#MAVEN402) to specify a range of allowable versions\. + +For example, to specify an exact version of a dependency: + +``` +<dependency> + <groupId>software.amazon.awscdk</groupId> + <artifactId>s3</artifactId> + <version>1.23.0</version> +</dependency> +``` + +To specify that any 1\.x\.x version is acceptable \(note use of right parenthesis to indicate that the end of the range excludes version 2\.0\.0\): + +``` +<dependency> + <groupId>software.amazon.awscdk</groupId> + <artifactId>s3</artifactId> + <version>[1.0.0,2.0.0)</version> +</dependency> +``` + +Maven automatically downloads and installs the latest versions that allow all requirements to be fulfilled when you build your application\. + +If you prefer to pin dependencies to a specific version, you can issue `mvn versions:use-latest-versions` to rewrite the version specifications in `pom.xml` to the latest available versions when you decide to upgrade\. + +------ +#### [ C\# ] + +Use the Visual Studio NuGet GUI \(**Tools** > **NuGet Package Manager** > **Manage NuGet Packages for Solution**\) to install the desired version of your application's AWS Construct Library modules\. ++ The **Installed** panel shows you what modules are currently installed; you can install any available version of any module from this page\. ++ The **Updates** panel shows you modules for which updates are available, and lets you update some or all of them\. + +------ + +\([back to list](#troubleshooting_top)\)<a name="troubleshooting_toolkit"></a> + +**After updating the AWS CDK, the AWS CDK Toolkit \(CLI\) reports a mismatch with the AWS Construct Library** +The version of the AWS CDK Toolkit \(which provides the `cdk` command\) must be at least equal to the version of the AWS Construct Library\. The Toolkit is intended to be backward compatible within the same major version; the latest 1\.x version of the toolkit can be used with any 1\.x release of the library\. For this reason, we recommend you install this component globally and keep it up\-to\-date\. + +``` +npm update -g aws-cdk +``` + +If, for some reason, you need to work with multiple versions of the AWS CDK Toolkit, you can install a specific version of the toolkit locally in your project folder\. + +If you are using a language other than TypeScript or JavaScript, first create a `node_modules` folder in your project directory\. Then, regardless of language, use `npm` to install the AWS CDK Toolkit, omitting the `-g` flag and specifying the desired version\. For example: + +``` +npm install aws-cdk@1.50.0 +``` + +To run a locally\-installed AWS CDK Toolkit, use the command `npx aws-cdk` rather than just `cdk`\. For example: + +``` +npx aws-cdk deploy MyStack +``` + +`npx aws-cdk` runs the local version of the AWS CDK Toolkit if one exists, and falls back to the global version when a project doesn't have a local installation\. You may find it convenient to set up a shell alias or batch file to make sure `cdk` is always invoked this way\. For example, Linux users might add the following statement to their `.bash_profile` file\. + +``` +alias cdk="npx aws-cdk" +``` + +\([back to list](#troubleshooting_top)\)<a name="troubleshooting_nobucket"></a> + +**When deploying my AWS CDK stack, I receive a `NoSuchBucket` error** +Your AWS environment does not have a staging bucket, which the AWS CDK uses to hold resources during deployment\. Stacks require this bucket if they contain [Assets](assets.md) or synthesize to AWS CloudFormation templates larger than 50 kilobytes\. You can create the staging bucket with the following command: + +``` +cdk bootstrap aws://ACCOUNT-NUMBER/REGION +``` + +To avoid generating unexpected AWS charges, the AWS CDK does not automatically create a staging bucket\. You must bootstrap your environment explicitly\. + +By default, the staging bucket is created in the region\(s\) used by stacks in the current AWS CDK application, or the region specified in your local AWS profile \(set by `aws configure`\), using that profile's account\. You can specify a different account and region on the command line as follows\. \(You must specify the account and region if you are not in an app's directory\.\) + +``` +cdk bootstrap aws://ACCOUNT-NUMBER/REGION +``` + +You must bootstrap in every region where you will deploy stacks that require a staging bucket\. + +For more information, see [Bootstrapping](bootstrapping.md) + +\([back to list](#troubleshooting_top)\)<a name="troubleshooting_forbidden_null"></a> + +**When deploying my AWS CDK stack, I receive a `forbidden: null` message** +You are deploying a stack that requires the use of a staging bucket, but are using an IAM role or account that lacks permission to write to it\. \(The staging bucket is used when deploying stacks that contain assets or that synthesize an AWS CloudFormation template larger than 50K\.\) Use an account or role that has permission to perform the action `s3:*` against the resource `arn:aws:s3:::cdktoolkit-stagingbucket-*`\. + +\([back to list](#troubleshooting_top)\)<a name="troubleshooting_app_required"></a> + +**When synthesizing an AWS CDK stack, I get the message `--app is required either in command-line, in cdk.json or in ~/.cdk.json`** + This message usually means that you aren't in the main directory of your AWS CDK project when you issue `cdk synth`\. The file `cdk.json` in this directory, created by the `cdk init` command, contains the command line needed to run \(and thereby synthesize\) your AWS CDK app\. For a TypeScript app, for example, the default `cdk.json` looks something like this: + +``` +{ + "app": "npx ts-node bin/my-cdk-app.ts" +} +``` + + We recommend issuing `cdk` commands only in your project's main directory, so the AWS CDK toolkit can find `cdk.json` there and successfully run your app\. + + If this isn't practical for some reason, the AWS CDK Toolkit looks for the app's command line in two other locations: ++ in `cdk.json` in your home directory ++ on the `cdk synth` command itself using the `-a` option + +For example, you might synthesize a stack from a TypeScript app as follows\. + +``` +cdk synth --app "npx ts-node my-cdk-app.ts" MyStack +``` + +\([back to list](#troubleshooting_top)\)<a name="troubleshooting_resource_count"></a> + +**When synthesizing an AWS CDK stack, I receive an error because the AWS CloudFormation template contains too many resources** +The AWS CDK generates and deploys AWS CloudFormation templates\. AWS CloudFormation has a hard limit on the number of resources a stack can contain\. With the AWS CDK, you can run up against this limit more quickly than you might expect\. + +**Note** +The AWS CloudFormation resource limit is 500 at this writing\. See [AWS CloudFormation quotas](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cloudformation-limits.html) for the current resource limit\. + +The AWS Construct Library's higher\-level, intent\-based constructs automatically provision any auxiliary resources that are needed for logging, key management, authorization, and other purposes\. For example, granting one resource access to another generates any IAM objects needed for the relevant services to communicate\. + +In our experience, real\-world use of intent\-based constructs results in 1–5 AWS CloudFormation resources per construct, though this can vary\. For serverless applications, 5–8 AWS resources per API endpoint is typical\. + +Patterns, which represent a higher level of abstraction, let you define even more AWS resources with even less code\. The AWS CDK code in [Creating an AWS Fargate service using the AWS CDK](ecs_example.md), for example, generates more than fifty AWS CloudFormation resources while defining only three constructs\! + +Exceeding the AWS CloudFormation resource limit is an error during AWS CloudFormation synthesis\. The AWS CDK issues a warning if your stack exceeds 80% of the limit\. You can use a different limit by setting the `maxResources` property on your stack, or disable validation by setting `maxResources` to 0\. + +**Tip** +You can get an exact count of the resources in your synthesized output using the following utility script\. \(Since every AWS CDK developer needs Node\.js, the script is written in JavaScript\.\) + +``` +// rescount.js - count the resources defined in a stack +// invoke with: node rescount.js <path-to-stack-json> +// e.g. node rescount.js cdk.out/MyStack.template.json + +import * as fs from 'fs'; +const path = process.argv[2]; + +if (path) fs.readFile(path, 'utf8', function(err, contents) { + console.log(err ? `${err}` : + `${Object.keys(JSON.parse(contents).Resources).length} resources defined in ${path}`); +}); else console.log("Please specify the path to the stack's output .json file"); +``` + +As your stack's resource count approaches the limit, consider re\-architecting to reduce the number of resources your stack contains: for example, by combining some Lambda functions, or by breaking your stack into multiple stacks\. The CDK supports [references between stacks](resources.md#resource_stack), so it is straightforward to separate your app's functionality into different stacks in whatever way makes the most sense to you\. + +**Note** +AWS CloudFormation experts often suggest the use of nested stacks as a solution to the resource limit\. The AWS CDK supports this approach via the [`NestedStack`](stacks.md#stack_nesting) construct\. + +\([back to list](#troubleshooting_top)\)<a name="troubleshooting_availability_zones"></a> + +**I specified three \(or more\) Availability Zones for my EC2 Auto\-Scaling Group or Virtual Private Cloud, but it was only deployed in two** +To get the number of Availability Zones you requested, specify the account and region in the stack's `env` property\. If you do not specify both, the AWS CDK, by default, synthesizes the stack as environment\-agnostic, such that it can be deployed to any region\. You can then deploy the stack to a specific region using AWS CloudFormation\. Because some regions have only two availability zones, an environment\-agnostic template never uses more than two\. + +**Note** +In the past, regions have occasionally launched with only one availability zone\. Environment\-agnostic AWS CDK stacks cannot be deployed to such regions\. At this writing, however, all AWS regions have at least two AZs\. + +You can change this behavior by overriding your stack's [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.Stack.html#availabilityzones](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.Stack.html#availabilityzones) \(Python: `availability_zones`\) property to explicitly specify the zones you want to use\. + +For more information about specifying a stack's account and region at synthesis time, while retaining the flexibility to deploy to any region, see [Environments](environments.md)\. + +\([back to list](#troubleshooting_top)\)<a name="troubleshooting_resource_not_deleted"></a> + +**My S3 bucket, DynamoDB table, or other resource is not deleted when I issue `cdk destroy`** +By default, resources that can contain user data have a `removalPolicy` \(Python: `removal_policy`\) property of `RETAIN`, and the resource is not deleted when the stack is destroyed\. Instead, the resource is orphaned from the stack\. You must then delete the resource manually after the stack is destroyed\. Until you do, redeploying the stack fails, because the name of the new resource being created during deployment conflicts with the name of the orphaned resource\. + +If you set a resource's removal policy to `DESTROY`, that resource will be deleted when the stack is destroyed\. + +------ +#### [ TypeScript ] + +``` +import * as cdk from '@aws-cdk/core'; +import * as s3 from '@aws-cdk/aws-s3'; + +export class CdkTestStack extends cdk.Stack { + constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { + super(scope, id, props); + + const bucket = new s3.Bucket(this, 'Bucket', { + removalPolicy: cdk.RemovalPolicy.DESTROY, + }); + } +} +``` + +------ +#### [ JavaScript ] + +``` +const cdk = require('@aws-cdk/core'); +const s3 = require('@aws-cdk/aws-s3'); + +class CdkTestStack extends cdk.Stack { + constructor(scope, id, props) { + super(scope, id, props); + + const bucket = new s3.Bucket(this, 'Bucket', { + removalPolicy: cdk.RemovalPolicy.DESTROY + }); + } +} + +module.exports = { CdkTestStack } +``` + +------ +#### [ Python ] + +``` +import aws_cdk.core as cdk +import aws_cdk.aws_s3 as s3 + +class CdkTestStack(cdk.stack): + def __init__(self, scope: cdk.Construct, id: str, **kwargs): + super().__init__(scope, id, **kwargs) + + bucket = s3.Bucket(self, "Bucket", + removal_policy=cdk.RemovalPolicy.DESTROY) +``` + +------ +#### [ Java ] + +``` +software.amazon.awscdk.core.*; +import software.amazon.awscdk.services.s3.*; + +public class CdkTestStack extends Stack { + public CdkTestStack(final Construct scope, final String id) { + this(scope, id, null); + } + + public CdkTestStack(final Construct scope, final String id, final StackProps props) { + super(scope, id, props); + + Bucket.Builder.create(this, "Bucket") + .removalPolicy(RemovalPolicy.DESTROY).build(); + } +} +``` + +------ +#### [ C\# ] + +``` +using Amazon.CDK; +using Amazon.CDK.AWS.S3; + +public CdkTestStack(Construct scope, string id, IStackProps props) : base(scope, id, props) +{ + new Bucket(this, "Bucket", new BucketProps { + RemovalPolicy = RemovalPolicy.DESTROY + }); +} +``` + +------ + +**Note** +AWS CloudFormation cannot delete a non\-empty Amazon S3 bucket\. If you set an Amazon S3 bucket's removal policy to `DESTROY`, and it contains data, attempting to destroy the stack will fail because the bucket cannot be deleted\. You can have the AWS CDK delete the objects in the bucket before attempting to destroy it by setting the bucket's `autoDeleteObjects` prop to `true`\. + +\([back to list](#troubleshooting_top)\) \ No newline at end of file diff --git a/v1/use_cfn_public_registry.md b/v1/use_cfn_public_registry.md new file mode 100644 index 00000000..647dd309 --- /dev/null +++ b/v1/use_cfn_public_registry.md @@ -0,0 +1,112 @@ +# Using resources from the AWS CloudFormation Public Registry<a name="use_cfn_public_registry"></a> + + The AWS CloudFormation Public Registry is a collection of AWS CloudFormation extensions from both AWS and third parties that are available for use by all AWS customers\. You can also publish your own extension for others to use\. Extensions are of two types: resources and modules\. You can use public resource extensions in your AWS CDK app using the [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.CfnResource.html](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.CfnResource.html) construct\. + +All public extensions published by AWS are available to all accounts in all regions without any action on your part\. On the other hand, you must activate each third\-party extension you want to use, in each account and region where you want to use it\. + +**Note** +When you use AWS CloudFormation with third\-party resource types, you will incur charges based on the number of handler operations you run per month and handler operation duration\. See [CloudFormation pricing](http://aws.amazon.com/cloudformation/pricing/) for complete details\. + +See [Using public extensions in CloudFormation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/registry-public.html) for complete documentation of this feature from the AWS CloudFormation side\. + +## Activating a third\-party resource in your account and region<a name="use_cfn_public_registry_activate"></a> + +Extensions published by AWS do not require activation; they are always available in every account and region\. You can activate a third\-party extension through the AWS Management Console, via the AWS Command Line Interface, or by deploying a special AWS CloudFormation resource\. + +To activate a third\-party extension through the AWS Management Console, or to simply see what resources are available, follow these steps\. + +![\[Image NOT FOUND\]](http://docs.aws.amazon.com/cdk/v1/guide/images/activate-cfn-extension.png) + +1. Log in to the AWS account in which you want to use the extension, then switch to the region where you want to use it\. + +1. Navigate to the CloudFormation console via the **Services** menu\. + +1. Click **Public extensions** on the navigation bar, then activate the **Third party** radio button under **Publisher**\. A list of the available third\-party public extensions appears\. \(You may also choose **AWS** to see a list of the public extensions published by AWS, though you don't need to activate them\.\) + +1. Browse the list and find the extension you want to activate, or search for it, then activate the radio button in the upper right corner of the extension's card\. + +1. Click the **Activate** button at the top of the list to activate the selected extension\. The extension's **Activate** page appears\. + +1. In the **Activate** page, you may override the extension's default name, specify an execution role and logging configuration, and choose whether to automatically update the extension when a new version is released\. When you have set these options as you like, click **Activate extension** at the bottom of the page\. + +To activate a third\-party extension using the AWS CLI, use the `activate-type `command, substituting the ARN of the custom type you want to use for the one given\. + +``` +aws cloudformation activate-type --public-type-arn public_extension_ARN --auto-update-activated +``` + +To activate an extension through CloudFormation or the CDK, deploy a resource of type `AWS::CloudFormation::TypeActivation`, specifying the following properties\. ++ `TypeName` \- The name of the type, such as `AWSQS::EKS::Cluster`\. ++ `MajorVersion` \- The major version number of the extension that you want; omit if you want the latest version\. ++ `AutoUpdate` \- Whether to automatically update this extension when a new minor version is released by the publisher\. \(Major version updates require explicitly changing the `MajorVersion` property\.\) ++ `ExecutionRoleArn` \- The ARN of the IAM role under which this extension will run\. ++ `LoggingConfig` \- The logging configuration for the extension\. + +The `TypeActivation` resource can be deployed by the CDK using the [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.CfnResource.html](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.CfnResource.html) construct, as shown below for the actual extensions\. + +## Adding a resource from the AWS CloudFormation Public Registry to your CDK app<a name="use_cfn_public_registry_add"></a> + + Use the [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.CfnResource.html](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.CfnResource.html) construct to include a resource from the AWS CloudFormation Public Registry in your application\. This construct is in the CDK's `core` module\. + +For example, suppose there is a public resource named `MY::S5::UltimateBucket` that you want to use in your AWS CDK application\. This resource takes one property: the bucket name\. The corresponding `CfnResource` instantiation looks like this\. + +------ +#### [ TypeScript ] + +``` +const ubucket = new CfnResource(this, 'MyUltimateBucket', { + type: 'MY::S5::UltimateBucket::MODULE', + properties: { + BucketName: 'UltimateBucket' + } +}); +``` + +------ +#### [ JavaScript ] + +``` +const ubucket = new CfnResource(this, 'MyUltimateBucket', { + type: 'MY::S5::UltimateBucket::MODULE', + properties: { + BucketName: 'UltimateBucket' + } +}); +``` + +------ +#### [ Python ] + +``` +ubucket = CfnResource(self, "MyUltimateBucket", + type="MY::S5::UltimateBucket::MODULE", + properties=dict( + BucketName="UltimateBucket")) +``` + +------ +#### [ Java ] + +``` +CfnResource.Builder.create(this, "MyUltimateBucket") + .type("MY::S5::UltimateBucket::MODULE") + .properties(java.util.Map.of( // Map.of requires Java 9+ + "BucketName", "UltimateBucket")) + .build(); +``` + +------ +#### [ C\# ] + +``` +new CfnResource(this, "MyUltimateBucket", new CfnResourceProps +{ + Type = "MY::S5::UltimateBucket::MODULE", + Properties = new Dictionary<string, object> + { + ["BucketName"] = "UltimateBucket" + } +}); +``` + +------ \ No newline at end of file diff --git a/v1/use_cfn_template.md b/v1/use_cfn_template.md new file mode 100644 index 00000000..dd288e5e --- /dev/null +++ b/v1/use_cfn_template.md @@ -0,0 +1,712 @@ +# Import or migrate an existing AWS CloudFormation template<a name="use_cfn_template"></a> + +The [https://docs.aws.amazon.com/cdk/api/v1/docs/cloudformation-include-readme.html](https://docs.aws.amazon.com/cdk/api/v1/docs/cloudformation-include-readme.html) construct converts the resources in an imported AWS CloudFormation template to AWS CDK L1 constructs\. You can work with these in your app just as if they were defined in AWS CDK code, even using them within higher\-level AWS CDK constructs, letting you use \(for example\) the L2 permission grant methods with the resources they define\. + +This construct essentially adds an AWS CDK API wrapper to any resource in the template\. You can use this capability to migrate your existing AWS CloudFormation templates to the AWS CDK a piece at a time in order to take advantage of the AWS CDK's convenient higher\-level abstractions, or just to vend your AWS CloudFormation templates to AWS CDK developers by providing an AWS CDK construct API\. + +**Note** +The AWS CDK also includes [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.CfnInclude.html](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.CfnInclude.html), which was previously used for the same general purpose\. However, it lacks much of the functionality of `cloudformation-include.CfnInclude`\. + +## Install the `cloudformation-include` module<a name="use_cfn_template_install"></a> + +Follow these instructions to install the `cloudformation-include` module\. + +------ +#### [ TypeScript ] + +``` +npm install @aws-cdk/cloudformation-include +``` + +------ +#### [ JavaScript ] + +``` +npm install @aws-cdk/cloudformation-include +``` + +------ +#### [ Python ] + +``` +python -m pip install aws-cdk.cloudformation-include +``` + +------ +#### [ Java ] + +Add the following to the `<dependencies>` container of `pom.xml`\. + +``` +<dependency> + <groupId>software.amazon.awscdk</groupId> + <artifactId>cdk-cloudformation-include</artifactId> + <version>${cdk.version}</version> +</dependency> +``` + +------ +#### [ C\# ] + +Right\-click the project in Visual Studio's Solution Explorer and choose **Manage NuGet Packages**\. Search for and install the package `Amazon.CDK.CloudFormation.Include`\. Or change to your project's directory and issue: + +``` +dotnet add package Amazon.CDK.CloudFormation.Include +``` + +------ + +## Importing an AWS CloudFormation template<a name="w55aac31b9c11"></a> + + Here is a simple AWS CloudFormation template we'll use for the examples in this topic\. Save it as `my-template.json`\. After you've tried these examples with the provided template, you might explore further using a template for an actual stack you've already deployed, which you can obtain from the AWS CloudFormation console\. + +**Tip** +You can use either a JSON or YAML template\. We recommend JSON if available, since YAML parsers can vary slightly in what they accept\. + +``` +{ + "Resources": { + "MyBucket": { + "Type": "AWS::S3::Bucket", + "Properties": { + "BucketName": "MyBucket", + } + } + } +} +``` + +And here's how you import it into your stack using `cloudformation-include`\. + +------ +#### [ TypeScript ] + +``` +import * as cdk from '@aws-cdk/core'; +import * as cfninc from '@aws-cdk/cloudformation-include'; + +export class MyStack extends cdk.Stack { + constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { + super(scope, id, props); + + const template = new cfninc.CfnInclude(this, 'Template', { + templateFile: 'my-template.json', + }); + } +} +``` + +------ +#### [ JavaScript ] + +``` +const cdk = require('@aws-cdk/core'); +const cfninc = require('@aws-cdk/cloudformation-include'); + +class MyStack extends cdk.Stack { + constructor(scope, id, props) { + super(scope, id, props); + + const template = new cfninc.CfnInclude(this, 'Template', { + templateFile: 'my-template.json', + }); + } +} + +module.exports = { MyStack } +``` + +------ +#### [ Python ] + +``` +from aws_cdk import core +from aws_cdk import cloudformation_include as cfn_inc + +class MyStack(core.Stack): + + def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + template = cfn_inc.CfnInclude(self, "Template", + template_file="my-template.json") +``` + +------ +#### [ Java ] + +``` +import software.amazon.awscdk.core.Construct; +import software.amazon.awscdk.core.Stack; +import software.amazon.awscdk.core.StackProps; +import software.amazon.awscdk.cloudformation.include.CfnInclude; + +public class MyStack extends Stack { + public MyStack(final Construct scope, final String id) { + this(scope, id, null); + } + + public MyStack(final Construct scope, final String id, final StackProps props) { + super(scope, id, props); + + CfnInclude template = CfnInclude.Builder.create(this, "Template") + .templateFile("my-template.json") + .build(); + } +} +``` + +------ +#### [ C\# ] + +``` +using Amazon.CDK; +using cfnInc = Amazon.CDK.CloudFormation.Include; + +namespace MyApp +{ + public class MyStack : Stack + { + internal MyStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) + { + var template = new cfnInc.CfnInclude(this, "Template", new cfnInc.CfnIncludeProps + { + TemplateFile = "my-template.json" + }); + } + } +} +``` + +------ + +By default, importing a resource preserves the resource's original logical ID from the template\. This behavior is suitable for migrating an AWS CloudFormation template to the AWS CDK, where the logical IDs must be retained for AWS CloudFormation to recognize these as the same resources from the AWS CloudFormation template\. + +If you are instead developing an AWS CDK construct wrapper for the template so it can be used by AWS CDK developers \("vending"\), have the AWS CDK generate new resource IDs instead, so the construct can be used multiple times in a stack without name conflicts\. To do this, set the `preserveLogicalIds` property to false when importing the template\. + +------ +#### [ TypeScript ] + +``` +const template = new cfninc.CfnInclude(this, 'MyConstruct', { + templateFile: 'my-template.json', + preserveLogicalIds: false +}); +``` + +------ +#### [ JavaScript ] + +``` +const template = new cfninc.CfnInclude(this, 'MyConstruct', { + templateFile: 'my-template.json', + preserveLogicalIds: false +}); +``` + +------ +#### [ Python ] + +``` +template = cfn_inc.CfnInclude(self, "Template", + template_file="my-template.json", + preserve_logical_ids=False) +``` + +------ +#### [ Java ] + +``` +CfnInclude template = CfnInclude.Builder.create(this, "Template") + .templateFile("my-template.json") + .preserveLogicalIds(false) + .build(); +``` + +------ +#### [ C\# ] + +``` +var template = new cfnInc.CfnInclude(this, "Template", new cfn_inc.CfnIncludeProps +{ + TemplateFile = "my-template.json", + PreserveLogicalIds = false +}); +``` + +------ + +To put the imported resources under the control of your AWS CDK app, add the stack to the `App` as usual\. + +------ +#### [ TypeScript ] + +``` +import * as cdk from '@aws-cdk/core'; +import { MyStack } from '../lib/my-stack'; + +const app = new cdk.App(); +new MyStack(app, 'MyStack'); +``` + +------ +#### [ JavaScript ] + +``` +const cdk = require('@aws-cdk/core'); +const { MyStack } = require('../lib/my-stack'); + +const app = new cdk.App(); +new MyStack(app, 'MyStack'); +``` + +------ +#### [ Python ] + +``` +from aws_cdk import core +from mystack.my_stack import MyStack + +app = core.App() +MyStack(app, "MyStack") +``` + +------ +#### [ Java ] + +``` +import software.amazon.awscdk.core.App; + +public class MyApp { + public static void main(final String[] args) { + App app = new App(); + + new MyStack(app, "MyStack"); + } +} +``` + +------ +#### [ C\# ] + +``` +using Amazon.CDK; + +namespace CdkApp +{ + sealed class Program + { + public static void Main(string[] args) + { + var app = new App(); + new MyStack(app, "MyStack"); + } + } +} +``` + +------ + +To verify that there will be no unintended changes to the AWS resources in the stack, perform a diff, omitting the AWS CDK\-specific metadata\. + +``` +cdk diff --no-version-reporting --no-path-metadata --no-asset-metadata +``` + +When you `cdk deploy` the stack, your AWS CDK app becomes the source of truth for the stack\. Going forward, make changes to the AWS CDK app, not to the AWS CloudFormation template\. + +## Accessing imported resources<a name="use_cfn_template_cfninclude_access"></a> + +The name `template` in the example code represents the imported AWS CloudFormation template\. To access a resource from it, use this object's [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_cloudformation-include.CfnInclude.html#get-wbr-resourcelogicalid-span-class-api-icon-api-icon-experimental-title-this-api-element-is-experimental-it-may-change-without-notice-span](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_cloudformation-include.CfnInclude.html#get-wbr-resourcelogicalid-span-class-api-icon-api-icon-experimental-title-this-api-element-is-experimental-it-may-change-without-notice-span) method\. To access the returned resource as a specific kind of resource, cast the result to the desired type\. \(Casting is not necessary in Python and JavaScript\.\) + +------ +#### [ TypeScript ] + +``` +const cfnBucket = template.getResource('MyBucket') as s3.CfnBucket; +``` + +------ +#### [ JavaScript ] + +``` +const cfnBucket = template.getResource('MyBucket'); +``` + +------ +#### [ Python ] + +``` +cfn_bucket = template.get_resource("MyBucket") +``` + +------ +#### [ Java ] + +``` +CfnBucket cfnBucket = (CfnBucket)template.getResource("MyBucket"); +``` + +------ +#### [ C\# ] + +``` +var cfnBucket = (CfnBucket)template.GetResource("MyBucket"); +``` + +------ + +In our example, `cfnBucket` is now an instance of the [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-s3.CfnBucket.html](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-s3.CfnBucket.html) class, a L1 construct that exactly represents the corresponding AWS CloudFormation resource\. You can treat it like any other resource of its type, for example getting its ARN by way of the `bucket.attrArn` property\. + +To wrap the L1 `CfnBucket` resource in a L2 [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-s3.Bucket.html](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-s3.Bucket.html) instance instead, use the static methods [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-s3.Bucket.html#static-from-wbr-bucket-wbr-arnscope-id-bucketarn](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-s3.Bucket.html#static-from-wbr-bucket-wbr-arnscope-id-bucketarn), [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-s3.Bucket.html#static-from-wbr-bucket-wbr-attributesscope-id-attrs](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-s3.Bucket.html#static-from-wbr-bucket-wbr-attributesscope-id-attrs), or [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-s3.Bucket.html#static-from-wbr-bucket-wbr-namescope-id-bucketname](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-s3.Bucket.html#static-from-wbr-bucket-wbr-namescope-id-bucketname)\. Usually the `fromBucketName()` method is the most convenient\. For example: + +------ +#### [ TypeScript ] + +``` +const bucket = s3.Bucket.fromBucketName(this, 'Bucket', cfnBucket.ref); +``` + +------ +#### [ JavaScript ] + +``` +const bucket = s3.Bucket.fromBucketName(this, 'Bucket', cfnBucket.ref); +``` + +------ +#### [ Python ] + +``` +bucket = s3.Bucket.from_bucket_name(self, "Bucket", cfn_bucket.ref) +``` + +------ +#### [ Java ] + +``` +Bucket bucket = (Bucket)Bucket.fromBucketName(this, "Bucket", cfnBucket.getRef()); +``` + +------ +#### [ C\# ] + +``` +var bucket = (Bucket)Bucket.FromBucketName(this, "Bucket", cfnBucket.Ref); +``` + +------ + +Other L2 constructs have similar methods for creating the construct from an existing resource\. + +Constructing the `Bucket` this way doesn't create a second Amazon S3 bucket; instead, the new `Bucket` instance encapsulates the existing `CfnBucket`\. + +In the example, `bucket` is now an L2 `Bucket` construct that you can use as you would one you declared yourself\. For example, if `lambdaFunc` is an AWS Lambda function, and you wish to grant it write access to the bucket, you can do so using the bucket's convenient [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-s3.Bucket.html#grant-wbr-read-wbr-writeidentity-objectskeypattern](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-s3.Bucket.html#grant-wbr-read-wbr-writeidentity-objectskeypattern) method, without needing to construct the necessary IAM policy yourself\. + +------ +#### [ TypeScript ] + +``` +bucket.grantWrite(lambdaFunc); +``` + +------ +#### [ JavaScript ] + +``` +bucket.grantWrite(lambdaFunc); +``` + +------ +#### [ Python ] + +``` +bucket.grant_write(lambda_func) +``` + +------ +#### [ Java ] + +``` +bucket.grantWrite(lambdaFunc); +``` + +------ +#### [ C\# ] + +``` +bucket.GrantWrite(lambdaFunc); +``` + +------ + +## Replacing parameters<a name="use_cfn_template_cfninclude_params"></a> + +If your included AWS CloudFormation template has parameters, you can replace these with build\-time values when you import the template, using the `parameters` property\. In the example below, we replace the `UploadBucket` parameter with the ARN of a bucket defined elsewhere in our AWS CDK code\. + +------ +#### [ TypeScript ] + +``` +const template = new cfninc.CfnInclude(this, 'Template', { + templateFile: 'my-template.json', + parameters: { + 'UploadBucket': bucket.bucketArn, + }, +}); +``` + +------ +#### [ JavaScript ] + +``` +const template = new cfninc.CfnInclude(this, 'Template', { + templateFile: 'my-template.json', + parameters: { + 'UploadBucket': bucket.bucketArn, + }, +}); +``` + +------ +#### [ Python ] + +``` +template = cfn_inc.CfnInclude(self, "Template", + template_file="my-template.json", + parameters=dict(UploadBucket=bucket.bucket_arn) +) +``` + +------ +#### [ Java ] + +``` +CfnInclude template = CfnInclude.Builder.create(this, "Template") + .templateFile("my-template.json") + .parameters(java.util.Map.of( // Map.of requires Java 9+ + "UploadBucket", bucket.getBucketArn())) + .build(); +``` + +------ +#### [ C\# ] + +``` +var template = new cfnInc.CfnInclude(this, "Template", new cfnInc.CfnIncludeProps +{ + TemplateFile = "my-template.json", + Parameters = new Dictionary<string, string> + { + { "UploadBucket", bucket.BucketArn } + } +}); +``` + +------ + +## Other template elements<a name="use_cfn_template_cfninclude_other"></a> + +You can import any AWS CloudFormation template element, not just resources\. The imported elements become part of the AWS CDK stack\. To import these elements, use the following methods of the `CfnInclude` object\. ++ [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_cloudformation-include.CfnInclude.html#get-wbr-conditionconditionname-span-class-api-icon-api-icon-experimental-title-this-api-element-is-experimental-it-may-change-without-notice-span](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_cloudformation-include.CfnInclude.html#get-wbr-conditionconditionname-span-class-api-icon-api-icon-experimental-title-this-api-element-is-experimental-it-may-change-without-notice-span) \- AWS CloudFormation [conditions](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/conditions-section-structure.html) ++ [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_cloudformation-include.CfnInclude.html#get-wbr-hookhooklogicalid-span-class-api-icon-api-icon-experimental-title-this-api-element-is-experimental-it-may-change-without-notice-span](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_cloudformation-include.CfnInclude.html#get-wbr-hookhooklogicalid-span-class-api-icon-api-icon-experimental-title-this-api-element-is-experimental-it-may-change-without-notice-span) \- AWS CloudFormation [hooks](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/blue-green.html) for blue\-green deployments ++ [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_cloudformation-include.CfnInclude.html#get-wbr-mappingmappingname-span-class-api-icon-api-icon-experimental-title-this-api-element-is-experimental-it-may-change-without-notice-span](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_cloudformation-include.CfnInclude.html#get-wbr-mappingmappingname-span-class-api-icon-api-icon-experimental-title-this-api-element-is-experimental-it-may-change-without-notice-span) \- AWS CloudFormation [mappings](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/mappings-section-structure.html) ++ [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_cloudformation-include.CfnInclude.html#get-wbr-outputlogicalid-span-class-api-icon-api-icon-experimental-title-this-api-element-is-experimental-it-may-change-without-notice-span](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_cloudformation-include.CfnInclude.html#get-wbr-outputlogicalid-span-class-api-icon-api-icon-experimental-title-this-api-element-is-experimental-it-may-change-without-notice-span) \- AWS CloudFormation [outputs](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html) ++ [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_cloudformation-include.CfnInclude.html#get-wbr-parameterparametername-span-class-api-icon-api-icon-experimental-title-this-api-element-is-experimental-it-may-change-without-notice-span](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_cloudformation-include.CfnInclude.html#get-wbr-parameterparametername-span-class-api-icon-api-icon-experimental-title-this-api-element-is-experimental-it-may-change-without-notice-span) \- AWS CloudFormation [parameters](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html) ++ [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_cloudformation-include.CfnInclude.html#get-wbr-rulerulename-span-class-api-icon-api-icon-experimental-title-this-api-element-is-experimental-it-may-change-without-notice-span](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_cloudformation-include.CfnInclude.html#get-wbr-rulerulename-span-class-api-icon-api-icon-experimental-title-this-api-element-is-experimental-it-may-change-without-notice-span) \- AWS CloudFormation [rules](https://docs.aws.amazon.com/servicecatalog/latest/adminguide/reference-template_constraint_rules.html) for Service Catalog templates + +Each of these methods returns an instance of a class representing the specific type of AWS CloudFormation element\. These objects are mutable; changes you make to them will appear in the template generated from the AWS CDK stack\. The code below, for example, imports a parameter from the template and modifies its default\. + +------ +#### [ TypeScript ] + +``` +const param = template.getParameter('MyParameter'); +param.default = "AWS CDK" +``` + +------ +#### [ JavaScript ] + +``` +const param = template.getParameter('MyParameter'); +param.default = "AWS CDK" +``` + +------ +#### [ Python ] + +``` +param = template.get_parameter("MyParameter") +param.default = "AWS CDK" +``` + +------ +#### [ Java ] + +``` +CfnParameter param = template.getParameter("MyParameter"); +param.setDefaultValue("AWS CDK") +``` + +------ +#### [ C\# ] + +``` +var cfnBucket = (CfnBucket)template.GetResource("MyBucket"); +var param = template.GetParameter("MyParameter"); +param.Default = "AWS CDK"; +``` + +------ + +## Nested stacks<a name="use_cfn_template_cfninclude_nested"></a> + +You may import [nested stacks](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-nested-stacks.html) by specifying them either when you import their main template, or at some later point\. The nested template must be stored in a local file, but referenced as a `NestedStack` resource in the main template, and the resource name used in the AWS CDK code must match the name used for the nested stack in the main template\. + +Given this resource definition in the main template, the following code shows how to import the referenced nested stack both ways\. + +``` +"NestedStack": { + "Type": "AWS::CloudFormation::Stack", + "Properties": { + "TemplateURL": "https://my-s3-template-source.s3.amazonaws.com/nested-stack.json" + } +``` + +------ +#### [ TypeScript ] + +``` +// include nested stack when importing main stack +const mainTemplate = new cfninc.CfnInclude(this, 'MainStack', { + templateFile: 'main-template.json', + loadNestedStacks: { + 'NestedStack': { + templateFile: 'nested-template.json', + }, + }, +}); + +// or add it some time after importing the main stack +const nestedTemplate = mainTemplate.loadNestedStack('NestedTemplate', { + templateFile: 'nested-template.json', +}); +``` + +------ +#### [ JavaScript ] + +``` +// include nested stack when importing main stack +const mainTemplate = new cfninc.CfnInclude(this, 'MainStack', { + templateFile: 'main-template.json', + loadNestedStacks: { + 'NestedStack': { + templateFile: 'nested-template.json', + }, + }, +}); + +// or add it some time after importing the main stack +const nestedTemplate = mainTemplate.loadNestedStack('NestedStack', { + templateFile: 'my-nested-template.json', +}); +``` + +------ +#### [ Python ] + +``` +# include nested stack when importing main stack +main_template = cfn_inc.CfnInclude(self, "MainStack", + template_file="main-template.json", + load_nested_stacks=dict(NestedStack= + cfn_inc.CfnIncludeProps(template_file="nested-template.json"))) + +# or add it some time after importing the main stack +nested_template = main_template.load_nested_stack("NestedStack", + template_file="nested-template.json") +``` + +------ +#### [ Java ] + +``` +CfnInclude mainTemplate = CfnInclude.Builder.create(this, "MainStack") + .templateFile("main-template.json") + .loadNestedStacks(java.util.Map.of( // Map.of requires Java 9+ + "NestedStack", CfnIncludeProps.builder() + .templateFile("nested-template.json").build())) + .build(); + +// or add it some time after importing the main stack +IncludedNestedStack nestedTemplate = mainTemplate.loadNestedStack("NestedTemplate", CfnIncludeProps.builder() + .templateFile("nested-template.json") + .build()); +``` + +------ +#### [ C\# ] + +``` +// include nested stack when importing main stack +var mainTemplate = new cfnInc.CfnInclude(this, "MainStack", new cfnInc.CfnIncludeProps +{ + TemplateFile = "main-template.json", + LoadNestedStacks = new Dictionary<string, cfnInc.ICfnIncludeProps> + { + { "NestedStack", new cfnInc.CfnIncludeProps { TemplateFile = "nested-template.json" } } + } +}); + +// or add it some time after importing the main stack +var nestedTemplate = mainTemplate.LoadNestedStack("NestedTemplate", new cfnInc.CfnIncludeProps { + TemplateFile = 'nested-template.json' +}); +``` + +------ + +You can import multiple nested stacks with either or both methods\. When importing the main template, you provide a mapping between the resource name of each nested stack and its template file, and this mapping can contain any number of entries\. To do it after the initial import, call `loadNestedStack()` once for each nested stack\. + +After importing a nested stack, you can access it using the main template's [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_cloudformation-include.CfnInclude.html#get-wbr-nested-wbr-stacklogicalid-span-class-api-icon-api-icon-experimental-title-this-api-element-is-experimental-it-may-change-without-notice-span](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_cloudformation-include.CfnInclude.html#get-wbr-nested-wbr-stacklogicalid-span-class-api-icon-api-icon-experimental-title-this-api-element-is-experimental-it-may-change-without-notice-span) method\. + +------ +#### [ TypeScript ] + +``` +const nestedStack = mainTemplate.getNestedStack('NestedStack').stack; +``` + +------ +#### [ JavaScript ] + +``` +const nestedStack = mainTemplate.getNestedStack('NestedStack').stack; +``` + +------ +#### [ Python ] + +``` +nested_stack = main_template.get_nested_stack("NestedStack").stack +``` + +------ +#### [ Java ] + +``` +NestedStack nestedStack = mainTemplate.getNestedStack("NestedStack").getStack(); +``` + +------ +#### [ C\# ] + +``` +var nestedStack = mainTemplate.GetNestedStack("NestedStack").Stack; +``` + +------ + +The `getNestedStack()` method returns an [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_cloudformation-include.IncludedNestedStack.html](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_cloudformation-include.IncludedNestedStack.html) instance, from which you can access the AWS CDK [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.NestedStack.html](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_core.NestedStack.html) instance via the `stack` property \(as shown in the example\) or the original AWS CloudFormation template object via `includedTemplate`, from which you can load resources and other AWS CloudFormation elements\. \ No newline at end of file diff --git a/v1/videos.md b/v1/videos.md new file mode 100644 index 00000000..4912590d --- /dev/null +++ b/v1/videos.md @@ -0,0 +1,16 @@ +# Videos<a name="videos"></a> + +Enjoy these videos presented by members of the AWS CDK team\. + +**Note** +Since the AWS CDK is always evolving, some of the code presented in these videos may not work quite the same way it did when the video was recorded\. This is especially true for modules that were under active development at the time\. It's also possible that we've since added a better way to achieve the same result\. Consult this Developer Guide and the [AWS CDK API Reference](https://docs.aws.amazon.com/cdk/api/v1/docs/aws-construct-library.html) for up\-to\-date information\. + +## Infrastructure *is* Code with the AWS CDK<a name="videos-infrastructure-is-code"></a> + +## Deep dive into AWS Cloud Development Kit \(AWS CDK\)<a name="videos-deep-dive"></a> + +## Contributing to the AWS Construct Library<a name="videos-contributing"></a> + +## Faster deployments with CDK Pipelines<a name="videos-pipeliens"></a> + +## How to contribute to the AWS CDK using GitPod<a name="videos-gitpod"></a> \ No newline at end of file diff --git a/v1/vscode.md b/v1/vscode.md new file mode 100644 index 00000000..3c089740 --- /dev/null +++ b/v1/vscode.md @@ -0,0 +1,3 @@ +# AWS Toolkit for Visual Studio Code<a name="vscode"></a> + +The [AWS Toolkit for Visual Studio Code](https://aws.amazon.com/visualstudiocode/) is an open source plug\-in for Visual Studio Code that makes it easier to create, debug, and deploy applications on AWS\. The toolkit provides an integrated experience for developing AWS CDK applications, including the AWS CDK Explorer feature to list your AWS CDK projects and browse the various components of the CDK application\. [Install the AWS Toolkit](https://docs.aws.amazon.com/toolkit-for-vscode/latest/userguide/setup-toolkit.html) and learn more about [using the AWS CDK Explorer](https://docs.aws.amazon.com/toolkit-for-vscode/latest/userguide/cdk-explorer.html)\. \ No newline at end of file diff --git a/v1/work-with-cdk-csharp.md b/v1/work-with-cdk-csharp.md new file mode 100644 index 00000000..fff79cf0 --- /dev/null +++ b/v1/work-with-cdk-csharp.md @@ -0,0 +1,191 @@ +# Working with the AWS CDK in C\#<a name="work-with-cdk-csharp"></a> + +\.NET is a fully\-supported client language for the AWS CDK and is considered stable\. C\# is the main \.NET language for which we provide examples and support\. You can choose to write AWS CDK applications in other \.NET languages, such as Visual Basic or F\#, but AWS offers limited support for using these languages with the CDK\. + +You can develop AWS CDK applications in C\# using familiar tools including Visual Studio, Visual Studio Code, the `dotnet` command, and the NuGet package manager\. The modules comprising the AWS Construct Library are distributed via [nuget\.org](https://www.nuget.org/packages?q=amazon.cdk.aws)\. + +We suggest using [Visual Studio 2019](https://visualstudio.microsoft.com/downloads/) \(any edition\) on Windows to develop AWS CDK apps in C\#\. + +## Prerequisites<a name="csharp-prerequisites"></a> + +To work with the AWS CDK, you must have an AWS account and credentials and have installed Node\.js and the AWS CDK Toolkit\. See [AWS CDK Prerequisites](work-with.md#work-with-prerequisites)\. + +C\# AWS CDK applications require \.NET Core v3\.1 or later, [available here](https://dotnet.microsoft.com/download/dotnet-core/3.1)\. + +**Note** +Third\-party Language Deprecation: language version is only supported until its EOL \(End Of Life\) shared by the vendor or community and is subject to change with prior notice\. + +The \.NET toolchain includes `dotnet`, a command\-line tool for building and running \.NET applications and managing NuGet packages\. Even if you work mainly in Visual Studio, this command can be useful for batch operations and for installing AWS Construct Library packages\. + +## Creating a project<a name="csharp-newproject"></a> + +You create a new AWS CDK project by invoking `cdk init` in an empty directory\. + +``` +mkdir my-project +cd my-project +cdk init app --language csharp +``` + +`cdk init` uses the name of the project folder to name various elements of the project, including classes, subfolders, and files\. Hyphens in the folder name are converted to underscores\. However, the name should otherwise follow the form of a C\# identifier; for example, it should not start with a number or contain spaces\. + +The resulting project includes a reference to the `Amazon.CDK` NuGet package\. It and its dependencies are installed automatically by NuGet\. + +## Managing AWS Construct Library modules<a name="csharp-managemodules"></a> + +The \.NET ecosystem uses the NuGet package manager\. AWS Construct Library modules are named like `Amazon.CDK.AWS.SERVICE-NAME` where the service name is a short name without an AWS or Amazon prefix\. For example, the NuGet package name for the Amazon S3 module is `Amazon.CDK.AWS.S3`\. If you can't find a package you want, [search Nuget\.org](https://www.nuget.org/packages?q=amazon.cdk.aws)\. + +**Note** +The [\.NET edition of the CDK API Reference](https://docs.aws.amazon.com/cdk/api/v1/dotnet/api/index.html) also shows the package names\. + +Some services' AWS Construct Library support is in more than one module\. For example, Amazon Route 53 has the three modules in addition to the main `Amazon.CDK.AWS.Route53` module, named `Route53.Patterns`, `Route53.Resolver`, and `Route53.Targets`\. + +The AWS CDK's core module, which you'll need in most AWS CDK apps, is imported in C\# code as `Amazon.CDK`\. Modules for the various services in the AWS Construct Library live under `Amazon.CDK.AWS` and are named the same as their NuGet package name\. For example, the Amazon S3 module's namespace is `Amazon.CDK.AWS.S3`\. + +We recommend writing a single C\# `using` directive for each AWS Construct Library module you use in each of your C\# source files\. You may find it convenient to use an alias for a namespace or type to help resolve name conflicts\. You can always use a type's fully\-qualfiied name \(including its namespace\) without a `using` statement\. + +**Important** +All AWS Construct Library modules used in your project must be the same version\. + +NuGet has four standard, mostly\-equivalent interfaces; you can use the one that suits your needs and working style\. You can also use compatible tools, such as [Paket](https://fsprojects.github.io/Paket/) or [MyGet](https://www.myget.org/)\. + +### The Visual Studio NuGet GUI<a name="csharp-vs-nuget-gui"></a> + +Visual Studio's NuGet tools are accessible from **Tools** > **NuGet Package Manager** > **Manage NuGet Packages for Solution**\. Use the **Browse** tab to find the AWS Construct Library packages you want to install\. You can choose the desired version, including pre\-release versions \(mark the **Include prerelease** checkbox\) and add them to any of the open projects\. + +**Note** +All AWS Construct Library modules deemed "experimental" \(see [Versioning](reference.md#versioning)\) are flagged as pre\-release in NuGet\. + +![\[Image NOT FOUND\]](http://docs.aws.amazon.com/cdk/v1/guide/images/visual-studio-nuget.png) + +Look on the **Updates** page to install new versions of your packages\. + +### The NuGet console<a name="csharp-vs-nuget-console"></a> + +The NuGet console is a PowerShell\-based interface to NuGet that works in the context of a Visual Studio project\. You can open it in Visual Studio by choosing **Tools** > **NuGet Package Manager** > **Package Manager Console**\. For more information about using this tool, see [Install and Manage Packages with the Package Manager Console in Visual Studio](https://docs.microsoft.com/en-us/nuget/consume-packages/install-use-packages-powershell)\. + +### The `dotnet` command<a name="csharp-vs-dotnet-command"></a> + +The `dotnet` command is the primary command\-line tool for working with Visual Studio C\# projects\. You can invoke it from any Windows command prompt\. Among its many capabilities, `dotnet` can add NuGet dependencies to a Visual Studio project\. + +Assuming you're in the same directory as the Visual Studio project \(`.csproj`\) file, issue a command like the following to install a package\. + +``` +dotnet add package Amazon.CDK.AWS.S3 +``` + +You may issue the command from another directory by including the path to the project file, or to the directory that contains it, after the `add` keyword\. The following example assumes that you are in your AWS CDK project's main directory\. + +``` +dotnet add src/PROJECT-DIR package Amazon.CDK.AWS.S3 +``` + +To install a specific version of a package, include the `-v` flag and the desired version\. AWS Construct Library modules that are deemed "experimental" \(see [Versioning](reference.md#versioning)\) are flagged as pre\-release in NuGet, and must be installed using an explicit version number\. + +``` +dotnet add package Amazon.CDK.AWS.S3 -v VERSION-NUMBER +``` + +To update a package, issue the same `dotnet add` command you used to install it\. If you do not specify a version number, the latest version is installed\. For experimental modules, again, you must specify an explicit version number\. + +For more information about managing packages using the `dotnet` command, see [Install and Manage Packages Using the dotnet CLI](https://docs.microsoft.com/en-us/nuget/consume-packages/install-use-packages-dotnet-cli)\. + +### The `nuget` command<a name="csharp-vs-nuget-command"></a> + +The `nuget` command line tool can install and update NuGet packages\. However, it requires your Visual Studio project to be set up differently from the way `cdk init` sets up projects\. \(Technical details: `nuget` works with `Packages.config` projects, while `cdk init` creates a newer\-style `PackageReference` project\.\) + +We do not recommend the use of the `nuget` tool with AWS CDK projects created by `cdk init`\. If you are using another type of project, and want to use `nuget`, see the [NuGet CLI Reference](https://docs.microsoft.com/en-us/nuget/reference/nuget-exe-cli-reference)\. + +## AWS CDK idioms in C\#<a name="csharp-cdk-idioms"></a> + +### Props<a name="csharp-props"></a> + +All AWS Construct Library classes are instantiated using three arguments: the *scope* in which the construct is being defined \(its parent in the construct tree\), an *id*, and *props*, a bundle of key/value pairs that the construct uses to configure the resources it creates\. Other classes and methods also use the "bundle of attributes" pattern for arguments\. + +In C\#, props are expressed using a props type\. In idiomatic C\# fashion, we can use an object initializer to set the various properties\. Here we're creating an Amazon S3 bucket using the `Bucket` construct; its corresponding props type is `BucketProps`\. + +``` +var bucket = new Bucket(this, "MyBucket", new BucketProps { + Versioned = true +}); +``` + +**Tip** +Add the package `Amazon.JSII.Analyzers` to your project to get required\-values checking in your props definitions inside Visual Studio\. + +When extending a class or overriding a method, you may want to accept additional props for your own purposes that are not understood by the parent class\. To do this, subclass the appropriate props type and add the new attributes\. + +``` +// extend BucketProps for use with MimeBucket +class MimeBucketProps : BucketProps { + public string MimeType { get; set; } +} + +// hypothetical bucket that enforces MIME type of objects inside it +class MimeBucket : Bucket { + public MimeBucket( readonly Construct scope, readonly string id, readonly MimeBucketProps props=null) : base(scope, id, props) { + // ... + } +} + +// instantiate our MimeBucket class +var bucket = new MimeBucket(this, "MyBucket", new MimeBucketProps { + Versioned = true, + MimeType = "image/jpeg" +}); +``` + +When calling the parent class's initializer or overridden method, you can generally pass the props you received\. The new type is compatible with its parent, and extra props you added are ignored\. + +A future release of the AWS CDK could coincidentally add a new property with a name you used for your own property\. This won't cause any technical issues using your construct or method \(since your property isn't passed "up the chain," the parent class or overridden method will simply use a default value\) but it may cause confusion for your construct's users\. You can avoid this potential problem by naming your properties so they clearly belong to your construct\. If there are many new properties, bundle them into an appropriately\-named class and pass them as a single property\. + +### Generic structures<a name="csharp-generic-structures"></a> + +In some APIs, the AWS CDK uses JavaScript arrays or untyped objects as input to a method\. \(See, for example, AWS CodeBuild's [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-codebuild.BuildSpec.html#to-wbr-build-wbr-spec](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-codebuild.BuildSpec.html#to-wbr-build-wbr-spec) method\.\) In C\#, these objects are represented as `System.Collections.Generic.Dictionary<String, Object>`\. In cases where the values are all strings, you can use `Dictionary<String, String>`\. JavaScript arrays are represented as `object[]` or `string[]` in C\#\. + +**Tip** +You might define short aliases to make it easier to work with these specific dictionary types\. + +``` +using StringDict = System.Collections.Generic.Dictionary<string, string>; +using ObjectDict = System.Collections.Generic.Dictionary<string, object>; +``` + +### Missing values<a name="csharp-missing-values"></a> + +In C\#, missing values in AWS CDK objects such as props are represented by `null`\. The null\-conditional member access operator `?.` and the null coalescing operator `??` are convenient for working with these values\. + +``` +// mimeType is null if props is null or if props.MimeType is null +string mimeType = props?.MimeType; + +// mimeType defaults to text/plain. either props or props.MimeType can be null +string MimeType = props?.MimeType ?? "text/plain"; +``` + +## Building, synthesizing, and deploying<a name="csharp-running"></a> + +The AWS CDK automatically compiles your app before running it\. However, it can be useful to build your app manually to check for errors and run tests\. You can do this by pressing F6 in Visual Studio or by issuing `dotnet build src` from the command line, where `src` is the directory in your project directory that contains the Visual Studio Solution \(`.sln`\) file\. + +The [stacks](stacks.md) defined in your AWS CDK app can be synthesized and deployed individually or together using the commands below\. Generally, you should be in your project's main directory when you issue them\. ++ `cdk synth`: Synthesizes a AWS CloudFormation template from one or more of the stacks in your AWS CDK app\. ++ `cdk deploy`: Deploys the resources defined by one or more of the stacks in your AWS CDK app to AWS\. + +You can specify the names of multiple stacks to be synthesized or deployed in a single command\. If your app defines only one stack, you do not need to specify it\. + +``` +cdk synth # app defines single stack +cdk deploy Happy Grumpy # app defines two or more stacks; two are deployed +``` + +You may also use the wildcards \* \(any number of characters\) and ? \(any single character\) to identify stacks by pattern\. When using wildcards, enclose the pattern in quotes\. Otherwise, the shell may try to expand it to the names of files in the current directory before they are passed to the AWS CDK Toolkit\. + +``` +cdk synth "Stack?" # Stack1, StackA, etc. +cdk deploy "*Stack" # PipeStack, LambdaStack, etc. +``` + +**Tip** +You don't need to explicitly synthesize stacks before deploying them; `cdk deploy` performs this step for you to make sure your latest code gets deployed\. + +For full documentation of the `cdk` command, see [AWS CDK Toolkit \(`cdk` command\)](cli.md)\. \ No newline at end of file diff --git a/v1/work-with-cdk-go.md b/v1/work-with-cdk-go.md new file mode 100644 index 00000000..68efe058 --- /dev/null +++ b/v1/work-with-cdk-go.md @@ -0,0 +1,137 @@ +# Working with the AWS CDK in Go<a name="work-with-cdk-go"></a> + +Go is a fully\-supported client language for the AWS CDK and is considered stable\. Working with the AWS CDK in Go uses familiar tools\. The Go version of the AWS CDK even uses Go\-style identifiers\. + +Unlike the other languages the CDK supports, Go is not a traditional object\-oriented programming language\. Go uses composition where other languages often leverage inheritance\. We have tried to employ idiomatic Go approaches as much as possible, but there are places where the CDK charts its own course\. + +This topic explains the ins and outs of working with the AWS CDK in Go\. See the [announcement blog post](https://aws.amazon.com/blogs/developer/getting-started-with-the-aws-cloud-development-kit-and-go/) for a walkthrough of a simple Go project for the AWS CDK\. + +## Prerequisites<a name="go-prerequisites"></a> + +To work with the AWS CDK, you must have an AWS account and credentials and have installed Node\.js and the AWS CDK Toolkit\. See [AWS CDK Prerequisites](work-with.md#work-with-prerequisites)\. + +The Go bindings for the AWS CDK use the standard [Go toolchain](https://golang.org/dl/), v1\.16 or later\. You can use the editor of your choice\. + +**Note** +Third\-party Language Deprecation: language version is only supported until its EOL \(End Of Life\) shared by the vendor or community and is subject to change with prior notice\. + +## Creating a project<a name="go-newproject"></a> + +You create a new AWS CDK project by invoking `cdk init` in an empty directory\. + +``` +mkdir my-project +cd my-project +cdk init app --language go +``` + +`cdk init` uses the name of the project folder to name various elements of the project, including classes, subfolders, and files\. Hyphens in the folder name are converted to underscores\. However, the name should otherwise follow the form of a Go identifier; for example, it should not start with a number or contain spaces\. + +The resulting project includes a reference to the AWS CDK Go module, `github.com/aws/aws-cdk-go/awscdk`, in `go.mod`\. The CDK and its dependencies are automatically installed when you build your app\. + +## Managing AWS Construct Library modules<a name="go-managemodules"></a> + +In most AWS CDK documentation and examples, the word "module" is used primarily to refer to AWS Construct Library modules, one or more per AWS service, which differs from idiomatic Go usage of the term\. The CDK Construct Library is provided in one Go module with the individual Construct Library modules, which support the various AWS services, provided as Go packages within that module\. + +Some services' AWS Construct Library support is in more than one Construct Library module \(Go package\)\. For example, Amazon Route 53 has three Construct Library modules in addition to the main `awsroute53` package, named `awsroute53patterns`, `awsroute53resolver`, and `awsroute53targets`\. + +The AWS CDK's core package, which you'll need in most AWS CDK apps, is imported in Go code as `github.com/aws/aws-cdk-go/awscdk`\. Packages for the various services in the AWS Construct Library live under `github.com/aws/aws-cdk-go/awscdk`\. For example, the Amazon S3 module's namespace is `github.com/aws/aws-cdk-go/awscdk/awss3`\. + +``` +import ( + "github.com/aws/aws-cdk-go/awscdk/awss3" 2.16.0 + // ... +) +``` + +The contents of the Amazon S3 Go package are then available in the `awss3` namespace\. For example, to instantiate a bucket, you would call `awss3.NewBucket()`\. + +You may specify an alias when importing if you prefer more concise names: + +``` +import ( + s3 "github.com/aws/aws-cdk-go/awscdk/awss3" // use s3.NewBucket etc. + // ... +) +``` + +The code examples in this guide use the actual Go package names, so it is clear which Go packages \(AWS Construct Library modules\) are needed\. + +## AWS CDK idioms in Go<a name="go-cdk-idioms"></a> + +### Field and method names<a name="go-naming"></a> + +Field and method names use camel casing \(`likeThis`\) in TypeScript, the CDK's language of origin\. In Go, these follow Go conventions, so are Pascal\-cased \(`LikeThis`\)\. + +### Missing values and pointer conversion<a name="go-missing-values"></a> + +In Go, missing values in AWS CDK objects such as property bundles are represented by `nil`\. Go doesn't have nullable types; the only type that can contain `nil` is a pointer\. To allow values to be optional, then, all CDK properties, arguments, and return values are pointers, even for primitive types\. This applies to required values as well as optional ones, so if a required value later becomes optional, no breaking change in type is needed\. + +When passing literal values or expressions, you can use the following helper functions to create pointers to the values\. ++ `jsii.String` ++ `jsii.Number` ++ `jsii.Bool` ++ `jsii.Time` + +For consistency, we recommend that you use pointers similarly when defining your own constructs, even though it may seem more convenient to, for example, receive your construct's `id` as a string rather than a pointer to a string\. + +When dealing with optional AWS CDK values, including primitive values as well as complex types, you should explicitly test pointers to make sure they are not `nil` before doing anything with it\. Go does not have "syntactic sugar" to help handle empty or missing values as some other languages do\. However, required values in property bundles and similar structures are guaranteed to exist \(construction fails otherwise\), so these values need not be `nil`\-checked\. + +### Constructs and Props<a name="go-props"></a> + +Constructs, which represent one or more AWS resources and their associated attributes, are represented in Go as interfaces\. For example, `awss3.Bucket` is an interface\. Every construct has a factory function, such as `awss3.NewBucket`, to return a struct that implements the corresponding interface\. + +All factory functions take three arguments: the `scope` in which the construct is being defined \(its parent in the construct tree\), an `id`, and `props`, a bundle of key/value pairs that the construct uses to configure the resources it creates\. The "bundle of attributes" pattern is also used elsewhere in the AWS CDK\. + +In Go, props are represented by a specific struct type for each construct\. For example, an `awss3.Bucket` takes a props argument of type `awss3.BucketProps`\. Use a struct literal to write props arguments\. + +``` +var bucket = awss3.NewBucket(stack, jsii.String("MyBucket"), &awss3.BucketProps{ + Versioned: jsii.Bool(true), +}) +``` + +### Generic structures<a name="go-generic-structures"></a> + +In some places, the AWS CDK uses JavaScript arrays or untyped objects as input to a method\. \(See, for example, AWS CodeBuild's [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-codebuild.BuildSpec.html#to-wbr-build-wbr-spec](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-codebuild.BuildSpec.html#to-wbr-build-wbr-spec) method\.\) In Go, these objects are represented as slices and an empty interface, respectively\. + +The CDK provides variadic helper functions such as `jsii.Strings` for building slices containing primitive types\. + +``` +jsii.Strings("One", "Two", "Three") +``` + +### Developing custom constructs<a name="go-writing-constructs"></a> + +In Go, it is usually more straightforward to write a new construct than to extend an existing one\. First, define a new struct type, anonymously embedding one or more existing types if extension\-like semantics are desired\. Write methods for any new functionality you're adding and the fields necessary to hold the data they need\. Define a props interface if your construct needs one\. Finally, write a factory function `NewMyConstruct()` to return an instance of your construct\. + +If you are simply changing some default values on an existing construct or adding a simple behavior at instantiation, you don't need all that plumbing\. Instead, write a factory function that calls the factory function of the construct you're "extending\." In other CDK languages, for example, you might create a `TypedBucket` construct that enforces the type of objects in an Amazon S3 bucket by overriding the `s3.Bucket` type and, in your new type's initializer, adding a bucket policy that allows only specified filename extensions to be added to the bucket\. In Go, it is easier to simply write a `NewTypedBucket` that returns an `s3.Bucket` \(instantiated using `s3.NewBucket`\) to which you have added an appropriate bucket policy\. No new construct type is necessary because the functionality is already available in the standard bucket construct; the new "construct" just provides a simpler way to configure it\. + +## Building, synthesizing, and deploying<a name="go-running"></a> + +The AWS CDK automatically compiles your app before running it\. However, it can be useful to build your app manually to check for errors and to run tests\. You can do this by issuing `go build` at a command prompt while in your project's root directory\. + +Run any tests you've written by running `go test` at a command prompt\. + +The [stacks](stacks.md) defined in your AWS CDK app can be synthesized and deployed individually or together using the commands below\. Generally, you should be in your project's main directory when you issue them\. ++ `cdk synth`: Synthesizes a AWS CloudFormation template from one or more of the stacks in your AWS CDK app\. ++ `cdk deploy`: Deploys the resources defined by one or more of the stacks in your AWS CDK app to AWS\. + +You can specify the names of multiple stacks to be synthesized or deployed in a single command\. If your app defines only one stack, you do not need to specify it\. + +``` +cdk synth # app defines single stack +cdk deploy Happy Grumpy # app defines two or more stacks; two are deployed +``` + +You may also use the wildcards \* \(any number of characters\) and ? \(any single character\) to identify stacks by pattern\. When using wildcards, enclose the pattern in quotes\. Otherwise, the shell may try to expand it to the names of files in the current directory before they are passed to the AWS CDK Toolkit\. + +``` +cdk synth "Stack?" # Stack1, StackA, etc. +cdk deploy "*Stack" # PipeStack, LambdaStack, etc. +``` + +**Tip** +You don't need to explicitly synthesize stacks before deploying them; `cdk deploy` performs this step for you to make sure your latest code gets deployed\. + +For full documentation of the `cdk` command, see [AWS CDK Toolkit \(`cdk` command\)](cli.md)\. \ No newline at end of file diff --git a/v1/work-with-cdk-java.md b/v1/work-with-cdk-java.md new file mode 100644 index 00000000..883e3647 --- /dev/null +++ b/v1/work-with-cdk-java.md @@ -0,0 +1,158 @@ +# Working with the AWS CDK in Java<a name="work-with-cdk-java"></a> + +Java is a fully\-supported client language for the AWS CDK and is considered stable\. You can develop AWS CDK applications in Java using familiar tools, including the JDK \(Oracle's, or an OpenJDK distribution such as Amazon Corretto\) and Apache Maven\. The modules comprising the AWS Construct Library are distributed via the [Maven Central Repository](https://search.maven.org/search?q=g:software.amazon.awscdk)\. + +The AWS CDK supports Java 8 and later\. We recommend using the latest version you can, however, because later versions of the language include improvements that are particularly convenient for developing AWS CDK applications\. For example, Java 9 introduces the `Map.of()` method \(a convenient way to declare hashmaps that would be written as object literals in TypeScript\)\. Java 10 introduces local type inference using the `var` keyword\. + +**Note** +Most code examples in this Developer Guide work with Java 8\. A few examples use `Map.of()`; these examples include comments noting that they require Java 9\. + +You can use any text editor, or a Java IDE that can read Maven projects, to work on your AWS CDK apps\. We provide [Eclipse](https://www.eclipse.org/downloads/) hints in this Guide, but IntelliJ IDEA, NetBeans, and other IDEs can import Maven projects and can be used for developing AWS CDK applications in Java\. + +It is possible to write AWS CDK applications in JVM\-hosted languages other than Java \(for example, Kotlin, Groovy, Clojure, or Scala\), but the experience may not be particularly idiomatic, and we are unable to provide any support for these languages\. + +## Prerequisites<a name="java-prerequisites"></a> + +To work with the AWS CDK, you must have an AWS account and credentials and have installed Node\.js and the AWS CDK Toolkit\. See [AWS CDK Prerequisites](work-with.md#work-with-prerequisites)\. + +Java AWS CDK applications require Java 8 \(v1\.8\) or later\. We recommend [Amazon Corretto](https://aws.amazon.com/corretto/), but you can use any OpenJDK distribution or [Oracle's JDK](https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html)\. You will also need [Apache Maven](https://maven.apache.org/download.cgi) 3\.5 or later\. You can also use tools such as Gradle, but the application skeletons generated by the AWS CDK Toolkit are Maven projects\. + +**Note** +Third\-party Language Deprecation: language version is only supported until its EOL \(End Of Life\) shared by the vendor or community and is subject to change with prior notice\. + +## Creating a project<a name="java-newproject"></a> + +You create a new AWS CDK project by invoking `cdk init` in an empty directory\. + +``` +mkdir my-project +cd my-project +cdk init app --language java +``` + +`cdk init` uses the name of the project folder to name various elements of the project, including classes, subfolders, and files\. Hyphens in the folder name are converted to underscores\. However, the name should otherwise follow the form of a Java identifier; for example, it should not start with a number or contain spaces\. + +The resulting project includes a reference to the `software.amazon.awscdk.core` Maven package\. It and its dependencies are automatically installed by Maven\. + +If you are using an IDE, you can now open or import the project\. In Eclipse, for example, choose **File** > **Import** > **Maven** > **Existing Maven Projects**\. Make sure that the project settings are set to use Java 8 \(1\.8\)\. + +## Managing AWS Construct Library modules<a name="java-managemodules"></a> + +Use Maven to install AWS Construct Library packages, which are in the group `software.amazon.awscdk` and named with a short version \(no AWS or Amazon prefix\) of their service's name\. For example, the Maven artifact ID for Amazon S3 is `s3`\. [Search the Maven Central Repository](https://search.maven.org/search?q=software.amazon.awscdk) to find the names of all AWS CDK and AWS Construct Module libraries\. + +**Note** +The [Java edition of the CDK API Reference](https://docs.aws.amazon.com/cdk/api/v1/java/index.html) also shows the package names\. + +Some services' AWS Construct Library support is in more than one module\. For example, Amazon Route 53 has the three modules in addition to the main `software.amazon.awscdk.route53` module, named `route53-patterns`, `route53resolver`, and `route53-targets`\. + +The AWS CDK's core module, which you'll need in most AWS CDK apps, is imported in Java code as `software.amazon.awscdk.core`\. Modules for the various services in the AWS Construct Library live under `software.amazon.awscdk.services` and are named similarly to their Maven package name\. For example, the Amazon S3 module's namespace is `software.amazon.awscdk.services.s3`\. + +We recommend writing a separate Java `import` statement for each AWS Construct Library class you use in each of your Java source files, and avoiding wildcard imports\. You can always use a type's fully\-qualified name \(including its namespace\) without an `import` statement\. + +**Important** +All AWS Construct Library modules used in your project must be the same version\. + +Specify the modules that your application depends on by editing `pom.xml` and adding a new `<dependency>` element in the `<dependencies>` container\. For example, the following `<dependency>` element specifies the Amazon S3 construct library module: + +``` +<dependency> + <groupId>software.amazon.awscdk</groupId> + <artifactId>s3</artifactId> + <version>${cdk.version}</version> +</dependency> +``` + +**Tip** +If you use a Java IDE, it probably has features for managing Maven dependencies\. We recommend editing `pom.xml` directly, however, unless you are absolutely sure the IDE's functionality matches what you'd do by hand\. + +The default `pom.xml` defines the variable `cdk.version` to be the version of the AWS CDK that created the project\. You can easily update the version required by updating the value of this variable, which keeps all AWS Construct Library module versions in sync\. + +``` +<cdk.version>1.XX.Y</cdk.version> +``` + +This value can be any valid Maven version specifier\. For example, `[1.XX.Y,2.0)` indicates that any version between the current version 1\.XX\.Y \(inclusive\) and 2\.0 \(exclusive\), may be installed\. However, to avoid mismatched versions, we recommend using a fixed version like 1\.XX and updating it when moving a new AWS CDK release\. + +## AWS CDK idioms in Java<a name="java-cdk-idioms"></a> + +### Props<a name="java-props"></a> + +All AWS Construct Library classes are instantiated using three arguments: the *scope* in which the construct is being defined \(its parent in the construct tree\), an *id*, and *props*, a bundle of key/value pairs that the construct uses to configure the resources it creates\. Other classes and methods also use the "bundle of attributes" pattern for arguments\. + +In Java, props are expressed using the [Builder pattern](https://en.wikipedia.org/wiki/Builder_pattern)\. Each construct type has a corresponding props type; for example, the `Bucket` construct \(which represents an Amazon S3 bucket\) takes as its props an instance of `BucketProps`\. + +The `BucketProps` class \(like every AWS Construct Library props class\) has an inner class called `Builder`\. The `BucketProps.Builder` type offers methods to set the various properties of a `BucketProps` instance\. Each method returns the `Builder` instance, so the method calls can be chained to set multiple properties\. At the end of the chain, you call `build()` to actually produce the `BucketProps` object\. + +``` +Bucket bucket = new Bucket(this, "MyBucket", new BucketProps.Builder() + .versioned(true) + .encryption(BucketEncryption.KMS_MANAGED) + .build()); +``` + +Constructs, and other classes that take a props\-like object as their final argument, offer a shortcut\. The class has a `Builder` of its own that instantiates it and its props object in one step\. This way, you don't need to explicitly instantiate \(for example\) both `BucketProps` and a `Bucket`—and you don't need an import for the props type\. + +``` +Bucket bucket = Bucket.Builder.create(this, "MyBucket") + .versioned(true) + .encryption(BucketEncryption.KMS_MANAGED) + .build(); +``` + +When deriving your own construct from an existing construct, you may want to accept additional properties\. We recommend that you follow these builder patterns\. However, this isn't as simple as subclassing a construct class\. You must provide the moving parts of the two new `Builder` classes yourself\. You may prefer to simply have your construct accept one or more additional arguments\. You should provide additional constructors when an argument is optional\. + +### Generic structures<a name="java-generic-structures"></a> + +In some APIs, the AWS CDK uses JavaScript arrays or untyped objects as input to a method\. \(See, for example, AWS CodeBuild's [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-codebuild.BuildSpec.html#to-wbr-build-wbr-spec](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-codebuild.BuildSpec.html#to-wbr-build-wbr-spec) method\.\) In Java, these objects are represented as `java.util.Map<String, Object>`\. In cases where the values are all strings, you can use `Map<String, String>`\. + +Java does not provide a way to write literals for such containers like some other languages do\. In Java 9 and later, you can use [https://docs.oracle.com/javase/9/docs/api/java/util/Map.html#ofEntries-java.util.Map.Entry...-](https://docs.oracle.com/javase/9/docs/api/java/util/Map.html#ofEntries-java.util.Map.Entry...-) to conveniently define maps of up to ten entries inline with one of these calls\. + +``` +java.util.Map.of( + "base-directory", "dist", + "files", "LambdaStack.template.json" + ) +``` + +To create maps with more than ten entries, use [https://docs.oracle.com/javase/9/docs/api/java/util/Map.html#ofEntries-java.util.Map.Entry...-](https://docs.oracle.com/javase/9/docs/api/java/util/Map.html#ofEntries-java.util.Map.Entry...-)\. + +If you are using Java 8, you could provide your own methods similar to to these\. + +JavaScript arrays are represented as `List<Object>` or `List<String>` in Java\. The method `java.util.Arrays.asList` is convenient for defining short `List`s\. + +``` +List<String> cmds = Arrays.asList("cd lambda", "npm install", "npm install typescript") +``` + +### Missing values<a name="java-missing-values"></a> + +In Java, missing values in AWS CDK objects such as props are represented by `null`\. You must explicitly test any value that could be `null` to make sure it contains a value before doing anything with it\. Java does not have "syntactic sugar" to help handle null values as some other languages do\. You may find Apache ObjectUtil's [defaultIfNull](https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/ObjectUtils.html#defaultIfNull-T-T-) and [firstNonNull](https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/ObjectUtils.html#firstNonNull-T...-) useful in some situations\. Alternatively, write your own static helper methods to make it easier to handle potentially null values and make your code more readable\. + +## Building, synthesizing, and deploying<a name="java-running"></a> + +The AWS CDK automatically compiles your app before running it\. However, it can be useful to build your app manually to check for errors and to run tests\. You can do this in your IDE \(for example, press Control\-B in Eclipse\) or by issuing `mvn compile` at a command prompt while in your project's root directory\. + +Run any tests you've written by running `mvn test` at a command prompt\. + +The [stacks](stacks.md) defined in your AWS CDK app can be synthesized and deployed individually or together using the commands below\. Generally, you should be in your project's main directory when you issue them\. ++ `cdk synth`: Synthesizes a AWS CloudFormation template from one or more of the stacks in your AWS CDK app\. ++ `cdk deploy`: Deploys the resources defined by one or more of the stacks in your AWS CDK app to AWS\. + +You can specify the names of multiple stacks to be synthesized or deployed in a single command\. If your app defines only one stack, you do not need to specify it\. + +``` +cdk synth # app defines single stack +cdk deploy Happy Grumpy # app defines two or more stacks; two are deployed +``` + +You may also use the wildcards \* \(any number of characters\) and ? \(any single character\) to identify stacks by pattern\. When using wildcards, enclose the pattern in quotes\. Otherwise, the shell may try to expand it to the names of files in the current directory before they are passed to the AWS CDK Toolkit\. + +``` +cdk synth "Stack?" # Stack1, StackA, etc. +cdk deploy "*Stack" # PipeStack, LambdaStack, etc. +``` + +**Tip** +You don't need to explicitly synthesize stacks before deploying them; `cdk deploy` performs this step for you to make sure your latest code gets deployed\. + +For full documentation of the `cdk` command, see [AWS CDK Toolkit \(`cdk` command\)](cli.md)\. \ No newline at end of file diff --git a/v1/work-with-cdk-javascript.md b/v1/work-with-cdk-javascript.md new file mode 100644 index 00000000..f7b3183a --- /dev/null +++ b/v1/work-with-cdk-javascript.md @@ -0,0 +1,294 @@ +# Working with the AWS CDK in JavaScript<a name="work-with-cdk-javascript"></a> + +JavaScript is a fully\-supported client language for the AWS CDK and is considered stable\. Working with the AWS CDK in JavaScript uses familiar tools, including [Node\.js](https://nodejs.org/) and the Node Package Manager \(`npm`\)\. You may also use [Yarn](https://yarnpkg.com/) if you prefer, though the examples in this Guide use NPM\. The modules comprising the AWS Construct Library are distributed via the NPM repository, [npmjs\.org](https://www.npmjs.com/)\. + +You can use any editor or IDE; many AWS CDK developers use [Visual Studio Code](https://code.visualstudio.com/) \(or its open\-source equivalent [VSCodium](https://vscodium.com/)\), which has good support for JavaScript\. + +## Prerequisites<a name="javascript-prerequisites"></a> + +To work with the AWS CDK, you must have an AWS account and credentials and have installed Node\.js and the AWS CDK Toolkit\. See [AWS CDK Prerequisites](work-with.md#work-with-prerequisites)\. + +JavaScript AWS CDK applications require no additional prerequisites beyond these\. + +**Note** +Third\-party Language Deprecation: language version is only supported until its EOL \(End Of Life\) shared by the vendor or community and is subject to change with prior notice\. + +## Creating a project<a name="javascript-newproject"></a> + +You create a new AWS CDK project by invoking `cdk init` in an empty directory\. + +``` +mkdir my-project +cd my-project +cdk init app --language javascript +``` + +Creating a project also installs the [https://docs.aws.amazon.com/cdk/api/v1/docs/core-readme.html](https://docs.aws.amazon.com/cdk/api/v1/docs/core-readme.html) module and its dependencies\. + +`cdk init` uses the name of the project folder to name various elements of the project, including classes, subfolders, and files\. Hyphens in the folder name are converted to underscores\. However, the name should otherwise follow the form of a JavaScript identifier; for example, it should not start with a number or contain spaces\. + +## Using local `cdk`<a name="typescript-local"></a> + +For the most part, this guide assumes you install the CDK Toolkit globally \(`npm install -g aws-cdk`\), and the provided command examples \(such as `cdk synth`\) follow this assumption\. This approach makes it easy to keep the CDK Toolkit up to date, and since the CDK takes a strict approach to backward compatibility, there is generally little risk in always using the latest version\. + +Some teams prefer to specify all dependencies within each project, including tools like the CDK Toolkit\. This practice lets you pin such components to specific versions and ensure that all developers on your team \(and your CI/CD environment\) use exactly those versions\. This eliminates a possible source of change, helping to make builds and deployments more consistent and repeatable\. + +The CDK includes a dependency for the CDK Toolkit in the JavaScript project template's `package.json`, so if you want to use this approach, you don't need to make any changes to your project\. All you need to do is use slightly different commands for building your app and for issuing `cdk` commands\. + +| Operation | Use global CDK Toolkit | Use local CDK Toolkit | +| --- |--- |--- | +| Initialize project | `cdk init --language javascript` | `npx aws-cdk init --language javascript` | +| --- |--- |--- | +| Run CDK Toolkit command | `cdk ...` | `npm run cdk ...` or `npx aws-cdk ...` | +| --- |--- |--- | + +`npx aws-cdk` runs the version of the CDK Toolkit installed locally in the current project, if one exists, falling back to the global installation, if any\. If no global installation exists, `npx` downloads a temporary copy of the CDK Toolkit and runs that\. You may specify an arbitrary version of the CDK Toolkit using the `@` syntax: `npx aws-cdk@1.120 --version` prints `1.120.0`\. + +**Tip** +Set up an alias so you can use the `cdk` command with a local CDK Toolkit installation\. + +``` +alias cdk="npx aws-cdk" +``` + +``` +doskey cdk=npx aws-cdk $* +``` + +## Managing AWS Construct Library modules<a name="javascript-managemodules"></a> + +Use the Node Package Manager \(`npm`\) to install and update AWS Construct Library modules for use by your apps, as well as other packages you need\. \(You may use `yarn` instead of `npm` if you prefer\.\) `npm` also installs the dependencies for those modules automatically\. + +The AWS CDK core module is named `@aws-cdk/core`\. AWS Construct Library modules are named like `@aws-cdk/SERVICE-NAME`\. The service name has an *aws\-* prefix\. If you're unsure of a module's name, [search for it on NPM](https://www.npmjs.com/search?q=%40aws-cdk)\. + +**Note** +The [CDK API Reference](https://docs.aws.amazon.com/cdk/api/v1/docs/aws-construct-library.html) also shows the package names\. + +For example, the command below installs the modules for Amazon S3 and AWS Lambda\. + +``` +npm install @aws-cdk/aws-s3 @aws-cdk/aws-lambda +``` + +Some services' Construct Library support is in more than one module\. For example, besides the `@aws-cdk/aws-route53` module, there are three additional Amazon Route 53 modules, named `aws-route53-targets`, `aws-route53-patterns`, and `aws-route53resolver`\. + +Your project's dependencies are maintained in `package.json`\. You can edit this file to lock some or all of your dependencies to a specific version or to allow them to be updated to newer versions under certain criteria\. To update your project's NPM dependencies to the latest permitted version according to the rules you specified in `package.json`: + +``` +npm update +``` + +In JavaScript, you import modules into your code under the same name you use to install them using NPM\. We recommend the following practices when importing AWS CDK classes and AWS Construct Library modules in your applications\. Following these guidelines will help make your code consistent with other AWS CDK applications as well as easier to understand\. ++ Use `require()`, not ES6\-style `import` directives\. Older versions of Node\.js do not support ES6 imports, so using the older syntax is more widely compatible\. \(If you really want to use ES6 imports, use [esm](https://www.npmjs.com/package/esm) to ensure your project is compatible with all supported versions of Node\.js\.\) ++ Generally, import individual classes from `@aws-cdk/core`\. + + ``` + const { App, Construct } = require('@aws-cdk/core'); + ``` ++ If you need many classes from the core module, you may use a namespace alias of `cdk` instead of importing the individual classes\. Avoid doing both\. + + ``` + const cdk = require('@aws-cdk/core'); + ``` ++ Generally, import AWS Construct Libraries using short namespace aliases\. + + ``` + const s3 = require('@aws-cdk/aws-s3'); + ``` + +**Important** +All AWS Construct Library modules used in your project must be the same version\. + +## AWS CDK idioms in JavaScript<a name="javascript-cdk-idioms"></a> + +### Props<a name="javascript-props"></a> + +All AWS Construct Library classes are instantiated using three arguments: the *scope* in which the construct is being defined \(its parent in the construct tree\), an *id*, and *props*, a bundle of key/value pairs that the construct uses to configure the AWS resources it creates\. Other classes and methods also use the "bundle of attributes" pattern for arguments\. + +Using an IDE or editor that has good JavaScript autocomplete will help avoid misspelling property names\. If a construct is expecting an `encryptionKeys` property, and you spell it `encryptionkeys`, when instantiating the construct, you haven't passed the value you intended\. This can cause an error at synthesis time if the property is required, or cause the property to be silently ignored if it is optional\. In the latter case, you may get a default behavior you intended to override\. Take special care here\. + +When subclassing an AWS Construct Library class \(or overriding a method that takes a props\-like argument\), you may want to accept additional properties for your own use\. These values will be ignored by the parent class or overridden method, because they are never accessed in that code, so you can generally pass on all the props you received\. + +A future release of the AWS CDK could coincidentally add a new property with a name you used for your own property\. Passing the value you receive up the inheritance chain can then cause unexpected behavior\. It's safer to pass a shallow copy of the props you received with your property removed or set to `undefined`\. For example: + +``` +super(scope, name, {...props, encryptionKeys: undefined}); +``` + +Alternatively, name your properties so that it is clear that they belong to your construct\. This way, it is unlikely they will collide with properties in future AWS CDK releases\. If there are many of them, use a single appropriately\-named object to hold them\. + +### Missing values<a name="javascript-missing-values"></a> + +Missing values in an object \(such as `props`\) have the value `undefined` in JavaScript\. The usual techniques apply for dealing with these\. For example, a common idiom for accessing a property of a value that may be undefined is as follows: + +``` +// a may be undefined, but if it is not, it may have an attribute b +// c is undefined if a is undefined, OR if a doesn't have an attribute b +let c = a && a.b; +``` + +However, if `a` could have some other "falsy" value besides `undefined`, it is better to make the test more explicit\. Here, we'll take advantage of the fact that `null` and `undefined` are equal to test for them both at once: + +``` +let c = a == null ? a : a.b; +``` + +**Tip** +Node\.js 14\.0 and later support new operators that can simplify the handling of undefined values\. For more information, see the [optional chaining](https://github.com/tc39/proposal-optional-chaining/blob/master/README.md) and [nullish coalescing](https://github.com/tc39/proposal-nullish-coalescing/blob/master/README.md) proposals\. + +## Synthesizing and deploying<a name="javascript-running"></a> + +The [stacks](stacks.md) defined in your AWS CDK app can be synthesized and deployed individually or together using the commands below\. Generally, you should be in your project's main directory when you issue them\. ++ `cdk synth`: Synthesizes a AWS CloudFormation template from one or more of the stacks in your AWS CDK app\. ++ `cdk deploy`: Deploys the resources defined by one or more of the stacks in your AWS CDK app to AWS\. + +You can specify the names of multiple stacks to be synthesized or deployed in a single command\. If your app defines only one stack, you do not need to specify it\. + +``` +cdk synth # app defines single stack +cdk deploy Happy Grumpy # app defines two or more stacks; two are deployed +``` + +You may also use the wildcards \* \(any number of characters\) and ? \(any single character\) to identify stacks by pattern\. When using wildcards, enclose the pattern in quotes\. Otherwise, the shell may try to expand it to the names of files in the current directory before they are passed to the AWS CDK Toolkit\. + +``` +cdk synth "Stack?" # Stack1, StackA, etc. +cdk deploy "*Stack" # PipeStack, LambdaStack, etc. +``` + +**Tip** +You don't need to explicitly synthesize stacks before deploying them; `cdk deploy` performs this step for you to make sure your latest code gets deployed\. + +For full documentation of the `cdk` command, see [AWS CDK Toolkit \(`cdk` command\)](cli.md)\. + +## Using TypeScript examples with JavaScript<a name="javascript-using-typescript-examples"></a> + +[TypeScript](https://www.typescriptlang.org/) is the language we use to develop the AWS CDK, and it was the first language supported for developing applications, so many available AWS CDK code examples are written in TypeScript\. These code examples can be a good resource for JavaScript developers; you just need to remove the TypeScript\-specific parts of the code\. + +TypeScript snippets often use the newer ECMAScript `import` and `export` keywords to import objects from other modules and to declare the objects to be made available outside the current module\. Node\.js has just begun supporting these keywords in its latest releases\. Depending on the version of Node\.js you're using, you might rewrite imports and exports to use the older syntax\. + +Imports can be replaced with calls to the `require()` function\. + +------ +#### [ TypeScript ] + +``` +import * as cdk from '@aws-cdk/core'; +import { Bucket, BucketPolicy } from '@aws-cdk/aws-s3'; +``` + +------ +#### [ JavaScript ] + +``` +const cdk = require('@aws-cdk/core'); +const { Bucket, BucketPolicy } = require('@aws-cdk/aws-s3'); +``` + +------ + +Exports can be assigned to the `module.exports` object\. + +------ +#### [ TypeScript ] + +``` +export class Stack1 extends cdk.Stack { + // ... +} + +export class Stack2 extends cdk.Stack { + // ... +} +``` + +------ +#### [ JavaScript ] + +``` +class Stack1 extends cdk.Stack { + // ... +} + +class Stack2 extends cdk.Stack { + // ... +} + +module.exports = { Stack1, Stack2 } +``` + +------ + +**Note** +An alternative to using the old\-style imports and exports is to use the [https://www.npmjs.com/package/esm](https://www.npmjs.com/package/esm) module\. + +Once you've got the imports and exports sorted, you can dig into the actual code\. You may run into these commonly\-used TypeScript features: ++ Type annotations ++ Interface definitions ++ Type conversions/casts ++ Access modifiers + +Type annotations may be provided for variables, class members, function parameters, and function return types\. For variables, parameters, and members, types are specified by following the identifier with a colon and the type\. Function return values follow the function signature and consist of a colon and the type\. + +To convert type\-annotated code to JavaScript, remove the colon and the type\. Class members must have some value in JavaScript; set them to `undefined` if they only have a type annotation in TypeScript\. + +------ +#### [ TypeScript ] + +``` +var encrypted: boolean = true; + +class myStack extends core.Stack { + bucket: s3.Bucket; + // ... +} + +function makeEnv(account: string, region: string) : object { + // ... +} +``` + +------ +#### [ JavaScript ] + +``` +var encrypted = true; + +class myStack extends core.Stack { + bucket = undefined; + // ... +} + +function makeEnv(account, region) { + // ... +} +``` + +------ + +In TypeScript, interfaces are used to give bundles of required and optional properties, and their types, a name\. You can then use the interface name as a type annotation\. TypeScript will make sure that the object you use as, for example, an argument to a function has the required properties of the right types\. + +``` +interface myFuncProps { + code: lambda.Code, + handler?: string +} +``` + +JavaScript does not have an interface feature, so once you've removed the type annotations, delete the interface declarations entirely\. + +When a function or method returns a general\-purpose type \(such as `object`\), but you want to treat that value as a more specific child type to access properties or methods that are not part of the more general type's interface, TypeScript lets you *cast* the value using `as` followed by a type or interface name\. JavaScript doesn't support \(or need\) this, so simply remove `as` and the following identifier\. A less\-common cast syntax is to use a type name in brackets, `<LikeThis>`; these casts, too, must be removed\. + +Finally, TypeScript supports the access modifiers `public`, `protected`, and `private` for members of classes\. All class members in JavaScript are public\. Simply remove these modifiers wherever you see them\. + +Knowing how to identify and remove these TypeScript features goes a long way toward adapting short TypeScript snippets to JavaScript\. But it may be impractical to convert longer TypeScript examples in this fashion, since they are more likely to use other TypeScript features\. For these situations, we recommend [Sucrase](https://github.com/alangpierce/sucrase)\. Sucrase won't complain if code uses an undefined variable, for example, as `tsc` would\. If it is syntactically valid, then with few exceptions, Sucrase can translate it to JavaScript\. This makes it particularly valuable for converting snippets that may not be runnable on their own\. + +## Migrating to TypeScript<a name="javascript-to-typescript"></a> + +Many JavaScript developers move to [TypeScript](https://www.typescriptlang.org/) as their projects get larger and more complex\. TypeScript is a superset of JavaScript—all JavaScript code is valid TypeScript code, so no changes to your code are required—and it is also a supported AWS CDK language\. Type annotations and other TypeScript features are optional and can be added to your AWS CDK app as you find value in them\. TypeScript also gives you early access to new JavaScript features, such as optional chaining and nullish coalescing, before they're finalized—and without requiring that you upgrade Node\.js\. + +TypeScript's "shape\-based" interfaces, which define bundles of required and optional properties \(and their types\) within an object, allow common mistakes to be caught while you're writing the code, and make it easier for your IDE to provide robust autocomplete and other real\-time coding advice\. + +Coding in TypeScript does involve an additional step: compiling your app with the TypeScript compiler, `tsc`\. For typical AWS CDK apps, compilation requires a few seconds at most\. + +The easiest way to migrate an existing JavaScript AWS CDK app to TypeScript is to create a new TypeScript project using `cdk init app --language typescript`, then copy your source files \(and any other necessary files, such as assets like AWS Lambda function source code\) to the new project\. Rename your JavaScript files to end in `.ts` and begin developing in TypeScript\. \ No newline at end of file diff --git a/v1/work-with-cdk-python.md b/v1/work-with-cdk-python.md new file mode 100644 index 00000000..3864a54b --- /dev/null +++ b/v1/work-with-cdk-python.md @@ -0,0 +1,227 @@ +# Working with the AWS CDK in Python<a name="work-with-cdk-python"></a> + +Python is a fully\-supported client language for the AWS CDK and is considered stable\. Working with the AWS CDK in Python uses familiar tools, including the standard Python implementation \(CPython\), virtual environments with `virtualenv`, and the Python package installer `pip`\. The modules comprising the AWS Construct Library are distributed via [pypi\.org](https://pypi.org/search/?q=aws-cdk)\. The Python version of the AWS CDK even uses Python\-style identifiers \(for example, `snake_case` method names\)\. + +You can use any editor or IDE\. Many AWS CDK developers use [Visual Studio Code](https://code.visualstudio.com/) \(or its open\-source equivalent [VSCodium](https://vscodium.com/)\), which has good support for Python via an [official extension](https://marketplace.visualstudio.com/items?itemName=ms-python.python)\. The IDLE editor included with Python will suffice to get started\. The Python modules for the AWS CDK do have type hints, which are useful for a linting tool or an IDE that supports type validation\. + +## Prerequisites<a name="python-prerequisites"></a> + +To work with the AWS CDK, you must have an AWS account and credentials and have installed Node\.js and the AWS CDK Toolkit\. See [AWS CDK Prerequisites](work-with.md#work-with-prerequisites)\. + +Python AWS CDK applications require Python 3\.6 or later\. If you don't already have it installed, [download a compatible version](https://www.python.org/downloads/) for your operating system at [python\.org](https://www.python.org/)\. If you run Linux, your system may have come with a compatible version, or you may install it using your distro's package manager \(`yum`, `apt`, etc\.\)\. Mac users may be interested in [Homebrew](https://brew.sh/), a Linux\-style package manager for macOS\. + +**Note** +Third\-party Language Deprecation: language version is only supported until its EOL \(End Of Life\) shared by the vendor or community and is subject to change with prior notice\. + +The Python package installer, `pip`, and virtual environment manager, `virtualenv`, are also required\. Windows installations of compatible Python versions include these tools\. On Linux, `pip` and `virtualenv` may be provided as separate packages in your package manager\. Alternatively, you may install them with the following commands: + +``` +python -m ensurepip --upgrade +python -m pip install --upgrade pip +python -m pip install --upgrade virtualenv +``` + +If you encounter a permission error, run the above commands with the `--user` flag so that the modules are installed in your user directory, or use `sudo` to obtain the permissions to install the modules system\-wide\. + +**Note** +It is common for Linux distros to use the executable name `python3` for Python 3\.x, and have `python` refer to a Python 2\.x installation\. Some distros have an optional package you can install that makes the `python` command refer to Python 3\. Failing that, you can adjust the command used to run your application by editing `cdk.json` in the project's main directory\. + +**Note** +On Windows, you may want to invoke Python \(and pip\) using the py executable, the [>Python launcher for Windows](https://docs.python.org/3/using/windows.html#launcher)\. Among other things, the launcher allows you to easily specify which installed version of Python you want to use\. +If typing python at the command line results in a message about installing Python from the Windows Store, even after installing a Windows version of Python, open Windows' Manage App Execution Aliases settings panel and turn off the two App Installer entries for Python\. + +## Creating a project<a name="python-newproject"></a> + +You create a new AWS CDK project by invoking `cdk init` in an empty directory\. + +``` +mkdir my-project +cd my-project +cdk init app --language python +``` + +`cdk init` uses the name of the project folder to name various elements of the project, including classes, subfolders, and files\. Hyphens in the folder name are converted to underscores\. However, the name should otherwise follow the form of a Python identifier; for example, it should not start with a number or contain spaces\. + +After initializing the project, activate the project's virtual environment\. This allows the project's dependencies to be installed locally in the project folder, instead of globally\. + +``` +source .venv/bin/activate +``` + +**Note** +You may recognize this as the Mac/Linux command to activate a virtual environment\. The Python templates include a batch file, `source.bat`, that allows the same command to be used on Windows\. The traditional Windows command, `.venv\Scripts\activate.bat`, works, too\. +If you initialized your AWS CDK project using CDK Toolkit v1\.70\.0 or earlier, your virtual environment is in the `.env` directory instead of `.venv`\. + +After activating your virtual environment, install the app's standard dependencies: + +``` +python -m pip install -r requirements.txt +``` + +**Important** +Activate the project's virtual environment whenever you start working on it\. Otherwise, you won't have access to the modules installed there, and modules you install will go in the Python global module directory \(or will result in a permission error\)\. + +## Managing AWS Construct Library modules<a name="python-managemodules"></a> + +Use the Python package installer, pip, to install and update AWS Construct Library modules for use by your apps, as well as other packages you need\. pip also installs the dependencies for those modules automatically\. If your system does not recognize pip as a standalone command, invoke pip as a Python module, like this: + +``` +python -m pip PIP-COMMAND +``` + +The AWS CDK core module is named `aws-cdk.core`\. AWS Construct Library modules are named like `aws-cdk.SERVICE-NAME`\. The service name includes an *aws* prefix\. If you're unsure of a module's name, [search for it at PyPI](https://pypi.org/search/?q=aws-cdk)\. For example, the command below installs the modules for Amazon S3 and AWS Lambda\. + +``` +python -m pip install aws-cdk.aws-s3 aws-cdk.aws-lambda +``` + +Some services' Construct Library support is in more than one module\. For example, besides the `aws-cdk.aws-route53` module, there are three additional Amazon Route 53 modules, named `aws-route53-targets`, `aws-route53-patterns`, and `aws-route53resolver`\. + +**Note** +The [Python edition of the CDK API Reference](https://docs.aws.amazon.com/cdk/api/v1/python/index.html) also shows the package names\. + +The names used for importing AWS Construct Library modules into your Python code are similar to their package names\. Simply replace the hyphens with underscores\. + +``` +import aws_cdk.aws_s3 as s3 +import aws_cdk.aws_lambda as lambda_ +``` + +We recommend the following practices when importing AWS CDK classes and AWS Construct Library modules in your applications\. Following these guidelines will help make your code consistent with other AWS CDK applications as well as easier to understand\. ++ Generally, import individual classes from `aws_cdk.core`\. + + ``` + from aws_cdk.core import App, Construct + ``` ++ If you need many classes from the core module, you may use a namespace alias of `cdk` instead of importing individual classes\. Avoid doing both\. + + ``` + import aws_cdk.core as cdk + ``` ++ Generally, import AWS Construct Libraries using short namespace aliases\. + + ``` + import aws_cdk.aws_s3 as s3 + ``` + +After installing a module, update your project's `requirements.txt` file, which lists your project's dependencies\. It is best to do this manually rather than using `pip freeze`\. `pip freeze` captures the current versions of all modules installed in your Python virtual environment, which can be useful when bundling up a project to be run elsewhere\. + +Usually, though, your `requirements.txt` should list only top\-level dependencies \(modules that your app depends on directly\) and not the dependencies of those modules\. This strategy makes updating your dependencies simpler\. Here is what your `requirements.txt` file might look like if you have installed the Amazon S3 and AWS Lambda modules as shown earlier\. + +``` +aws-cdk.aws-s3==X.YY.ZZ +aws-cdk.aws-lambda==X.YY.ZZ +``` + +You can edit `requirements.txt` to allow upgrades; simply replace the `==` preceding a version number with `~=` to allow upgrades to a higher compatible version, or remove the version requirement entirely to specify the latest available version of the module\. + +With `requirements.txt` edited appropriately to allow upgrades, issue this command to upgrade your project's installed modules at any time: + +``` +pip install --upgrade -r requirements.txt +``` + +**Important** +All AWS Construct Library modules used in your project must be the same version\. + +## AWS CDK idioms in Python<a name="python-cdk-idioms"></a> + +### Language conflicts<a name="python-keywords"></a> + +In Python, `lambda` is a language keyword, so you cannot use it as a name for the AWS Lambda construct library module or Lambda functions\. The Python convention for such conflicts is to use a trailing underscore, as in `lambda_`, in the variable name\. + +By convention, the second argument to AWS CDK constructs is named `id`\. When writing your own stacks and constructs, calling a parameter `id` "shadows" the Python built\-in function `id()`, which returns an object's unique identifier\. This function isn't used very often, but if you should happen to need it in your construct, rename the argument, for example `construct_id`\. + +### Arguments and properties<a name="python-props"></a> + +All AWS Construct Library classes are instantiated using three arguments: the *scope* in which the construct is being defined \(its parent in the construct tree\), an *id*, and *props*, a bundle of key/value pairs that the construct uses to configure the resources it creates\. Other classes and methods also use the "bundle of attributes" pattern for arguments\. + +*scope* and *id* should always be passed as positional arguments, not keyword arguments, because their names change if the construct accepts a property named *scope* or *id*\. + +In Python, props are expressed as keyword arguments\. If an argument contains nested data structures, these are expressed using a class which takes its own keyword arguments at instantiation\. The same pattern is applied to other method calls that take a structured argument\. + +For example, in a Amazon S3 bucket's `add_lifecycle_rule` method, the `transitions` property is a list of `Transition` instances\. + +``` +bucket.add_lifecycle_rule( + transitions=[ + Transition( + storage_class=StorageClass.GLACIER, + transition_after=Duration.days(10) + ) + ] +) +``` + +When extending a class or overriding a method, you may want to accept additional arguments for your own purposes that are not understood by the parent class\. In this case you should accept the arguments you don't care about using the `**kwargs` idiom, and use keyword\-only arguments to accept the arguments you're interested in\. When calling the parent's constructor or the overridden method, pass only the arguments it is expecting \(often just `**kwargs`\)\. Passing arguments that the parent class or method doesn't expect results in an error\. + +``` +class MyConstruct(Construct): + def __init__(self, id, *, MyProperty=42, **kwargs): + super().__init__(self, id, **kwargs) + # ... +``` + +A future release of the AWS CDK could coincidentally add a new property with a name you used for your own property\. This won't cause any technical issues for users of your construct or method \(since your property isn't passed "up the chain," the parent class or overridden method will simply use a default value\) but it may cause confusion\. You can avoid this potential problem by naming your properties so they clearly belong to your construct\. If there are many new properties, bundle them into an appropriately\-named class and pass it as a single keyword argument\. + +### Missing values<a name="python-missing-values"></a> + +The AWS CDK uses `None` to represent missing or undefined values\. When working with `**kwargs`, use the dictionary's `get()` method to provide a default value if a property is not provided\. Avoid using `kwargs[...]`, as this raises `KeyError` for missing values\. + +``` +encrypted = kwargs.get("encrypted") # None if no property "encrypted" exists +encrypted = kwargs.get("encrypted", False) # specify default of False if property is missing +``` + +Some AWS CDK methods \(such as `tryGetContext()` to get a runtime context value\) may return `None`, which you will need to check explicitly\. + +### Using interfaces<a name="python-interfaces"></a> + +Python doesn't have an interface feature as some other languages do, though it does have [abstract base classes](https://docs.python.org/3/library/abc.html), which are similar\. \(If you're not familiar with interfaces, Wikipedia has [a good introduction](https://en.wikipedia.org/wiki/Interface_(computing)#In_object-oriented_languages)\.\) TypeScript, the language in which the AWS CDK is implemented, does provide interfaces, and constructs and other AWS CDK objects often require an object that adheres to a particular interface, rather than inheriting from a particular class\. So the AWS CDK provides its own interface feature as part of the [JSII](https://github.com/aws/jsii) layer\. + +To indicate that a class implements a particular interface, you can use the `@jsii.implements` decorator: + +``` +from aws_cdk.core import IAspect, IConstruct +import jsii + +@jsii.implements(IAspect) +class MyAspect(): + def visit(self, node: IConstruct) -> None: + print("Visited", node.node.path) +``` + +### Type pitfalls<a name="python-type-pitfalls"></a> + +Python uses dynamic typing, where all variables may refer to a value of any type\. Parameters and return values may be annotated with types, but these are "hints" and are not enforced\. This means that in Python, it is easy to pass the incorrect type of value to a AWS CDK construct\. Instead of getting a type error during build, as you would from a statically\-typed language, you may instead get a runtime error when the JSII layer \(which translates between Python and the AWS CDK's TypeScript core\) is unable to deal with the unexpected type\. + +In our experience, the type errors Python programmers make tend to fall into these categories\. ++ Passing a single value where a construct expects a container \(Python list or dictionary\) or vice versa\. ++ Passing a value of a type associated with a layer 1 \(`CfnXxxxxx`\) construct to an L2 or L3 construct, or vice versa\. + +The AWS CDK Python modules include type annotations, so you can use tools that support them to help with types\. If you are not using an IDE that supports these, such as [PyCharm](https://www.jetbrains.com/pycharm/), you might want to call the [MyPy](http://mypy-lang.org/) type validator as a step in your build process\. There are also runtime type checkers that can improve error messages for type\-related errors\. + +## Synthesizing and deploying<a name="python-running"></a> + +The [stacks](stacks.md) defined in your AWS CDK app can be synthesized and deployed individually or together using the commands below\. Generally, you should be in your project's main directory when you issue them\. ++ `cdk synth`: Synthesizes a AWS CloudFormation template from one or more of the stacks in your AWS CDK app\. ++ `cdk deploy`: Deploys the resources defined by one or more of the stacks in your AWS CDK app to AWS\. + +You can specify the names of multiple stacks to be synthesized or deployed in a single command\. If your app defines only one stack, you do not need to specify it\. + +``` +cdk synth # app defines single stack +cdk deploy Happy Grumpy # app defines two or more stacks; two are deployed +``` + +You may also use the wildcards \* \(any number of characters\) and ? \(any single character\) to identify stacks by pattern\. When using wildcards, enclose the pattern in quotes\. Otherwise, the shell may try to expand it to the names of files in the current directory before they are passed to the AWS CDK Toolkit\. + +``` +cdk synth "Stack?" # Stack1, StackA, etc. +cdk deploy "*Stack" # PipeStack, LambdaStack, etc. +``` + +**Tip** +You don't need to explicitly synthesize stacks before deploying them; `cdk deploy` performs this step for you to make sure your latest code gets deployed\. + +For full documentation of the `cdk` command, see [AWS CDK Toolkit \(`cdk` command\)](cli.md)\. \ No newline at end of file diff --git a/v1/work-with-cdk-typescript.md b/v1/work-with-cdk-typescript.md new file mode 100644 index 00000000..52aa3746 --- /dev/null +++ b/v1/work-with-cdk-typescript.md @@ -0,0 +1,166 @@ +# Working with the AWS CDK in TypeScript<a name="work-with-cdk-typescript"></a> + +TypeScript is a fully\-supported client language for the AWS CDK and is considered stable\. Working with the AWS CDK in TypeScript uses familiar tools, including Microsoft's TypeScript compiler \(`tsc`\), [Node\.js](https://nodejs.org/) and the Node Package Manager \(`npm`\)\. You may also use [Yarn](https://yarnpkg.com/) if you prefer, though the examples in this Guide use NPM\. The modules comprising the AWS Construct Library are distributed via the NPM repository, [npmjs\.org](https://www.npmjs.com/)\. + +You can use any editor or IDE; many AWS CDK developers use [Visual Studio Code](https://code.visualstudio.com/) \(or its open\-source equivalent [VSCodium](https://vscodium.com/)\), which has excellent support for TypeScript\. + +## Prerequisites<a name="typescript-prerequisites"></a> + +To work with the AWS CDK, you must have an AWS account and credentials and have installed Node\.js and the AWS CDK Toolkit\. See [AWS CDK Prerequisites](work-with.md#work-with-prerequisites)\. + +You also need TypeScript itself \(version 2\.7 or later\)\. If you don't already have it, you can install it using `npm`\. + +``` +npm install -g typescript +``` + +**Note** +If you get a permission error, and have administrator access on your system, try `sudo npm install -g typescript`\. + +Keep TypeScript up to date with a regular `npm update -g typescript`\. + +**Note** +Third\-party Language Deprecation: language version is only supported until its EOL \(End Of Life\) shared by the vendor or community and is subject to change with prior notice\. + +## Creating a project<a name="typescript-newproject"></a> + +You create a new AWS CDK project by invoking `cdk init` in an empty directory\. + +``` +mkdir my-project +cd my-project +cdk init app --language typescript +``` + +Creating a project also installs the [https://docs.aws.amazon.com/cdk/api/v1/docs/core-readme.html](https://docs.aws.amazon.com/cdk/api/v1/docs/core-readme.html) module and its dependencies\. + +`cdk init` uses the name of the project folder to name various elements of the project, including classes, subfolders, and files\. Hyphens in the folder name are converted to underscores\. However, the name should otherwise follow the form of a TypeScript identifier; for example, it should not start with a number or contain spaces\. + +## Using local `tsc` and `cdk`<a name="typescript-local"></a> + +For the most part, this guide assumes you install TypeScript and the CDK Toolkit globally \(`npm install -g typescript aws-cdk`\), and the provided command examples \(such as `cdk synth`\) follow this assumption\. This approach makes it easy to keep both components up to date, and since both take a strict approach to backward compatibility, there is generally little risk in always using the latest versions\. + +Some teams prefer to specify all dependencies within each project, including tools like the TypeScript compiler and the CDK Toolkit\. This practice lets you pin these components to specific versions and ensure that all developers on your team \(and your CI/CD environment\) use exactly those versions\. This eliminates a possible source of change, helping to make builds and deployments more consistent and repeatable\. + +The CDK includes dependencies for both TypeScript and the CDK Toolkit in the TypeScript project template's `package.json`, so if you want to use this approach, you don't need to make any changes to your project\. All you need to do is use slightly different commands for building your app and for issuing `cdk` commands\. + +| Operation | Use global tools | Use local tools | +| --- |--- |--- | +| Initialize project | `cdk init --language typescript` | `npx aws-cdk init --language typescript` | +| --- |--- |--- | +| Build | `tsc` | `npm run build` | +| --- |--- |--- | +| Run CDK Toolkit command | `cdk ...` | `npm run cdk ...` or `npx aws-cdk ...` | +| --- |--- |--- | + +`npx aws-cdk` runs the version of the CDK Toolkit installed locally in the current project, if one exists, falling back to the global installation, if any\. If no global installation exists, `npx` downloads a temporary copy of the CDK Toolkit and runs that\. You may specify an arbitrary version of the CDK Toolkit using the `@` syntax: `npx aws-cdk@1.120 --version` prints `1.120.0`\. + +**Tip** +Set up an alias so you can use the `cdk` command with a local CDK Toolkit installation\. + +``` +alias cdk="npx aws-cdk" +``` + +``` +doskey cdk=npx aws-cdk $* +``` + +## Managing AWS Construct Library modules<a name="typescript-managemodules"></a> + +Use the Node Package Manager \(`npm`\) to install and update AWS Construct Library modules for use by your apps, as well as other packages you need\. \(You may use `yarn` instead of `npm` if you prefer\.\) `npm` also installs the dependencies for those modules automatically\. + +The AWS CDK core module is named `@aws-cdk/core`\. AWS Construct Library modules are named like `@aws-cdk/SERVICE-NAME`\. The service name has an *aws* prefix\. If you're unsure of a module's name, [search for it on NPM](https://www.npmjs.com/search?q=%40aws-cdk)\. + +**Note** +The [CDK API Reference](https://docs.aws.amazon.com/cdk/api/v1/docs/aws-construct-library.html) also shows the package names\. + +For example, the command below installs the modules for Amazon S3 and AWS Lambda\. + +``` +npm install @aws-cdk/aws-s3 @aws-cdk/aws-lambda +``` + +Some services' Construct Library support is in more than one module\. For example, besides the `@aws-cdk/aws-route53` module, there are three additional Amazon Route 53 modules, named `aws-route53-targets`, `aws-route53-patterns`, and `aws-route53resolver`\. + +Your project's dependencies are maintained in `package.json`\. You can edit this file to lock some or all of your dependencies to a specific version or to allow them to be updated to newer versions under certain criteria\. To update your project's NPM dependencies to the latest permitted version according to the rules you specified in `package.json`: + +``` +npm update +``` + +In TypeScript, you import modules into your code under the same name you use to install them using NPM\. We recommend the following practices when importing AWS CDK classes and AWS Construct Library modules in your applications\. Following these guidelines will help make your code consistent with other AWS CDK applications as well as easier to understand\. ++ Use ES6\-style `import` directives, not `require()`\. ++ Generally, import individual classes from `@aws-cdk/core`\. + + ``` + import { App, Construct } from '@aws-cdk/core'; + ``` ++ If you need many classes from the core module, you may use a namespace alias of `cdk` instead of importing the individual classes\. Avoid doing both\. + + ``` + import * as cdk from '@aws-cdk/core'; + ``` ++ Generally, import AWS Construct Libraries using short namespace aliases\. + + ``` + import * as s3 from '@aws-cdk/aws-s3'; + ``` + +**Important** +All AWS Construct Library modules used in your project must be the same version\. + +## AWS CDK idioms in TypeScript<a name="typescript-cdk-idioms"></a> + +### Props<a name="typescript-props"></a> + +All AWS Construct Library classes are instantiated using three arguments: the *scope* in which the construct is being defined \(its parent in the construct tree\), an *id*, and *props*, a bundle of key/value pairs that the construct uses to configure the AWS resources it creates\. Other classes and methods also use the "bundle of attributes" pattern for arguments\. + +In TypeScript, the shape of `props` is defined using an interface that tells you the required and optional arguments and their types\. Such an interface is defined for each kind of `props` argument, usually specific to a single construct or method\. For example, the [Bucket](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-s3.Bucket.html) construct \(in the `@aws-cdk/aws-s3 module`\) specifies a `props` argument conforming to the [BucketProps](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-s3.BucketProps.html) interface\. + +If a property is itself an object, for example the [websiteRedirect](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-s3.BucketProps.html#websiteredirect) property of `BucketProps`, that object will have its own interface to which its shape must conform, in this case [RedirectTarget](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-s3.RedirectTarget.html)\. + +If you are subclassing an AWS Construct Library class \(or overriding a method that takes a props\-like argument\), you can inherit from the existing interface to create a new one that specifies any new props your code requires\. When calling the parent class or base method, generally you can pass the entire props argument you received, since any attributes provided in the object but not specified in the interface will be ignored\. + +A future release of the AWS CDK could coincidentally add a new property with a name you used for your own property\. Passing the value you receive up the inheritance chain can then cause unexpected behavior\. It's safer to pass a shallow copy of the props you received with your property removed or set to `undefined`\. For example: + +``` +super(scope, name, {...props, encryptionKeys: undefined}); +``` + +Alternatively, name your properties so that it is clear that they belong to your construct\. This way, it is unlikely they will collide with properties in future AWS CDK releases\. If there are many of them, use a single appropriately\-named object to hold them\. + +### Missing values<a name="typescript-missing-values"></a> + +Missing values in an object \(such as props\) have the value `undefined` in TypeScript\. Recent versions of the language include operators that simplify working with these values, making it easier to specify defaults and "short\-circuit" chaining when an undefined value is reached\. For more information about these features, see the [TypeScript 3\.7 Release Notes](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html), specifically the first two features, Optional Chaining and Nullish Coalescing\. + +## Building, synthesizing, and deploying<a name="typescript-running"></a> + +Generally, you should be in the project's root directory when building and running your application\. + +Node\.js cannot run TypeScript directly; instead, your application is converted to JavaScript using the TypeScript compiler, `tsc`\. The resulting JavaScript code is then executed\. + +The AWS CDK automatically does this whenever it needs to run your app\. However, it can be useful to compile manually to check for errors and to run tests\. To compile your TypeScript app manually, issue `npm run build`\. You may also issue `npm run watch` to enter watch mode, in which the TypeScript compiler automatically rebuilds your app whenever you save changes to a source file\. + +The [stacks](stacks.md) defined in your AWS CDK app can be synthesized and deployed individually or together using the commands below\. Generally, you should be in your project's main directory when you issue them\. ++ `cdk synth`: Synthesizes a AWS CloudFormation template from one or more of the stacks in your AWS CDK app\. ++ `cdk deploy`: Deploys the resources defined by one or more of the stacks in your AWS CDK app to AWS\. + +You can specify the names of multiple stacks to be synthesized or deployed in a single command\. If your app defines only one stack, you do not need to specify it\. + +``` +cdk synth # app defines single stack +cdk deploy Happy Grumpy # app defines two or more stacks; two are deployed +``` + +You may also use the wildcards \* \(any number of characters\) and ? \(any single character\) to identify stacks by pattern\. When using wildcards, enclose the pattern in quotes\. Otherwise, the shell may try to expand it to the names of files in the current directory before they are passed to the AWS CDK Toolkit\. + +``` +cdk synth "Stack?" # Stack1, StackA, etc. +cdk deploy "*Stack" # PipeStack, LambdaStack, etc. +``` + +**Tip** +You don't need to explicitly synthesize stacks before deploying them; `cdk deploy` performs this step for you to make sure your latest code gets deployed\. + +For full documentation of the `cdk` command, see [AWS CDK Toolkit \(`cdk` command\)](cli.md)\. \ No newline at end of file diff --git a/v1/work-with-cdk-v2.md b/v1/work-with-cdk-v2.md new file mode 100644 index 00000000..f93d3762 --- /dev/null +++ b/v1/work-with-cdk-v2.md @@ -0,0 +1,34 @@ +# Migrating to AWS CDK v2<a name="work-with-cdk-v2"></a> + +Version 2 of the AWS CDK provides an improved development experience that aims to make Infrastructure as Code \(IAC\) even simpler\. + +CDK v1 entered maintenance on June 1, 2022\. During the maintenance phase, CDK v1 will receive critical bug fixes and security patches only, and new features will be developed exclusively for CDK v2\. On June 1, 2023, support will end entirely for AWS CDK v1\. For more details, see [AWS CDK Maintenance Policy](https://github.com/aws/aws-cdk-rfcs/blob/master/text/0079-cdk-2.0.md#aws-cdk-maintenance-policy)\. + +For information on migrating your apps to AWS CDK v2, see [Migrating to AWS CDK v2](../../v2/guide/migrating-v2.html) in the AWS CDK v2 Developer Guide\. + +**Tip** +To identify stacks deployed with AWS CDK v1, use the [awscdk\-v1\-stack\-finder](https://www.npmjs.com/package/awscdk-v1-stack-finder) utility\. + +## CDK Toolkit v2 compatibility<a name="work-with-cdk-v2-cli"></a> + +CDK v2 requires v2 or later of the CDK Toolkit\. This version is backward\-compatible with CDK v1 apps, so you can use a single globally\-installed version of CDK Toolkit with all your AWS CDK projects, whether they use v1 or v2\. An exception is that CDK Toolkit v2 only creates CDK v2 projects\. + +If you need to create both v1 and v2 CDK projects, **do not install CDK Toolkit v2 globally\.** \(Remove it if you already have it installed: `npm remove -g aws-cdk`\.\) To invoke the CDK Toolkit, use npx to run v1 or v2 of the CDK Toolkit as desired\. + +``` +npx aws-cdk@1.x init app --language typescript +npx aws-cdk@2.x init app --language typescript +``` + +**Tip** +Set up command line aliases so you can use cdk and cdk2 commands to invoke the desired version of the CDK Toolkit\. + +``` +alias cdk="npx aws-cdk@1.x" +alias cdk2="npx aws-cdk@2.x" +``` + +``` +doskey cdk=npx aws-cdk@1.x $* +doskey cdk2=npx aws-cdk@2.x $* +``` \ No newline at end of file diff --git a/v1/work-with.md b/v1/work-with.md new file mode 100644 index 00000000..09e79c33 --- /dev/null +++ b/v1/work-with.md @@ -0,0 +1,74 @@ +# Working with the AWS CDK<a name="work-with"></a> + +The AWS Cloud Development Kit \(AWS CDK\) lets you define your AWS cloud infrastructure in a general\-purpose programming language\. Currently, the AWS CDK supports TypeScript, JavaScript, Python, Java, C\#, and Go\. It is also possible to use other JVM and \.NET languages, though we are unable to provide support for every such language\. + +**Note** +This Guide does not currently include instructions or code examples for Go aside from [Working with the AWS CDK in Go](work-with-cdk-go.md)\. + +We develop the AWS CDK in TypeScript and use [JSII](https://github.com/aws/jsii) to provide a "native" experience in other supported languages\. For example, we distribute AWS Construct Library modules using your preferred language's standard repository, and you install them using the language's standard package manager\. Methods and properties are even named using your language's recommended naming patterns\. + +## AWS CDK prerequisites<a name="work-with-prerequisites"></a> + +To use the AWS CDK, you need an AWS account and a corresponding access key\. If you don't have an AWS account yet, see [Create and Activate an AWS Account](https://aws.amazon.com/premiumsupport/knowledge-center/create-and-activate-aws-account/)\. To find out how to obtain an access key ID and secret access key for your AWS account, see [Understanding and Getting Your Security Credentials](https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html)\. To find out how to configure your workstation so the AWS CDK uses your credentials, see [Setting Credentials in Node\.js](https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/setting-credentials-node.html)\. + +**Tip** +If you have the [AWS CLI](https://aws.amazon.com/cli/) installed, the simplest way to set up your workstation with your AWS credentials is to open a command prompt and type: + +``` +aws configure +``` + +All AWS CDK applications require Node\.js 10\.13 or later, even if you work in Python, Java, C\#, or Go\. You may download a compatible version at [nodejs\.org](https://nodejs.org/)\. We recommend the [active LTS version](https://nodejs.org/en/about/releases/) \(at this writing, the latest 16\.x release\)\. Node\.js versions 13\.0\.0 through 13\.6\.0 are not compatible with the AWS CDK due to compatibility issues with its dependencies\. + +After installing Node\.js, install the AWS CDK Toolkit \(the `cdk` command\): + +``` +npm install -g aws-cdk +``` + +**Note** +If you get a permission error, and have administrator access on your system, try `sudo npm install -g aws-cdk`\. + +Test the installation by issuing `cdk --version`\. + +If you get an error message at this point, try uninstalling \(`npm uninstall -g aws-cdk`\) and reinstalling\. As a last resort, delete the `node-modules` folder from the current project as well as the global `node-modules` folder\. To figure out where this folder is, issue `npm config get prefix`\. + +### Language\-specific prerequisites<a name="work-with-prerequisites-language"></a> + +The specific language you work in also has its own prerequisites, described in the corresponding topic listed here\. ++ [Working with the AWS CDK in TypeScript](work-with-cdk-typescript.md) ++ [Working with the AWS CDK in JavaScript](work-with-cdk-javascript.md) ++ [Working with the AWS CDK in Python](work-with-cdk-python.md) ++ [Working with the AWS CDK in Java](work-with-cdk-java.md) ++ [Working with the AWS CDK in C\#](work-with-cdk-csharp.md) ++ [Working with the AWS CDK in Go](work-with-cdk-go.md) + +**Note** +Third\-party Language Deprecation: language version is only supported until its EOL \(End Of Life\) shared by the vendor or community and is subject to change with prior notice\. + +## AWS Construct Library<a name="work-with-library"></a> + +The AWS CDK includes the AWS Construct Library, a collection of construct modules organized by AWS service\. The [AWS CDK API Reference](https://docs.aws.amazon.com/cdk/api/v1/docs/aws-construct-library.html) provides detailed documentation of the constructs \(and other components\) in the library\. A version of the API Reference is provided for each supported programming language\. + +Each module's reference material is broken into the following sections\. ++ *Overview*: Introductory material you'll need to know to work with the service in the AWS CDK, including concepts and examples\. ++ *Constructs*: Library classes that represent one or more concrete AWS resources\. These are the "curated" \(L2\) resources or patterns \(L3 resources\) that provide a high\-level interface with sane defaults\. ++ *Classes*: Non\-construct classes that provide functionality used by constructs in the module\. ++ *Structs*: Data structures \(attribute bundles\) that define the structure of composite values such as properties \(the `props` argument of constructs\) and options\. ++ *Interfaces*: Interfaces, whose names all begin with "I", define the absolute minimum functionality for the corresponding construct or other class\. The CDK uses construct interfaces to represent AWS resources that are defined outside your AWS CDK app and imported by methods such as `Bucket.fromBucketArn()`\. ++ *Enums*: Collections of named values for use in specifying certain construct parameters\. Using an enumerated value allows the CDK to check these values for validity during synthesis\. ++ *CloudFormation Resources*: These L1 constructs, whose names begin with "Cfn", represent exactly the resources defined in the CloudFormation specification\. They are automatically generated from that specification with each CDK release\. Each L2 or L3 construct encapsulates one or more CloudFormation resources\. ++ *CloudFormation Property Types*: The collection of named values that define the properties for each CloudFormation Resource\. + +### Interfaces vs\. construct classes<a name="work-with-library-interfaces"></a> + +The AWS CDK uses interfaces in a specific way that might not be obvious even if you are familiar with interfaces as a programming concept\. + +The AWS CDK supports importing resources defined outside CDK applications using methods such as `Bucket.fromBucketArn()`\. Imported resources cannot be modified and may not have all the functionality available with resources defined in your CDK app using e\.g\. the `Bucket` class\. Interfaces, then, represent the bare minimum functionality available in the CDK for a given AWS resource type, *including imported resources\.* + +When instantiating resources in your CDK app, then, you should always use concrete classes such as `Bucket`\. When specifying the type of an argument you are accepting in one of your own constructs, use the interface type such as `IBucket` if you are prepared to deal with imported resources \(that is, you won't need to change them\)\. If you require a CDK\-defined construct, specify the most general type you can use\. + +Some interfaces are minimum versions of properties or options bundles \(shown in the AWS CDK API Reference as Structs\) that are associated with specific constructs\. For example, `IBucketProps` is the smallest set of properties required to instantiate a bucket\. Such interfaces can be useful when subclassing constructs to accept arguments that you'll pass on to your parent class\. If you require one or more additional properties, you'll want to implement or derive from this interface, or from a more specific type such as `BucketProps`\. + +**Note** +Some programming languages supported by the AWS CDK don't have an interface feature\. In these languages, interfaces are just ordinary classes\. You can identify them by their names, which follow the pattern of an initial "I" followed by the name of some other construct \(e\.g\. `IBucket`\)\. The same rules apply\. \ No newline at end of file diff --git a/v2/.DS_Store b/v2/.DS_Store deleted file mode 100644 index 9b931010..00000000 Binary files a/v2/.DS_Store and /dev/null differ diff --git a/v2/about_examples.md b/v2/about_examples.md new file mode 100644 index 00000000..eea1ebeb --- /dev/null +++ b/v2/about_examples.md @@ -0,0 +1,3 @@ +# AWS CDK examples<a name="about_examples"></a> + +For more examples of AWS CDK stacks and apps in your favorite supported programming language, see the [CDK Examples](https://github.com/aws-samples/aws-cdk-examples) repository on GitHub\. \ No newline at end of file diff --git a/v2/apps.md b/v2/apps.md new file mode 100644 index 00000000..b7938985 --- /dev/null +++ b/v2/apps.md @@ -0,0 +1,228 @@ +# Apps<a name="apps"></a> + +As described in [Constructs](constructs.md), to provision infrastructure resources, all constructs that represent AWS resources must be defined, directly or indirectly, within the scope of a [Stack](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html) construct\. An [App](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.App.html) is a container for one or more stacks: it serves as each stack's scope\. Stacks within a single `App` can easily refer to each others' resources \(and attributes of those resources\)\. The AWS CDK infers dependencies between stacks so that they can be deployed in the correct order\. You can deploy any or all of the stacks defined within an app at with a single `cdk deploy` command\. + +The following example declares a stack class named `MyFirstStack` that includes a single Amazon S3 bucket\. + +------ +#### [ TypeScript ] + +``` +class MyFirstStack extends Stack { + constructor(scope: Construct, id: string, props?: StackProps) { + super(scope, id, props); + + new s3.Bucket(this, 'MyFirstBucket'); + } +} +``` + +------ +#### [ JavaScript ] + +``` +class MyFirstStack extends Stack { + constructor(scope, id, props) { + super(scope, id, props); + + new s3.Bucket(this, 'MyFirstBucket'); + } +} +``` + +------ +#### [ Python ] + +``` +class MyFirstStack(Stack): + + def __init__(self, scope: Construct, id: str, **kwargs): + super().__init__(scope, id, **kwargs) + + s3.Bucket(self, "MyFirstBucket") +``` + +------ +#### [ Java ] + +``` +public class MyFirstStack extends Stack { + public MyFirstStack(final Construct scope, final String id) { + this(scope, id, null); + } + + public MyFirstStack(final Construct scope, final String id, final StackProps props) { + super(scope, id, props); + + new Bucket(this, "MyFirstBucket"); + } +} +``` + +------ +#### [ C\# ] + +``` +public class MyFirstStack : Stack +{ + public MyFirstStack(Stack scope, string id, StackProps props = null) : base(scope, id, props) + { + new Bucket(this, "MyFirstBucket"); + } +} +``` + +------ + +However, this code has only *declared* a stack\. For the stack to actually be synthesized into an AWS CloudFormation template and deployed, it must be instantiated\. And, like all CDK constructs, it must be instantiated in some context\. The `App` is that context\. + +## The app construct<a name="apps_construct"></a> + +To define the previous stack within the scope of an application, use the [App](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.App.html) construct\. The following example app instantiates a `MyFirstStack` and produces the AWS CloudFormation template that the stack defined\. + +------ +#### [ TypeScript ] + +``` +const app = new App(); +new MyFirstStack(app, 'hello-cdk'); +app.synth(); +``` + +------ +#### [ JavaScript ] + +``` +const app = new App(); +new MyFirstStack(app, 'hello-cdk'); +app.synth(); +``` + +------ +#### [ Python ] + +``` +app = App() +MyFirstStack(app, "hello-cdk") +app.synth() +``` + +------ +#### [ Java ] + +``` +App app = new App(); +new MyFirstStack(app, "hello-cdk"); +app.synth(); +``` + +------ +#### [ C\# ] + +``` +var app = new App(); +new MyFirstStack(app, "hello-cdk"); +app.Synth(); +``` + +------ + +The `App` construct doesn't require any initialization arguments, because it's the only construct that can be used as a root for the construct tree\. You can now use the `App` instance as a scope for defining a single instance of your stack\. + +## App lifecycle<a name="lifecycle"></a> + +The following diagram shows the phases that the AWS CDK goes through when you call the cdk deploy\. This command deploys the resources that your app defines\. + +![\[Image NOT FOUND\]](http://docs.aws.amazon.com/cdk/v2/guide/images/Lifecycle.png) + +An AWS CDK app goes through the following phases in its lifecycle\. + +1\. Construction \(or Initialization\) + Your code instantiates all of the defined constructs and then links them together\. In this stage, all of the constructs \(app, stacks, and their child constructs\) are instantiated and the constructor chain is executed\. Most of your app code is executed in this stage\. + +2\. Preparation +All constructs that have implemented the `prepare` method participate in a final round of modifications, to set up their final state\. The preparation phase happens automatically\. As a user, you don't see any feedback from this phase\. It's rare to need to use the "prepare" hook, and generally not recommended\. Be very careful when mutating the construct tree during this phase, because the order of operations could impact behavior\. + +3\. Validation +All constructs that have implemented the `validate` method can validate themselves to ensure that they're in a state that will correctly deploy\. You will get notified of any validation failures that happen during this phase\. Generally, we recommend performing validation as soon as possible \(usually as soon as you get some input\) and throwing exceptions as early as possible\. Performing validation early improves diagnosability as stack traces will be more accurate, and ensures that your code can continue to execute safely\. + +4\. Synthesis +This is the final stage of the execution of your AWS CDK app\. It's triggered by a call to `app.synth()`, and it traverses the construct tree and invokes the `synthesize` method on all constructs\. Constructs that implement `synthesize` can participate in synthesis and emit deployment artifacts to the resulting cloud assembly\. These artifacts include AWS CloudFormation templates, AWS Lambda application bundles, file and Docker image assets, and other deployment artifacts\. [Cloud assemblies](#apps_cloud_assembly) describes the output of this phase\. In most cases, you won't need to implement the `synthesize` method\. + +5\. Deployment +In this phase, the AWS CDK Toolkit takes the deployment artifacts cloud assembly produced by the synthesis phase and deploys it to an AWS environment\. It uploads assets to Amazon S3 and Amazon ECR, or wherever they need to go\. Then, it starts an AWS CloudFormation deployment to deploy the application and create the resources\. + +By the time the AWS CloudFormation deployment phase \(step 5\) starts, your AWS CDK app has already finished and exited\. This has the following implications: ++ The AWS CDK app can't respond to events that happen during deployment, such as a resource being created or the whole deployment finishing\. To run code during the deployment phase, you must inject it into the AWS CloudFormation template as a [custom resource](cfn_layer.md#cfn_layer_custom)\. For more information about adding a custom resource to your app, see the [AWS CloudFormation module](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_cloudformation-readme.html), or the [custom\-resource](https://github.com/aws-samples/aws-cdk-examples/tree/master/typescript/custom-resource/) example\. ++ The AWS CDK app might have to work with values that can't be known at the time it runs\. For example, if the AWS CDK app defines an Amazon S3 bucket with an automatically generated name, and you retrieve the `bucket.bucketName` \(Python: `bucket_name`\) attribute, that value is not the name of the deployed bucket\. Instead, you get a `Token` value\. To determine whether a particular value is available, call `cdk.isUnresolved(value)` \(Python: `is_unresolved`\)\. See [Tokens](tokens.md) for details\. + +## Cloud assemblies<a name="apps_cloud_assembly"></a> + +The call to `app.synth()` is what tells the AWS CDK to synthesize a cloud assembly from an app\. Typically you don't interact directly with cloud assemblies\. They are files that include everything needed to deploy your app to a cloud environment\. For example, it includes an AWS CloudFormation template for each stack in your app\. It also includes a copy of any file assets or Docker images that you reference in your app\. + +See the [cloud assembly specification](https://github.com/aws/aws-cdk/blob/master/design/cloud-assembly.md) for details on how cloud assemblies are formatted\. + +To interact with the cloud assembly that your AWS CDK app creates, you typically use the AWS CDK Toolkit, a command line tool\. But any tool that can read the cloud assembly format can be used to deploy your app\. + +The CDK Toolkit needs to know how to execute your AWS CDK app\. If you created the project from a template using the `cdk init` command, your app's `cdk.json` file includes an `app` key\. This key specifies the necessary command for the language that the app is written in\. If your language requires compilation, the command line performs this step before running the app, so you can't forget to do it\. + +------ +#### [ TypeScript ] + +``` +{ + "app": "npx ts-node --prefer-ts-exts bin/my-app.ts" +} +``` + +------ +#### [ JavaScript ] + +``` +{ + "app": "node bin/my-app.js" +} +``` + +------ +#### [ Python ] + +``` +{ + "app": "python app.py" +} +``` + +------ +#### [ Java ] + +``` +{ + "app": "mvn -e -q compile exec:java" +} +``` + +------ +#### [ C\# ] + +``` +{ + "app": "dotnet run -p src/MyApp/MyApp.csproj" +} +``` + +------ + +If you didn't create your project using the CDK Toolkit, or if you want to override the command line given in `cdk.json`, you can use the \-\-app option when issuing the `cdk` command\. + +``` +cdk --app 'executable' cdk-command ... +``` + +The *executable* part of the command indicates the command that should be run to execute your CDK application\. Use quotation marks as shown, since such commands contain spaces\. The *cdk\-command* is a subcommand like synth or deploy that tells the CDK Toolkit what you want to do with your app\. Follow this with any additional options needed for that subcommand\. + +The CLI can also interact directly with an already\-synthesized cloud assembly\. To do that, pass the directory in which the cloud assembly is stored in \-\-app\. The following example lists the stacks defined in the cloud assembly stored under `./my-cloud-assembly`\. + +``` +cdk --app ./my-cloud-assembly ls +``` \ No newline at end of file diff --git a/v2/guide/concepts/aspects.adoc b/v2/aspects.md similarity index 51% rename from v2/guide/concepts/aspects.adoc rename to v2/aspects.md index 0f52852d..5d2accfa 100644 --- a/v2/guide/concepts/aspects.adoc +++ b/v2/aspects.md @@ -1,139 +1,107 @@ -include::../attributes.txt[] +# Aspects<a name="aspects"></a> -// Attributes -[.topic] -[#aspects] -= Aspects and the {aws} CDK -:info_titleabbrev: Aspects -:keywords: {aws} CDK, aspects +Aspects are a way to apply an operation to all constructs in a given scope\. The aspect could modify the constructs, such as by adding tags\. Or it could verify something about the state of the constructs, such as making sure that all buckets are encrypted\. -[abstract] --- -Aspects are a way to apply an operation to all constructs in a given scope. The aspect could modify the constructs, such as by adding tags. Or it could verify something about the state of the constructs, such as making sure that all buckets are encrypted. --- +To apply an aspect to a construct and all constructs in the same scope, call [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Aspects.html#static-ofscope](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Aspects.html#static-ofscope)`.of(SCOPE).add()` with a new aspect, as shown in the following example\. -// Content start +------ +#### [ TypeScript ] -Aspects are a way to apply an operation to all constructs in a given scope. The aspect could modify the constructs, such as by adding tags. Or it could verify something about the state of the constructs, such as making sure that all buckets are encrypted. +``` +Aspects.of(myConstruct).add(new SomeAspect(...)); +``` -To apply an aspect to a construct and all constructs in the same scope, call `link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Aspects.html#static-ofscope[Aspects].of(<SCOPE>).add()` with a new aspect, as shown in the following example. +------ +#### [ JavaScript ] -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +``` Aspects.of(myConstruct).add(new SomeAspect(...)); ----- +``` -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -Aspects.of(myConstruct).add(new SomeAspect(...)); ----- +------ +#### [ Python ] -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- +``` Aspects.of(my_construct).add(SomeAspect(...)) ----- +``` + +------ +#### [ Java ] -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- +``` Aspects.of(myConstruct).add(new SomeAspect(...)); ----- +``` -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- +------ +#### [ C\# ] + +``` Aspects.Of(myConstruct).add(new SomeAspect(...)); ----- +``` + +------ -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -awscdk.Aspects_Of(stack).Add(awscdk.NewTag(...)) ----- -==== +The AWS CDK uses aspects to [tag resources](tagging.md), but the framework can also be used for other purposes\. For example, you can use it to validate or change the AWS CloudFormation resources that are defined for you by higher\-level constructs\. -The {aws} CDK uses aspects to xref:tagging[tag resources], but the framework can also be used for other purposes. For example, you can use it to validate or change the {aws} CloudFormation resources that are defined for you by higher-level constructs. +## Aspects in detail<a name="aspects_detail"></a> -[#aspects-detail] -== Aspects in detail +Aspects employ the [visitor pattern](https://en.wikipedia.org/wiki/Visitor_pattern)\. An aspect is a class that implements the following interface\. -Aspects employ the link:https://en.wikipedia.org/wiki/Visitor_pattern[visitor pattern]. An aspect is a class that implements the following interface. +------ +#### [ TypeScript ] -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +``` interface IAspect { visit(node: IConstruct): void;} ----- +``` -JavaScript:: -JavaScript doesn't have interfaces as a language feature. Therefore, an aspect is simply an instance of a class having a `visit` method that accepts the node to be operated on. +------ +#### [ JavaScript ] -Python:: -Python doesn't have interfaces as a language feature. Therefore, an aspect is simply an instance of a class having a `visit` method that accepts the node to be operated on. +JavaScript doesn't have interfaces as a language feature\. Therefore, an aspect is simply an instance of a class having a `visit` method that accepts the node to be operated on\. -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- +------ +#### [ Python ] + +Python doesn't have interfaces as a language feature\. Therefore, an aspect is simply an instance of a class having a `visit` method that accepts the node to be operated on\. + +------ +#### [ Java ] + +``` public interface IAspect { public void visit(Construct node); } ----- +``` + +------ +#### [ C\# ] -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- +``` public interface IAspect { void Visit(IConstruct node); } ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -type IAspect interface { - Visit(node constructs.IConstruct) -} ----- -==== +``` + +------ + +When you call `Aspects.of(SCOPE).add(...)`, the construct adds the aspect to an internal list of aspects\. You can obtain the list with `Aspects.of(SCOPE)`\. -When you call `Aspects.of(<SCOPE>).add(...)`, the construct adds the aspect to an internal list of aspects. You can obtain the list with `Aspects.of(<SCOPE>)`. +During the [prepare phase](apps.md#lifecycle), the AWS CDK calls the `visit` method of the object for the construct and each of its children in top\-down order\. -During the xref:deploy-how-synth-app[prepare phase], the {aws} CDK calls the `visit` method of the object for the construct and each of its children in top-down order. +The `visit` method is free to change anything in the construct\. In strongly typed languages, cast the received construct to a more specific type before accessing construct\-specific properties or methods\. -The `visit` method is free to change anything in the construct. In strongly typed languages, cast the received construct to a more specific type before accessing construct-specific properties or methods. +Aspects don't propagate across `Stage` construct boundaries, because `Stages` are self\-contained and immutable after definition\. Apply aspects on the `Stage` construct itself \(or lower\) if you want them to visit constructs inside the `Stage`\. -Aspects don't propagate across `Stage` construct boundaries, because `Stages` are self-contained and immutable after definition. Apply aspects on the `Stage` construct itself (or lower) if you want them to visit constructs inside the ``Stage``. +## Example<a name="aspects_example"></a> -[#aspects-example] -== Example +The following example validates that all buckets created in the stack have versioning enabled\. The aspect adds an error annotation to the constructs that fail the validation\. This results in the synth operation failing and prevents deploying the resulting cloud assembly\. -The following example validates that all buckets created in the stack have versioning enabled. The aspect adds an error annotation to the constructs that fail the validation. This results in the `synth` operation failing and prevents deploying the resulting cloud assembly. +------ +#### [ TypeScript ] -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +``` class BucketVersioningChecker implements IAspect { public visit(node: IConstruct): void { // See that we're dealing with a CfnBucket @@ -143,7 +111,7 @@ class BucketVersioningChecker implements IAspect { // can be a token (IResolvable). if (!node.versioningConfiguration || (!Tokenization.isResolvable(node.versioningConfiguration) - && node.versioningConfiguration.status !== 'Enabled')) { + && node.versioningConfiguration.status !== 'Enabled') { Annotations.of(node).addError('Bucket versioning is not enabled'); } } @@ -152,12 +120,12 @@ class BucketVersioningChecker implements IAspect { // Later, apply to the stack Aspects.of(stack).add(new BucketVersioningChecker()); ----- +``` -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +------ +#### [ JavaScript ] + +``` class BucketVersioningChecker { visit(node) { // See that we're dealing with a CfnBucket @@ -167,7 +135,7 @@ class BucketVersioningChecker { // can be a token (IResolvable). if (!node.versioningConfiguration || !Tokenization.isResolvable(node.versioningConfiguration) - && node.versioningConfiguration.status !== 'Enabled')) { + && node.versioningConfiguration.status !== 'Enabled') { Annotations.of(node).addError('Bucket versioning is not enabled'); } } @@ -176,12 +144,12 @@ class BucketVersioningChecker { // Later, apply to the stack Aspects.of(stack).add(new BucketVersioningChecker()); ----- +``` + +------ +#### [ Python ] -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- +``` @jsii.implements(cdk.IAspect) class BucketVersioningChecker: @@ -198,12 +166,12 @@ class BucketVersioningChecker: # Later, apply to the stack Aspects.of(stack).add(BucketVersioningChecker()) ----- +``` -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- +------ +#### [ Java ] + +``` public class BucketVersioningChecker implements IAspect { @Override @@ -222,14 +190,15 @@ public class BucketVersioningChecker implements IAspect } } + // Later, apply to the stack Aspects.of(stack).add(new BucketVersioningChecker()); ----- +``` -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- +------ +#### [ C\# ] + +``` class BucketVersioningChecker : Amazon.Jsii.Runtime.Deputy.DeputyBase, IAspect { public void Visit(IConstruct node) @@ -248,5 +217,6 @@ class BucketVersioningChecker : Amazon.Jsii.Runtime.Deputy.DeputyBase, IAspect // Later, apply to the stack Aspects.Of(stack).add(new BucketVersioningChecker()); ----- -==== \ No newline at end of file +``` + +------ \ No newline at end of file diff --git a/v2/guide/concepts/assets.adoc b/v2/assets.md similarity index 50% rename from v2/guide/concepts/assets.adoc rename to v2/assets.md index 3eb4307d..7fcbea10 100644 --- a/v2/guide/concepts/assets.adoc +++ b/v2/assets.md @@ -1,69 +1,43 @@ -include::../attributes.txt[] +# Assets<a name="assets"></a> -// Attributes -[.topic] -:info_titleabbrev: Assets -:keywords: {aws} CDK, Assets, Amazon S3, Amazon ECR +Assets are local files, directories, or Docker images that can be bundled into AWS CDK libraries and apps\. For example, an asset might be a directory that contains the handler code for an AWS Lambda function\. Assets can represent any artifact that the app needs to operate\. -[#assets] -= Assets and the {aws} CDK +You add assets through APIs that are exposed by specific AWS constructs\. For example, when you define a [lambda\.Function](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.Function.html) construct, the [code](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.Function.html#code) property lets you pass an [asset](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.Code.html#static-fromwbrassetpath-options) \(directory\)\. `Function` uses assets to bundle the contents of the directory and use it for the function's code\. Similarly, [ecs\.ContainerImage\.fromAsset](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs.ContainerImage.html#static-fromwbrassetdirectory-props) uses a Docker image built from a local directory when defining an Amazon ECS task definition\. -[abstract] --- -Assets are local files, directories, or Docker images. --- +## Assets in detail<a name="assets_details"></a> -// Content start +When you refer to an asset in your app, the [cloud assembly](apps.md#apps_cloud_assembly) that's synthesized from your application includes metadata information with instructions for the AWS CDK CLI\. The instructions include where to find the asset on the local disk and what type of bundling to perform based on the asset type, such as a directory to compress \(zip\) or a Docker image to build\. -Assets are local files, directories, or Docker images that can be bundled into {aws} CDK libraries and apps. For example, an asset might be a directory that contains the handler code for an {aws} Lambda function. Assets can represent any artifact that the app needs to operate. +The AWS CDK generates a source hash for assets\. This can be used at construction time to determine whether the contents of an asset have changed\. -The following tutorial video provides a comprehensive overview of CDK assets, and explains how you can use them in your infrastructure as code (IaC). +By default, the AWS CDK creates a copy of the asset in the cloud assembly directory, which defaults to `cdk.out`, under the source hash\. This way, the cloud assembly is self\-contained, so if it moved over to a different host for deployment, it can still be deployed\. See [Cloud assemblies](apps.md#apps_cloud_assembly) for details\. -video::jHNtXQmkKfw[youtube,align = center,height = 390,fileref = https://www.youtube.com/embed/jHNtXQmkKfw,width = 480] +When the AWS CDK deploys an app that references assets \(either directly by the app code or through a library\), the AWS CDK CLI first prepares and publishes the assets to an Amazon S3 bucket or Amazon ECR repository\. \(The S3 bucket or repository is created during bootstrapping\.\) Only then are the resources defined in the stack deployed\. -You add assets through APIs that are exposed by specific {aws} constructs. For example, when you define a https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.Function.html[`lambda.Function`] construct, the https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.Function.html#code[`code`] property lets you pass an https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.Code.html#static-fromwbrassetpath-options[`asset`] (directory). `Function` uses assets to bundle the contents of the directory and use it for the function's code. Similarly, https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs.ContainerImage.html#static-fromwbrassetdirectory-props[`ecs.ContainerImage.fromAsset`] uses a Docker image built from a local directory when defining an Amazon ECS task definition. +This section describes the low\-level APIs available in the framework\. -[#assets-details] -== Assets in detail +## Asset types<a name="assets_types"></a> -When you refer to an asset in your app, the xref:deploy-how-synth-assemblies[cloud assembly] that's synthesized from your application includes metadata information with instructions for the {aws} CDK CLI. The instructions include where to find the asset on the local disk and what type of bundling to perform based on the asset type, such as a directory to compress (zip) or a Docker image to build. +The AWS CDK supports the following types of assets: -The {aws} CDK generates a source hash for assets. This can be used at construction time to determine whether the contents of an asset have changed. +Amazon S3 assets +These are local files and directories that the AWS CDK uploads to Amazon S3\. -By default, the {aws} CDK creates a copy of the asset in the cloud assembly directory, which defaults to `cdk.out`, under the source hash. This way, the cloud assembly is self-contained, so if it moved over to a different host for deployment, it can still be deployed. See xref:deploy-how-synth-assemblies[Cloud assemblies] for details. +Docker Image +These are Docker images that the AWS CDK uploads to Amazon ECR\. -When the {aws} CDK deploys an app that references assets (either directly by the app code or through a library), the {aws} CDK CLI first prepares and publishes the assets to an Amazon S3 bucket or Amazon ECR repository. (The S3 bucket or repository is created during bootstrapping.) Only then are the resources defined in the stack deployed. +These asset types are explained in the following sections\. -This section describes the low-level APIs available in the framework. +## Amazon S3 assets<a name="assets_types_s3"></a> -[#assets-types] -== Asset types +You can define local files and directories as assets, and the AWS CDK packages and uploads them to Amazon S3 through the [aws\-s3\-assets](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3_assets-readme.html) module\. -The {aws} CDK supports the following types of assets: +The following example defines a local directory asset and a file asset\. -Amazon S3 assets:: -+ -These are local files and directories that the {aws} CDK uploads to Amazon S3. +------ +#### [ TypeScript ] -Docker Image:: -+ -These are Docker images that the {aws} CDK uploads to Amazon ECR. - -These asset types are explained in the following sections. - -[#assets-types-s3] -== Amazon S3 assets - -You can define local files and directories as assets, and the {aws} CDK packages and uploads them to Amazon S3 through the https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3_assets-readme.html[`aws-s3-assets`] module. - -The following example defines a local directory asset and a file asset. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +``` import { Asset } from 'aws-cdk-lib/aws-s3-assets'; // Archived and uploaded to Amazon S3 as a .zip file @@ -75,12 +49,12 @@ const directoryAsset = new Asset(this, "SampleZippedDirAsset", { const fileAsset = new Asset(this, 'SampleSingleFileAsset', { path: path.join(__dirname, 'file-asset.txt') }); ----- +``` -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +------ +#### [ JavaScript ] + +``` const { Asset } = require('aws-cdk-lib/aws-s3-assets'); // Archived and uploaded to Amazon S3 as a .zip file @@ -92,12 +66,12 @@ const directoryAsset = new Asset(this, "SampleZippedDirAsset", { const fileAsset = new Asset(this, 'SampleSingleFileAsset', { path: path.join(__dirname, 'file-asset.txt') }); ----- +``` + +------ +#### [ Python ] -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- +``` import os.path dirname = os.path.dirname(__file__) @@ -112,12 +86,12 @@ directory_asset = Asset(self, "SampleZippedDirAsset", file_asset = Asset(self, 'SampleSingleFileAsset', path=os.path.join(dirname, 'file-asset.txt') ) ----- +``` -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- +------ +#### [ Java ] + +``` import java.io.File; import software.amazon.awscdk.services.s3.assets.Asset; @@ -132,14 +106,14 @@ Asset directoryAsset = Asset.Builder.create(this, "SampleZippedDirAsset") // Uploaded to Amazon S3 as-is Asset fileAsset = Asset.Builder.create(this, "SampleSingleFileAsset") .path(new File(startDir, "file-asset.txt").toString()).build(); ----- +``` + +------ +#### [ C\# ] -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- +``` using System.IO; -using Amazon.CDK.{aws}.S3.Assets; +using Amazon.CDK.AWS.S3.Assets; // Archived and uploaded to Amazon S3 as a .zip file var directoryAsset = new Asset(this, "SampleZippedDirAsset", new AssetProps @@ -152,53 +126,32 @@ var fileAsset = new Asset(this, "SampleSingleFileAsset", new AssetProps { Path = Path.Combine(Directory.GetCurrentDirectory(), "file-asset.txt") }); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -dirName, err := os.Getwd() -if err != nil { - panic(err) -} - -awss3assets.NewAsset(stack, jsii.String("SampleZippedDirAsset"), &awss3assets.AssetProps{ - Path: jsii.String(path.Join(dirName, "sample-asset-directory")), -}) +``` -awss3assets.NewAsset(stack, jsii.String("SampleSingleFileAsset"), &awss3assets.AssetProps{ - Path: jsii.String(path.Join(dirName, "file-asset.txt")), -}) ----- -==== +------ -In most cases, you don't need to directly use the APIs in the `aws-s3-assets` module. Modules that support assets, such as `aws-lambda`, have convenience methods so that you can use assets. For Lambda functions, the https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.Code.html#static-fromwbrassetpath-options[`fromAsset()`] static method enables you to specify a directory or a .zip file in the local file system. +In most cases, you don't need to directly use the APIs in the `aws-s3-assets` module\. Modules that support assets, such as `aws-lambda`, have convenience methods so that you can use assets\. For Lambda functions, the [fromAsset\(\)](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.Code.html#static-fromwbrassetpath-options) static method enables you to specify a directory or a \.zip file in the local file system\. -[#assets-types-s3-lambda] -=== Lambda function example +### Lambda function example<a name="assets_types_s3_lambda"></a> -A common use case is creating Lambda functions with the handler code as an Amazon S3 asset. +A common use case is creating Lambda functions with the handler code as an Amazon S3 asset\. -The following example uses an Amazon S3 asset to define a Python handler in the local directory `handler`. It also creates a Lambda function with the local directory asset as the `code` property. Following is the Python code for the handler. +The following example uses an Amazon S3 asset to define a Python handler in the local directory `handler`\. It also creates a Lambda function with the local directory asset as the `code` property\. Following is the Python code for the handler\. -[source,python,subs="verbatim,attributes"] ----- +``` def lambda_handler(event, context): message = 'Hello World!' return { 'message': message } ----- +``` + +The code for the main AWS CDK app should look like the following\. -The code for the main {aws} CDK app should look like the following. +------ +#### [ TypeScript ] -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +``` import * as cdk from 'aws-cdk-lib'; import { Constructs } from 'constructs'; import * as lambda from 'aws-cdk-lib/aws-lambda'; @@ -215,12 +168,12 @@ export class HelloAssetStack extends cdk.Stack { }); } } ----- +``` -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +------ +#### [ JavaScript ] + +``` const cdk = require('aws-cdk-lib'); const lambda = require('aws-cdk-lib/aws-lambda'); const path = require('path'); @@ -238,12 +191,12 @@ class HelloAssetStack extends cdk.Stack { } module.exports = { HelloAssetStack } ----- +``` + +------ +#### [ Python ] -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- +``` from aws_cdk import Stack from constructs import Construct from aws_cdk import aws_lambda as lambda_ @@ -259,12 +212,12 @@ class HelloAssetStack(Stack): code=lambda_.Code.from_asset(os.path.join(dirname, 'handler')), runtime=lambda_.Runtime.PYTHON_3_6, handler="index.lambda_handler") ----- +``` -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- +------ +#### [ Java ] + +``` import java.io.File; import software.amazon.awscdk.Stack; @@ -289,14 +242,14 @@ public class HelloAssetStack extends Stack { .handler("index.lambda_handler").build(); } } ----- +``` + +------ +#### [ C\# ] -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- +``` using Amazon.CDK; -using Amazon.CDK.{aws}.Lambda; +using Amazon.CDK.AWS.Lambda; using System.IO; public class HelloAssetStack : Stack @@ -311,68 +264,25 @@ public class HelloAssetStack : Stack }); } } ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -import ( - "os" - "path" - - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/aws-cdk-go/awscdk/v2/awslambda" - "github.com/aws/aws-cdk-go/awscdk/v2/awss3assets" - "github.com/aws/constructs-go/constructs/v10" - "github.com/aws/jsii-runtime-go" -) - -func HelloAssetStack(scope constructs.Construct, id string, props *HelloAssetStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - stack := awscdk.NewStack(scope, &id, &sprops) - - dirName, err := os.Getwd() - if err != nil { - panic(err) - } - - awslambda.NewFunction(stack, jsii.String("myLambdaFunction"), &awslambda.FunctionProps{ - Code: awslambda.AssetCode_FromAsset(jsii.String(path.Join(dirName, "handler")), &awss3assets.AssetOptions{}), - Runtime: awslambda.Runtime_PYTHON_3_6(), - Handler: jsii.String("index.lambda_handler"), - }) - - return stack -} ----- -==== +``` -The `Function` method uses assets to bundle the contents of the directory and use it for the function's code. +------ -[TIP] -==== +The `Function` method uses assets to bundle the contents of the directory and use it for the function's code\. -Java `.jar` files are ZIP files with a different extension. These are uploaded as-is to Amazon S3, but when deployed as a Lambda function, the files they contain are extracted, which you might not want. To avoid this, place the `.jar` file in a directory and specify that directory as the asset. +**Tip** +Java `.jar` files are ZIP files with a different extension\. These are uploaded as\-is to Amazon S3, but when deployed as a Lambda function, the files they contain are extracted, which you might not want\. To avoid this, place the `.jar` file in a directory and specify that directory as the asset\. -==== +### Deploy\-time attributes example<a name="assets_types_s3_deploy"></a> -[#assets-types-s3-deploy] -=== Deploy-time attributes example +Amazon S3 asset types also expose [deploy\-time attributes](resources.md#resources_attributes) that can be referenced in AWS CDK libraries and apps\. The AWS CDK CLI command cdk synth displays asset properties as AWS CloudFormation parameters\. -Amazon S3 asset types also expose xref:resources-attributes[deploy-time attributes] that can be referenced in {aws} CDK libraries and apps. The {aws} CDK CLI command `cdk synth` displays asset properties as {aws} CloudFormation parameters. +The following example uses deploy\-time attributes to pass the location of an image asset into a Lambda function as environment variables\. \(The kind of file doesn't matter; the PNG image used here is only an example\.\) -The following example uses deploy-time attributes to pass the location of an image asset into a Lambda function as environment variables. (The kind of file doesn't matter; the PNG image used here is only an example.) +------ +#### [ TypeScript ] -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +``` import { Asset } from 'aws-cdk-lib/aws-s3-assets'; import * as path from 'path'; @@ -387,15 +297,15 @@ new lambda.Function(this, "myLambdaFunction", { environment: { 'S3_BUCKET_NAME': imageAsset.s3BucketName, 'S3_OBJECT_KEY': imageAsset.s3ObjectKey, - 'S3_OBJECT_URL': imageAsset.s3ObjectUrl + 'S3_URL': imageAsset.s3Url } }); ----- +``` -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +------ +#### [ JavaScript ] + +``` const { Asset } = require('aws-cdk-lib/aws-s3-assets'); const path = require('path'); @@ -410,15 +320,15 @@ new lambda.Function(this, "myLambdaFunction", { environment: { 'S3_BUCKET_NAME': imageAsset.s3BucketName, 'S3_OBJECT_KEY': imageAsset.s3ObjectKey, - 'S3_OBJECT_URL': imageAsset.s3ObjectUrl + 'S3_URL': imageAsset.s3Url } }); ----- +``` + +------ +#### [ Python ] -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- +``` import os.path import aws_cdk.aws_lambda as lambda_ @@ -436,13 +346,13 @@ lambda_.Function(self, "myLambdaFunction", environment=dict( S3_BUCKET_NAME=image_asset.s3_bucket_name, S3_OBJECT_KEY=image_asset.s3_object_key, - S3_OBJECT_URL=image_asset.s3_object_url)) ----- + S3_URL=image_asset.s3_url)) +``` -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- +------ +#### [ Java ] + +``` import java.io.File; import software.amazon.awscdk.Stack; @@ -467,19 +377,19 @@ public class FunctionStack extends Stack { .environment(java.util.Map.of( // Java 9 or later "S3_BUCKET_NAME", imageAsset.getS3BucketName(), "S3_OBJECT_KEY", imageAsset.getS3ObjectKey(), - "S3_OBJECT_URL", imageAsset.getS3ObjectUrl())) + "S3_URL", imageAsset.getS3Url())) .build(); } } ----- +``` + +------ +#### [ C\# ] -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- +``` using Amazon.CDK; -using Amazon.CDK.{aws}.Lambda; -using Amazon.CDK.{aws}.S3.Assets; +using Amazon.CDK.AWS.Lambda; +using Amazon.CDK.AWS.S3.Assets; using System.IO; using System.Collections.Generic; @@ -497,59 +407,23 @@ new Function(this, "myLambdaFunction", new FunctionProps { ["S3_BUCKET_NAME"] = imageAsset.S3BucketName, ["S3_OBJECT_KEY"] = imageAsset.S3ObjectKey, - ["S3_OBJECT_URL"] = imageAsset.S3ObjectUrl + ["S3_URL"] = imageAsset.S3Url } }); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -import ( - "os" - "path" - - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/aws-cdk-go/awscdk/v2/awslambda" - "github.com/aws/aws-cdk-go/awscdk/v2/awss3assets" -) +``` -dirName, err := os.Getwd() -if err != nil { - panic(err) -} +------ -imageAsset := awss3assets.NewAsset(stack, jsii.String("SampleAsset"), &awss3assets.AssetProps{ - Path: jsii.String(path.Join(dirName, "images/my-image.png")), -}) - -awslambda.NewFunction(stack, jsii.String("myLambdaFunction"), &awslambda.FunctionProps{ - Code: awslambda.AssetCode_FromAsset(jsii.String(path.Join(dirName, "handler"))), - Runtime: awslambda.Runtime_PYTHON_3_6(), - Handler: jsii.String("index.lambda_handler"), - Environment: &map[string]*string{ - "S3_BUCKET_NAME": imageAsset.S3BucketName(), - "S3_OBJECT_KEY": imageAsset.S3ObjectKey(), - "S3_URL": imageAsset.S3ObjectUrl(), - }, -}) ----- -==== - -[#assets-types-s3-permissions] -=== Permissions - -If you use Amazon S3 assets directly through the https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3_assets-readme.html[`aws-s3-assets`] module, IAM roles, users, or groups, and you need to read assets in runtime, then grant those assets IAM permissions through the https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3_assets.Asset.html#grantwbrreadgrantee[`asset.grantRead`] method. - -The following example grants an IAM group read permissions on a file asset. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +### Permissions<a name="assets_types_s3_permissions"></a> + +If you use Amazon S3 assets directly through the [aws\-s3\-assets](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3_assets-readme.html) module, IAM roles, users, or groups, and you need to read assets in runtime, then grant those assets IAM permissions through the [asset\.grantRead](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3_assets.Asset.html#grantwbrreadgrantee) method\. + +The following example grants an IAM group read permissions on a file asset\. + +------ +#### [ TypeScript ] + +``` import { Asset } from 'aws-cdk-lib/aws-s3-assets'; import * as path from 'path'; @@ -559,12 +433,12 @@ const asset = new Asset(this, 'MyFile', { const group = new iam.Group(this, 'MyUserGroup'); asset.grantRead(group); ----- +``` + +------ +#### [ JavaScript ] -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +``` const { Asset } = require('aws-cdk-lib/aws-s3-assets'); const path = require('path'); @@ -574,12 +448,12 @@ const asset = new Asset(this, 'MyFile', { const group = new iam.Group(this, 'MyUserGroup'); asset.grantRead(group); ----- +``` -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- +------ +#### [ Python ] + +``` from aws_cdk.aws_s3_assets import Asset import aws_cdk.aws_iam as iam @@ -591,12 +465,12 @@ dirname = os.path.dirname(__file__) group = iam.Group(self, "MyUserGroup") asset.grant_read(group) ----- +``` + +------ +#### [ Java ] -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- +``` import java.io.File; import software.amazon.awscdk.Stack; @@ -616,15 +490,15 @@ public class GrantStack extends Stack { Group group = new Group(this, "MyUserGroup"); asset.grantRead(group); } } ----- +``` -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- +------ +#### [ C\# ] + +``` using Amazon.CDK; -using Amazon.CDK.{aws}.IAM; -using Amazon.CDK.{aws}.S3.Assets; +using Amazon.CDK.AWS.IAM; +using Amazon.CDK.AWS.S3.Assets; using System.IO; var asset = new Asset(this, "MyFile", new AssetProps { @@ -633,71 +507,42 @@ var asset = new Asset(this, "MyFile", new AssetProps { var group = new Group(this, "MyUserGroup"); asset.GrantRead(group); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -import ( - "os" - "path" - - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/aws-cdk-go/awscdk/v2/awsiam" - "github.com/aws/aws-cdk-go/awscdk/v2/awss3assets" -) +``` -dirName, err := os.Getwd() -if err != nil { - panic(err) -} - -asset := awss3assets.NewAsset(stack, jsii.String("MyFile"), &awss3assets.AssetProps{ - Path: jsii.String(path.Join(dirName, "my-image.png")), -}) - -group := awsiam.NewGroup(stack, jsii.String("MyUserGroup"), &awsiam.GroupProps{}) +------ -asset.GrantRead(group) ----- -==== +## Docker image assets<a name="assets_types_docker"></a> -[#assets-types-docker] -== Docker image assets +The AWS CDK supports bundling local Docker images as assets through the [aws\-ecr\-assets](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecr_assets-readme.html) module\. -The {aws} CDK supports bundling local Docker images as assets through the https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecr_assets-readme.html[`aws-ecr-assets`] module. +The following example defines a Docker image that is built locally and pushed to Amazon ECR\. Images are built from a local Docker context directory \(with a Dockerfile\) and uploaded to Amazon ECR by the AWS CDK CLI or your app's CI/CD pipeline\. The images can be naturally referenced in your AWS CDK app\. -The following example defines a Docker image that is built locally and pushed to Amazon ECR. Images are built from a local Docker context directory (with a Dockerfile) and uploaded to Amazon ECR by the {aws} CDK CLI or your app's CI/CD pipeline. The images can be naturally referenced in your {aws} CDK app. +------ +#### [ TypeScript ] -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +``` import { DockerImageAsset } from 'aws-cdk-lib/aws-ecr-assets'; const asset = new DockerImageAsset(this, 'MyBuildImage', { directory: path.join(__dirname, 'my-image') }); ----- +``` -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +------ +#### [ JavaScript ] + +``` const { DockerImageAsset } = require('aws-cdk-lib/aws-ecr-assets'); const asset = new DockerImageAsset(this, 'MyBuildImage', { directory: path.join(__dirname, 'my-image') }); ----- +``` + +------ +#### [ Python ] -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- +``` from aws_cdk.aws_ecr_assets import DockerImageAsset import os.path @@ -705,69 +550,45 @@ dirname = os.path.dirname(__file__) asset = DockerImageAsset(self, 'MyBuildImage', directory=os.path.join(dirname, 'my-image')) ----- +``` -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- +------ +#### [ Java ] + +``` import software.amazon.awscdk.services.ecr.assets.DockerImageAsset; File startDir = new File(System.getProperty("user.dir")); DockerImageAsset asset = DockerImageAsset.Builder.create(this, "MyBuildImage") .directory(new File(startDir, "my-image").toString()).build(); ----- +``` + +------ +#### [ C\# ] -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- +``` using System.IO; -using Amazon.CDK.{aws}.ECR.Assets; +using Amazon.CDK.AWS.ECR.Assets; var asset = new DockerImageAsset(this, "MyBuildImage", new DockerImageAssetProps { Directory = Path.Combine(Directory.GetCurrentDirectory(), "my-image") }); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -import ( - "os" - "path" - - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/aws-cdk-go/awscdk/v2/awsecrassets" -) +``` -dirName, err := os.Getwd() -if err != nil { - panic(err) -} +------ -asset := awsecrassets.NewDockerImageAsset(stack, jsii.String("MyBuildImage"), &awsecrassets.DockerImageAssetProps{ - Directory: jsii.String(path.Join(dirName, "my-image")), -}) ----- -==== +The `my-image` directory must include a Dockerfile\. The AWS CDK CLI builds a Docker image from `my-image`, pushes it to an Amazon ECR repository, and specifies the name of the repository as an AWS CloudFormation parameter to your stack\. Docker image asset types expose [deploy\-time attributes](resources.md#resources_attributes) that can be referenced in AWS CDK libraries and apps\. The AWS CDK CLI command cdk synth displays asset properties as AWS CloudFormation parameters\. -The `my-image` directory must include a Dockerfile. The {aws} CDK CLI builds a Docker image from `my-image`, pushes it to an Amazon ECR repository, and specifies the name of the repository as an {aws} CloudFormation parameter to your stack. Docker image asset types expose xref:resources-attributes[deploy-time attributes] that can be referenced in {aws} CDK libraries and apps. The {aws} CDK CLI command `cdk synth` displays asset properties as {aws} CloudFormation parameters. +### Amazon ECS task definition example<a name="assets_types_docker_ecs"></a> -[#assets-types-docker-ecs] -=== Amazon ECS task definition example +A common use case is to create an Amazon ECS [TaskDefinition](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs.TaskDefinition.html) to run Docker containers\. The following example specifies the location of a Docker image asset that the AWS CDK builds locally and pushes to Amazon ECR\. -A common use case is to create an Amazon ECS https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs.TaskDefinition.html[`TaskDefinition`] to run Docker containers. The following example specifies the location of a Docker image asset that the {aws} CDK builds locally and pushes to Amazon ECR. +------ +#### [ TypeScript ] -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +``` import * as ecs from 'aws-cdk-lib/aws-ecs'; import * as ecr_assets from 'aws-cdk-lib/aws-ecr-assets'; import * as path from 'path'; @@ -784,12 +605,12 @@ const asset = new ecr_assets.DockerImageAsset(this, 'MyBuildImage', { taskDefinition.addContainer("my-other-container", { image: ecs.ContainerImage.fromDockerImageAsset(asset) }); ----- +``` -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +------ +#### [ JavaScript ] + +``` const ecs = require('aws-cdk-lib/aws-ecs'); const ecr_assets = require('aws-cdk-lib/aws-ecr-assets'); const path = require('path'); @@ -806,12 +627,12 @@ const asset = new ecr_assets.DockerImageAsset(this, 'MyBuildImage', { taskDefinition.addContainer("my-other-container", { image: ecs.ContainerImage.fromDockerImageAsset(asset) }); ----- +``` + +------ +#### [ Python ] -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- +``` import aws_cdk.aws_ecs as ecs import aws_cdk.aws_ecr_assets as ecr_assets @@ -827,12 +648,12 @@ asset = ecr_assets.DockerImageAsset(self, 'MyBuildImage', task_definition.add_container("my-other-container", image=ecs.ContainerImage.from_docker_image_asset(asset)) ----- +``` + +------ +#### [ Java ] -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- +``` import java.io.File; import software.amazon.awscdk.services.ecs.FargateTaskDefinition; @@ -853,16 +674,15 @@ taskDefinition.addContainer("my-other-container", ContainerDefinitionOptions.builder() .image(ContainerImage.fromDockerImageAsset(asset)) .build(); -) ----- +``` + +------ +#### [ C\# ] -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- +``` using System.IO; -using Amazon.CDK.{aws}.ECS; -using Amazon.CDK.{aws}.Ecr.Assets; +using Amazon.CDK.AWS.ECS; +using Amazon.CDK.AWS.Ecr.Assets; var taskDefinition = new FargateTaskDefinition(this, "TaskDef", new FargateTaskDefinitionProps { @@ -879,53 +699,18 @@ taskDefinition.AddContainer("my-other-container", new ContainerDefinitionOptions { Image = ContainerImage.FromDockerImageAsset(asset) }); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -import ( - "os" - "path" - - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/aws-cdk-go/awscdk/v2/awsecrassets" - "github.com/aws/aws-cdk-go/awscdk/v2/awsecs" -) - -dirName, err := os.Getwd() -if err != nil { - panic(err) -} - -taskDefinition := awsecs.NewTaskDefinition(stack, jsii.String("TaskDef"), &awsecs.TaskDefinitionProps{ - MemoryMiB: jsii.String("1024"), - Cpu: jsii.String("512"), -}) +``` -asset := awsecrassets.NewDockerImageAsset(stack, jsii.String("MyBuildImage"), &awsecrassets.DockerImageAssetProps{ - Directory: jsii.String(path.Join(dirName, "my-image")), -}) +------ -taskDefinition.AddContainer(jsii.String("MyOtherContainer"), &awsecs.ContainerDefinitionOptions{ - Image: awsecs.ContainerImage_FromDockerImageAsset(asset), -}) ----- -==== +### Deploy\-time attributes example<a name="assets_types_docker_deploy"></a> +The following example shows how to use the deploy\-time attributes `repository` and `imageUri` to create an Amazon ECS task definition with the AWS Fargate launch type\. Note that the Amazon ECR repo lookup requires the image's tag, not its URI, so we snip it from the end of the asset's URI\. -[#assets-types-docker-deploy] -=== Deploy-time attributes example +------ +#### [ TypeScript ] -The following example shows how to use the deploy-time attributes `repository` and `imageUri` to create an Amazon ECS task definition with the {aws} Fargate launch type. Note that the Amazon ECR repo lookup requires the image's tag, not its URI, so we snip it from the end of the asset's URI. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +``` import * as ecs from 'aws-cdk-lib/aws-ecs'; import * as path from 'path'; import { DockerImageAsset } from 'aws-cdk-lib/aws-ecr-assets'; @@ -942,12 +727,12 @@ const taskDefinition = new ecs.FargateTaskDefinition(this, "TaskDef", { taskDefinition.addContainer("my-other-container", { image: ecs.ContainerImage.fromEcrRepository(asset.repository, asset.imageUri.split(":").pop()) }); ----- +``` + +------ +#### [ JavaScript ] -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +``` const ecs = require('aws-cdk-lib/aws-ecs'); const path = require('path'); const { DockerImageAsset } = require('aws-cdk-lib/aws-ecr-assets'); @@ -964,12 +749,12 @@ const taskDefinition = new ecs.FargateTaskDefinition(this, "TaskDef", { taskDefinition.addContainer("my-other-container", { image: ecs.ContainerImage.fromEcrRepository(asset.repository, asset.imageUri.split(":").pop()) }); ----- +``` + +------ +#### [ Python ] -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- +``` import aws_cdk.aws_ecs as ecs from aws_cdk.aws_ecr_assets import DockerImageAsset @@ -985,12 +770,12 @@ task_definition = ecs.FargateTaskDefinition(self, "TaskDef", task_definition.add_container("my-other-container", image=ecs.ContainerImage.from_ecr_repository( asset.repository, asset.image_uri.rpartition(":")[-1])) ----- +``` -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- +------ +#### [ Java ] + +``` import java.io.File; import software.amazon.awscdk.services.ecr.assets.DockerImageAsset; @@ -1014,15 +799,15 @@ String imageTag = imageUri.substring(imageUri.lastIndexOf(":") + 1); taskDefinition.addContainer("my-other-container", ContainerDefinitionOptions.builder().image(ContainerImage.fromEcrRepository( asset.getRepository(), imageTag)).build()); ----- +``` + +------ +#### [ C\# ] -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- +``` using System.IO; -using Amazon.CDK.{aws}.ECS; -using Amazon.CDK.{aws}.ECR.Assets; +using Amazon.CDK.AWS.ECS; +using Amazon.CDK.AWS.ECR.Assets; var asset = new DockerImageAsset(this, "my-image", new DockerImageAssetProps { Directory = Path.Combine(Directory.GetCurrentDirectory(), "demo-image") @@ -1038,96 +823,62 @@ taskDefinition.AddContainer("my-other-container", new ContainerDefinitionOptions { Image = ContainerImage.FromEcrRepository(asset.Repository, asset.ImageUri.Split(":").Last()) }); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -import ( - "os" - "path" - - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/aws-cdk-go/awscdk/v2/awsecrassets" - "github.com/aws/aws-cdk-go/awscdk/v2/awsecs" -) - -dirName, err := os.Getwd() -if err != nil { - panic(err) -} - -asset := awsecrassets.NewDockerImageAsset(stack, jsii.String("MyImage"), &awsecrassets.DockerImageAssetProps{ - Directory: jsii.String(path.Join(dirName, "demo-image")), -}) +``` -taskDefinition := awsecs.NewFargateTaskDefinition(stack, jsii.String("TaskDef"), &awsecs.FargateTaskDefinitionProps{ - MemoryLimitMiB: jsii.Number(1024), - Cpu: jsii.Number(512), -}) +------ -taskDefinition.AddContainer(jsii.String("MyOtherContainer"), &awsecs.ContainerDefinitionOptions{ - Image: awsecs.ContainerImage_FromEcrRepository(asset.Repository(), asset.ImageTag()), -}) ----- -==== +### Build arguments example<a name="assets_types_docker_build"></a> -[#assets-types-docker-build] -=== Build arguments example +You can provide customized build arguments for the Docker build step through the `buildArgs` \(Python: `build_args`\) property option when the AWS CDK CLI builds the image during deployment\. -You can provide customized build arguments for the Docker build step through the `buildArgs` (Python: `build_args`) property option when the {aws} CDK CLI builds the image during deployment. +------ +#### [ TypeScript ] -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +``` const asset = new DockerImageAsset(this, 'MyBuildImage', { directory: path.join(__dirname, 'my-image'), buildArgs: { HTTP_PROXY: 'http://10.20.30.2:1234' } }); ----- +``` -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +------ +#### [ JavaScript ] + +``` const asset = new DockerImageAsset(this, 'MyBuildImage', { directory: path.join(__dirname, 'my-image'), buildArgs: { HTTP_PROXY: 'http://10.20.30.2:1234' } }); ----- +``` + +------ +#### [ Python ] -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -asset = DockerImageAsset(self, "MyBuildImage", +``` +asset = DockerImageAsset(self, "MyBulidImage", directory=os.path.join(dirname, "my-image"), build_args=dict(HTTP_PROXY="http://10.20.30.2:1234")) ----- +``` -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- +------ +#### [ Java ] + +``` DockerImageAsset asset = DockerImageAsset.Builder.create(this, "my-image"), .directory(new File(startDir, "my-image").toString()) .buildArgs(java.util.Map.of( // Java 9 or later "HTTP_PROXY", "http://10.20.30.2:1234")) .build(); ----- +``` + +------ +#### [ C\# ] -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- +``` var asset = new DockerImageAsset(this, "MyBuildImage", new DockerImageAssetProps { Directory = Path.Combine(Directory.GetCurrentDirectory(), "my-image"), BuildArgs = new Dictionary<string, string> @@ -1135,48 +886,25 @@ var asset = new DockerImageAsset(this, "MyBuildImage", new DockerImageAssetProps ["HTTP_PROXY"] = "http://10.20.30.2:1234" } }); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -dirName, err := os.Getwd() -if err != nil { - panic(err) -} - -asset := awsecrassets.NewDockerImageAsset(stack, jsii.String("MyBuildImage"), &awsecrassets.DockerImageAssetProps{ - Directory: jsii.String(path.Join(dirName, "my-image")), - BuildArgs: &map[string]*string{ - "HTTP_PROXY": jsii.String("http://10.20.30.2:1234"), - }, -}) ----- -==== - -[#assets-types-docker-permissions] -=== Permissions - -If you use a module that supports Docker image assets, such as https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs-readme.html[`aws-ecs`], the {aws} CDK manages permissions for you when you use assets directly or through https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs.ContainerImage.html#static-fromwbrecrwbrrepositoryrepository-tag[`ContainerImage.fromEcrRepository`] (Python: `from_ecr_repository`). If you use Docker image assets directly, make sure that the consuming principal has permissions to pull the image. +``` -In most cases, you should use https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecr.Repository.html#grantwbrpullgrantee[`asset.repository.grantPull`] method (Python: `grant_pull`). This modifies the IAM policy of the principal to enable it to pull images from this repository. If the principal that is pulling the image is not in the same account, or if it's an {aws} service that doesn't assume a role in your account (such as {aws} CodeBuild), you must grant pull permissions on the resource policy and not on the principal's policy. Use the https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecr.Repository.html#addwbrtowbrresourcewbrpolicystatement[`asset.repository.addToResourcePolicy`] method (Python: `add_to_resource_policy`) to grant the appropriate principal permissions. +------ -[#assets-cfn] -== {aws} CloudFormation resource metadata +### Permissions<a name="assets_types_docker_permissions"></a> -[NOTE] -==== +If you use a module that supports Docker image assets, such as [aws\-ecs](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs-readme.html), the AWS CDK manages permissions for you when you use assets directly or through [ContainerImage\.fromEcrRepository](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs.ContainerImage.html#static-fromwbrecrwbrrepositoryrepository-tag) \(Python: `from_ecr_repository`\)\. If you use Docker image assets directly, make sure that the consuming principal has permissions to pull the image\. -This section is relevant only for construct authors. In certain situations, tools need to know that a certain CFN resource is using a local asset. For example, you can use the {aws} SAM CLI to invoke Lambda functions locally for debugging purposes. See xref:sam[{aws} SAM integration] for details. +In most cases, you should use [asset\.repository\.grantPull](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecr.Repository.html#grantwbrpullgrantee) method \(Python: `grant_pull`\. This modifies the IAM policy of the principal to enable it to pull images from this repository\. If the principal that is pulling the image is not in the same account, or if it's an AWS service that doesn't assume a role in your account \(such as AWS CodeBuild\), you must grant pull permissions on the resource policy and not on the principal's policy\. Use the [asset\.repository\.addToResourcePolicy](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecr.Repository.html#addwbrtowbrresourcewbrpolicystatement) method \(Python: `add_to_resource_policy`\) to grant the appropriate principal permissions\. -==== +## AWS CloudFormation resource metadata<a name="assets_cfn"></a> -To enable such use cases, external tools consult a set of metadata entries on {aws} CloudFormation resources: +**Note** +This section is relevant only for construct authors\. In certain situations, tools need to know that a certain CFN resource is using a local asset\. For example, you can use the AWS SAM CLI to invoke Lambda functions locally for debugging purposes\. See [AWS SAM integration](sam.md) for details\. -* `aws:asset:path` – Points to the local path of the asset. -* `aws:asset:property` – The name of the resource property where the asset is used. +To enable such use cases, external tools consult a set of metadata entries on AWS CloudFormation resources: ++ `aws:asset:path` – Points to the local path of the asset\. ++ `aws:asset:property` – The name of the resource property where the asset is used\. -Using these two metadata entries, tools can identify that assets are used by a certain resource, and enable advanced local experiences. +Using these two metadata entries, tools can identify that assets are used by a certain resource, and enable advanced local experiences\. -To add these metadata entries to a resource, use the `asset.addResourceMetadata` (Python: `add_resource_metadata`) method. \ No newline at end of file +To add these metadata entries to a resource, use the `asset.addResourceMetadata` \(Python: `add_resource_metadata`\) method\. \ No newline at end of file diff --git a/v2/best-practices.md b/v2/best-practices.md new file mode 100644 index 00000000..249fbfc7 --- /dev/null +++ b/v2/best-practices.md @@ -0,0 +1,194 @@ +# Best practices for developing and deploying cloud infrastructure with the AWS CDK<a name="best-practices"></a> + +With the AWS CDK, developers or administrators can define their cloud infrastructure by using a supported programming language\. CDK applications should be organized into logical units, such as API, database, and monitoring resources, and optionally have a pipeline for automated deployments\. The logical units should be implemented as constructs including the following: ++ Infrastructure \(such as Amazon S3 buckets, Amazon RDS databases, or an Amazon VPC network\) ++ Runtime code \(such as AWS Lambda functions\) ++ Configuration code + +Stacks define the deployment model of these logical units\. For a more detailed introduction to the concepts behind the CDK, see [Getting started with the AWS CDK](getting_started.md)\. + +The AWS CDK reflects careful consideration of the needs of our customers and internal teams and of the failure patterns that often arise during the deployment and ongoing maintenance of complex cloud applications\. We discovered that failures are often related to "out\-of\-band" changes to an application that aren't fully tested, such as configuration changes\. Therefore, we developed the AWS CDK around a model in which your entire application is defined in code, not only business logic but also infrastructure and configuration\. That way, proposed changes can be carefully reviewed, comprehensively tested in environments resembling production to varying degrees, and fully rolled back if something goes wrong\. + +![\[Image NOT FOUND\]](http://docs.aws.amazon.com/cdk/v2/guide/images/all-in-one.jpg) + +At deployment time, the AWS CDK synthesizes a cloud assembly that contains the following: ++ AWS CloudFormation templates that describe your infrastructure in all target environments ++ File assets that contain your runtime code and their supporting files + +With the CDK, every commit in your application's main version control branch can represent a complete, consistent, deployable version of your application\. Your application can then be deployed automatically whenever a change is made\. + +The philosophy behind the AWS CDK leads to our recommended best practices, which we have divided into four broad categories\. ++ [Organization best practices](#best-practices-organization) ++ [Coding best practices](#best-practices-code) ++ [Construct best practices](#best-practices-constructs) ++ [Application best practices](#best-practices-apps) + +**Tip** +Also consider [best practices for AWS CloudFormation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/best-practices.html) and the individual AWS services that you use, where applicable to CDK\-defined infrastructure\. + +## Organization best practices<a name="best-practices-organization"></a> + +In the beginning stages of AWS CDK adoption, it's important to consider how to set up your organization for success\. It's a best practice to have a team of experts responsible for training and guiding the rest of the company as they adopt the CDK\. The size of this team might vary, from one or two people at a small company to a full\-fledged Cloud Center of Excellence \(CCoE\) at a larger company\. This team is responsible for setting standards and policies for cloud infrastructure at your company, and also for training and mentoring developers\. + +The CCoE might provide guidance on what programming languages should be used for cloud infrastructure\. Details will vary from one organization to the next, but a good policy helps make sure that developers can understand and maintain the company's cloud infrastructure\. + +The CCoE also creates a "landing zone" that defines your organizational units within AWS\. A landing zone is a pre\-configured, secure, scalable, multi\-account AWS environment based on best practice blueprints\. To tie together the services that make up your landing zone, you can use [AWS Control Tower](https://aws.amazon.com/controltower/), which configures and manages your entire multi\-account system from a single user interface\. + +Development teams should be able to use their own accounts for testing and deploy new resources in these accounts as needed\. Individual developers can treat these resources as extensions of their own development workstation\. Using [CDK Pipelines](cdk_pipeline.md), the AWS CDK applications can then be deployed via a CI/CD account to testing, integration, and production environments \(each isolated in its own AWS Region or account\)\. This is done by merging the developers' code into your organization's canonical repository\. + +![\[Image NOT FOUND\]](http://docs.aws.amazon.com/cdk/v2/guide/images/best-practice-deploy-to-multiple-accounts.png) + +## Coding best practices<a name="best-practices-code"></a> + +This section presents best practices for organizing your AWS CDK code\. The following diagram shows the relationship between a team and that team's code repositories, packages, applications, and construct libraries\. + +![\[Image NOT FOUND\]](http://docs.aws.amazon.com/cdk/v2/guide/images/code-organization.jpg) + +### Start simple and add complexity only when you need it<a name="best-practices-code-kiss"></a> + +The guiding principle for most of our best practices is to keep things simple as possible—but no simpler\. Add complexity only when your requirements dictate a more complicated solution\. With the AWS CDK, you can refactor your code as necessary to support new requirements\. You don't have to architect for all possible scenarios upfront\. + +### Align with the AWS Well\-Architected Framework<a name="best-practices-code-well-architected"></a> + +The [AWS Well\-Architected](http://aws.amazon.com/architecture/well-architected/) Framework defines a *component* as the code, configuration, and AWS resources that together deliver against a requirement\. A component is often the unit of technical ownership, and is decoupled from other components\. The term *workload* is used to identify a set of components that together deliver business value\. A workload is usually the level of detail that business and technology leaders communicate about\. + +An AWS CDK application maps to a component as defined by the AWS Well\-Architected Framework\. AWS CDK apps are a mechanism to codify and deliver Well\-Architected cloud application best practices\. You can also create and share components as reusable code libraries through artifact repositories, such as AWS CodeArtifact\. + +### Every application starts with a single package in a single repository<a name="best-practices-code-package"></a> + +A single package is the entry point of your AWS CDK app\. Here, you define how and where to deploy the different logical units of your application\. You also define the CI/CD pipeline to deploy the application\. The app's constructs define the logical units of your solution\. + +Use additional packages for constructs that you use in more than one application\. \(Shared constructs should also have their own lifecycle and testing strategy\.\) Dependencies between packages in the same repository are managed by your repo's build tooling\. + +Although it's possible, we don't recommend putting multiple applications in the same repository, especially when using automated deployment pipelines\. Doing this increases the "blast radius" of changes during deployment\. When there are multiple applications in a repository, changes to one application trigger deployment of the others \(even if the others haven't changed\)\. Furthermore, a break in one application prevents the other applications from being deployed\. + +### Move code into repositories based on code lifecycle or team ownership<a name="best-practices-code-repo"></a> + +When packages begin to be used in multiple applications, move them to their own repository\. This way, the packages can be referenced by application build systems that use them, and they can also be updated on cadences independent of the application lifecycles\. However, at first it might make sense to put all shared constructs in one repository\. + +Also, move packages to their own repository when different teams are working on them\. This helps enforce access control\. + +To consume packages across repository boundaries, you need a private package repository—similar to NPM, PyPi, or Maven Central, but internal to your organization\. You also need a release process that builds, tests, and publishes the package to the private package repository\. [CodeArtifact](https://docs.aws.amazon.com/codeartifact/latest/ug/) can host packages for most popular programming languages\. + +Dependencies on packages in the package repository are managed by your language's package manager, such as NPM for TypeScript or JavaScript applications\. Your package manager helps to make sure that builds are repeatable\. It does this by recording the specific versions of every package that your application depends on\. It also lets you upgrade those dependencies in a controlled manner\. + +Shared packages need a different testing strategy\. For a single application, it might be good enough to deploy the application to a testing environment and confirm that it still works\. But shared packages must be tested independently of the consuming application, as if they were being released to the public\. \(Your organization might choose to actually release some shared packages to the public\.\) + +Keep in mind that a construct can be arbitrarily simple or complex\. A `Bucket` is a construct, but `CameraShopWebsite` could be a construct, too\. + +### Infrastructure and runtime code live in the same package<a name="best-practices-code-all"></a> + +In addition to generating AWS CloudFormation templates for deploying infrastructure, the AWS CDK also bundles runtime assets like Lambda functions and Docker images and deploys them alongside your infrastructure\. This makes it possible to combine the code that defines your infrastructure and the code that implements your runtime logic into a single construct\. It's a best practice to do this\. These two kinds of code don't need to live in separate repositories or even in separate packages\. + +To evolve the two kinds of code together, you can use a self\-contained construct that completely describes a piece of functionality, including its infrastructure and logic\. With a self\-contained construct, you can test the two kinds of code in isolation, share and reuse the code across projects, and version all the code in sync\. + +## Construct best practices<a name="best-practices-constructs"></a> + +This section contains best practices for developing constructs\. Constructs are reusable, composable modules that encapsulate resources\. They're the building blocks of AWS CDK apps\. + +### Model with constructs, deploy with stacks<a name="best-practices-constructs-model"></a> + +Stacks are the unit of deployment: everything in a stack is deployed together\. So when building your application's higher\-level logical units from multiple AWS resources, represent each logical unit as a [https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html](https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html), not as a [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html)\. Use stacks only to describe how your constructs should be composed and connected for your various deployment scenarios\. + +For example, if one of your logical units is a website, the constructs that make it up \(such as an Amazon S3 bucket, API Gateway, Lambda functions, or Amazon RDS tables\) should be composed into a single high\-level construct\. Then that construct should be instantiated in one or more stacks for deployment\. + +By using constructs for building and stacks for deploying, you improve reuse potential of your infrastructure and give yourself more flexibility in how it's deployed\. + +### Configure with properties and methods, not environment variables<a name="best-practices-constructs-config"></a> + +Environment variable lookups inside constructs and stacks are a common anti\-pattern\. Both constructs and stacks should accept a properties object to allow for full configurability completely in code\. Doing otherwise introduces a dependency on the machine that the code will run on, which creates yet more configuration information that you have to track and manage\. + +In general, environment variable lookups should be limited to the top level of an AWS CDK app\. They should also be used to pass in information that's needed for running in a development environment\. For more information, see [Environments](environments.md)\. + +### Unit test your infrastructure<a name="best-practices-constructs-test"></a> + +To consistently run a full suite of unit tests at build time in all environments, avoid network lookups during synthesis and model all your production stages in code\. \(These best practices are covered later\.\) If any single commit always results in the same generated template, you can trust the unit tests that you write to confirm that the generated templates look the way you expect\. For more information, see [Testing constructs](testing.md)\. + +### Don't change the logical ID of stateful resources<a name="best-practices-constructs-logicalid"></a> + +Changing the logical ID of a resource results in the resource being replaced with a new one at the next deployment\. For stateful resources like databases and S3 buckets, or persistent infrastructure like an Amazon VPC, this is seldom what you want\. Be careful about any refactoring of your AWS CDK code that could cause the ID to change\. Write unit tests that assert that the logical IDs of your stateful resources remain static\. The logical ID is derived from the `id` you specify when you instantiate the construct, and the construct's position in the construct tree\. For more information, see [Logical IDs](identifiers.md#identifiers_logical_ids)\. + +### Constructs aren't enough for compliance<a name="best-practices-constructs-compliance"></a> + +Many enterprise customers write their own wrappers for L2 constructs \(the "curated" constructs that represent individual AWS resources with built\-in sane defaults and best practices\)\. These wrappers enforce security best practices such as static encryption and specific IAM policies\. For example, you might create a `MyCompanyBucket` that you then use in your applications in place of the usual Amazon S3 `Bucket` construct\. This pattern is useful for surfacing security guidance early in the software development lifecycle, but don't rely on it as the sole means of enforcement\. + +Instead, use AWS features such as [service control policies](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps.html) and [permission boundaries](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html) to enforce your security guardrails at the organization level\. Use [Aspects](aspects.md) or tools like [CloudFormation Guard](https://github.com/aws-cloudformation/cloudformation-guard) to make assertions about the security properties of infrastructure elements before deployment\. Use AWS CDK for what it does best\. + +Finally, keep in mind that writing your own "L2\+" constructs might prevent your developers from taking advantage of AWS CDK packages such as [AWS Solutions Constructs](https://docs.aws.amazon.com/solutions/latest/constructs/welcome.html) or third\-party constructs from Construct Hub\. These packages are typically built on standard AWS CDK constructs and won't be able to use your wrapper constructs\. + +## Application best practices<a name="best-practices-apps"></a> + +In this section we discuss how to write your AWS CDK applications, combining constructs to define how your AWS resources are connected\. + +### Make decisions at synthesis time<a name="best-practices-apps-synth"></a> + +Although AWS CloudFormation lets you make decisions at deployment time \(using `Conditions`, `{ Fn::If }`, and `Parameters`\), and the AWS CDK gives you some access to these mechanisms, we recommend against using them\. The types of values that you can use and the types of operations you can perform on them are limited compared to what's available in a general\-purpose programming language\. + +Instead, try to make all decisions, such as which construct to instantiate, in your AWS CDK application by using your programming language's `if` statements and other features\. For example, a common CDK idiom, iterating over a list and instantiating a construct with values from each item in the list, simply isn't possible using AWS CloudFormation expressions\. + +Treat AWS CloudFormation as an implementation detail that the AWS CDK uses for robust cloud deployments, not as a language target\. You're not writing AWS CloudFormation templates in TypeScript or Python, you're writing CDK code that happens to use CloudFormation for deployment\. + +### Use generated resource names, not physical names<a name="best-practices-apps-names"></a> + +Names are a precious resource\. Each name can only be used once\. Therefore, if you hardcode a table name or bucket name into your infrastructure and application, you can't deploy that piece of infrastructure twice in the same account\. \(The name we're talking about here is the name specified by, for example, the `bucketName` property on an Amazon S3 bucket construct\.\) + +What's worse, you can't make changes to the resource that require it to be replaced\. If a property can only be set at resource creation, such as the `KeySchema` of an Amazon DynamoDB table, then that property is immutable\. Changing this property requires a new resource\. However, the new resource must have the same name in order to be a true replacement\. But it can't have the same name while the existing resource is still using that name\. + +A better approach is to specify as few names as possible\. If you omit resource names, the AWS CDK will generate them for you in a way that won't cause problems\. Suppose you have a table as a resource\. You can then pass the generated table name as an environment variable into your AWS Lambda function\. In your AWS CDK application, you can reference the table name as `table.tableName`\. Alternatively, you can generate a configuration file on your Amazon EC2 instance on startup, or write the actual table name to the AWS Systems Manager Parameter Store so your application can read it from there\. + +If the place you need it is another AWS CDK stack, that's even more straightforward\. Supposing that one stack defines the resource and another stack needs to use it, the following applies: ++ If the two stacks are in the same AWS CDK app, pass a reference between the two stacks\. For example, save a reference to the resource's construct as an attribute of the defining stack \(`this.stack.uploadBucket = myBucket`\)\. Then, pass that attribute to the constructor of the stack that needs the resource\. ++ When the two stacks are in different AWS CDK apps, use a static `from` method to use an externally defined resource based on its ARN, name, or other attributes\. \(For example, use `Table.fromArn()` for a DynamoDB table\)\. Use the `CfnOutput` construct to print the ARN or other required value in the output of `cdk deploy`, or look in the AWS Management Console\. Alternatively, the second app can read the CloudFormation template generated by the first app and retrieve that value from the `Outputs` section\. + +### Define removal policies and log retention<a name="best-practices-apps-removal-logs"></a> + +The AWS CDK attempts to keep you from losing data by defaulting to policies that retain everything you create\. For example, the default removal policy on resources that contain data \(such as Amazon S3 buckets and database tables\) is not to delete the resource when it is removed from the stack\. Instead, the resource is orphaned from the stack\. Similarly, the CDK's default is to retain all logs forever\. In production environments, these defaults can quickly result in the storage of large amounts of data that you don't actually need, and a corresponding AWS bill\. + +Consider carefully what you want these policies to be for each production resource and specify them accordingly\. Use [Aspects](aspects.md) to validate the removal and logging policies in your stack\. + +### Separate your application into multiple stacks as dictated by deployment requirements<a name="best-practices-apps-separate"></a> + +There is no hard and fast rule to how many stacks your application needs\. You'll usually end up basing the decision on your deployment patterns\. Keep in mind the following guidelines: ++ It's typically more straightforward to keep as many resources in the same stack as possible, so keep them together unless you know you want them separated\. ++ Consider keeping stateful resources \(like databases\) in a separate stack from stateless resources\. You can then turn on termination protection on the stateful stack\. This way, you can freely destroy or create multiple copies of the stateless stack without risk of data loss\. ++ Stateful resources are more sensitive to construct renaming—renaming leads to resource replacement\. Therefore, don't nest stateful resources inside constructs that are likely to be moved around or renamed \(unless the state can be rebuilt if lost, like a cache\)\. This is another good reason to put stateful resources in their own stack\. + +### Commit `cdk.context.json` to avoid non\-deterministic behavior<a name="best-practices-apps-context"></a> + +Determinism is key to successful AWS CDK deployments\. An AWS CDK app should have essentially the same result whenever it is deployed to a given environment\. + +Since your AWS CDK app is written in a general\-purpose programming language, it can execute arbitrary code, use arbitrary libraries, and make arbitrary network calls\. For example, you could use an AWS SDK to retrieve some information from your AWS account while synthesizing your app\. Recognize that doing so will result in additional credential setup requirements, increased latency, and a chance, however small, of failure every time you run `cdk synth`\. + +Never modify your AWS account or resources during synthesis\. Synthesizing an app should not have side effects\. Changes to your infrastructure should happen only in the deployment phase, after the AWS CloudFormation template has been generated\. This way, if there's a problem, AWS CloudFormation can automatically roll back the change\. To make changes that can't be easily made within the AWS CDK framework, use [custom resources](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.custom_resources-readme.html) to execute arbitrary code at deployment time\. + +Even strictly read\-only calls are not necessarily safe\. Consider what happens if the value returned by a network call changes\. What part of your infrastructure will that impact? What will happen to already\-deployed resources? Following are two example situations in which a sudden change in values might cause a problem\. ++ If you provision an Amazon VPC to all available Availability Zones in a specified Region, and the number of AZs is two on deployment day, then your IP space gets split in half\. If AWS launches a new Availability Zone the next day, the next deployment after that tries to split your IP space into thirds, requiring all subnets to be recreated\. This probably won't be possible because your Amazon EC2 instances are still running, and you'll have to clean this up manually\. ++ If you query for the latest Amazon Linux machine image and deploy an Amazon EC2 instance, and the next day a new image is released, a subsequent deployment picks up the new AMI and replaces all your instances\. This might not be what you expected to happen\. + +These situations can be pernicious because the AWS\-side change might occur after months or years of successful deployments\. Suddenly your deployments are failing "for no reason" and you long ago forgot what you did and why\. + +Fortunately, the AWS CDK includes a mechanism called *context providers* to record a snapshot of non\-deterministic values\. This allows future synthesis operations to produce exactly the same template as they did when first deployed\. The only changes in the new template are the changes that *you* made in your code\. When you use a construct's `.fromLookup()` method, the result of the call is cached in `cdk.context.json`\. You should commit this to version control along with the rest of your code to make sure that future executions of your CDK app use the same value\. The CDK Toolkit includes commands to manage the context cache, so you can refresh specific entries when you need to\. For more information, see [Runtime context](context.md)\. + +If you need some value \(from AWS or elsewhere\) for which there is no native CDK context provider, we recommend writing a separate script\. The script should retrieve the value and write it to a file, then read that file in your CDK app\. Run the script only when you want to refresh the stored value, not as part of your regular build process\. + +### Let the AWS CDK manage roles and security groups<a name="best-practices-apps-roles"></a> + +With the AWS CDK construct library's `grant()` convenience methods, you can create AWS Identity and Access Management roles that grant access to one resource by another using minimally scoped permissions\. For example, consider a line like the following: + +``` +myBucket.grantRead(myLambda) +``` + +This single line adds a policy to the Lambda function's role \(which is also created for you\)\. That role and its policies are more than a dozen lines of CloudFormation that you don't have to write\. The AWS CDK grants only the minimal permissions required for the function to read from the bucket\. + +If you require developers to always use predefined roles that were created by a security team, AWS CDK coding becomes much more complicated\. Your teams could lose a lot of flexibility in how they design their applications\. A better alternative is to use [service control policies](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps.html) and [permission boundaries](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html) to make sure that developers stay within the guardrails\. + +### Model all production stages in code<a name="best-practices-apps-stages"></a> + +In traditional AWS CloudFormation scenarios, your goal is to produce a single artifact that is parameterized so that it can be deployed to various target environments after applying configuration values specific to those environments\. In the CDK, you can, and should, build that configuration into your source code\. Create a stack for your production environment, and create a separate stack for each of your other stages\. Then, put the configuration values for each stack in the code\. Use services like [Secrets Manager](https://aws.amazon.com/secrets-manager/) and [Systems Manager](https://aws.amazon.com/systems-manager/) Parameter Store for sensitive values that you don't want to check in to source control, using the names or ARNs of those resources\. + +When you synthesize your application, the cloud assembly created in the `cdk.out` folder contains a separate template for each environment\. Your entire build is deterministic\. There are no out\-of\-band changes to your application, and any given commit always yields the exact same AWS CloudFormation template and accompanying assets\. This makes unit testing much more reliable\. + +### Measure everything<a name="best-practices-apps-measure"></a> + +Achieving the goal of full continuous deployment, with no human intervention, requires a high level of automation\. That automation is only possible with extensive amounts of monitoring\. To measure all aspects of your deployed resources, create metrics, alarms, and dashboards\. Don't stop at measuring things like CPU usage and disk space\. Also record your business metrics, and use those measurements to automate deployment decisions like rollbacks\. Most of the L2 constructs in AWS CDK have convenience methods to help you create metrics, such as the `metricUserErrors()` method on the [dynamodb\.Table](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_dynamodb.Table.html) class\. \ No newline at end of file diff --git a/v2/bootstrapping.md b/v2/bootstrapping.md new file mode 100644 index 00000000..5882f422 --- /dev/null +++ b/v2/bootstrapping.md @@ -0,0 +1,599 @@ +# Bootstrapping<a name="bootstrapping"></a> + +*Bootstrapping* is the process of provisioning resources for the AWS CDK before you can deploy AWS CDK apps into an AWS [environment](environments.md)\. \(An AWS environment is a combination of an AWS account and Region\)\. + +These resources include an Amazon S3 bucket for storing files and IAM roles that grant permissions needed to perform deployments\. + +The required resources are defined in an AWS CloudFormation stack, called the *bootstrap stack*, which is usually named `CDKToolkit`\. Like any AWS CloudFormation stack, it appears in the AWS CloudFormation console once it has been deployed\. + +**Note** +CDK v2 uses a bootstrap template dubbed the modern template\. The legacy template from CDK v1 is not supported in v2\. + +Environments are independent\. If you want to deploy to multiple environments \(different AWS accounts or different Regions in the same account\), each environment must be bootstrapped separately\. + +**Important** +You may incur AWS charges for data stored in the bootstrapped resources\. + +**Note** +Earlier versions of the bootstrap template created an AWS KMS key in each bootstrapped environment by default\. To avoid charges for the KMS key, re\-bootstrap these environments using `--no-bootstrap-customer-key`\. The current default is no KMS key, which helps avoid these charges\. + +If you attempt to deploy an AWS CDK application into an environment that doesn't have the necessary resources, an error message reminds you to bootstrap the environment\. + +If you are using CDK Pipelines to deploy into another account's environment, and you receive a message like the following: + +``` +Policy contains a statement with one or more invalid principals +``` + +This error message means that the appropriate IAM roles do not exist in the other environment\. The most likely cause is a lack of bootstrapping\. + +**Note** +Do not delete and recreate an account's bootstrap stack if you are using CDK Pipelines to deploy into that account\. The pipeline will stop working\. To update the bootstrap stack to a new version, instead re\-run `cdk bootstrap` to update the bootstrap stack in place\. + +## How to bootstrap<a name="bootstrapping-howto"></a> + +Bootstrapping is the deployment of an AWS CloudFormation template to a specific AWS environment \(account and Region\)\. The bootstrapping template accepts parameters that customize some aspects of the bootstrapped resources \(see [Customizing bootstrapping](#bootstrapping-customizing)\)\. Thus, you can bootstrap in one of two ways\. ++ Use the AWS CDK Toolkit's cdk bootstrap command\. This is the simplest method and works well if you have only a few environments to bootstrap\. ++ Deploy the template provided by the AWS CDK Toolkit using another AWS CloudFormation deployment tool\. This lets you use AWS CloudFormation StackSets or AWS Control Tower and also the AWS CloudFormation console or the AWS CLI\. You can make small modifications to the template before deployment\. This approach is more flexible and is suitable for large\-scale deployments\. + +It is not an error to bootstrap an environment more than once\. If an environment you bootstrap has already been bootstrapped, its bootstrap stack will be upgraded if necessary\. Otherwise, nothing happens\. + +### Bootstrapping with the AWS CDK Toolkit<a name="bootstrapping-howto-cli"></a> + +Use the `cdk bootstrap` command to bootstrap one or more AWS environments\. In its basic form, this command bootstraps one or more specified AWS environments \(two, in this example\)\. + +``` +cdk bootstrap aws://ACCOUNT-NUMBER-1/REGION-1 aws://ACCOUNT-NUMBER-2/REGION-2 ... +``` + +The following examples illustrate bootstrapping of one and two environments, respectively\. \(Both use the same AWS account\.\) As shown in the second example, the `aws://` prefix is optional when specifying an environment\. + +``` +cdk bootstrap aws://123456789012/us-east-1 +cdk bootstrap 123456789012/us-east-1 123456789012/us-west-1 +``` + +The CDK Toolkit always synthesizes the AWS CDK app in the current directory\. If you do not specify at least one environment in the `cdk bootstrap` command, it bootstraps all the environments referenced in the app\. + +If a stack is environment\-agnostic \(meaning it doesn't have an `env` property\), then the CDK's environment is applied to make the stack environment\-specific\. The CDK's environment is the one specified using \-\-profile or environment variables, or the default AWS environment otherwise\. That environment is then bootstrapped\. + +For example, the following command synthesizes the current AWS CDK app using the `prod` AWS profile, then bootstraps its environments\. + +``` +cdk bootstrap --profile prod +``` + +### Bootstrapping from the AWS CloudFormation template<a name="bootstrapping-howto-cfn"></a> + +AWS CDK bootstrapping is performed by an AWS CloudFormation template\. To get a copy of this template in the file `bootstrap-template.yaml`, run the following command\. + +------ +#### [ macOS/Linux ] + +``` +cdk bootstrap --show-template > bootstrap-template.yaml +``` + +------ +#### [ Windows ] + +On Windows, PowerShell must be used to preserve the encoding of the template\. + +``` +powershell "cdk bootstrap --show-template | Out-File -encoding utf8 bootstrap-template.yaml" +``` + +------ + +The template is also available in the [AWS CDK GitHub repository](https://github.com/aws/aws-cdk/blob/master/packages/aws-cdk/lib/api/bootstrap/bootstrap-template.yaml)\. + +Deploy this template using cdk bootstrap \-\-template *TEMPLATE\_FILENAME* or your preferred deployment mechanism for AWS CloudFormation templates\. For example, the following command deploys the template using the AWS CLI: + +------ +#### [ macOS/Linux ] + +``` +aws cloudformation create-stack \ + --stack-name CDKToolkit \ + --template-body file://bootstrap-template.yaml +``` + +------ +#### [ Windows ] + +``` +aws cloudformation create-stack ^ + --stack-name CDKToolkit ^ + --template-body file://bootstrap-template.yaml +``` + +------ + +## Bootstrapping template<a name="bootstrapping-template"></a> + +As previously mentioned, AWS CDK v1 supported two bootstrapping templates, legacy and modern\. CDK v2 supports only the modern template\. For reference, here are the high\-level differences between these two templates\. + +[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/cdk/v2/guide/bootstrapping.html) + +\* *We will add additional resources to the bootstrap template as needed\.* + +An environment that was bootstrapped using the legacy template must be upgraded to use the modern template for CDK v2 by re\-bootstrapping\. Re\-deploy all AWS CDK applications in the environment at least once before deleting the legacy bucket\. + +## Customizing bootstrapping<a name="bootstrapping-customizing"></a> + +There are two ways to customize the bootstrapping resources\. ++ Use command line parameters with the `cdk bootstrap` command\. This lets you modify a few aspects of the template\. ++ Modify the default bootstrap template and deploy it yourself\. This gives you more complete control over the bootstrap resources\. + +The following command line options, when used with CDK Toolkit's cdk bootstrap, provide commonly needed adjustments to the bootstrapping template\. ++ \-\-bootstrap\-bucket\-name overrides the name of the Amazon S3 bucket\. May require changes to your CDK app \(see [Stack synthesizers](#bootstrapping-synthesizers)\)\. ++ \-\-bootstrap\-kms\-key\-id overrides the AWS KMS key used to encrypt the S3 bucket\. ++ \-\-cloudformation\-execution\-policies specifies the ARNs of managed policies that should be attached to the deployment role assumed by AWS CloudFormation during deployment of your stacks\. By default, stacks are deployed with full administrator permissions using the `AdministratorAccess` policy\. + + The policy ARNs must be passed as a single string argument, with the individual ARNs separated by commas\. For example: + + ``` + --cloudformation-execution-policies "arn:aws:iam::aws:policy/AWSLambda_FullAccess,arn:aws:iam::aws:policy/AWSCodeDeployFullAccess". + ``` +**Important** +To avoid deployment failures, be sure the policies that you specify are sufficient for any deployments you will perform in the environment being bootstrapped\. ++ \-\-qualifier is a string that is added to the names of all resources in the bootstrap stack\. A qualifier lets you avoid resource name clashes when you provision multiple bootstrap stacks in the same environment\. The default is `hnb659fds` \(this value has no significance\)\. + + Changing the qualifier also requires that your CDK app pass the changed value to the stack synthesizer\. For more information, see [Stack synthesizers](#bootstrapping-synthesizers)\. ++ \-\-tags adds one or more AWS CloudFormation tags to the bootstrap stack\. ++ \-\-trust lists the AWS accounts that may deploy into the environment being bootstrapped\. + + Use this flag when bootstrapping an environment that a CDK Pipeline in another environment will deploy into\. The account doing the bootstrapping is always trusted\. ++ \-\-trust\-for\-lookup lists the AWS accounts that may look up context information from the environment being bootstrapped\. + + Use this flag to give accounts permission to synthesize stacks that will be deployed into the environment, without actually giving them permission to deploy those stacks directly\. ++ \-\-termination\-protection prevents the bootstrap stack from being deleted\. For more information, see [Protecting a stack from being deleted](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-protect-stacks.html) in the *AWS CloudFormation User Guide*\. + +**Important** +The modern bootstrap template effectively grants the permissions implied by the `--cloudformation-execution-policies` to any AWS account in the `--trust` list\. By default, this extends permissions to read and write to any resource in the bootstrapped account\. Make sure to [configure the bootstrapping stack](#bootstrapping-customizing) with policies and trusted accounts that you are comfortable with\. + +### Customizing the template<a name="bootstrapping-customizing-extended"></a> + +When you need more customization than the AWS CDK Toolkit switches can provide, you can modify the bootstrap template to suit your needs\. Remember that you can obtain the template by using the \-\-show\-template flag\. + +``` +cdk bootstrap --show-template +``` + +Any modifications you make must adhere to the [bootstrapping template contract](#bootstrapping-contract)\. + +Deploy your modified template as described in [Bootstrapping from the AWS CloudFormation template](#bootstrapping-howto-cfn), or using cdk bootstrap \-\-template\. + +``` +cdk bootstrap --template bootstrap-template.yaml +``` + +## Stack synthesizers<a name="bootstrapping-synthesizers"></a> + +Your AWS CDK app needs to know about the bootstrapping resources available to it in order to successfully synthesize a stack that can be deployed\. The *stack synthesizer* is an AWS CDK class that controls how the stack's template is synthesized\. This includes how it uses bootstrapping resources \(for example, how it refers to assets stored in the bootstrap bucket\)\. + +The AWS CDK's built\-in stack synthesizers is called `DefaultStackSynthesizer`\. It includes capabilities for cross\-account deployments and [CDK Pipelines](cdk_pipeline.md) deployments\. + +You can pass a stack synthesizer to a stack when you instantiate it using the `synthesizer` property\. + +------ +#### [ TypeScript ] + +``` +new MyStack(this, 'MyStack', { + // stack properties + synthesizer: new DefaultStackSynthesizer({ + // synthesizer properties + }), +}); +``` + +------ +#### [ JavaScript ] + +``` +new MyStack(this, 'MyStack', { + // stack properties + synthesizer: new DefaultStackSynthesizer({ + // synthesizer properties + }), +}); +``` + +------ +#### [ Python ] + +``` +MyStack(self, "MyStack", + # stack properties + synthesizer=DefaultStackSynthesizer( + # synthesizer properties +)) +``` + +------ +#### [ Java ] + + + +``` +new MyStack(app, "MyStack", StackProps.builder() + // stack properties + .synthesizer(DefaultStackSynthesizer.Builder.create() + // synthesizer properties + .build()) + .build(); +``` + +------ +#### [ C\# ] + +``` +new MyStack(app, "MyStack", new StackProps +// stack properties +{ + Synthesizer = new DefaultStackSynthesizer(new DefaultStackSynthesizerProps + { + // synthesizer properties + }) +}); +``` + +------ + +If you don't provide the `synthesizer` property, `DefaultStackSynthesizer` is used\. + +## Customizing synthesis<a name="bootstrapping-custom-synth"></a> + +Depending on the changes you made to the bootstrap template, you may also need to customize synthesis\. The `DefaultStackSynthesizer` can be customized using the properties described as follows\. + +If none of these properties provide the customizations you require, you can write your synthesizer as a class that implements `IStackSynthesizer` \(perhaps deriving from `DefaultStackSynthesizer`\)\. + +### Changing the qualifier<a name="bootstrapping-custom-synth-qualifiers"></a> + +The *qualifier* is added to the name of bootstrap resources to distinguish the resources in separate bootstrap stacks\. To deploy two different versions of the bootstrap stack in the same environment \(AWS account and Region\), the stacks must have different qualifiers\. + +This feature is intended for name isolation between automated tests of the CDK itself\. Unless you can very precisely scope down the IAM permissions given to the AWS CloudFormation execution role, there are no permission isolation benefits to having two different bootstrap stacks in a single account\. Therefore, there's usually no need to change this value\. + +To change the qualifier, configure the `DefaultStackSynthesizer` either by instantiating the synthesizer with the property: + +------ +#### [ TypeScript ] + +``` +new MyStack(this, 'MyStack', { + synthesizer: new DefaultStackSynthesizer({ + qualifier: 'MYQUALIFIER', + }), +}); +``` + +------ +#### [ JavaScript ] + +``` +new MyStack(this, 'MyStack', { + synthesizer: new DefaultStackSynthesizer({ + qualifier: 'MYQUALIFIER', + }), +}) +``` + +------ +#### [ Python ] + +``` +MyStack(self, "MyStack", + synthesizer=DefaultStackSynthesizer( + qualifier="MYQUALIFIER" +)) +``` + +------ +#### [ Java ] + +``` +new MyStack(app, "MyStack", StackProps.builder() + .synthesizer(DefaultStackSynthesizer.Builder.create() + .qualifier("MYQUALIFIER") + .build()) + .build(); +``` + +------ +#### [ C\# ] + +``` +new MyStack(app, "MyStack", new StackProps +{ + Synthesizer = new DefaultStackSynthesizer(new DefaultStackSynthesizerProps + { + Qualifier = "MYQUALIFIER" + }) +}); +``` + +------ + +Or by configuring the qualifier as a context key in `cdk.json`\. + +``` +{ + "app": "...", + "context": { + "@aws-cdk/core:bootstrapQualifier": "MYQUALIFIER" + } +} +``` + +### Changing the resource names<a name="bootstrapping-custom-synth-names"></a> + +All the other `DefaultStackSynthesizer` properties relate to the names of the resources in the bootstrapping template\. You only need to provide any of these properties if you modified the bootstrap template and changed the resource names or naming scheme\. + +All properties accept the special placeholders `${Qualifier}`, `${AWS::Partition}`, `${AWS::AccountId}`, and `${AWS::Region}`\. These placeholders are replaced with the values of the `qualifier` parameter and the AWS partition, account ID, and Region values for the stack's environment, respectively\. + +The following example shows the most commonly used properties for `DefaultStackSynthesizer` along with their default values, as if you were instantiating the synthesizer\. For a complete list, see [DefaultStackSynthesizerProps](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.DefaultStackSynthesizerProps.html#properties)\. + +------ +#### [ TypeScript ] + +``` +new DefaultStackSynthesizer({ + // Name of the S3 bucket for file assets + fileAssetsBucketName: 'cdk-${Qualifier}-assets-${AWS::AccountId}-${AWS::Region}', + bucketPrefix: '', + + // Name of the ECR repository for Docker image assets + imageAssetsRepositoryName: 'cdk-${Qualifier}-container-assets-${AWS::AccountId}-${AWS::Region}', + + // ARN of the role assumed by the CLI and Pipeline to deploy here + deployRoleArn: 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-deploy-role-${AWS::AccountId}-${AWS::Region}', + deployRoleExternalId: '', + + // ARN of the role used for file asset publishing (assumed from the CLI role) + fileAssetPublishingRoleArn: 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-file-publishing-role-${AWS::AccountId}-${AWS::Region}', + fileAssetPublishingExternalId: '', + + // ARN of the role used for Docker asset publishing (assumed from the CLI role) + imageAssetPublishingRoleArn: 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-image-publishing-role-${AWS::AccountId}-${AWS::Region}', + imageAssetPublishingExternalId: '', + + // ARN of the role passed to CloudFormation to execute the deployments + cloudFormationExecutionRole: 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-cfn-exec-role-${AWS::AccountId}-${AWS::Region}', + + // ARN of the role used to look up context information in an environment + lookupRoleArn: 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-lookup-role-${AWS::AccountId}-${AWS::Region}', + lookupRoleExternalId: '', + + // Name of the SSM parameter which describes the bootstrap stack version number + bootstrapStackVersionSsmParameter: '/cdk-bootstrap/${Qualifier}/version', + + // Add a rule to every template which verifies the required bootstrap stack version + generateBootstrapVersionRule: true, + +}) +``` + +------ +#### [ JavaScript ] + +``` +new DefaultStackSynthesizer({ + // Name of the S3 bucket for file assets + fileAssetsBucketName: 'cdk-${Qualifier}-assets-${AWS::AccountId}-${AWS::Region}', + bucketPrefix: '', + + // Name of the ECR repository for Docker image assets + imageAssetsRepositoryName: 'cdk-${Qualifier}-container-assets-${AWS::AccountId}-${AWS::Region}', + + // ARN of the role assumed by the CLI and Pipeline to deploy here + deployRoleArn: 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-deploy-role-${AWS::AccountId}-${AWS::Region}', + deployRoleExternalId: '', + + // ARN of the role used for file asset publishing (assumed from the CLI role) + fileAssetPublishingRoleArn: 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-file-publishing-role-${AWS::AccountId}-${AWS::Region}', + fileAssetPublishingExternalId: '', + + // ARN of the role used for Docker asset publishing (assumed from the CLI role) + imageAssetPublishingRoleArn: 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-image-publishing-role-${AWS::AccountId}-${AWS::Region}', + imageAssetPublishingExternalId: '', + + // ARN of the role passed to CloudFormation to execute the deployments + cloudFormationExecutionRole: 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-cfn-exec-role-${AWS::AccountId}-${AWS::Region}', + + // ARN of the role used to look up context information in an environment + lookupRoleArn: 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-lookup-role-${AWS::AccountId}-${AWS::Region}', + lookupRoleExternalId: '', + + // Name of the SSM parameter which describes the bootstrap stack version number + bootstrapStackVersionSsmParameter: '/cdk-bootstrap/${Qualifier}/version', + + // Add a rule to every template which verifies the required bootstrap stack version + generateBootstrapVersionRule: true, +}) +``` + +------ +#### [ Python ] + +``` +DefaultStackSynthesizer( + # Name of the S3 bucket for file assets + file_assets_bucket_name="cdk-${Qualifier}-assets-${AWS::AccountId}-${AWS::Region}", + bucket_prefix="", + + # Name of the ECR repository for Docker image assets + image_assets_repository_name="cdk-${Qualifier}-container-assets-${AWS::AccountId}-${AWS::Region}", + + # ARN of the role assumed by the CLI and Pipeline to deploy here + deploy_role_arn="arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-deploy-role-${AWS::AccountId}-${AWS::Region}", + deploy_role_external_id="", + + # ARN of the role used for file asset publishing (assumed from the CLI role) + file_asset_publishing_role_arn="arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-file-publishing-role-${AWS::AccountId}-${AWS::Region}", + file_asset_publishing_external_id="", + + # ARN of the role used for Docker asset publishing (assumed from the CLI role) + image_asset_publishing_role_arn="arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-image-publishing-role-${AWS::AccountId}-${AWS::Region}", + image_asset_publishing_external_id="", + + # ARN of the role passed to CloudFormation to execute the deployments + cloud_formation_execution_role="arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + + # ARN of the role used to look up context information in an environment + lookup_role_arn="arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-lookup-role-${AWS::AccountId}-${AWS::Region}", + lookup_role_external_id="", + + # Name of the SSM parameter which describes the bootstrap stack version number + bootstrap_stack_version_ssm_parameter="/cdk-bootstrap/${Qualifier}/version", + + # Add a rule to every template which verifies the required bootstrap stack version + generate_bootstrap_version_rule=True, +) +``` + +------ +#### [ Java ] + +``` +DefaultStackSynthesizer.Builder.create() + // Name of the S3 bucket for file assets + .fileAssetsBucketName("cdk-${Qualifier}-assets-${AWS::AccountId}-${AWS::Region}") + .bucketPrefix('') + + // Name of the ECR repository for Docker image assets + .imageAssetsRepositoryName("cdk-${Qualifier}-container-assets-${AWS::AccountId}-${AWS::Region}") + + // ARN of the role assumed by the CLI and Pipeline to deploy here + .deployRoleArn("arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-deploy-role-${AWS::AccountId}-${AWS::Region}") + .deployRoleExternalId("") + + // ARN of the role used for file asset publishing (assumed from the CLI role) + .fileAssetPublishingRoleArn("arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-file-publishing-role-${AWS::AccountId}-${AWS::Region}") + .fileAssetPublishingExternalId("") + + // ARN of the role used for Docker asset publishing (assumed from the CLI role) + .imageAssetPublishingRoleArn("arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-image-publishing-role-${AWS::AccountId}-${AWS::Region}") + .imageAssetPublishingExternalId("") + + // ARN of the role passed to CloudFormation to execute the deployments + .cloudFormationExecutionRole("arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-cfn-exec-role-${AWS::AccountId}-${AWS::Region}") + + .lookupRoleArn("arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-lookup-role-${AWS::AccountId}-${AWS::Region}") + .lookupRoleExternalId("") + + // Name of the SSM parameter which describes the bootstrap stack version number + .bootstrapStackVersionSsmParameter("/cdk-bootstrap/${Qualifier}/version") + + // Add a rule to every template which verifies the required bootstrap stack version + .generateBootstrapVersionRule(true) +.build() +``` + +------ +#### [ C\# ] + +``` +new DefaultStackSynthesizer(new DefaultStackSynthesizerProps +{ + // Name of the S3 bucket for file assets + FileAssetsBucketName = "cdk-${Qualifier}-assets-${AWS::AccountId}-${AWS::Region}", + BucketPrefix = "", + + // Name of the ECR repository for Docker image assets + ImageAssetsRepositoryName = "cdk-${Qualifier}-container-assets-${AWS::AccountId}-${AWS::Region}", + + // ARN of the role assumed by the CLI and Pipeline to deploy here + DeployRoleArn = "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-deploy-role-${AWS::AccountId}-${AWS::Region}", + DeployRoleExternalId = "", + + // ARN of the role used for file asset publishing (assumed from the CLI role) + FileAssetPublishingRoleArn = "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-file-publishing-role-${AWS::AccountId}-${AWS::Region}", + FileAssetPublishingExternalId = "", + + // ARN of the role used for Docker asset publishing (assumed from the CLI role) + ImageAssetPublishingRoleArn = "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-image-publishing-role-${AWS::AccountId}-${AWS::Region}", + ImageAssetPublishingExternalId = "", + + // ARN of the role passed to CloudFormation to execute the deployments + CloudFormationExecutionRole = "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + + LookupRoleArn = "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-lookup-role-${AWS::AccountId}-${AWS::Region}", + LookupRoleExternalId = "", + + // Name of the SSM parameter which describes the bootstrap stack version number + BootstrapStackVersionSsmParameter = "/cdk-bootstrap/${Qualifier}/version", + + // Add a rule to every template which verifies the required bootstrap stack version + GenerateBootstrapVersionRule = true, +}) +``` + +------ + +## The bootstrapping template contract<a name="bootstrapping-contract"></a> + +The requirements of the bootstrapping stack depend on the stack synthesizer in use\. If you write your own stack synthesizer, you have complete control of the bootstrap resources that your synthesizer requires and how the synthesizer finds them\. + +This section describes the expectations that the `DefaultStackSynthesizer` has of the bootstrapping template\. + +### Versioning<a name="bootstrapping-contract-versioning"></a> + +The template should contain a resource to create an SSM parameter with a well\-known name and an output to reflect the template's version\. + +``` +Resources: + CdkBootstrapVersion: + Type: AWS::SSM::Parameter + Properties: + Type: String + Name: + Fn::Sub: '/cdk-bootstrap/${Qualifier}/version' + Value: 4 +Outputs: + BootstrapVersion: + Value: + Fn::GetAtt: [CdkBootstrapVersion, Value] +``` + +### Roles<a name="bootstrapping-contract-roles"></a> + +The `DefaultStackSynthesizer` requires five IAM roles for five different purposes\. If you are not using the default roles, you must tell the synthesizer the ARNs for the roles you want to use\. + +The roles are as follows: ++ The *deployment role* is assumed by the AWS CDK Toolkit and by AWS CodePipeline to deploy into an environment\. Its `AssumeRolePolicy` controls who can deploy into the environment\. In the template, you can see the permissions that this role needs\. ++ The *lookup role* is assumed by the AWS CDK Toolkit to perform context lookups in an environment\. Its `AssumeRolePolicy` controls who can deploy into the environment\. The permissions this role needs can be seen in the template\. ++ The *file publishing role* and the *image publishing role* are assumed by the AWS CDK Toolkit and by AWS CodeBuild projects to publish assets into an environment\. They're used to write to the S3 bucket and the ECR repository, respectively\. These roles require write access to these resources\. ++ *The AWS CloudFormation execution role* is passed to AWS CloudFormation to perform the actual deployment\. Its permissions are the permissions that the deployment will execute under\. The permissions are passed to the stack as a parameter that lists managed policy ARNs\. + +### Outputs<a name="bootstrapping-contract-outputs"></a> + +The AWS CDK Toolkit requires that the following CloudFormation outputs exist on the bootstrap stack\. ++ `BucketName`: the name of the file asset bucket ++ `BucketDomainName`: the file asset bucket in domain name format ++ `BootstrapVersion`: the current version of the bootstrap stack + +### Template history<a name="bootstrap-template-history"></a> + +The bootstrap template is versioned and evolves over time with the AWS CDK itself\. If you provide your own bootstrap template, keep it up to date with the canonical default template\. You want to make sure that your template continues to work with all CDK features\. + +This section contains a list of the changes made in each version\. + + +| Template version | AWS CDK version | Changes | +| --- | --- | --- | +| 1 | 1\.40\.0 | Initial version of template with Bucket, Key, Repository, and Roles\. | +| 2 | 1\.45\.0 | Split asset publishing role into separate file and image publishing roles\. | +| 3 | 1\.46\.0 | Add FileAssetKeyArn export to be able to add decrypt permissions to asset consumers\. | +| 4 | 1\.61\.0 | AWS KMS permissions are now implicit via Amazon S3 and no longer require FileAsetKeyArn\. Add CdkBootstrapVersion SSM parameter so the bootstrap stack version can be verified without knowing the stack name\. | +| 5 | 1\.87\.0 | Deployment role can read SSM parameter\. | +| 6 | 1\.108\.0 | Add lookup role separate from deployment role\. | +| 6 | 1\.109\.0 | Attach aws\-cdk:bootstrap\-role tag to deployment, file publishing, and image publishing roles\. | +| 7 | 1\.110\.0 | Deployment role can no longer read Buckets in the target account directly\. \(However, this role is effectively an administrator, and could always use its AWS CloudFormation permissions to make the bucket readable anyway\)\. | +| 8 | 1\.114\.0 | The lookup role has full read\-only permissions to the target environment, and has a aws\-cdk:bootstrap\-role tag as well\. | +| 9 | 2\.1\.0 | Fixes Amazon S3 asset uploads from being rejected by commonly referenced encryption SCP\. | +| 10 | 2\.4\.0 | Amazon ECR ScanOnPush is now enabled by default\. | +| 11 | 2\.18\.0 | Adds policy allowing Lambda to pull from Amazon ECR repos so it survives re\-bootstrapping\. | +| 12 | 2\.20\.0 | Adds support for experimental cdk import\. | +| 13 | 2\.25\.0 | Makes container images in bootstrap\-created Amazon ECR repositories immutable\. | +| 14 | 2\.34\.0 | Turns off Amazon ECR image scanning at the repository level by default to allow bootstrapping Regions that do not support image scanning\. | \ No newline at end of file diff --git a/v2/guide/deploy/create-cdk-pipeline.adoc b/v2/cdk_pipeline.md similarity index 54% rename from v2/guide/deploy/create-cdk-pipeline.adoc rename to v2/cdk_pipeline.md index 46192948..35d3dfcf 100644 --- a/v2/guide/deploy/create-cdk-pipeline.adoc +++ b/v2/cdk_pipeline.md @@ -1,254 +1,184 @@ -include::../attributes.txt[] +# Continuous integration and delivery \(CI/CD\) using CDK Pipelines<a name="cdk_pipeline"></a> -// Attributes +[CDK Pipelines](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.pipelines-readme.html) is a construct library module for painless continuous delivery of AWS CDK applications\. Whenever you check your AWS CDK app's source code in to AWS CodeCommit, GitHub, or AWS CodeStar, CDK Pipelines can automatically build, test, and deploy your new version\. -:https---docs-aws-amazon-com-cdk-api-v2-docs-aws-cdk-lib-pipelines-CodePipeline-html-addwbrstagestage-optionss: https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.pipelines.CodePipeline.html#addwbrstagestage-optionss -:https---github-com-aws-aws-cdk-blob-master-packages--aws-cdk-pipelines-ORIGINAL-API-md: https://github.com/aws/aws-cdk/blob/master/packages/@aws-cdk/pipelines/ORIGINAL_API.md +CDK Pipelines are self\-updating\. If you add application stages or stacks, the pipeline automatically reconfigures itself to deploy those new stages or stacks\. -[.topic] -[#cdk-pipeline] -= Continuous integration and delivery (CI/CD) using CDK Pipelines -:info_titleabbrev: Create CDK Pipelines +**Note** +CDK Pipelines supports two APIs\. One is the original API that was made available in the CDK Pipelines Developer Preview\. The other is a modern API that incorporates feedback from CDK customers received during the preview phase\. The examples in this topic use the modern API\. For details on the differences between the two supported APIs, see [CDK Pipelines original API](https://github.com/aws/aws-cdk/blob/master/packages/@aws-cdk/pipelines/ORIGINAL_API.md)\. -// Content start +## Bootstrap your AWS environments<a name="cdk_pipeline_bootstrap"></a> -Use the https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.pipelines-readme.html[CDK Pipelines] module from the {aws} Construct Library to configure continuous delivery of {aws} CDK applications. When you commit your CDK app's source code into {aws} CodeCommit, GitHub, or {aws} CodeStar, CDK Pipelines can automatically build, test, and deploy your new version. +Before you can use CDK Pipelines, you must bootstrap the AWS environments to which you will deploy your stacks\. An [environment](environments.md) is an account/Region pair to which you want to deploy a CDK stack\. -CDK Pipelines are self-updating. If you add application stages or stacks, the pipeline automatically reconfigures itself to deploy those new stages or stacks. +A CDK Pipeline involves at least two environments\. One environment is where the pipeline is provisioned\. The other environment is where you want to deploy the application's stacks \(or its stages, which are groups of related stacks\)\. These environments can be the same, though best practices recommend you isolate stages from each other in different AWS accounts or Regions\. -[NOTE] -==== +**Note** +See [Bootstrapping](bootstrapping.md) for more information on the kinds of resources created by bootstrapping and how to customize the bootstrap stack\. -CDK Pipelines supports two APIs. One is the original API that was made available in the CDK Pipelines Developer Preview. The other is a modern API that incorporates feedback from CDK customers received during the preview phase. The examples in this topic use the modern API. For details on the differences between the two supported APIs, see link:https://github.com/aws/aws-cdk/blob/master/packages/@aws-cdk/pipelines/ORIGINAL_API.md[CDK Pipelines original API] in the _aws-cdk GitHub repository_. +Continuous deployment with CDK Pipelines requires the following to be included in the CDK Toolkit stack: ++ An S3 bucket ++ An Amazon ECR repository ++ IAM roles to give the various parts of a pipeline the permissions they need -==== +The CDK Toolkit upgrades your existing bootstrap stack or creates a new one if necessary\. -[#cdk-pipeline-bootstrap] -== Bootstrap your {aws} environments +To bootstrap an environment that can provision an AWS CDK pipeline, invoke `cdk bootstrap` as shown in the following example\. Invoking the AWS CDK Toolkit via the `npx` command temporarily installs it if necessary\. It will also use the version of the Toolkit installed in the current project, if one exists\. -Before you can use CDK Pipelines, you must bootstrap the {aws} xref:environments[environment] that you will deploy your stacks to. +\-\-cloudformation\-execution\-policies specifies the ARN of a policy under which future CDK Pipelines deployments will execute\. The default `AdministratorAccess` policy makes sure that your pipeline can deploy every type of AWS resource\. If you use this policy, make sure you trust all the code and dependencies that make up your AWS CDK app\. -A CDK Pipeline involves at least two environments. The first environment is where the pipeline is provisioned. The second environment is where you want to deploy the application's stacks or stages to (stages are groups of related stacks). These environments can be the same, but a best practice recommendation is to isolate stages from each other in different environments. +Most organizations mandate stricter controls on what kinds of resources can be deployed by automation\. Check with the appropriate department within your organization to determine the policy your pipeline should use\. -[NOTE] -==== +You can omit the \-\-profile option in the following situations: ++ If your default AWS profile contains the necessary credentials ++ If you want to use the environment variables `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, and `AWS_DEFAULT_REGION` to provide your AWS account credentials -See xref:bootstrapping[{aws} CDK bootstrapping] for more information on the kinds of resources created by bootstrapping and how to customize the bootstrap stack. +------ +#### [ macOS/Linux ] -==== +``` +npx cdk bootstrap aws://ACCOUNT-NUMBER/REGION --profile ADMIN-PROFILE \ + --cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess +``` -Continuous deployment with CDK Pipelines requires the following to be included in the CDK Toolkit stack: +------ +#### [ Windows ] -* An Amazon Simple Storage Service (Amazon S3) bucket. -* An Amazon ECR repository. -* IAM roles to give the various parts of a pipeline the permissions they need. +``` +npx cdk bootstrap aws://ACCOUNT-NUMBER/REGION --profile ADMIN-PROFILE ^ + --cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess +``` -The CDK Toolkit will upgrade your existing bootstrap stack or creates a new one if necessary. +------ -To bootstrap an environment that can provision an {aws} CDK pipeline, invoke `cdk bootstrap` as shown in the following example. Invoking the {aws} CDK Toolkit via the `npx` command temporarily installs it if necessary. It will also use the version of the Toolkit installed in the current project, if one exists. +To bootstrap additional environments into which AWS CDK applications will be deployed by the pipeline, use the following commands instead\. The \-\-trust option indicates which other account should have permissions to deploy AWS CDK applications into this environment\. For this option, specify the pipeline's AWS account ID\. -`--cloudformation-execution-policies` specifies the ARN of a policy under which future CDK Pipelines deployments will execute. The default `AdministratorAccess` policy makes sure that your pipeline can deploy every type of {aws} resource. If you use this policy, make sure you trust all the code and dependencies that make up your {aws} CDK app. +Again, you can omit the \-\-profile option in the following situations: ++ If your default AWS profile contains the necessary credentials ++ If you're using the `AWS_*` environment variables to provide your AWS account credentials -Most organizations mandate stricter controls on what kinds of resources can be deployed by automation. Check with the appropriate department within your organization to determine the policy your pipeline should use. +------ +#### [ macOS/Linux ] -You can omit the `--profile` option if your default {aws} profile contains the necessary authentication configuration and {aws} Region. +``` +npx cdk bootstrap aws://ACCOUNT-NUMBER/REGION --profile ADMIN-PROFILE \ + --cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess \ + --trust PIPELINE-ACCOUNT-NUMBER +``` -==== -[role="tablist"] -macOS/Linux:: -+ -[source,none,subs="verbatim,attributes"] ----- -npx cdk bootstrap aws://<ACCOUNT-NUMBER>/<REGION> --profile <ADMIN-PROFILE> \ - --cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess ----- +------ +#### [ Windows ] -Windows:: -+ -[source,none,subs="verbatim,attributes"] ----- -npx cdk bootstrap aws://<ACCOUNT-NUMBER></REGION> --profile< ADMIN-PROFILE> ^ - --cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess ----- -==== +``` +npx cdk bootstrap aws://ACCOUNT-NUMBER/REGION --profile ADMIN-PROFILE ^ + --cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess ^ + --trust PIPELINE-ACCOUNT-NUMBER +``` -To bootstrap additional environments into which {aws} CDK applications will be deployed by the pipeline, use the following commands instead. The `--trust` option indicates which other account should have permissions to deploy {aws} CDK applications into this environment. For this option, specify the pipeline's {aws} account ID. +------ -Again, you can omit the `--profile` option if your default {aws} profile contains the necessary authentication configuration and {aws} Region. +**Tip** +Use administrative credentials only to bootstrap and to provision the initial pipeline\. Afterward, use the pipeline itself, not your local machine, to deploy changes\. -==== -[role="tablist"] -macOS/Linux:: -+ -[source,none,subs="verbatim,attributes"] ----- -npx cdk bootstrap aws://<ACCOUNT-NUMBER>/<REGION> --profile <ADMIN-PROFILE> \ - --cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess \ - --trust <PIPELINE-ACCOUNT-NUMBER> ----- - -Windows:: -+ -[source,none,subs="verbatim,attributes"] ----- -npx cdk bootstrap aws://<ACCOUNT-NUMBER>/<REGION> --profile <ADMIN-PROFILE> ^ - --cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess ^ - --trust <PIPELINE-ACCOUNT-NUMBER> ----- -==== +If you are upgrading a legacy bootstrapped environment, the previous Amazon S3 bucket is orphaned when the new bucket is created\. Delete it manually by using the Amazon S3 console\. +## Initialize project<a name="cdk_pipeline_init"></a> -[TIP] -==== +Create a new, empty GitHub project and clone it to your workstation in the `my-pipeline` directory\. \(Our code examples in this topic use GitHub\. You can also use AWS CodeStar or AWS CodeCommit\.\) -Use administrative credentials only to bootstrap and to provision the initial pipeline. Afterward, use the pipeline itself, not your local machine, to deploy changes. +``` +git clone GITHUB-CLONE-URL my-pipeline +cd my-pipeline +``` -==== +**Note** +You can use a name other than `my-pipeline` for your app's main directory\. However, if you do so, you will have to tweak the file and class names later in this topic\. This is because the AWS CDK Toolkit bases some file and class names on the name of the main directory\. -If you are upgrading a legacy bootstrapped environment, the previous Amazon S3 bucket is orphaned when the new bucket is created. Delete it manually by using the Amazon S3 console. +After cloning, initialize the project as usual\. -[#cdk-pipeline-protect] -=== Protecting your bootstrap stack from deletion +------ +#### [ TypeScript ] -If a bootstrap stack is deleted, the {aws} resources that were originally provisioned in the environment to support CDK deployments will also be deleted. This will cause the pipeline to stop working. If this happens, there is no general solution for recovery. +``` +cdk init app --language typescript +``` -After your environment is bootstrapped, do not delete and recreate the environment's bootstrap stack. Instead, try to update the bootstrap stack to a new version by running the `cdk bootstrap` command again. +------ +#### [ JavaScript ] -To protect against accidental deletion of your bootstrap stack, we recommend that you provide the `--termination-protection` option with the `cdk bootstrap` command to enable termination protection. You can enable termination protection on new or existing bootstrap stacks. To learn more about this option, see `xref:ref-cli-cmd-bootstrap-options-termination-protection[--termination-protection]`. +``` +cdk init app --language javascript +``` -After enabling termination protection, you can use the {aws} CLI or CloudFormation console to verify. +------ +#### [ Python ] -. Run the following command to enable termination protection on a new or existing bootstrap stack: -+ -[source,none,subs="verbatim,attributes"] ----- -$ cdk bootstrap --termination-protection ----- -+ -. Use the {aws} CLI or CloudFormation console to verify. The following is an example, using the {aws} CLI. If you modified your bootstrap stack name, replace `CDKToolkit` with your stack name: -+ -[source,none,subs="verbatim,attributes"] ----- -$ aws cloudformation describe-stacks --stack-name <CDKToolkit> --query "Stacks[0].EnableTerminationProtection" -true ----- +``` +cdk init app --language python +``` -[#cdk-pipeline-init] -== Initialize a project +After the app has been created, also enter the following two commands\. These activate the app's Python virtual environment and install the AWS CDK core dependencies\. -Create a new, empty GitHub project and clone it to your workstation in the `my-pipeline` directory. (Our code examples in this topic use GitHub. You can also use {aws} CodeStar or {aws} CodeCommit.) +``` +source .venv/bin/activate +python -m pip install -r requirements.txt +``` -[source,none,subs="verbatim,attributes"] ----- -git clone <GITHUB-CLONE-URL> my-pipeline -cd my-pipeline ----- - -[NOTE] -==== - -You can use a name other than `my-pipeline` for your app's main directory. However, if you do so, you will have to tweak the file and class names later in this topic. This is because the {aws} CDK Toolkit bases some file and class names on the name of the main directory. - -==== - -After cloning, initialize the project as usual. - -==== -[role="tablist"] -TypeScript:: -+ -[source,none,subs="verbatim,attributes"] ----- -$ cdk init app --language typescript ----- - -JavaScript:: -+ -[source,none,subs="verbatim,attributes"] ----- -$ cdk init app --language javascript ----- - -Python:: -+ -[source,none,subs="verbatim,attributes"] ----- -$ cdk init app --language python ----- -+ -After the app has been created, also enter the following two commands. These activate the app's Python virtual environment and install the {aws} CDK core dependencies. -+ -[source,none,subs="verbatim,attributes"] ----- -$ source .venv/bin/activate # On Windows, run `.\venv\Scripts\activate` instead -$ python -m pip install -r requirements.txt ----- - -Java:: -+ -[source,none,subs="verbatim,attributes"] ----- -$ cdk init app --language java ----- -+ -If you are using an IDE, you can now open or import the project. In Eclipse, for example, choose *File* > *Import* > *Maven* > **Existing Maven Projects**. Make sure that the project settings are set to use Java 8 (1.8). - -C#:: -+ -[source,none,subs="verbatim,attributes"] ----- -$ cdk init app --language csharp ----- -+ -If you are using Visual Studio, open the solution file in the `src` directory. - -Go:: -+ -[source,none,subs="verbatim,attributes"] ----- -$ cdk init app --language go ----- -+ -After the app has been created, also enter the following command to install the {aws} Construct Library modules that the app requires. -+ -[source,none,subs="verbatim,attributes"] ----- -$ go get ----- -==== - -[IMPORTANT] -==== - -Be sure to commit your `cdk.json` and `cdk.context.json` files to source control. The context information (such as feature flags and cached values retrieved from your {aws} account) are part of your project's state. The values may be different in another environment, which can cause unexpected changes in your results. For more information, see xref:context[Context values and the {aws} CDK]. - -==== - -[#cdk-pipeline-define] -== Define a pipeline - -Your CDK Pipelines application will include at least two stacks: one that represents the pipeline itself, and one or more stacks that represent the application deployed through it. Stacks can also be grouped into _stages_, which you can use to deploy copies of infrastructure stacks to different environments. For now, we'll consider the pipeline, and later delve into the application it will deploy. - -The construct `link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.pipelines.CodePipeline.html[CodePipeline]` is the construct that represents a CDK Pipeline that uses {aws} CodePipeline as its deployment engine. When you instantiate `CodePipeline` in a stack, you define the source location for the pipeline (such as a GitHub repository). You also define the commands to build the app. - -For example, the following defines a pipeline whose source is stored in a GitHub repository. It also includes a build step for a TypeScript CDK application. Fill in the information about your GitHub repo where indicated. - -[NOTE] -==== - -By default, the pipeline authenticates to GitHub using a personal access token stored in Secrets Manager under the name `github-token`. - -==== - -You'll also need to update the instantiation of the pipeline stack to specify the {aws} account and Region. - -==== -[role="tablist"] -TypeScript:: -In `lib/my-pipeline-stack.ts` (may vary if your project folder isn't named `my-pipeline`): -+ -[source,javascript,subs="verbatim,attributes"] ----- +------ +#### [ Java ] + +``` +cdk init app --language java +``` + +If you are using an IDE, you can now open or import the project\. In Eclipse, for example, choose **File** > **Import** > **Maven** > **Existing Maven Projects**\. Make sure that the project settings are set to use Java 8 \(1\.8\)\. + +------ +#### [ C\# ] + +``` +cdk init app --language csharp +``` + +If you are using Visual Studio, open the solution file in the `src` directory\. + +------ +#### [ Go ] + +``` +cdk init app --language go +``` + +After the app has been created, also enter the following command to install the AWS Construct Library modules that the app requires\. + +``` +go get +``` + +------ + +**Important** +Be sure to commit your `cdk.json` and `cdk.context.json` files to source control\. The context information \(such as feature flags and cached values retrieved from your AWS account\) are part of your project's state\. The values may be different in another environment, which can cause unexpected changes in your results\. For more information, see [Runtime context](context.md)\. + +## Define a pipeline<a name="cdk_pipeline_define"></a> + +Your CDK Pipelines application will include at least two stacks: one that represents the pipeline itself, and one or more stacks that represent the application deployed through it\. Stacks can also be grouped into *stages*, which you can use to deploy copies of infrastructure stacks to different environments\. For now, we'll consider the pipeline, and later delve into the application it will deploy\. + +The construct [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.pipelines.CodePipeline.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.pipelines.CodePipeline.html) is the construct that represents a CDK Pipeline that uses AWS CodePipeline as its deployment engine\. When you instantiate `CodePipeline` in a stack, you define the source location for the pipeline \(such as a GitHub repository\)\. You also define the commands to build the app\. + +For example, the following defines a pipeline whose source is stored in a GitHub repository\. It also includes a build step for a TypeScript CDK application\. Fill in the information about your GitHub repo where indicated\. + +**Note** +By default, the pipeline authenticates to GitHub using a personal access token stored in Secrets Manager under the name `github-token`\. + +You'll also need to update the instantiation of the pipeline stack to specify the AWS account and Region\. + +------ +#### [ TypeScript ] + +In `lib/my-pipeline-stack.ts` \(may vary if your project folder isn't named `my-pipeline`\): + +``` import * as cdk from 'aws-cdk-lib'; import { Construct } from 'constructs'; import { CodePipeline, CodePipelineSource, ShellStep } from 'aws-cdk-lib/pipelines'; @@ -266,12 +196,11 @@ export class MyPipelineStack extends cdk.Stack { }); } } ----- -+ -In `bin/my-pipeline.ts` (may vary if your project folder isn't named `my-pipeline`): -+ -[source,javascript,subs="verbatim,attributes"] ----- +``` + +In `bin/my-pipeline.ts` \(may vary if your project folder isn't named `my-pipeline`\): + +``` #!/usr/bin/env node import * as cdk from 'aws-cdk-lib'; import { MyPipelineStack } from '../lib/my-pipeline-stack'; @@ -285,13 +214,14 @@ new MyPipelineStack(app, 'MyPipelineStack', { }); app.synth(); ----- +``` -JavaScript:: -In `lib/my-pipeline-stack.js` (may vary if your project folder isn't named `my-pipeline`): -+ -[source,javascript,subs="verbatim,attributes"] ----- +------ +#### [ JavaScript ] + +In `lib/my-pipeline-stack.js` \(may vary if your project folder isn't named `my-pipeline`\): + +``` const cdk = require('aws-cdk-lib'); const { CodePipeline, CodePipelineSource, ShellStep } = require('aws-cdk-lib/pipelines'); @@ -310,12 +240,11 @@ const { CodePipeline, CodePipelineSource, ShellStep } = require('aws-cdk-lib/pip } module.exports = { MyPipelineStack } ----- -+ -In `bin/my-pipeline.js` (may vary if your project folder isn't named `my-pipeline`): -+ -[source,javascript,subs="verbatim,attributes"] ----- +``` + +In `bin/my-pipeline.js` \(may vary if your project folder isn't named `my-pipeline`\): + +``` #!/usr/bin/env node const cdk = require('aws-cdk-lib'); @@ -330,15 +259,16 @@ new MyPipelineStack(app, 'MyPipelineStack', { }); app.synth(); ----- +``` -Python:: -In `my-pipeline/my-pipeline-stack.py` (may vary if your project folder isn't named `my-pipeline`): -+ -[source,python,subs="verbatim,attributes"] ----- +------ +#### [ Python ] + +In `my-pipeline/my-pipeline-stack.py` \(may vary if your project folder isn't named `my-pipeline`\): + +``` import aws_cdk as cdk -from constructs import Construct +from constructs import Constuct from aws_cdk.pipelines import CodePipeline, CodePipelineSource, ShellStep class MyPipelineStack(cdk.Stack): @@ -346,38 +276,38 @@ class MyPipelineStack(cdk.Stack): def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: super().__init__(scope, construct_id, **kwargs) - pipeline = CodePipeline(self, "Pipeline", + pipeline = CodePipeline(self, "Pipeline", pipeline_name="MyPipeline", - synth=ShellStep("Synth", + synth=ShellStep("Synth", input=CodePipelineSource.git_hub("OWNER/REPO", "main"), - commands=["npm install -g aws-cdk", - "python -m pip install -r requirements.txt", + commands=["npm install -g aws-cdk", + "python -m pip install -r requirements.txt", "cdk synth"] ) ) ----- -+ +``` + In `app.py`: -+ -[source,python,subs="verbatim,attributes"] ----- + +``` #!/usr/bin/env python3 import aws_cdk as cdk from my_pipeline.my_pipeline_stack import MyPipelineStack app = cdk.App() -MyPipelineStack(app, "MyPipelineStack", +MyPipelineStack(app, "MyPipelineStack", env=cdk.Environment(account="111111111111", region="eu-west-1") ) app.synth() ----- +``` + +------ +#### [ Java ] -Java:: -In `src/main/java/com/myorg/MyPipelineStack.java` (may vary if your project folder isn't named `my-pipeline`): -+ -[source,java,subs="verbatim,attributes"] ----- +In `src/main/java/com/myorg/MyPipelineStack.java` \(may vary if your project folder isn't named `my-pipeline`\): + +``` package com.myorg; import java.util.Arrays; @@ -405,12 +335,11 @@ public class MyPipelineStack extends Stack { .build(); } } ----- -+ -In `src/main/java/com/myorg/MyPipelineApp.java` (may vary if your project folder isn't named `my-pipeline`): -+ -[source,java,subs="verbatim,attributes"] ----- +``` + +In `src/main/java/com/myorg/MyPipelineApp.java` \(may vary if your project folder isn't named `my-pipeline`\): + +``` package com.myorg; import software.amazon.awscdk.App; @@ -431,13 +360,14 @@ public class MyPipelineApp { app.synth(); } } ----- +``` + +------ +#### [ C\# ] + +In `src/MyPipeline/MyPipelineStack.cs` \(may vary if your project folder isn't named `my-pipeline`\): -C#:: -In `src/MyPipeline/MyPipelineStack.cs` (may vary if your project folder isn't named `my-pipeline`): -+ -[source,csharp,subs="verbatim,attributes"] ----- +``` using Amazon.CDK; using Amazon.CDK.Pipelines; @@ -459,12 +389,11 @@ namespace MyPipeline } } } ----- -+ -In `src/MyPipeline/Program.cs` (may vary if your project folder isn't named `my-pipeline`): -+ -[source,csharp,subs="verbatim,attributes"] ----- +``` + +In `src/MyPipeline/Program.cs` \(may vary if your project folder isn't named `my-pipeline`\): + +``` using Amazon.CDK; namespace MyPipeline @@ -476,7 +405,7 @@ namespace MyPipeline var app = new App(); new MyPipelineStack(app, "MyPipelineStack", new StackProps { - Env = new Amazon.CDK.Environment { + Env = new Amazon.CDK.Environment { Account = "111111111111", Region = "eu-west-1" } }); @@ -484,161 +413,40 @@ namespace MyPipeline } } } ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -package main - -import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - codebuild "github.com/aws/aws-cdk-go/awscdk/v2/awscodebuild" - ssm "github.com/aws/aws-cdk-go/awscdk/v2/awsssm" - pipeline "github.com/aws/aws-cdk-go/awscdk/v2/pipelines" - "github.com/aws/constructs-go/constructs/v10" - "github.com/aws/jsii-runtime-go" - "os" -) - -// my CDK Stack with resources -func NewCdkStack(scope constructs.Construct, id *string, props *awscdk.StackProps) awscdk.Stack { - stack := awscdk.NewStack(scope, id, props) +``` - // create an example ssm parameter - _ = ssm.NewStringParameter(stack, jsii.String("ssm-test-param"), &ssm.StringParameterProps{ - ParameterName: jsii.String("/testparam"), - Description: jsii.String("ssm parameter for demo"), - StringValue: jsii.String("my test param"), - }) - - return stack -} +------ -// my CDK Application -func NewCdkApplication(scope constructs.Construct, id *string, props *awscdk.StageProps) awscdk.Stage { - stage := awscdk.NewStage(scope, id, props) +You must deploy a pipeline manually once\. After that, the pipeline keeps itself up to date from the source code repository\. So be sure that the code in the repo is the code you want deployed\. Check in your changes and push to GitHub, then deploy: - _ = NewCdkStack(stage, jsii.String("cdk-stack"), &awscdk.StackProps{Env: props.Env}) - - return stage -} - -// my CDK Pipeline -func NewCdkPipeline(scope constructs.Construct, id *string, props *awscdk.StackProps) awscdk.Stack { - stack := awscdk.NewStack(scope, id, props) - - // GitHub repo with owner and repository name - githubRepo := pipeline.CodePipelineSource_GitHub(jsii.String("owner/repo"), jsii.String("main"), &pipeline.GitHubSourceOptions{ - Authentication: awscdk.SecretValue_SecretsManager(jsii.String("my-github-token"), nil), - }) - - // self mutating pipeline - myPipeline := pipeline.NewCodePipeline(stack, jsii.String("cdkPipeline"), &pipeline.CodePipelineProps{ - PipelineName: jsii.String("CdkPipeline"), - // self mutation true - pipeline changes itself before application deployment - SelfMutation: jsii.Bool(true), - CodeBuildDefaults: &pipeline.CodeBuildOptions{ - BuildEnvironment: &codebuild.BuildEnvironment{ - // image version 6.0 recommended for newer go version - BuildImage: codebuild.LinuxBuildImage_FromCodeBuildImageId(jsii.String("aws/codebuild/standard:6.0")), - }, - }, - Synth: pipeline.NewCodeBuildStep(jsii.String("Synth"), &pipeline.CodeBuildStepProps{ - Input: githubRepo, - Commands: &[]*string{ - jsii.String("npm install -g aws-cdk"), - jsii.String("cdk synth"), - }, - }), - }) - - // deployment of actual CDK application - myPipeline.AddStage(NewCdkApplication(stack, jsii.String("MyApplication"), &awscdk.StageProps{ - Env: targetAccountEnv(), - }), &pipeline.AddStageOpts{ - Post: &[]pipeline.Step{ - pipeline.NewCodeBuildStep(jsii.String("Manual Steps"), &pipeline.CodeBuildStepProps{ - Commands: &[]*string{ - jsii.String("echo \"My CDK App deployed, manual steps go here ... \""), - }, - }), - }, - }) - - return stack -} - -// main app -func main() { - defer jsii.Close() - - app := awscdk.NewApp(nil) - - // call CDK Pipeline - NewCdkPipeline(app, jsii.String("CdkPipelineStack"), &awscdk.StackProps{ - Env: pipelineEnv(), - }) - - app.Synth(nil) -} - -// env determines the {aws} environment (account+region) in which our stack is to -// be deployed. For more information see: https://docs.aws.amazon.com/cdk/latest/guide/environments.html -func pipelineEnv() *awscdk.Environment { - return &awscdk.Environment{ - Account: jsii.String(os.Getenv("CDK_DEFAULT_ACCOUNT")), - Region: jsii.String(os.Getenv("CDK_DEFAULT_REGION")), - } -} - -func targetAccountEnv() *awscdk.Environment { - return &awscdk.Environment{ - Account: jsii.String(os.Getenv("CDK_DEFAULT_ACCOUNT")), - Region: jsii.String(os.Getenv("CDK_DEFAULT_REGION")), - } -} ----- -==== - -You must deploy a pipeline manually once. After that, the pipeline keeps itself up to date from the source code repository. So be sure that the code in the repo is the code you want deployed. Check in your changes and push to GitHub, then deploy: - -[source,none,subs="verbatim,attributes"] ----- +``` git add --all git commit -m "initial commit" git push cdk deploy ----- +``` -[TIP] -==== +**Tip** +Now that you've done the initial deployment, your local AWS account no longer needs administrative access\. This is because all changes to your app will be deployed via the pipeline\. All you need to be able to do is push to GitHub\. -Now that you've done the initial deployment, your local {aws} account no longer needs administrative access. This is because all changes to your app will be deployed via the pipeline. All you need to be able to do is push to GitHub. +## Application stages<a name="cdk_pipeline_stages"></a> -==== +To define a multi\-stack AWS application that can be added to the pipeline all at once, define a subclass of `[Stage](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stage.html)`\. \(This is different from `CdkStage` in the CDK Pipelines module\.\) -[#cdk-pipeline-stages] -== Application stages +The stage contains the stacks that make up your application\. If there are dependencies between the stacks, the stacks are automatically added to the pipeline in the right order\. Stacks that don't depend on each other are deployed in parallel\. You can add a dependency relationship between stacks by calling `stack1.addDependency(stack2)`\. -To define a multi-stack {aws} application that can be added to the pipeline all at once, define a subclass of `link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stage.html[Stage]`. (This is different from `CdkStage` in the CDK Pipelines module.) +Stages accept a default `env` argument, which becomes the default environment for the stacks inside it\. \(Stacks can still have their own environment specified\.\)\. -The stage contains the stacks that make up your application. If there are dependencies between the stacks, the stacks are automatically added to the pipeline in the right order. Stacks that don't depend on each other are deployed in parallel. You can add a dependency relationship between stacks by calling `stack1.addDependency(stack2)`. +An application is added to the pipeline by calling `[addStage](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.pipelines.CodePipeline.html#addwbrstagestage-optionss)()` with instances of [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stage.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stage.html)\. A stage can be instantiated and added to the pipeline multiple times to define different stages of your DTAP or multi\-Region application pipeline\. -Stages accept a default `env` argument, which becomes the default environment for the stacks inside it. (Stacks can still have their own environment specified.). +We will create a stack containing a simple Lambda function and place that stack in a stage\. Then we will add the stage to the pipeline so it can be deployed\. -An application is added to the pipeline by calling `link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.pipelines.CodePipeline.html#addwbrstagestage-optionss[addStage()]` with instances of https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stage.html[Stage]. A stage can be instantiated and added to the pipeline multiple times to define different stages of your DTAP or multi-Region application pipeline. +------ +#### [ TypeScript ] -We will create a stack containing a simple Lambda function and place that stack in a stage. Then we will add the stage to the pipeline so it can be deployed. +Create the new file `lib/my-pipeline-lambda-stack.ts` to hold our application stack containing a Lambda function\. -==== -[role="tablist"] -TypeScript:: -Create the new file `lib/my-pipeline-lambda-stack.ts` to hold our application stack containing a Lambda function. -+ -[source,javascript,subs="verbatim,attributes"] ----- +``` import * as cdk from 'aws-cdk-lib'; import { Construct } from 'constructs'; import { Function, InlineCode, Runtime } from 'aws-cdk-lib/aws-lambda'; @@ -646,38 +454,36 @@ import { Function, InlineCode, Runtime } from 'aws-cdk-lib/aws-lambda'; export class MyLambdaStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); - + new Function(this, 'LambdaFunction', { - runtime: Runtime.NODEJS_18_X, + runtime: Runtime.NODEJS_12_X, handler: 'index.handler', code: new InlineCode('exports.handler = _ => "Hello, CDK";') }); } } ----- -+ -Create the new file `lib/my-pipeline-app-stage.ts` to hold our stage. -+ -[source,javascript,subs="verbatim,attributes"] ----- +``` + +Create the new file `lib/my-pipeline-app-stage.ts` to hold our stage\. + +``` import * as cdk from 'aws-cdk-lib'; import { Construct } from "constructs"; import { MyLambdaStack } from './my-pipeline-lambda-stack'; export class MyPipelineAppStage extends cdk.Stage { - + constructor(scope: Construct, id: string, props?: cdk.StageProps) { super(scope, id, props); - - const lambdaStack = new MyLambdaStack(this, 'LambdaStack'); + + const lambdaStack = new MyLambdaStack(this, 'LambdaStack'); } } ----- -+ -Edit `lib/my-pipeline-stack.ts` to add the stage to our pipeline. -+ -[source,javascript,subs="verbatim,attributes"] ----- +``` + +Edit `lib/my-pipeline-stack.ts` to add the stage to our pipeline\. + +``` import * as cdk from 'aws-cdk-lib'; import { Construct } from 'constructs'; import { CodePipeline, CodePipelineSource, ShellStep } from 'aws-cdk-lib/pipelines'; @@ -700,22 +506,23 @@ export class MyPipelineStack extends cdk.Stack { })); } } ----- +``` + +------ +#### [ JavaScript ] -JavaScript:: -Create the new file `lib/my-pipeline-lambda-stack.js` to hold our application stack containing a Lambda function. -+ -[source,javascript,subs="verbatim,attributes"] ----- +Create the new file `lib/my-pipeline-lambda-stack.js` to hold our application stack containing a Lambda function\. + +``` const cdk = require('aws-cdk-lib'); const { Function, InlineCode, Runtime } = require('aws-cdk-lib/aws-lambda'); class MyLambdaStack extends cdk.Stack { constructor(scope, id, props) { super(scope, id, props); - + new Function(this, 'LambdaFunction', { - runtime: Runtime.NODEJS_18_X, + runtime: Runtime.NODEJS_12_X, handler: 'index.handler', code: new InlineCode('exports.handler = _ => "Hello, CDK";') }); @@ -723,31 +530,29 @@ class MyLambdaStack extends cdk.Stack { } module.exports = { MyLambdaStack } ----- -+ -Create the new file `lib/my-pipeline-app-stage.js` to hold our stage. -+ -[source,javascript,subs="verbatim,attributes"] ----- +``` + +Create the new file `lib/my-pipeline-app-stage.js` to hold our stage\. + +``` const cdk = require('aws-cdk-lib'); const { MyLambdaStack } = require('./my-pipeline-lambda-stack'); class MyPipelineAppStage extends cdk.Stage { - + constructor(scope, id, props) { super(scope, id, props); - - const lambdaStack = new MyLambdaStack(this, 'LambdaStack'); + + const lambdaStack = new MyLambdaStack(this, 'LambdaStack'); } } module.exports = { MyPipelineAppStage }; ----- -+ -Edit `lib/my-pipeline-stack.ts` to add the stage to our pipeline. -+ -[source,javascript,subs="verbatim,attributes"] ----- +``` + +Edit `lib/my-pipeline-stack.ts` to add the stage to our pipeline\. + +``` const cdk = require('aws-cdk-lib'); const { CodePipeline, CodePipelineSource, ShellStep } = require('aws-cdk-lib/pipelines'); const { MyPipelineAppStage } = require('./my-pipeline-app-stage'); @@ -772,13 +577,14 @@ const { MyPipelineAppStage } = require('./my-pipeline-app-stage'); } module.exports = { MyPipelineStack } ----- +``` + +------ +#### [ Python ] + +Create the new file `my_pipeline/my_pipeline_lambda_stack.py` to hold our application stack containing a Lambda function\. -Python:: -Create the new file `my_pipeline/my_pipeline_lambda_stack.py` to hold our application stack containing a Lambda function. -+ -[source,python,subs="verbatim,attributes"] ----- +``` import aws_cdk as cdk from constructs import Construct from aws_cdk.aws_lambda import Function, InlineCode, Runtime @@ -787,17 +593,16 @@ class MyLambdaStack(cdk.Stack): def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: super().__init__(scope, construct_id, **kwargs) - Function(self, "LambdaFunction", - runtime=Runtime.NODEJS_18_X, + Function(self, "LambdaFunction", + runtime=Runtime.NODEJS_12_X, handler="index.handler", code=InlineCode("exports.handler = _ => 'Hello, CDK';") ) ----- -+ -Create the new file `my_pipeline/my_pipeline_app_stage.py` to hold our stage. -+ -[source,python,subs="verbatim,attributes"] ----- +``` + +Create the new file `my_pipeline/my_pipeline_app_stage.py` to hold our stage\. + +``` import aws_cdk as cdk from constructs import Construct from my_pipeline.my_pipeline_lambda_stack import MyLambdaStack @@ -807,12 +612,11 @@ class MyPipelineAppStage(cdk.Stage): super().__init__(scope, construct_id, **kwargs) lambdaStack = MyLambdaStack(self, "LambdaStack") ----- -+ -Edit `my_pipeline/my-pipeline-stack.py` to add the stage to our pipeline. -+ -[source,python,subs="verbatim,attributes"] ----- +``` + +Edit `my_pipeline/my-pipeline-stack.py` to add the stage to our pipeline\. + +``` import aws_cdk as cdk from constructs import Construct from aws_cdk.pipelines import CodePipeline, CodePipelineSource, ShellStep @@ -823,9 +627,9 @@ class MyPipelineStack(cdk.Stack): def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: super().__init__(scope, construct_id, **kwargs) - pipeline = CodePipeline(self, "Pipeline", + pipeline = CodePipeline(self, "Pipeline", pipeline_name="MyPipeline", - synth=ShellStep("Synth", + synth=ShellStep("Synth", input=CodePipelineSource.git_hub("OWNER/REPO", "main"), commands=["npm install -g aws-cdk", "python -m pip install -r requirements.txt", @@ -833,13 +637,14 @@ class MyPipelineStack(cdk.Stack): pipeline.add_stage(MyPipelineAppStage(self, "test", env=cdk.Environment(account="111111111111", region="eu-west-1"))) ----- +``` -Java:: -Create the new file `src/main/java/com.myorg/MyPipelineLambdaStack.java` to hold our application stack containing a Lambda function. -+ -[source,java,subs="verbatim,attributes"] ----- +------ +#### [ Java ] + +Create the new file `src/main/java/com.myorg/MyPipelineLambdaStack.java` to hold our application stack containing a Lambda function\. + +``` package com.myorg; import software.constructs.Construct; @@ -859,7 +664,7 @@ public class MyPipelineLambdaStack extends Stack { super(scope, id, props); Function.Builder.create(this, "LambdaFunction") - .runtime(Runtime.NODEJS_18_X) + .runtime(Runtime.NODEJS_12_X) .handler("index.handler") .code(new InlineCode("exports.handler = _ => 'Hello, CDK';")) .build(); @@ -867,12 +672,11 @@ public class MyPipelineLambdaStack extends Stack { } } ----- -+ -Create the new file `src/main/java/com.myorg/MyPipelineAppStage.java` to hold our stage. -+ -[source,java,subs="verbatim,attributes"] ----- +``` + +Create the new file `src/main/java/com.myorg/MyPipelineAppStage.java` to hold our stage\. + +``` package com.myorg; import software.constructs.Construct; @@ -887,17 +691,16 @@ public class MyPipelineAppStage extends Stage { public MyPipelineAppStage(final Construct scope, final String id, final StageProps props) { super(scope, id, props); - + Stack lambdaStack = new MyPipelineLambdaStack(this, "LambdaStack"); } } ----- -+ -Edit `src/main/java/com.myorg/MyPipelineStack.java` to add the stage to our pipeline. -+ -[source,java,subs="verbatim,attributes"] ----- +``` + +Edit `src/main/java/com.myorg/MyPipelineStack.java` to add the stage to our pipeline\. + +``` package com.myorg; import java.util.Arrays; @@ -925,7 +728,7 @@ public class MyPipelineStack extends Stack { .commands(Arrays.asList("npm install -g aws-cdk", "cdk synth")) .build()) .build(); - + pipeline.addStage(new MyPipelineAppStage(this, "test", StageProps.builder() .env(Environment.builder() .account("111111111111") @@ -934,16 +737,17 @@ public class MyPipelineStack extends Stack { .build())); } } ----- +``` + +------ +#### [ C\# ] + +Create the new file `src/MyPipeline/MyPipelineLambdaStack.cs` to hold our application stack containing a Lambda function\. -C#:: -Create the new file `src/MyPipeline/MyPipelineLambdaStack.cs` to hold our application stack containing a Lambda function. -+ -[source,csharp,subs="verbatim,attributes"] ----- +``` using Amazon.CDK; using Constructs; -using Amazon.CDK.{aws}.Lambda; +using Amazon.CDK.AWS.Lambda; namespace MyPipeline { @@ -953,19 +757,18 @@ namespace MyPipeline { new Function(this, "LambdaFunction", new FunctionProps { - Runtime = Runtime.NODEJS_18_X, + Runtime = Runtime.NODEJS_12_X, Handler = "index.handler", Code = new InlineCode("exports.handler = _ => 'Hello, CDK';") }); } } } ----- -+ -Create the new file `src/MyPipeline/MyPipelineAppStage.cs` to hold our stage. -+ -[source,csharp,subs="verbatim,attributes"] ----- +``` + +Create the new file `src/MyPipeline/MyPipelineAppStage.cs` to hold our stage\. + +``` using Amazon.CDK; using Constructs; @@ -979,12 +782,11 @@ namespace MyPipeline } } } ----- -+ -Edit `src/MyPipeline/MyPipelineStack.cs` to add the stage to our pipeline. -+ -[source,csharp,subs="verbatim,attributes"] ----- +``` + +Edit `src/MyPipeline/MyPipelineStack.cs` to add the stage to our pipeline\. + +``` using Amazon.CDK; using Constructs; using Amazon.CDK.Pipelines; @@ -1015,17 +817,16 @@ namespace MyPipeline } } } ----- -==== +``` + +------ -Every application stage added by `addStage()` results in the addition of a corresponding pipeline stage, represented by a `link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.pipelines.StageDeployment.html[StageDeployment]` instance returned by the `addStage()` call. You can add pre-deployment or post-deployment actions to the stage by calling its `addPre()` or `addPost()` method. +Every application stage added by `addStage()` results in the addition of a corresponding pipeline stage, represented by a [StageDeployment](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.pipelines.StageDeployment.html) instance returned by the `addStage()` call\. You can add pre\-deployment or post\-deployment actions to the stage by calling its `addPre()` or `addPost()` method\. -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +------ +#### [ TypeScript ] + +``` // import { ManualApprovalStep } from 'aws-cdk-lib/pipelines'; const testingStage = pipeline.addStage(new MyPipelineAppStage(this, 'testing', { @@ -1033,12 +834,12 @@ const testingStage = pipeline.addStage(new MyPipelineAppStage(this, 'testing', { })); testingStage.addPost(new ManualApprovalStep('approval')); ----- +``` + +------ +#### [ JavaScript ] -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +``` // const { ManualApprovalStep } = require('aws-cdk-lib/pipelines'); const testingStage = pipeline.addStage(new MyPipelineAppStage(this, 'testing', { @@ -1046,28 +847,28 @@ const testingStage = pipeline.addStage(new MyPipelineAppStage(this, 'testing', { })); testingStage.addPost(new ManualApprovalStep('approval')); ----- +``` -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- +------ +#### [ Python ] + +``` # from aws_cdk.pipelines import ManualApprovalStep testing_stage = pipeline.add_stage(MyPipelineAppStage(self, "testing", env=cdk.Environment(account="111111111111", region="eu-west-1"))) testing_stage.add_post(ManualApprovalStep('approval')) ----- +``` + +------ +#### [ Java ] -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- +``` // import software.amazon.awscdk.pipelines.StageDeployment; // import software.amazon.awscdk.pipelines.ManualApprovalStep; -StageDeployment testingStage = +StageDeployment testingStage = pipeline.addStage(new MyPipelineAppStage(this, "test", StageProps.builder() .env(Environment.builder() .account("111111111111") @@ -1076,12 +877,12 @@ StageDeployment testingStage = .build())); testingStage.addPost(new ManualApprovalStep("approval")); ----- +``` -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- +------ +#### [ C\# ] + +``` var testingStage = pipeline.AddStage(new MyPipelineAppStage(this, "test", new StageProps { Env = new Environment @@ -1091,17 +892,16 @@ var testingStage = pipeline.AddStage(new MyPipelineAppStage(this, "test", new St })); testingStage.AddPost(new ManualApprovalStep("approval")); ----- -==== +``` + +------ + +You can add stages to a [Wave](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.pipelines.Wave.html) to deploy them in parallel, for example when deploying a stage to multiple accounts or Regions\. -You can add stages to a `link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.pipelines.Wave.html[Wave]` to deploy them in parallel, for example when deploying a stage to multiple accounts or Regions. +------ +#### [ TypeScript ] -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +``` const wave = pipeline.addWave('wave'); wave.addStage(new MyApplicationStage(this, 'MyAppEU', { env: { account: '111111111111', region: 'eu-west-1' } @@ -1109,12 +909,12 @@ wave.addStage(new MyApplicationStage(this, 'MyAppEU', { wave.addStage(new MyApplicationStage(this, 'MyAppUS', { env: { account: '111111111111', region: 'us-west-1' } })); ----- +``` -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +------ +#### [ JavaScript ] + +``` const wave = pipeline.addWave('wave'); wave.addStage(new MyApplicationStage(this, 'MyAppEU', { env: { account: '111111111111', region: 'eu-west-1' } @@ -1122,23 +922,23 @@ wave.addStage(new MyApplicationStage(this, 'MyAppEU', { wave.addStage(new MyApplicationStage(this, 'MyAppUS', { env: { account: '111111111111', region: 'us-west-1' } })); ----- +``` + +------ +#### [ Python ] -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- +``` wave = pipeline.add_wave("wave") -wave.add_stage(MyApplicationStage(self, "MyAppEU", +wave.add_stage(MyApplicationStage(self, "MyAppEU", env=cdk.Environment(account="111111111111", region="eu-west-1"))) -wave.add_stage(MyApplicationStage(self, "MyAppUS", +wave.add_stage(MyApplicationStage(self, "MyAppUS", env=cdk.Environment(account="111111111111", region="us-west-1"))) ----- +``` -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- +------ +#### [ Java ] + +``` // import software.amazon.awscdk.pipelines.Wave; final Wave wave = pipeline.addWave("wave"); wave.addStage(new MyPipelineAppStage(this, "MyAppEU", StageProps.builder() @@ -1153,12 +953,12 @@ wave.addStage(new MyPipelineAppStage(this, "MyAppUS", StageProps.builder() .region("us-west-1") .build()) .build())); ----- +``` + +------ +#### [ C\# ] -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- +``` var wave = pipeline.AddWave("wave"); wave.AddStage(new MyPipelineAppStage(this, "MyAppEU", new StageProps { @@ -1174,88 +974,84 @@ wave.AddStage(new MyPipelineAppStage(this, "MyAppUS", new StageProps Account = "111111111111", Region = "us-west-1" } })); ----- -==== +``` -[#cdk-pipeline-validation] -== Testing deployments +------ -You can add steps to a CDK Pipeline to validate the deployments that you're performing. For example, you can use the CDK Pipeline library's `link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.pipelines.ShellStep.html[ShellStep]` to perform tasks such as the following: +## Testing deployments<a name="cdk_pipeline_validation"></a> -* Trying to access a newly deployed Amazon API Gateway backed by a Lambda function -* Checking a setting of a deployed resource by issuing an {aws} CLI command +You can add steps to a CDK Pipeline to validate the deployments that you're performing\. For example, you can use the CDK Pipeline library's `[ShellStep](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.pipelines.ShellStep.html)` to perform tasks such as the following: ++ Trying to access a newly deployed Amazon API Gateway backed by a Lambda function ++ Checking a setting of a deployed resource by issuing an AWS CLI command In its simplest form, adding validation actions looks like this: -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +------ +#### [ TypeScript ] + +``` // stage was returned by pipeline.addStage stage.addPost(new ShellStep("validate", { commands: ['../tests/validate.sh'], })); ----- +``` -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +------ +#### [ JavaScript ] + +``` // stage was returned by pipeline.addStage stage.addPost(new ShellStep("validate", { commands: ['../tests/validate.sh'], })); ----- +``` + +------ +#### [ Python ] -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- +``` # stage was returned by pipeline.add_stage stage.add_post(ShellStep("validate", commands=[''../tests/validate.sh''] )) ----- +``` -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- +------ +#### [ Java ] + +``` // stage was returned by pipeline.addStage stage.addPost(ShellStep.Builder.create("validate") .commands(Arrays.asList("'../tests/validate.sh'")) .build()); ----- +``` + +------ +#### [ C\# ] -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- +``` // stage was returned by pipeline.addStage stage.AddPost(new ShellStep("validate", new ShellStepProps { Commands = new string[] { "'../tests/validate.sh'" } })); ----- -==== +``` + +------ -Many {aws} CloudFormation deployments result in the generation of resources with unpredictable names. Because of this, CDK Pipelines provide a way to read {aws} CloudFormation outputs after a deployment. This makes it possible to pass (for example) the generated URL of a load balancer to a test action. +Many AWS CloudFormation deployments result in the generation of resources with unpredictable names\. Because of this, CDK Pipelines provide a way to read AWS CloudFormation outputs after a deployment\. This makes it possible to pass \(for example\) the generated URL of a load balancer to a test action\. -To use outputs, expose the `CfnOutput` object you're interested in. Then, pass it in a step's `envFromCfnOutputs` property to make it available as an environment variable within that step. +To use outputs, expose the `CfnOutput` object you're interested in\. Then, pass it in a step's `envFromCfnOutputs` property to make it available as an environment variable within that step\. -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +------ +#### [ TypeScript ] + +``` // given a stack lbStack that exposes a load balancer construct as loadBalancer this.loadBalancerAddress = new cdk.CfnOutput(lbStack, 'LbAddress', { value: `https://${lbStack.loadBalancer.loadBalancerDnsName}/` @@ -1266,12 +1062,12 @@ stage.addPost(new ShellStep("lbaddr", { envFromCfnOutputs: {lb_addr: lbStack.loadBalancerAddress}, commands: ['echo $lb_addr'] })); ----- +``` + +------ +#### [ JavaScript ] -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +``` // given a stack lbStack that exposes a load balancer construct as loadBalancer this.loadBalancerAddress = new cdk.CfnOutput(lbStack, 'LbAddress', { value: `https://${lbStack.loadBalancer.loadBalancerDnsName}/` @@ -1282,29 +1078,29 @@ stage.addPost(new ShellStep("lbaddr", { envFromCfnOutputs: {lb_addr: lbStack.loadBalancerAddress}, commands: ['echo $lb_addr'] })); ----- +``` -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- +------ +#### [ Python ] + +``` # given a stack lb_stack that exposes a load balancer construct as load_balancer -self.load_balancer_address = cdk.CfnOutput(lb_stack, "LbAddress", +self.load_balancer_address = cdk.CfnOutput(lb_stack, "LbAddress", value=f"https://{lb_stack.load_balancer.load_balancer_dns_name}/") # pass the load balancer address to a shell step -stage.add_post(ShellStep("lbaddr", +stage.add_post(ShellStep("lbaddr", env_from_cfn_outputs={"lb_addr": lb_stack.load_balancer_address} commands=["echo $lb_addr"])) ----- +``` + +------ +#### [ Java ] -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- +``` // given a stack lbStack that exposes a load balancer construct as loadBalancer loadBalancerAddress = CfnOutput.Builder.create(lbStack, "LbAddress") - .value(String.format("https://%s/", + .value(String.format("https://%s/", lbStack.loadBalancer.loadBalancerDnsName)) .build(); @@ -1313,12 +1109,12 @@ stage.addPost(ShellStep.Builder.create("lbaddr") java.util.Map.of("lbAddr", loadBalancerAddress)) .commands(Arrays.asList("echo $lbAddr")) .build()); ----- +``` -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- +------ +#### [ C\# ] + +``` // given a stack lbStack that exposes a load balancer construct as loadBalancer loadBalancerAddress = new CfnOutput(lbStack, "LbAddress", new CfnOutputProps { @@ -1333,19 +1129,18 @@ stage.AddPost(new ShellStep("lbaddr", new ShellStepProps }, Commands = new string[] { "echo $lbAddr" } })); ----- -==== +``` + +------ -You can write simple validation tests right in the `ShellStep`, but this approach becomes unwieldy when the test is more than a few lines. For more complex tests, you can bring additional files (such as complete shell scripts, or programs in other languages) into the `ShellStep` via the `inputs` property. The inputs can be any step that has an output, including a source (such as a GitHub repo) or another `ShellStep`. +You can write simple validation tests right in the `ShellStep`, but this approach becomes unwieldy when the test is more than a few lines\. For more complex tests, you can bring additional files \(such as complete shell scripts, or programs in other languages\) into the `ShellStep` via the `inputs` property\. The inputs can be any step that has an output, including a source \(such as a GitHub repo\) or another `ShellStep`\. -Bringing in files from the source repository is appropriate if the files are directly usable in the test (for example, if they are themselves executable). In this example, we declare our GitHub repo as `source` (rather than instantiating it inline as part of the `CodePipeline`). Then, we pass this fileset to both the pipeline and the validation test. +Bringing in files from the source repository is appropriate if the files are directly usable in the test \(for example, if they are themselves executable\)\. In this example, we declare our GitHub repo as `source` \(rather than instantiating it inline as part of the `CodePipeline`\)\. Then, we pass this fileset to both the pipeline and the validation test\. -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +------ +#### [ TypeScript ] + +``` const source = CodePipelineSource.gitHub('OWNER/REPO', 'main'); const pipeline = new CodePipeline(this, 'Pipeline', { @@ -1364,12 +1159,12 @@ stage.addPost(new ShellStep('validate', { input: source, commands: ['sh ../tests/validate.sh'] })); ----- +``` + +------ +#### [ JavaScript ] -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +``` const source = CodePipelineSource.gitHub('OWNER/REPO', 'main'); const pipeline = new CodePipeline(this, 'Pipeline', { @@ -1388,17 +1183,17 @@ stage.addPost(new ShellStep('validate', { input: source, commands: ['sh ../tests/validate.sh'] })); ----- +``` + +------ +#### [ Python ] -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- +``` source = CodePipelineSource.git_hub("OWNER/REPO", "main") -pipeline = CodePipeline(self, "Pipeline", +pipeline = CodePipeline(self, "Pipeline", pipeline_name="MyPipeline", - synth=ShellStep("Synth", + synth=ShellStep("Synth", input=source, commands=["npm install -g aws-cdk", "python -m pip install -r requirements.txt", @@ -1410,12 +1205,12 @@ stage = pipeline.add_stage(MyApplicationStage(self, "test", stage.add_post(ShellStep("validate", input=source, commands=["sh ../tests/validate.sh"], )) ----- +``` -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- +------ +#### [ Java ] + +``` final CodePipelineSource source = CodePipelineSource.gitHub("OWNER/REPO", "main"); final CodePipeline pipeline = CodePipeline.Builder.create(this, "pipeline") @@ -1426,7 +1221,7 @@ final CodePipeline pipeline = CodePipeline.Builder.create(this, "pipeline") .build()) .build(); -final StageDeployment stage = +final StageDeployment stage = pipeline.addStage(new MyPipelineAppStage(this, "test", StageProps.builder() .env(Environment.builder() .account("111111111111") @@ -1438,12 +1233,12 @@ stage.addPost(ShellStep.Builder.create("validate") .input(source) .commands(Arrays.asList("sh ../tests/validate.sh")) .build()); ----- +``` + +------ +#### [ C\# ] -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- +``` var source = CodePipelineSource.GitHub("OWNER/REPO", "main"); var pipeline = new CodePipeline(this, "pipeline", new CodePipelineProps @@ -1469,17 +1264,16 @@ stage.AddPost(new ShellStep("validate", new ShellStepProps Input = source, Commands = new string[] { "sh ../tests/validate.sh" } })); ----- -==== +``` -Getting the additional files from the synth step is appropriate if your tests need to be compiled, which is done as part of synthesis. +------ -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +Getting the additional files from the synth step is appropriate if your tests need to be compiled, which is done as part of synthesis\. + +------ +#### [ TypeScript ] + +``` const synthStep = new ShellStep('Synth', { input: CodePipelineSource.gitHub('OWNER/REPO', 'main'), commands: ['npm ci', 'npm run build', 'npx cdk synth'], @@ -1499,12 +1293,12 @@ stage.addPost(new ShellStep('validate', { input: synthStep, commands: ['node tests/validate.js'] })); ----- +``` -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +------ +#### [ JavaScript ] + +``` const synthStep = new ShellStep('Synth', { input: CodePipelineSource.gitHub('OWNER/REPO', 'main'), commands: ['npm ci', 'npm run build', 'npx cdk synth'], @@ -1524,19 +1318,19 @@ stage.addPost(new ShellStep('validate', { input: synthStep, commands: ['node tests/validate.js'] })); ----- +``` + +------ +#### [ Python ] -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -synth_step = ShellStep("Synth", +``` +synth_step = ShellStep("Synth", input=CodePipelineSource.git_hub("OWNER/REPO", "main"), commands=["npm install -g aws-cdk", "python -m pip install -r requirements.txt", "cdk synth"]) -pipeline = CodePipeline(self, "Pipeline", +pipeline = CodePipeline(self, "Pipeline", pipeline_name="MyPipeline", synth=synth_step) @@ -1548,23 +1342,23 @@ stage.add_post(ShellStep("validate", input=synth_step, commands=["node test/validate.js"], )) ----- +``` -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- +------ +#### [ Java ] + +``` final ShellStep synth = ShellStep.Builder.create("Synth") .input(CodePipelineSource.gitHub("OWNER/REPO", "main")) .commands(Arrays.asList("npm install -g aws-cdk", "cdk synth")) - .build(); - + .build(); + final CodePipeline pipeline = CodePipeline.Builder.create(this, "pipeline") .pipelineName("MyPipeline") .synth(synth) .build(); -final StageDeployment stage = +final StageDeployment stage = pipeline.addStage(new MyPipelineAppStage(this, "test", StageProps.builder() .env(Environment.builder() .account("111111111111") @@ -1576,12 +1370,12 @@ stage.addPost(ShellStep.Builder.create("validate") .input(synth) .commands(Arrays.asList("node ./tests/validate.js")) .build()); ----- +``` -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- +------ +#### [ C\# ] + +``` var synth = new ShellStep("Synth", new ShellStepProps { Input = CodePipelineSource.GitHub("OWNER/REPO", "main"), @@ -1607,52 +1401,46 @@ stage.AddPost(new ShellStep("validate", new ShellStepProps Input = synth, Commands = new string[] { "node ./tests/validate.js" } })); ----- -==== +``` + +------ -[#cdk-pipeline-security] -== Security notes +## Security notes<a name="cdk_pipeline_security"></a> -Any form of continuous delivery has inherent security risks. Under the {aws} https://aws.amazon.com/compliance/shared-responsibility-model/[Shared Responsibility Model], you are responsible for the security of your information in the {aws} Cloud. The CDK Pipelines library gives you a head start by incorporating secure defaults and modeling best practices. +Any form of continuous delivery has inherent security risks\. Under the AWS [Shared Responsibility Model](https://aws.amazon.com/compliance/shared-responsibility-model/), you are responsible for the security of your information in the AWS Cloud\. The CDK Pipelines library gives you a head start by incorporating secure defaults and modeling best practices\. -However, by its very nature, a library that needs a high level of access to fulfill its intended purpose cannot assure complete security. There are many attack vectors outside of {aws} and your organization. +However, by its very nature, a library that needs a high level of access to fulfill its intended purpose cannot assure complete security\. There are many attack vectors outside of AWS and your organization\. In particular, keep in mind the following: ++ Be mindful of the software you depend on\. Vet all third\-party software you run in your pipeline, because it can change the infrastructure that gets deployed\. ++ Use dependency locking to prevent accidental upgrades\. CDK Pipelines respects `package-lock.json` and `yarn.lock` to make sure that your dependencies are the ones you expect\. ++ Credentials for production environments should be short\-lived\. After bootstrapping and initial provisioning, there is no need for developers to have account credentials at all\. Changes can be deployed through the pipeline\. Reduce the possibility of credentials leaking by not needing them in the first place\. -* Be mindful of the software you depend on. Vet all third-party software you run in your pipeline, because it can change the infrastructure that gets deployed. -* Use dependency locking to prevent accidental upgrades. CDK Pipelines respects `package-lock.json` and `yarn.lock` to make sure that your dependencies are the ones you expect. -* CDK Pipelines runs on resources created in your own account, and the configuration of those resources is controlled by developers submitting code through the pipeline. Therefore, CDK Pipelines by itself cannot protect against malicious developers trying to bypass compliance checks. If your threat model includes developers writing CDK code, you should have external compliance mechanisms in place like https://aws.amazon.com/blogs/mt/proactively-keep-resources-secure-and-compliant-with-aws-cloudformation-hooks/[{aws} CloudFormation Hooks] (preventive) or https://aws.amazon.com/config/[{aws} Config] (reactive) that the {aws} CloudFormation Execution Role does not have permissions to disable. -* Credentials for production environments should be short-lived. After bootstrapping and initial provisioning, there is no need for developers to have account credentials at all. Changes can be deployed through the pipeline. Reduce the possibility of credentials leaking by not needing them in the first place. +## Troubleshooting<a name="cdk_pipeline_troubleshooting"></a> -[#cdk-pipeline-troubleshooting] -== Troubleshooting +The following issues are commonly encountered while getting started with CDK Pipelines\. -The following issues are commonly encountered while getting started with CDK Pipelines. +**Pipeline: Internal Failure** -*Pipeline: Internal Failure*:: -+ ----- -CREATE_FAILED | {aws}::CodePipeline::Pipeline | Pipeline/Pipeline +``` +CREATE_FAILED | AWS::CodePipeline::Pipeline | Pipeline/Pipeline Internal Failure ----- -+ -Check your GitHub access token. It might be missing, or might not have the permissions to access the repository. - -*Key: Policy contains a statement with one or more invalid principals*:: -+ ----- -CREATE_FAILED | {aws}::KMS::Key | Pipeline/Pipeline/ArtifactsBucketEncryptionKey +``` + Check your GitHub access token\. It might be missing, or might not have the permissions to access the repository\. + +**Key: Policy contains a statement with one or more invalid principals** + +``` +CREATE_FAILED | AWS::KMS::Key | Pipeline/Pipeline/ArtifactsBucketEncryptionKey Policy contains a statement with one or more invalid principals. ----- -+ -One of the target environments has not been bootstrapped with the new bootstrap stack. Make sure all your target environments are bootstrapped. - -*Stack is in ROLLBACK_COMPLETE state and cannot be updated*:: -+ ----- -Stack <STACK_NAME> is in ROLLBACK_COMPLETE state and cannot be updated. (Service: +``` + One of the target environments has not been bootstrapped with the new bootstrap stack\. Make sure all your target environments are bootstrapped\. + +**Stack is in ROLLBACK\_COMPLETE state and can not be updated\.** + +``` +Stack STACK_NAME is in ROLLBACK_COMPLETE state and can not be updated. (Service: AmazonCloudFormation; Status Code: 400; Error Code: ValidationError; Request ID: ...) ----- -+ -The stack failed its previous deployment and is in a non-retryable state. Delete the stack from the {aws} CloudFormation console and retry the deployment. \ No newline at end of file +``` +The stack failed its previous deployment and is in a non\-retryable state\. Delete the stack from the AWS CloudFormation console and retry the deployment\. \ No newline at end of file diff --git a/v2/cfn_layer.md b/v2/cfn_layer.md new file mode 100644 index 00000000..f6fd6747 --- /dev/null +++ b/v2/cfn_layer.md @@ -0,0 +1,510 @@ +# Abstractions and escape hatches<a name="cfn_layer"></a> + +The AWS CDK lets you describe AWS resources using constructs that operate at varying levels of abstraction\. ++ *Layer 1 \(L1\)* constructs directly represent AWS CloudFormation resources as defined by the CloudFormation specification\. These constructs can be identified via a name beginning with "Cfn," so they are also referred to as "Cfn constructs\." If a resource exists in AWS CloudFormation, it exists in the CDK as a L1 construct\. ++ *Layer 2 \(L2\)* or "curated" constructs are thoughtfully developed to provide a more ergonomic developer experience compared to the L1 construct they're built upon\. In a typical CDK app, L2 constructs are usually the most widely used type\. Often, L2 constructs define additional supporting resources, such as IAM policies, Amazon SNS topics, or AWS KMS keys\. L2 constructs provide sensible defaults, best practice security policies, and a more ergonomic developer experience\. ++ *Layer 3 \(L3\)* constructs or *patterns* define entire collections of AWS resources for specific use cases\. L3 constructs help to stand up a build pipeline, an Amazon ECS application, or one of many other types of common deployment scenarios\. Because they can constitute complete system designs, or substantial parts of a larger system, L3 constructs are often "opinionated\." They are built around a particular approach toward solving the problem at hand, and things work out better when you follow their lead\. + +**Tip** +For more details about AWS CDK constructs, see [Constructs](constructs.md)\. + +At the highest level, your AWS CDK application and the stacks in it are themselves abstractions of your entire cloud infrastructure, or significant chunks of it\. They can be parameterized to deploy them in different environments or for different needs\. + +Abstractions are powerful tools for designing and implementing cloud applications\. The AWS CDK gives you the power not only to build with its abstractions, but also to create new abstractions\. Using the existing open\-source L2 and L3 constructs as guidance, you can build your own L2 and L3 constructs to reflect your own organization's best practices and opinions\. + +No abstraction is perfect, and even good abstractions cannot cover every possible use case\. Although the value of the AWS CDK's model is plain, you might sometimes find a construct that almost fits your needs, lacking only a small \(or large\) tweak\. + +For this reason, the AWS CDK provides ways to "break out" of the construct model\. This lets you move to a lower level of abstraction or to a different model entirely\. As their name implies, the CDK's *escape hatches* let you "escape" the AWS CDK paradigm and extend it in ways the AWS CDK designers didn't anticipate\. Then you can wrap all that in a new construct to hide the underlying complexity and provide a clean API for developers\. + +Some situations in which you'll reach for escape hatches include: ++ An AWS service feature is available through AWS CloudFormation, but there are no L2 constructs for it\. ++ An AWS service feature is available through AWS CloudFormation, and there are L2 constructs for the service, but these don't yet expose the feature\. Because L2 constructs are developed "by hand," they may sometimes lag behind the L1 constructs\. ++ The feature is not yet available through AWS CloudFormation at all\. + +To determine whether a feature is available through AWS CloudFormation, see [AWS Resource and Property Types Reference](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html)\. + +## Using AWS CloudFormation constructs directly<a name="cfn_layer_cfn"></a> + +If there are no L2 classes available for the service, you can fall back to the automatically generated L1 constructs\. These map 1:1 to all available AWS CloudFormation resources and properties\. These resources can be recognized by their name starting with `Cfn`, such as `CfnBucket` or `CfnRole`\. You instantiate them exactly as you would use the equivalent AWS CloudFormation resource\. For more information, see [AWS Resource and Property Types Reference](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html)\. + +For example, to instantiate a low\-level Amazon S3 bucket L1 with analytics enabled, you would write something like the following\. + +------ +#### [ TypeScript ] + +``` +new s3.CfnBucket(this, 'MyBucket', { + analyticsConfigurations: [ + { + id: 'Config', + // ... + } + ] +}); +``` + +------ +#### [ JavaScript ] + +``` +new s3.CfnBucket(this, 'MyBucket', { + analyticsConfigurations: [ + { + id: 'Config' + // ... + } + ] +}); +``` + +------ +#### [ Python ] + +``` +s3.CfnBucket(self, "MyBucket", + analytics_configurations: [ + dict(id="Config", + # ... + ) + ] +) +``` + +------ +#### [ Java ] + +``` +CfnBucket.Builder.create(this, "MyBucket") + .analyticsConfigurations(Arrays.asList(java.util.Map.of( // Java 9 or later + "id", "Config", // ... + ))).build(); +``` + +------ +#### [ C\# ] + +``` +new CfnBucket(this, 'MyBucket', new CfnBucketProps { + AnalyticsConfigurations = new Dictionary<string, string> + { + ["id"] = "Config", + // ... + } +}); +``` + +------ + +There might be rare cases where you want to define a resource that doesn't have a corresponding `CfnXxx` class\. This could be a new resource type that hasn't yet been published in the AWS CloudFormation resource specification\. In cases like this, you can instantiate the `cdk.CfnResource` directly and specify the resource type and properties\. This is shown in the following example\. + +------ +#### [ TypeScript ] + +``` +new cdk.CfnResource(this, 'MyBucket', { + type: 'AWS::S3::Bucket', + properties: { + // Note the PascalCase here! These are CloudFormation identifiers. + AnalyticsConfigurations: [ + { + Id: 'Config', + // ... + } + ] + } +}); +``` + +------ +#### [ JavaScript ] + +``` +new cdk.CfnResource(this, 'MyBucket', { + type: 'AWS::S3::Bucket', + properties: { + // Note the PascalCase here! These are CloudFormation identifiers. + AnalyticsConfigurations: [ + { + Id: 'Config' + // ... + } + ] + } +}); +``` + +------ +#### [ Python ] + +``` +cdk.CfnResource(self, 'MyBucket', + type="AWS::S3::Bucket", + properties=dict( + # Note the PascalCase here! These are CloudFormation identifiers. + "AnalyticsConfigurations": [ + { + "Id": "Config", + # ... + } + ] + } +) +``` + +------ +#### [ Java ] + +``` +CfnResource.Builder.create(this, "MyBucket") + .type("AWS::S3::Bucket") + .properties(java.util.Map.of( // Map.of requires Java 9 or later + // Note the PascalCase here! These are CloudFormation identifiers + "AnalyticsConfigurations", Arrays.asList( + java.util.Map.of("Id", "Config", // ... + )))) + .build(); +``` + +------ +#### [ C\# ] + +``` +new CfnResource(this, "MyBucket", new CfnResourceProps +{ + Type = "AWS::S3::Bucket", + Properties = new Dictionary<string, object> + { // Note the PascalCase here! These are CloudFormation identifiers + ["AnalyticsConfigurations"] = new Dictionary<string, string>[] + { + new Dictionary<string, string> { + ["Id"] = "Config" + } + } + } +}); +``` + +------ + +For more information, see [AWS Resource and Property Types Reference](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html)\. + +## Modifying the AWS CloudFormation resource behind AWS constructs<a name="cfn_layer_resource"></a> + +If an L2 construct is missing a feature or you're trying to work around an issue, you can modify the L1 construct that's encapsulated by the L2 construct\. + +All L2 constructs contain within them the corresponding L1 construct\. For example, the high\-level `Bucket` construct wraps the low\-level `CfnBucket` construct\. Because the `CfnBucket` corresponds directly to the AWS CloudFormation resource, it exposes all features that are available through AWS CloudFormation\. + +The basic approach to get access to the L1 class is to use `construct.node.defaultChild` \(Python: `default_child`\), cast it to the right type \(if necessary\), and modify its properties\. Again, let's take the example of a `Bucket`\. + +------ +#### [ TypeScript ] + +``` +// Get the CloudFormation resource +const cfnBucket = bucket.node.defaultChild as s3.CfnBucket; + +// Change its properties +cfnBucket.analyticsConfiguration = [ + { + id: 'Config', + // ... + } +]; +``` + +------ +#### [ JavaScript ] + +``` +// Get the CloudFormation resource +const cfnBucket = bucket.node.defaultChild; + +// Change its properties +cfnBucket.analyticsConfiguration = [ + { + id: 'Config' + // ... + } +]; +``` + +------ +#### [ Python ] + +``` +# Get the CloudFormation resource +cfn_bucket = bucket.node.default_child + +# Change its properties +cfn_bucket.analytics_configuration = [ + { + "id": "Config", + # ... + } +] +``` + +------ +#### [ Java ] + +``` +// Get the CloudFormation resource +CfnBucket cfnBucket = (CfnBucket)bucket.getNode().getDefaultChild(); + +cfnBucket.setAnalyticsConfigurations( + Arrays.asList(java.util.Map.of( // Java 9 or later + "Id", "Config", // ... + )); +``` + +------ +#### [ C\# ] + +``` +// Get the CloudFormation resource +var cfnBucket = (CfnBucket)bucket.Node.DefaultChild; + +cfnBucket.AnalyticsConfigurations = new List<object> { + new Dictionary<string, string> + { + ["Id"] = "Config", + // ... + } +}; +``` + +------ + +You can also use this object to change AWS CloudFormation options such as `Metadata` and `UpdatePolicy`\. + +------ +#### [ TypeScript ] + +``` +cfnBucket.cfnOptions.metadata = { + MetadataKey: 'MetadataValue' +}; +``` + +------ +#### [ JavaScript ] + +``` +cfnBucket.cfnOptions.metadata = { + MetadataKey: 'MetadataValue' +}; +``` + +------ +#### [ Python ] + +``` +cfn_bucket.cfn_options.metadata = { + "MetadataKey": "MetadataValue" +} +``` + +------ +#### [ Java ] + +``` +cfnBucket.getCfnOptions().setMetadata(java.util.Map.of( // Java 9+ + "MetadataKey", "Metadatavalue")); +``` + +------ +#### [ C\# ] + +``` +cfnBucket.CfnOptions.Metadata = new Dictionary<string, object> +{ + ["MetadataKey"] = "Metadatavalue" +}; +``` + +------ + +## An unescape hatch<a name="cfn_layer_unescape"></a> + +The AWS CDK also provides the capability to go *up* an abstraction level, which we might cheekily refer to as an "unescape" hatch\. If you have an L1 construct, such as `CfnBucket`, you can create a new L2 construct \(`Bucket` in this case\) to wrap the L1 construct\. + +This is convenient when you create an L1 resource but want to use it with a construct that requires an L2 resource\. It's also helpful when you want to use convenience methods like `.grantXxxxx()` that aren't available on the L1 construct\. + +You move to the higher abstraction level using a static method on the L2 class called `.fromCfnXxxxx()`—for example, `Bucket.fromCfnBucket()` for Amazon S3 buckets\. The L1 resource is the only parameter\. + +------ +#### [ TypeScript ] + +``` +b1 = new s3.CfnBucket(this, "buck09", { ... }); +b2 = s3.Bucket.fromCfnBucket(b1); +``` + +------ +#### [ JavaScript ] + +``` +b1 = new s3.CfnBucket(this, "buck09", { ...} ); +b2 = s3.Bucket.fromCfnBucket(b1); +``` + +------ +#### [ Python ] + +``` +b1 = s3.CfnBucket(self, "buck09", ...) + b2 = s3.from_cfn_bucket(b1) +``` + +------ +#### [ Java ] + +``` +CfnBucket b1 = CfnBucket.Builder.create(this, "buck09") + // .... + .build(); +IBucket b2 = Bucket.fromCfnBucket(b1); +``` + +------ +#### [ C\# ] + +``` +var b1 = new CfnBucket(this, "buck09", new CfnBucketProps { ... }); +var v2 = Bucket.FromCfnBucket(b1); +``` + +------ + +L2 constructs created from L1 constructs are proxy objects that refer to the L1 resource, similar to those created from resource names, ARNs, or lookups\. Modifications to these constructs do not affect the final synthesized AWS CloudFormation template \(since you have the L1 resource, however, you can modify that instead\)\. For more information on proxy objects, see [Referencing resources in your AWS account](resources.md#resources_external)\. + +To avoid confusion, do not create multiple L2 constructs that refer to the same L1 construct\. For example, if you extract the `CfnBucket` from a `Bucket` using the technique in the [previous section](#cfn_layer_resource), you shouldn't create a second `Bucket` instance by calling `Bucket.fromCfnBucket()` with that `CfnBucket`\. It actually works as you'd expect \(only one `AWS::S3::Bucket` is synthesized\) but it makes your code more difficult to maintain\. + +## Raw overrides<a name="cfn_layer_raw"></a> + +If there are properties that are missing from the L1 construct, you can bypass all typing using raw overrides\. This also makes it possible to delete synthesized properties\. + +Use one of the `addOverride` methods \(Python: `add_override`\) methods, as shown in the following example\. + +------ +#### [ TypeScript ] + +``` +// Get the CloudFormation resource +const cfnBucket = bucket.node.defaultChild as s3.CfnBucket; + +// Use dot notation to address inside the resource template fragment +cfnBucket.addOverride('Properties.VersioningConfiguration.Status', 'NewStatus'); +cfnBucket.addDeletionOverride('Properties.VersioningConfiguration.Status'); + +// use index (0 here) to address an element of a list +cfnBucket.addOverride('Properties.Tags.0.Value', 'NewValue'); +cfnBucket.addDeletionOverride('Properties.Tags.0'); + +// addPropertyOverride is a convenience function for paths starting with "Properties." +cfnBucket.addPropertyOverride('VersioningConfiguration.Status', 'NewStatus'); +cfnBucket.addPropertyDeletionOverride('VersioningConfiguration.Status'); +cfnBucket.addPropertyOverride('Tags.0.Value', 'NewValue'); +cfnBucket.addPropertyDeletionOverride('Tags.0'); +``` + +------ +#### [ JavaScript ] + +``` +// Get the CloudFormation resource +const cfnBucket = bucket.node.defaultChild ; + +// Use dot notation to address inside the resource template fragment +cfnBucket.addOverride('Properties.VersioningConfiguration.Status', 'NewStatus'); +cfnBucket.addDeletionOverride('Properties.VersioningConfiguration.Status'); + +// use index (0 here) to address an element of a list +cfnBucket.addOverride('Properties.Tags.0.Value', 'NewValue'); +cfnBucket.addDeletionOverride('Properties.Tags.0'); + +// addPropertyOverride is a convenience function for paths starting with "Properties." +cfnBucket.addPropertyOverride('VersioningConfiguration.Status', 'NewStatus'); +cfnBucket.addPropertyDeletionOverride('VersioningConfiguration.Status'); +cfnBucket.addPropertyOverride('Tags.0.Value', 'NewValue'); +cfnBucket.addPropertyDeletionOverride('Tags.0'); +``` + +------ +#### [ Python ] + +``` +# Get the CloudFormation resource +cfn_bucket = bucket.node.default_child + +# Use dot notation to address inside the resource template fragment +cfn_bucket.add_override("Properties.VersioningConfiguration.Status", "NewStatus") +cfn_bucket.add_deletion_override("Properties.VersioningConfiguration.Status") + +# use index (0 here) to address an element of a list +cfn_bucket.add_override("Properties.Tags.0.Value", "NewValue") +cfn_bucket.add_deletion_override("Properties.Tags.0") + +# addPropertyOverride is a convenience function for paths starting with "Properties." +cfn_bucket.add_property_override("VersioningConfiguration.Status", "NewStatus") +cfn_bucket.add_property_deletion_override("VersioningConfiguration.Status") +cfn_bucket.add_property_override("Tags.0.Value", "NewValue") +cfn_bucket.add_property_deletion_override("Tags.0") +``` + +------ +#### [ Java ] + +``` +// Get the CloudFormation resource +CfnBucket cfnBucket = (CfnBucket)bucket.getNode().getDefaultChild(); + +// Use dot notation to address inside the resource template fragment +cfnBucket.addOverride("Properties.VersioningConfiguration.Status", "NewStatus"); +cfnBucket.addDeletionOverride("Properties.VersioningConfiguration.Status"); + +// use index (0 here) to address an element of a list +cfnBucket.addOverride("Properties.Tags.0.Value", "NewValue"); +cfnBucket.addDeletionOverride("Properties.Tags.0"); + +// addPropertyOverride is a convenience function for paths starting with "Properties." +cfnBucket.addPropertyOverride("VersioningConfiguration.Status", "NewStatus"); +cfnBucket.addPropertyDeletionOverride("VersioningConfiguration.Status"); +cfnBucket.addPropertyOverride("Tags.0.Value", "NewValue"); +cfnBucket.addPropertyDeletionOverride("Tags.0"); +``` + +------ +#### [ C\# ] + +``` +// Get the CloudFormation resource +var cfnBucket = (CfnBucket)bucket.node.defaultChild; + +// Use dot notation to address inside the resource template fragment +cfnBucket.AddOverride("Properties.VersioningConfiguration.Status", "NewStatus"); +cfnBucket.AddDeletionOverride("Properties.VersioningConfiguration.Status"); + +// use index (0 here) to address an element of a list +cfnBucket.AddOverride("Properties.Tags.0.Value", "NewValue"); +cfnBucket.AddDeletionOverride("Properties.Tags.0"); + +// addPropertyOverride is a convenience function for paths starting with "Properties." +cfnBucket.AddPropertyOverride("VersioningConfiguration.Status", "NewStatus"); +cfnBucket.AddPropertyDeletionOverride("VersioningConfiguration.Status"); +cfnBucket.AddPropertyOverride("Tags.0.Value", "NewValue"); +cfnBucket.AddPropertyDeletionOverride("Tags.0"); +``` + +------ + +## Custom resources<a name="cfn_layer_custom"></a> + +If the feature isn't available through AWS CloudFormation, but only through a direct API call, there's only one solution\. You must write an AWS CloudFormation Custom Resource to make the API call you need\. Don't worry, the AWS CDK makes it easier to write these and wrap them up into a regular construct interface\. From the perspective of a consumer of your construct, the feature feels native\. + +Building a custom resource involves writing a Lambda function that responds to a resource's `CREATE`, `UPDATE`, and `DELETE` lifecycle events\. If your custom resource needs to make only a single API call, consider using the [AwsCustomResource](https://github.com/awslabs/aws-cdk/tree/master/packages/%40aws-cdk/custom-resources)\. This makes it possible to perform arbitrary SDK calls during an AWS CloudFormation deployment\. Otherwise, you should write your own Lambda function to perform the work you need to get done\. + +The subject is too broad to cover completely here, but the following links should get you started: ++ [Custom Resources](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-custom-resources.html) ++ [Custom\-Resource Example](https://github.com/aws-samples/aws-cdk-examples/tree/master/typescript/custom-resource/) ++ For a more fully fledged example, see the [DnsValidatedCertificate](https://github.com/awslabs/aws-cdk/blob/master/packages/@aws-cdk/aws-certificatemanager/lib/dns-validated-certificate.ts) class in the CDK standard library\. This is implemented as a custom resource\. \ No newline at end of file diff --git a/v2/cli.md b/v2/cli.md new file mode 100644 index 00000000..62c971a4 --- /dev/null +++ b/v2/cli.md @@ -0,0 +1,594 @@ +# AWS CDK Toolkit \(`cdk` command\)<a name="cli"></a> + +The AWS CDK Toolkit, the CLI command `cdk`, is the primary tool for interacting with your AWS CDK app\. It executes your app, interrogates the application model you defined, and produces and deploys the AWS CloudFormation templates generated by the AWS CDK\. It also provides other features useful for creating and working with AWS CDK projects\. This topic contains information about common use cases of the CDK Toolkit\. + +The AWS CDK Toolkit is installed with the Node Package Manager\. In most cases, we recommend installing it globally\. + +``` +npm install -g aws-cdk # install latest version +npm install -g aws-cdk@X.YY.Z # install specific version +``` + +**Tip** +If you regularly work with multiple versions of the AWS CDK, consider installing a matching version of the AWS CDK Toolkit in individual CDK projects\. To do this, omit `-g` from the `npm install` command\. Then use `npx aws-cdk` to invoke it\. This runs the local version if one exists, falling back to a global version if not\. + +## Toolkit commands<a name="cli-commands"></a> + +All CDK Toolkit commands start with `cdk`, which is followed by a subcommand \(`list`, `synthesize`, `deploy`, etc\.\)\. Some subcommands have a shorter version \(`ls`, `synth`, etc\.\) that is equivalent\. Options and arguments follow the subcommand in any order\. The available commands are summarized here\. + + +| Command | Function | +| --- | --- | +| `cdk list` \(`ls`\) | Lists the stacks in the app | +| `cdk synthesize` \(`synth`\) | Synthesizes and prints the CloudFormation template for one or more specified stacks | +| `cdk bootstrap` | Deploys the CDK Toolkit staging stack; see [Bootstrapping](bootstrapping.md) | +| `cdk deploy` | Deploys one or more specified stacks | +| `cdk destroy` | Destroys one or more specified stacks | +| `cdk diff` | Compares the specified stack and its dependencies with the deployed stacks or a local CloudFormation template | +| `cdk metadata` | Displays metadata about the specified stack | +| `cdk init` | Creates a new CDK project in the current directory from a specified template | +| `cdk context` | Manages cached context values | +| `cdk docs` \(`doc`\) | Opens the CDK API Reference in your browser | +| `cdk doctor` | Checks your CDK project for potential problems | + +For the options available for each command, see [Built\-in help](#cli-help)\. + +## Specifying options and their values<a name="cli-options"></a> + +Command line options begin with two hyphens \(`--`\)\. Some frequently used options have single\-letter synonyms that begin with a single hyphen \(for example, `--app` has a synonym `-a`\)\. The order of options in an AWS CDK Toolkit command is not important\. + +All options accept a value, which must follow the option name\. The value may be separated from the name by white space or by an equals sign `=`\. The following two options are equivalent\. + +``` +--toolkit-stack-name MyBootstrapStack +--toolkit-stack-name=MyBootstrapStack +``` + +Some options are flags \(Booleans\)\. You may specify `true` or `false` as their value\. If you do not provide a value, the value is taken to be `true`\. You may also prefix the option name with `no-` to imply `false`\. + +``` +# sets staging flag to true +--staging +--staging=true +--staging true + +# sets staging flag to false +--no-staging +--staging=false +--staging false +``` + +A few options, namely `--context`, `--parameters`, `--plugin`, `--tags`, and `--trust`, may be specified more than once to specify multiple values\. These are noted as having `[array]` type in the CDK Toolkit help\. For example: + +``` +cdk bootstrap --tags costCenter=0123 --tags responsibleParty=jdoe +``` + +## Built\-in help<a name="cli-help"></a> + +The AWS CDK Toolkit has integrated help\. You can see general help about the utility and a list of the provided subcommands by issuing: + +``` +cdk --help +``` + +To see help for a particular subcommand, for example `deploy`, specify it before the `--help` flag\. + +``` +cdk deploy --help +``` + +Issue `cdk version` to display the version of the AWS CDK Toolkit\. Provide this information when requesting support\. + +## Version reporting<a name="version_reporting"></a> + +To gain insight into how the AWS CDK is used, the constructs used by AWS CDK applications are collected and reported by using a resource identified as `AWS::CDK::Metadata`\. This resource is added to AWS CloudFormation templates, and can easily be reviewed\. This information can also be used by AWS to identify stacks using a construct with known security or reliability issues\. It can also be used to contact their users with important information\. + +**Note** +Before version 1\.93\.0, the AWS CDK reported the names and versions of the modules loaded during synthesis, instead of the constructs used in the stack\. + +By default, the AWS CDK reports the use of constructs in the following NPM modules that are used in the stack: ++ AWS CDK core module ++ AWS Construct Library modules ++ AWS Solutions Constructs module ++ AWS Render Farm Deployment Kit module + +The `AWS::CDK::Metadata` resource looks something like the following\. + +``` +CDKMetadata: + Type: "AWS::CDK::Metadata" + Properties: + Analytics: "v2:deflate64:H4sIAND9SGAAAzXKSw5AMBAA0L1b2PdzBYnEAdio3RglglY60zQi7u6TWL/XKmNUlxeQSOKwaPTBqrNhwEWU3hGHiCzK0dWWfAxoL/Fd8mvk+QkS/0X6BdjnCdgmOOQKWz+AqqLDt2Y3YMnLYWwAAAA=" +``` + +The `Analytics` property is a gzipped, base64\-encoded, prefix\-encoded list of the constructs in the stack\. + +To opt out of version reporting, use one of the following methods: ++ Use the cdk command with the \-\-no\-version\-reporting argument to opt out for a single command\. + + ``` + cdk --no-version-reporting synth + ``` + + Remember, the AWS CDK Toolkit synthesizes fresh templates before deploying, so you should also add `--no-version-reporting` to `cdk deploy` commands\. ++ Set versionReporting to **false** in `./cdk.json` or `~/.cdk.json`\. This opts out unless you opt in by specifying `--version-reporting` on an individual command\. + + ``` + { + "app": "...", + "versionReporting": false + } + ``` + +## Specifying credentials and Region<a name="cli-environment"></a> + +The CDK Toolkit needs to know your AWS account credentials and the AWS Region that you're deploying into\. This is needed for deployment operations and to retrieve context values during synthesis\. Together, your account and Region make up the *environment*\. + +**Important** +We strongly recommend against using your main AWS account for day\-to\-day tasks\. Instead, create a user in IAM and use its credentials with the CDK\. + +Credentials and Region may be specified using environment variables or in configuration files\. These are the same variables and files used by other AWS tools such as the AWS CLI and the various AWS SDKs\. The CDK Toolkit looks for this information in the following order\. ++ The `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, and `AWS_DEFAULT_REGION` environment variables\. Always specify all three variables, not only one or two\. ++ A specific profile defined in the standard AWS `config` and `credentials` files, and specified using the `--profile` option on `cdk` commands\. ++ The `[default]` section of the standard AWS `config` and `credentials` files\. + +**Note** +The standard AWS `config` and `credentials` files are located at `~/.aws/config` and `~/.aws/credentials` \(macOS/Linux\) or `%USERPROFILE%\.aws\config` and `%USERPROFILE%\.aws\credentials` \(Windows\)\. + +The environment that you specify in your AWS CDK app by using the stack's `env` property is used during synthesis\. It's used to generate an environment\-specific AWS CloudFormation template, and during deployment, it overrides the account or Region specified by one of the preceding methods\. For more information, see [Environments](environments.md)\. + +If you have the AWS CLI installed, the easiest way to configure your account credentials and a default Region is to issue the following command: + +``` +aws configure +``` + +Provide your AWS access key ID, secret access key, and default Region when prompted\. These values are written to the `[default]` section of the `config` and `credentials` files\. + +If you don't have the AWS CLI installed, you can manually create or edit the `config` and `credentials` files to contain default credentials and a default Region\. Use the following format\. ++ In `~/.aws/config` or `%USERPROFILE%\.aws\config` + + ``` + [default] + region=us-west-2 + ``` ++ In `~/.aws/credentials` or `%USERPROFILE%\.aws\credentials` + + ``` + [default] + aws_access_key_id=AKIAI44QH8DHBEXAMPLE + aws_secret_access_key=je7MtGbClwBF/2Zp9Utk/h3yCo8nvbEXAMPLEKEY + ``` + +Besides specifying AWS credentials and a Region in the `[default]` section, you can also add one or more `[profile NAME]` sections, where *NAME* is the name of the profile\. ++ In `~/.aws/config` or `%USERPROFILE%\.aws\config` + + ``` + [profile test] + region=us-east-1 + + [profile prod] + region=us-west-1 + ``` ++ In `~/.aws/credentials` or `%USERPROFILE%\.aws\credentials` + + ``` + [profile test] + aws_access_key_id=AKIAI44QH8DHBEXAMPLE + aws_secret_access_key=je7MtGbClwBF/2Zp9Utk/h3yCo8nvbEXAMPLEKEY + + [profile test] + aws_access_key_id=AKIAI44QH8DHBEXAMPLE + aws_secret_access_key=je7MtGbClwBF/2Zp9Utk/h3yCo8nvbEXAMPLEKEY + ``` + +Always add named profiles to both the `config` and `credentials` files\. The AWS CDK Toolkit doesn't fall back to using the Region in the `[default]` section when the specified named profile is not found in the `config` file\. However, some other AWS tools do\. + +**Important** +Do not name a profile `default`\. That is, do not use a `[profile default]` section in either `config` or `credentials`\. + +**Note** +The AWS CDK uses credentials from the same sources files as other AWS tools and SDKs, including the [AWS Command Line Interface](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html)\. However, the AWS CDK might behave somewhat differently from these tools\. It uses the AWS SDK for JavaScript under the hood\. For complete details on setting up credentials for the AWS SDK for JavaScript, see [Setting credentials](https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/setting-credentials.html)\. + +You may optionally use the `--role-arn` \(or `-r`\) option to specify the ARN of an IAM role that should be used for deployment\. This role must be assumable by the AWS account being used\. + +## Specifying the app command<a name="cli-app-command"></a> + +Many features of the CDK Toolkit require one or more AWS CloudFormation templates be synthesized, which in turn requires running your application\. The AWS CDK supports programs written in a variety of languages\. Therefore, it uses a configuration option to specify the exact command necessary to run your app\. This option can be specified in two ways\. + +First, and most commonly, it can be specified using the `app` key inside the file `cdk.json`\. This is in the main directory of your AWS CDK project\. The CDK Toolkit provides an appropriate command when creating a new project with `cdk init`\. Here is the `cdk.json` from a fresh TypeScript project, for instance\. + +``` +{ + "app": "npx ts-node bin/hello-cdk.ts" +} +``` + +The CDK Toolkit looks for `cdk.json` in the current working directory when attempting to run your app\. Because of this, you might keep a shell open in your project's main directory for issuing CDK Toolkit commands\. + +The CDK Toolkit also looks for the app key in `~/.cdk.json` \(that is, in your home directory\) if it can't find it in `./cdk.json`\. Adding the app command here can be useful if you usually work with CDK code in the same language\. + +If you are in some other directory, or to run your app using a command other than the one in `cdk.json`, use the `--app` \(or `-a`\) option to specify it\. + +``` +cdk --app "npx ts-node bin/hello-cdk.ts" ls +``` + +When deploying, you may also specify a directory containing synthesized cloud assemblies, such as `cdk.out`, as the value of \-\-app\. The specified stacks are deployed from this directory; the app is not synthesized\. + +## Specifying stacks<a name="cli-stacks"></a> + +Many CDK Toolkit commands \(for example, `cdk deploy`\) work on stacks defined in your app\. If your app contains only one stack, the CDK Toolkit assumes you mean that one if you don't specify a stack explicitly\. + +Otherwise, you must specify the stack or stacks you want to work with\. You can do this by specifying the desired stacks by ID individually on the command line\. Recall that the ID is the value specified by the second argument when you instantiate the stack\. + +``` +cdk synth PipelineStack LambdaStack +``` + +You may also use wildcards to specify IDs that match a pattern\. ++ `?` matches any single character ++ `*` matches any number of characters \(`*` alone matches all stacks\) ++ `**` matches everything in a hierarchy + +You may also use the \-\-all option to specify all stacks\. + +If your app uses [CDK Pipelines](cdk_pipeline.md), the CDK Toolkit understands your stacks and stages as a hierarchy\. Also, the \-\-all option and the `*` wildcard only match top\-level stacks\. To match all the stacks, use `**`\. Also use `**` to indicate all the stacks under a particular hierarchy\. + +When using wildcards, enclose the pattern in quotes, or escape the wildcards with `\`\. If you don't, your shell may try to expand the pattern to the names of files in the current directory\. At best, this won't do what you expect; at worst, you could deploy stacks you didn't intend to\. This isn't strictly necessary on Windows because `cmd.exe` does not expand wildcards, but is good practice nonetheless\. + +``` +cdk synth "*Stack" # PipelineStack, LambdaStack, etc. +cdk synth 'Stack?' # StackA, StackB, Stack1, etc. +cdk synth \* # All stacks in the app, or all top-level stacks in a CDK Pipelines app +cdk synth '**' # All stacks in a CDK Pipelines app +cdk synth 'PipelineStack/Prod/**' # All stacks in Prod stage in a CDK Pipelines app +``` + +**Note** +The order in which you specify the stacks is not necessarily the order in which they will be processed\. The AWS CDK Toolkit accounts for dependencies between stacks when deciding the order in which to process them\. For example, let's say that one stack uses a value produced by another \(such as the ARN of a resource defined in the second stack\)\. In this case, the second stack is synthesized before the first one because of this dependency\. You can add dependencies between stacks manually using the stack's [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html#addwbrdependencytarget-reason](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html#addwbrdependencytarget-reason) method\. + +## Bootstrapping your AWS environment<a name="cli-bootstrap"></a> + +Deploying stacks with the CDK requires special dedicated AWS CDK resources to be provisioned\. The `cdk bootstrap` command creates the necessary resources for you\. You only need to bootstrap if you are deploying a stack that requires these dedicated resources\. See [Bootstrapping](bootstrapping.md) for details\. + +``` +cdk bootstrap +``` + +If issued with no arguments, as shown here, the `cdk bootstrap` command synthesizes the current app and bootstraps the environments its stacks will be deployed to\. If the app contains environment\-agnostic stacks, which don't explicitly specify an environment, the default account and Region are bootstrapped, or the environment specified using `--profile`\. + +Outside of an app, you must explicitly specify the environment to be bootstrapped\. You may also do so to bootstrap an environment that's not specified in your app or local AWS profile\. Credentials must be configured \(e\.g\. in `~/.aws/credentials`\) for the specified account and Region\. You may specify a profile that contains the required credentials\. + +``` +cdk bootstrap ACCOUNT-NUMBER/REGION # e.g. +cdk bootstrap 1111111111/us-east-1 +cdk bootstrap --profile test 1111111111/us-east-1 +``` + +**Important** +Each environment \(account/region combination\) to which you deploy such a stack must be bootstrapped separately\. + +You may incur AWS charges for what the AWS CDK stores in the bootstrapped resources\. Additionally, if you use `-bootstrap-customer-key`, an AWS KMS key will be created, which also incurs charges per environment\. + +**Note** +Earlier versions of the bootstrap template created a KMS key by default\. To avoid charges, re\-bootstrap using `--no-bootstrap-customer-key`\. + +**Note** +CDK Toolkit v2 does not support the original bootstrap template, dubbed the legacy template, used by default with CDK v1\. + +**Important** +The modern bootstrap template effectively grants the permissions implied by the `--cloudformation-execution-policies` to any AWS account in the `--trust` list\. By default, this extends permissions to read and write to any resource in the bootstrapped account\. Make sure to [configure the bootstrapping stack](bootstrapping.md#bootstrapping-customizing) with policies and trusted accounts that you are comfortable with\. + +## Creating a new app<a name="cli-init"></a> + +To create a new app, create a directory for it, then, inside the directory, issue `cdk init`\. + +``` +mkdir my-cdk-app +cd my-cdk-app +cdk init TEMPLATE --language LANGUAGE +``` + +The supported languages \(*LANGUAGE*\) are: + + +| Code | Language | +| --- | --- | +| `typescript` | TypeScript | +| `javascript` | JavaScript | +| `python` | Python | +| `java` | Java | +| `csharp` | C\# | + +*TEMPLATE* is an optional template\. If the desired template is *app*, the default, you may omit it\. The available templates are: + + +| Template | Description | +| --- | --- | +| `app` \(default\) | Creates an empty AWS CDK app\. | +| `sample-app` | Creates an AWS CDK app with a stack containing an Amazon SQS queue and an Amazon SNS topic\. | + +The templates use the name of the project folder to generate names for files and classes inside your new app\. + +## Listing stacks<a name="cli-list"></a> + +To see a list of the IDs of the stacks in your AWS CDK application, enter one of the following equivalent commands: + +``` +cdk list +cdk ls +``` + +If your application contains [CDK Pipelines](cdk_pipeline.md) stacks, the CDK Toolkit displays stack names as paths according to their location in the pipeline hierarchy\. \(For example, `PipelineStack`, `PipelineStack/Prod`, and `PipelineStack/Prod/MyService`\.\) + +If your app contains many stacks, you can specify full or partial stack IDs of the stacks to be listed\. For more information, see [Specifying stacks](#cli-stacks)\. + +Add the `--long` flag to see more information about the stacks, including the stack names and their environments \(AWS account and Region\)\. + +## Synthesizing stacks<a name="cli-synth"></a> + +The `cdk synthesize` command \(almost always abbreviated `synth`\) synthesizes a stack defined in your app into a CloudFormation template\. + +``` +cdk synth # if app contains only one stack +cdk synth MyStack +cdk synth Stack1 Stack2 +cdk synth "*" # all stacks in app +``` + +**Note** +The CDK Toolkit actually runs your app and synthesizes fresh templates before most operations \(such as when deploying or comparing stacks\)\. These templates are stored by default in the `cdk.out` directory\. The `cdk synth` command simply prints the generated templates for one or more specified stacks\. + +See `cdk synth --help` for all available options\. A few of the most frequently used options are covered in the following section\. + +### Specifying context values<a name="w55aac35b7c31c11"></a> + +Use the `--context` or `-c` option to pass [runtime context](context.md) values to your CDK app\. + +``` +# specify a single context value +cdk synth --context key=value MyStack + +# specify multiple context values (any number) +cdk synth --context key1=value1 --context key2=value2 MyStack +``` + +When deploying multiple stacks, the specified context values are normally passed to all of them\. If you want, you can specify different values for each stack by prefixing the stack name to the context value\. + +``` +# different context values for each stack +cdk synth --context Stack1:key=value Stack2:key=value Stack1 Stack2 +``` + +### Specifying display format<a name="w55aac35b7c31c13"></a> + +By default, the synthesized template is displayed in YAML format\. Add the `--json` flag to display it in JSON format instead\. + +``` +cdk synth --json MyStack +``` + +### Specifying output directory<a name="w55aac35b7c31c15"></a> + +Add the `--output` \(`-o`\) option to write the synthesized templates to a directory other than `cdk.out`\. + +``` +cdk synth --output=~/templates +``` + +## Deploying stacks<a name="cli-deploy"></a> + +The `cdk deploy` subcommand deploys one or more specified stacks to your AWS account\. + +``` +cdk deploy # if app contains only one stack +cdk deploy MyStack +cdk deploy Stack1 Stack2 +cdk deploy "*" # all stacks in app +``` + +**Note** +The CDK Toolkit runs your app and synthesizes fresh AWS CloudFormation templates before deploying anything\. Therefore, most command line options you can use with `cdk synth` \(for example, `--context`\) can also be used with `cdk deploy`\. + +See `cdk deploy --help` for all available options\. A few of the most useful options are covered in the following section\. + +### Skipping synthesis<a name="cli-deploy-nosynth"></a> + +The cdk deploy command normally synthesizes your app's stacks before deploying to make sure that the deployment reflects the latest version of your app\. If you know that you haven't changed your code since your last cdk synth, you can suppress the redundant synthesis step when deploying\. To do so, specify your project's `cdk.out` directory in the \-\-app option\. + +``` +cdk deploy --app cdk.out StackOne StackTwo +``` + +### Disabling rollback<a name="cli-deploy-norollback"></a> + +AWS CloudFormation has the ability to roll back changes so that deployments are atomic\. This means that they either succeed or fail as a whole\. The AWS CDK inherits this capability because it synthesizes and deploys AWS CloudFormation templates\. + +Rollback makes sure that your resources are in a consistent state at all times, which is vital for production stacks\. However, while you're still developing your infrastructure, some failures are inevitable, and rolling back failed deployments can slow you down\. + +For this reason, the CDK Toolkit lets you disable rollback by adding `--no-rollback` to your `cdk deploy` command\. With this flag, failed deployments are not rolled back\. Instead, resources deployed before the failed resource remain in place, and the next deployment starts with the failed resource\. You'll spend a lot less time waiting for deployments and a lot more time developing your infrastructure\. + +### Hot swapping<a name="cli-deploy-hotswap"></a> + +Use the `--hotswap` flag with `cdk deploy` to attempt to update your AWS resources directly instead of generating an AWS CloudFormation changeset and deploying it\. Deployment falls back to AWS CloudFormation deployment if hot swapping is not possible\. + +Currently hot swapping supports Lambda functions, Step Functions state machines, and Amazon ECS container images\. The `--hotswap` flag also disables rollback \(i\.e\., implies `--no-rollback`\)\. + +**Important** +Hot\-swapping is not recommended for production deployments\. + +### Watch mode<a name="cli-deploy-watch"></a> + +The CDK Toolkit's watch mode \( cdk deploy \-\-watch, or cdk watch for short\) continuously monitors your CDK app's source files and assets for changes\. It immediately performs a deployment of the specified stacks when a change is detected\. + +By default, these deployments use the `--hotswap` flag, which fast\-tracks deployment of changes to Lambda functions\. It also falls back to deploying through AWS CloudFormation if you have changed infrastructure configuration\. To have `cdk watch` always perform full AWS CloudFormation deployments, add the `--no-hotswap` flag to `cdk watch`\. + +Any changes made while `cdk watch` is already performing a deployment are combined into a single deployment, which begins as soon as the in\-progress deployment is complete\. + +Watch mode uses the `"watch"` key in the project's `cdk.json` to determine which files to monitor\. By default, these files are your application files and assets, but this can be changed by modifying the `"include"` and `"exclude"` entries in the `"watch"` key\. The following `cdk.json` file shows an example of these entries\. + +``` +{ + "app": "mvn -e -q compile exec:java", + "watch": { + "include": "src/main/**", + "exclude": "target/*" + } +} +``` + +`cdk watch` executes the `"build"` command from `cdk.json` to build your app before synthesis\. If your deployment requires any commands to build or package your Lambda code \(or anything else that's not in your CDK app\), add it here\. + +Git\-style wildcards, both `*` and `**`, can be used in the `"watch"` and `"build"` keys\. Each path is interpreted relative to the parent directory of `cdk.json`\. The default value of `include` is `**/*`, meaning all files and directories in the project root directory\. `exclude` is optional\. + +**Important** +Watch mode is not recommended for production deployments\. + +### Specifying AWS CloudFormation parameters<a name="w55aac35b7c33c19"></a> + +The AWS CDK Toolkit supports specifying AWS CloudFormation [parameters](parameters.md) at deployment\. You may provide these on the command line following the `--parameters` flag\. + +``` +cdk deploy MyStack --parameters uploadBucketName=UploadBucket +``` + +To define multiple parameters, use multiple `--parameters` flags\. + +``` +cdk deploy MyStack --parameters uploadBucketName=UpBucket --parameters downloadBucketName=DownBucket +``` + +If you are deploying multiple stacks, you can specify a different value of each parameter for each stack\. To do so, prefix the name of the parameter with the stack name and a colon\. Otherwise, the same value is passed to all stacks\. + +``` +cdk deploy MyStack YourStack --parameters MyStack:uploadBucketName=UploadBucket --parameters YourStack:uploadBucketName=UpBucket +``` + +By default, the AWS CDK retains values of parameters from previous deployments and uses them in later deployments if they are not specified explicitly\. Use the `--no-previous-parameters` flag to require all parameters to be specified\. + +### Specifying outputs file<a name="w55aac35b7c33c21"></a> + +If your stack declares AWS CloudFormation outputs, these are normally displayed on the screen at the conclusion of deployment\. To write them to a file in JSON format, use the `--outputs-file` flag\. + +``` +cdk deploy --outputs-file outputs.json MyStack +``` + +### Security\-related changes<a name="cli-security"></a> + +To protect you against unintended changes that affect your security posture, the AWS CDK Toolkit prompts you to approve security\-related changes before deploying them\. You can specify the level of change that requires approval: + +``` +cdk deploy --require-approval LEVEL +``` + +*LEVEL* can be one of the following: + + +| Term | Meaning | +| --- | --- | +| `never` | Approval is never required | +| `any-change` | Requires approval on any IAM or security\-group\-related change | +| `broadening` \(default\) | Requires approval when IAM statements or traffic rules are added; removals don't require approval | + +The setting can also be configured in the `cdk.json` file\. + +``` +{ + "app": "...", + "requireApproval": "never" +} +``` + +## Comparing stacks<a name="cli-diff"></a> + +The `cdk diff` command compares the current version of a stack \(and its dependencies\) defined in your app with the already\-deployed versions, or with a saved AWS CloudFormation template, and displays a list of changes\. + +``` +Stack HelloCdkStack +IAM Statement Changes +┌───┬──────────────────────────────┬────────┬──────────────────────────────┬──────────────────────────────┬───────────┐ +│ │ Resource │ Effect │ Action │ Principal │ Condition │ +├───┼──────────────────────────────┼────────┼──────────────────────────────┼──────────────────────────────┼───────────┤ +│ + │ ${Custom::S3AutoDeleteObject │ Allow │ sts:AssumeRole │ Service:lambda.amazonaws.com │ │ +│ │ sCustomResourceProvider/Role │ │ │ │ │ +│ │ .Arn} │ │ │ │ │ +├───┼──────────────────────────────┼────────┼──────────────────────────────┼──────────────────────────────┼───────────┤ +│ + │ ${MyFirstBucket.Arn} │ Allow │ s3:DeleteObject* │ AWS:${Custom::S3AutoDeleteOb │ │ +│ │ ${MyFirstBucket.Arn}/* │ │ s3:GetBucket* │ jectsCustomResourceProvider/ │ │ +│ │ │ │ s3:GetObject* │ Role.Arn} │ │ +│ │ │ │ s3:List* │ │ │ +└───┴──────────────────────────────┴────────┴──────────────────────────────┴──────────────────────────────┴───────────┘ +IAM Policy Changes +┌───┬────────────────────────────────────────────────────────┬────────────────────────────────────────────────────────┐ +│ │ Resource │ Managed Policy ARN │ +├───┼────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────┤ +│ + │ ${Custom::S3AutoDeleteObjectsCustomResourceProvider/Ro │ {"Fn::Sub":"arn:${AWS::Partition}:iam::aws:policy/serv │ +│ │ le} │ ice-role/AWSLambdaBasicExecutionRole"} │ +└───┴────────────────────────────────────────────────────────┴────────────────────────────────────────────────────────┘ +(NOTE: There may be security-related changes not in this list. See https://github.com/aws/aws-cdk/issues/1299) + +Parameters +[+] Parameter AssetParameters/4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392/S3Bucket AssetParameters4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392S3BucketBF7A7F3F: {"Type":"String","Description":"S3 bucket for asset \"4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392\""} +[+] Parameter AssetParameters/4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392/S3VersionKey AssetParameters4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392S3VersionKeyFAF93626: {"Type":"String","Description":"S3 key for asset version \"4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392\""} +[+] Parameter AssetParameters/4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392/ArtifactHash AssetParameters4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392ArtifactHashE56CD69A: {"Type":"String","Description":"Artifact hash for asset \"4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392\""} + +Resources +[+] AWS::S3::BucketPolicy MyFirstBucket/Policy MyFirstBucketPolicy3243DEFD +[+] Custom::S3AutoDeleteObjects MyFirstBucket/AutoDeleteObjectsCustomResource MyFirstBucketAutoDeleteObjectsCustomResourceC52FCF6E +[+] AWS::IAM::Role Custom::S3AutoDeleteObjectsCustomResourceProvider/Role CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092 +[+] AWS::Lambda::Function Custom::S3AutoDeleteObjectsCustomResourceProvider/Handler CustomS3AutoDeleteObjectsCustomResourceProviderHandler9D90184F +[~] AWS::S3::Bucket MyFirstBucket MyFirstBucketB8884501 + ├─ [~] DeletionPolicy + │ ├─ [-] Retain + │ └─ [+] Delete + └─ [~] UpdateReplacePolicy + ├─ [-] Retain + └─ [+] Delete +``` + +To compare your app's stacks with the existing deployment: + +``` +cdk diff MyStack +``` + +To compare your app's stacks with a saved CloudFormation template: + +``` +cdk diff --template ~/stacks/MyStack.old MyStack +``` + +## Configuration \(`cdk.json`\)<a name="cli-config"></a> + +Default values for many CDK Toolkit command line flags can be stored in a project's `cdk.json` file or in the `.cdk.json` file in your user directory\. Following is an alphabetical reference to the supported configuration settings\. + + +| Key | Notes | CDK Toolkit option | +| --- | --- | --- | +| app | The command that executes the CDK application\. | \-\-app | +| assetMetadata | If false, CDK does not add metadata to resources that use assets\. | \-\-no\-asset\-metadata | +| bootstrapKmsKeyId | Overrides the ID of the AWS KMS key used to encrypt the Amazon S3 deployment bucket\. | \-\-bootstrap\-kms\-key\-id | +| build | The command that compiles or builds the CDK application before synthesis\. Not permitted in \~/\.cdk\.json\. | \-\-build | +| browser | The command for launching a Web browser for the cdk docs subcommand\. | \-\-browser | +| context | See [Runtime context](context.md)\. Context values in a configuration file will not be erased by cdk context \-\-clear\. \(The CDK Toolkit places cached context values in cdk\.context\.json\.\) | \-\-context | +| debug | If true, CDK Toolkit emits more detailed information useful for debugging\. | \-\-debug | +| language | The language to be used for initializing new projects\. | \-\-language | +| lookups | If false, no context lookups are permitted\. Synthesis will fail if any context lookups need to be performed\. | \-\-no\-lookups | +| notices | If false, suppresses the display of messages about security vulnerabilities, regressions, and unsupported versions\. | \-\-no\-notices | +| output | The name of the directory into which the synthesized cloud assembly will be emitted \(default "cdk\.out"\)\. | \-\-output | +| outputsFile | The file to which AWS CloudFormation outputs from deployed stacks will be written \(in JSON format\)\. | \-\-outputs\-file | +| pathMetadata | If false, CDK path metadata is not added to synthesized templates\. | \-\-no\-path\-metadata | +| plugin | JSON array specifying the package names or local paths of packages that extend the CDK | \-\-plugin | +| profile | Name of the default AWS profile used for specifying Region and account credentials\. | \-\-profile | +| progress | If set to "events", the CDK Toolkit displays all AWS CloudFormation events during deployment, rather than a progress bar\. | \-\-progress | +| requireApproval | Default approval level for security changes\. See [Security\-related changes](#cli-security) | \-\-require\-approval | +| rollback | If false, failed deployments are not rolled back\. | \-\-no\-rollback | +| staging | If false, assets are not copied to the output directory \(use for local debugging of the source files with AWS SAM\)\. | \-\-no\-staging | +| tags | JSON object containing tags \(key\-value pairs\) for the stack\. | \-\-tags | +| toolkitBucketName | The name of the Amazon S3 bucket used for deploying assets such as Lambda functions and container images \(see [Bootstrapping your AWS environment](#cli-bootstrap)\. | \-\-toolkit\-bucket\-name | +| toolkitStackName | The name of the bootstrap stack \(see [Bootstrapping your AWS environment](#cli-bootstrap)\. | \-\-toolkit\-stack\-name | +| versionReporting | If false, opts out of version reporting\. | \-\-no\-version\-reporting | +| watch | JSON object containing "include" and "exclude" keys that indicate which files should \(or should not\) trigger a rebuild of the project when changed\. See [Watch mode](#cli-deploy-watch)\. | \-\-watch | \ No newline at end of file diff --git a/v2/compliance-validation.md b/v2/compliance-validation.md new file mode 100644 index 00000000..67d4b7a1 --- /dev/null +++ b/v2/compliance-validation.md @@ -0,0 +1,16 @@ +# Compliance validation for the AWS Cloud Development Kit \(AWS CDK\)<a name="compliance-validation"></a> + +The AWS CDK follows the [shared responsibility model](https://aws.amazon.com/compliance/shared-responsibility-model/) through the specific Amazon Web Services \(AWS\) services it supports\. For AWS service security information, see the [AWS service security documentation page](https://docs.aws.amazon.com/security/?id=docs_gateway#aws-security) and [AWS services that are in scope of AWS compliance efforts by compliance program](https://aws.amazon.com/compliance/services-in-scope/)\. + +The security and compliance of AWS services is assessed by third\-party auditors as part of multiple AWS compliance programs\. These include SOC, PCI, FedRAMP, HIPAA, and others\. AWS provides a frequently updated list of AWS services in scope of specific compliance programs at [AWS Services in Scope by Compliance Program](https://aws.amazon.com/compliance/services-in-scope/)\. + +Third\-party audit reports are available for you to download using AWS Artifact\. For more information, see [Downloading Reports in AWS Artifact](https://docs.aws.amazon.com/artifact/latest/ug/downloading-documents.html)\. + +For more information about AWS compliance programs, see [AWS Compliance Programs](https://aws.amazon.com/compliance/programs/)\. + +Your compliance responsibility when using the AWS CDK to access an AWS service is determined by the sensitivity of your data, your organization's compliance objectives, and applicable laws and regulations\. If your use of an AWS service is subject to compliance with standards such as HIPAA, PCI, or FedRAMP, AWS provides resources to help: ++ [Security and Compliance Quick Start Guides](https://aws.amazon.com/quickstart/?quickstart-all.sort-by=item.additionalFields.updateDate&quickstart-all.sort-order=desc&awsf.quickstart-homepage-filter=categories%23security-identity-compliance) – Deployment guides that discuss architectural considerations and provide steps for deploying security\-focused and compliance\-focused baseline environments on AWS\. ++ [Architecting for HIPAA Security and Compliance Whitepaper](https://d0.awsstatic.com/whitepapers/compliance/AWS_HIPAA_Compliance_Whitepaper.pdf) – A whitepaper that describes how companies can use AWS to create HIPAA\-compliant applications\. ++ [AWS Compliance Resources](https://aws.amazon.com/compliance/resources/) – A collection of workbooks and guides that might apply to your industry and location\. ++ [AWS Config](https://aws.amazon.com/config/) – A service that assesses how well your resource configurations comply with internal practices, industry guidelines, and regulations\. ++ [AWS Security Hub](https://aws.amazon.com/security-hub/) – A comprehensive view of your security state within AWS that helps you check your compliance with security industry standards and best practices\. \ No newline at end of file diff --git a/v2/constructs.md b/v2/constructs.md new file mode 100644 index 00000000..8eec8e44 --- /dev/null +++ b/v2/constructs.md @@ -0,0 +1,1219 @@ +# Constructs<a name="constructs"></a> + +Constructs are the basic building blocks of AWS CDK apps\. A construct represents a "cloud component" and encapsulates everything AWS CloudFormation needs to create the component\. + +**Note** +Constructs are part of the Construct Programming Model \(CPM\)\. They're also used by other tools such as CDK for Terraform \(CDKtf\), CDK for Kubernetes \(CDK8s\), and Projen\. + +A construct can represent a single AWS resource, such as an Amazon Simple Storage Service \(Amazon S3\) bucket\. A construct can also be a higher\-level abstraction consisting of multiple related AWS resources\. Examples of such components include a worker queue with its associated compute capacity, or a scheduled job with monitoring resources and a dashboard\. + +The AWS CDK includes a collection of constructs called the AWS Construct Library, containing constructs for every AWS service\. [Construct Hub](https://constructs.dev/search?q=&cdk=aws-cdk&cdkver=2&sort=downloadsDesc&offset=0) is a resource to help you discover additional constructs from AWS, third parties, and the open\-source CDK community\. + +**Important** +In AWS CDK v1, the `Construct` base class was in the CDK `core` module\. In CDK v2, there is a separate module called `constructs` that contains this class\. + +## AWS Construct library<a name="constructs_lib"></a> + +The AWS CDK includes the [AWS Construct Library](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-construct-library.html), which contains constructs representing AWS resources\. + +This library includes constructs that represent all the resources available on AWS\. For example, the `[s3\.Bucket](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html)` class represents an Amazon S3 bucket, and the `[dynamodb\.Table](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_dynamodb.Table.html)` class represents an Amazon DynamoDB table\. + +**L1 constructs** +There are three different levels of constructs in this library, beginning with low\-level constructs, which we call *CFN Resources* \(or **L1**, short for "layer 1"\)\. These constructs directly represent all resources available in AWS CloudFormation\. CFN Resources are periodically generated from the [AWS CloudFormation Resource Specification](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-resource-specification.html)\. They are named **Cfn***Xyz*, where *Xyz* is name of the resource\. For example, [CfnBucket](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.CfnBucket.html) represents the [AWS::S3::Bucket](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket.html) AWS CloudFormation resource\. When you use Cfn resources, you must explicitly configure all resource properties\. This requires a complete understanding of the details of the underlying AWS CloudFormation resource model\. + +**L2 constructs** +The next level of constructs, **L2**, also represent AWS resources, but with a higher\-level, intent\-based API\. They provide similar functionality, but incorporate the defaults, boilerplate, and glue logic you'd be writing yourself with a CFN Resource construct\. AWS constructs offer convenient defaults and reduce the need to know all the details about the AWS resources they represent\. They also provide convenience methods that make it simpler to work with the resource\. For example, the [s3\.Bucket](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html) class represents an Amazon S3 bucket with additional properties and methods, such as [bucket\.addLifeCycleRule\(\)](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html#addwbrlifecyclewbrrulerule), which adds a lifecycle rule to the bucket\. + +**L3 constructs** +Finally, the AWS Construct Library includes **L3** constructs, which we call *patterns*\. These constructs are designed to help you complete common tasks in AWS, often involving multiple kinds of resources\. For example, the [aws\-ecs\-patterns\.ApplicationLoadBalancedFargateService](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs_patterns.ApplicationLoadBalancedFargateService.html) construct represents an architecture that includes an AWS Fargate container cluster employing an Application Load Balancer\. The [aws\-apigateway\.LambdaRestApi](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_apigateway.LambdaRestApi.html) construct represents an Amazon API Gateway API that's backed by an AWS Lambda function\. + +For more information about how to navigate the library and discover constructs that can help you build your apps, see the [API Reference](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-construct-library.html)\. + +## Composition<a name="constructs_composition"></a> + +*Composition* is the key pattern for defining higher\-level abstractions through constructs\. A high\-level construct can be composed from any number of lower\-level constructs\. In turn, those could be composed from even lower\-level constructs, which eventually are composed from AWS resources\. + +From a bottom\-up perspective, you use constructs to organize the individual AWS resources that you want to deploy\. You use whatever abstractions are convenient for your purpose, with as many layers as you need\. + +Composition lets you define reusable components and share them like any other code\. For example, a team can define a construct that implements the company's best practice for a DynamoDB table with backup, global replication, automatic scaling, and monitoring\. The team can share the construct with other teams in their organization, or publicly\. + +Teams can use this construct in their preferred programming language like they would use any other library package to define their tables and comply with best practices\. When the library is updated, developers will get access to the new version's bug fixes and improvements through the workflows they already have for their other types of code\. + +## Initialization<a name="constructs_init"></a> + +Constructs are implemented in classes that extend the [https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html](https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html) base class\. You define a construct by instantiating the class\. All constructs take three parameters when they are initialized: ++ **scope** — The construct's parent or owner, either a stack or another construct, which determines its place in the [construct tree](#constructs_tree)\. You should usually pass `this` \(or `self` in Python\), which represents the current object, for the scope\. ++ **id** — An [identifier](identifiers.md) that must be unique within this scope\. The identifier serves as a namespace for everything that's defined within the current construct\. It's used to generate unique identifiers such as [resource names](resources.md#resources_physical_names) and AWS CloudFormation logical IDs\. ++ **props** — A set of properties or keyword arguments, depending upon the language, that define the construct's initial configuration\. In most cases, constructs provide sensible defaults, and if all props elements are optional, you can omit the **props** parameter completely\. + +Identifiers need only be unique within a scope\. This lets you instantiate and reuse constructs without concern for the constructs and identifiers they might contain, and enables composing constructs into higher\-level abstractions\. In addition, scopes make it possible to refer to groups of constructs all at once\. Examples include for [tagging](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Tag.html), or specifying where the constructs will be deployed\. + +## Apps and stacks<a name="constructs_apps_stacks"></a> + +We call your CDK application an *app*, which is represented by the AWS CDK class [App](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.App.html)\. The following example defines an app with a single stack that contains a single Amazon S3 bucket with versioning enabled: + +------ +#### [ TypeScript ] + +``` +import { App, Stack, StackProps } from 'aws-cdk-lib'; +import * as s3 from 'aws-cdk-lib/aws-s3'; + +class HelloCdkStack extends Stack { + constructor(scope: App, id: string, props?: StackProps) { + super(scope, id, props); + + new s3.Bucket(this, 'MyFirstBucket', { + versioned: true + }); + } +} + +const app = new App(); +new HelloCdkStack(app, "HelloCdkStack"); +``` + +------ +#### [ JavaScript ] + +``` +const { App , Stack } = require('aws-cdk-lib'); +const s3 = require('aws-cdk-lib/aws-s3'); + +class HelloCdkStack extends Stack { + constructor(scope, id, props) { + super(scope, id, props); + + new s3.Bucket(this, 'MyFirstBucket', { + versioned: true + }); + } +} + +const app = new App(); +new HelloCdkStack(app, "HelloCdkStack"); +``` + +------ +#### [ Python ] + +``` +from aws_cdk import App, Stack +import aws_cdk.aws_s3 as s3 +from constructs import Construct + +class HelloCdkStack(Stack): + + def __init__(self, scope: Construct, id: str, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + s3.Bucket(self, "MyFirstBucket", versioned=True) + +app = App() +HelloCdkStack(app, "HelloCdkStack") +``` + +------ +#### [ Java ] + +``` +import software.amazon.awscdk.*; +import software.amazon.awscdk.services.s3.*; + +public class HelloCdkStack extends Stack { + public HelloCdkStack(final Construct scope, final String id) { + this(scope, id, null); + } + + public HelloCdkStack(final Construct scope, final String id, final StackProps props) { + super(scope, id, props); + + Bucket.Builder.create(this, "MyFirstBucket") + .versioned(true).build(); + } +} +``` + +------ +#### [ C\# ] + +``` +using Amazon.CDK; +using Amazon.CDK.AWS.S3; + +namespace HelloCdkApp +{ + internal static class Program + { + public static void Main(string[] args) + { + var app = new App(); + new HelloCdkStack(app, "HelloCdkStack"); + app.Synth(); + } + } + + public class HelloCdkStack : Stack + { + public HelloCdkStack(Construct scope, string id, IStackProps props=null) : base(scope, id, props) + { + new Bucket(this, "MyFirstBucket", new BucketProps { Versioned = true }); + } + } +} +``` + +------ +#### [ Go ] + +``` +func NewHelloCdkStack(scope constructs.Construct, id string, props *HelloCdkStackProps) awscdk.Stack { + var sprops awscdk.StackProps + if props != nil { + sprops = props.StackProps + } + stack := awscdk.NewStack(scope, &id, &sprops) + + awss3.NewBucket(stack, jsii.String("MyFirstBucket"), &awss3.BucketProps{ + Versioned: jsii.Bool(true), + }) + + return stack +} +``` + +------ + +As you can see, you need a scope within which to define your bucket\. Resources eventually need to be deployed as part of an AWS CloudFormation stack into an *AWS [environment](environments.md)*\. The environment covers a specific AWS account and AWS Region\. AWS constructs, such as `s3.Bucket`, must be defined within the scope of a [Stack](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html)\. + +Stacks in AWS CDK apps extend the **Stack** base class, as shown in the previous example\. The following example is a common pattern when creating a stack within your AWS CDK app\. It shows how to extend the **Stack** class, define a constructor that accepts **scope**, **id**, and **props**, and invoke the base class constructor via `super` with the received **scope**, **id**, and **props**\. + +------ +#### [ TypeScript ] + +``` +class HelloCdkStack extends Stack { + constructor(scope: App, id: string, props?: StackProps) { + super(scope, id, props); + + //... + } +} +``` + +------ +#### [ JavaScript ] + +``` +class HelloCdkStack extends Stack { + constructor(scope, id, props) { + super(scope, id, props); + + //... + } +} +``` + +------ +#### [ Python ] + +``` +class HelloCdkStack(Stack): + + def __init__(self, scope: Construct, id: str, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + # ... +``` + +------ +#### [ Java ] + +``` +public class HelloCdkStack extends Stack { + public HelloCdkStack(final Construct scope, final String id) { + this(scope, id, null); + } + + public HelloCdkStack(final Construct scope, final String id, final StackProps props) { + super(scope, id, props); + + // ... + } +} +``` + +------ +#### [ C\# ] + +``` +public class HelloCdkStack : Stack +{ + public HelloCdkStack(Construct scope, string id, IStackProps props=null) : base(scope, id, props) + { + //... + } +} +``` + +------ + +## Using L1 constructs<a name="constructs_l1_using"></a> + +Once you have defined a stack, you can populate it with resources by instantiating constructs\. First, we'll do it with an L1 construct\. + +L1 constructs are exactly the resources defined by AWS CloudFormation—no more, no less\. You must provide the resource's required configuration yourself\. Here, for example, is how to create an Amazon S3 bucket using the `CfnBucket` class\. \(You'll see a similar definition using the `Bucket` class in the next section\.\) + +------ +#### [ TypeScript ] + +``` +const bucket = new s3.CfnBucket(this, "MyBucket", { + bucketName: "MyBucket" +}); +``` + +------ +#### [ JavaScript ] + +``` +const bucket = new s3.CfnBucket(this, "MyBucket", { + bucketName: "MyBucket" +}); +``` + +------ +#### [ Python ] + +``` +bucket = s3.CfnBucket(self, "MyBucket", bucket_name="MyBucket") +``` + +------ +#### [ Java ] + +``` +CfnBucket bucket = new CfnBucket.Builder().bucketName("MyBucket").build(); +``` + +------ +#### [ C\# ] + +``` +var bucket = new CfnBucket(this, "MyBucket", new CfnBucketProps +{ + BucketName= "MyBucket" +}); +``` + +------ +#### [ Go ] + +``` + awss3.NewCfnBucket(stack, jsii.String("MyBucket"), &awss3.CfnBucketProps{ + BucketName: jsii.String("MyBucket"), + }) +``` + +------ + +Construct properties that aren't simple Booleans, strings, numbers, or containers are handled differently in the supported languages\. + +------ +#### [ TypeScript ] + +``` +const bucket = new s3.CfnBucket(this, "MyBucket", { + bucketName: "MyBucket", + corsConfiguration: { + corsRules: [{ + allowedOrigins: ["*"], + allowedMethods: ["GET"] + }] + } +}); +``` + +------ +#### [ JavaScript ] + +``` +const bucket = new s3.CfnBucket(this, "MyBucket", { + bucketName: "MyBucket", + corsConfiguration: { + corsRules: [{ + allowedOrigins: ["*"], + allowedMethods: ["GET"] + }] + } +}); +``` + +------ +#### [ Python ] + +In Python, these properties are represented by types defined as inner classes of the L1 construct\. For example, the optional property `cors_configuraiton` of a `CfnBucket` requires a wrapper of type `CfnBucket.CorsConfigurationProperty`\. Here we are defining `cors_onfiguration` on a `CfnBucket` instance\. + +``` +bucket = CfnBucket(self, "MyBucket", bucket_name="MyBucket", + cors_configuration=CfnBucket.CorsConfigurationProperty( + cors_rules=[CfnBucket.CorsRuleProperty( + allowed_origins=["*"], + allowed_methods=["GET"] + )] + ) +) +``` + +------ +#### [ Java ] + +In Java, these properties are represented by types defined as inner classes of the L1 construct\. For example, the optional property `corsConfiguration` of a `CfnBucket` requires a wrapper of type `CfnBucket.CorsConfigurationProperty`\. Here we are defining `corsConfiguration` on a `CfnBucket` instance\. + +``` +CfnBucket bucket = CfnBucket.Builder.create(this, "MyBucket") + .bucketName("MyBucket") + .corsConfiguration(new CfnBucket.CorsConfigurationProperty.Builder() + .corsRules(Arrays.asList(new CfnBucket.CorsRuleProperty.Builder() + .allowedOrigins(Arrays.asList("*")) + .allowedMethods(Arrays.asList("GET")) + .build())) + .build()) + .build(); +``` + +------ +#### [ C\# ] + +In C\#, these properties are represented by types defined as inner classes of the L1 construct\. For example, the optional property `CorsConfiguration` of a `CfnBucket` requires a wrapper of type `CfnBucket.CorsConfigurationProperty`\. Here we are defining `CorsConfiguration` on a `CfnBucket` instance\. + +``` +var bucket = new CfnBucket(this, "MyBucket", new CfnBucketProps +{ + BucketName = "MyBucket", + CorsConfiguration = new CfnBucket.CorsConfigurationProperty + { + CorsRules = new object[] { + new CfnBucket.CorsRuleProperty + { + AllowedOrigins = new string[] { "*" }, + AllowedMethods = new string[] { "GET" }, + } + } + } +}); +``` + +------ +#### [ Go ] + +In Go, these types are named using the name of the L1 construct, an underscore, and the property name\. For example, the optional property `CorsConfiguration` of a `CfnBucket` requires a wrapper of type `CfnBucket_CorsConfigurationProperty`\. Here we are defining `CorsConfiguration` on a `CfnBucket` instance\. + +``` + awss3.NewCfnBucket(stack, jsii.String("MyBucket"), &awss3.CfnBucketProps{ + BucketName: jsii.String("MyBucket"), + CorsConfiguration: &awss3.CfnBucket_CorsConfigurationProperty{ + CorsRules: []awss3.CorsRule{ + awss3.CorsRule{ + AllowedOrigins: jsii.Strings("*"), + AllowedMethods: &[]awss3.HttpMethods{"GET"}, + }, + }, + }, + }) +``` + +------ + +**Important** +You can't use L2 property types with L1 constructs, or vice versa\. When working with L1 constructs, always use the types defined for the L1 construct you're using\. Do not use types from other L1 constructs \(some may have the same name, but they are not the same type\)\. +Some of our language\-specific API references currently have errors in the paths to L1 property types, or don't document these classes at all\. We hope to fix this soon\. In the meantime, remember that such types are always inner classes of the L1 construct they are used with\. + +## Using L2 constructs<a name="constructs_using"></a> + +The following example defines an Amazon S3 bucket by creating an instance of the [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html) class, an L2 construct\. + +------ +#### [ TypeScript ] + +``` +import * as s3 from 'aws-cdk-lib/aws-s3'; + +// "this" is HelloCdkStack +new s3.Bucket(this, 'MyFirstBucket', { + versioned: true +}); +``` + +------ +#### [ JavaScript ] + +``` +const s3 = require('aws-cdk-lib/aws-s3'); + +// "this" is HelloCdkStack +new s3.Bucket(this, 'MyFirstBucket', { + versioned: true +}); +``` + +------ +#### [ Python ] + +``` +import aws_cdk.aws_s3 as s3 + +# "self" is HelloCdkStack +s3.Bucket(self, "MyFirstBucket", versioned=True) +``` + +------ +#### [ Java ] + +``` +import software.amazon.awscdk.services.s3.*; + +public class HelloCdkStack extends Stack { + public HelloCdkStack(final Construct scope, final String id) { + this(scope, id, null); + } + + public HelloCdkStack(final Construct scope, final String id, final StackProps props) { + super(scope, id, props); + + Bucket.Builder.create(this, "MyFirstBucket") + .versioned(true).build(); + } +} +``` + +------ +#### [ C\# ] + +``` +using Amazon.CDK.AWS.S3; + +// "this" is HelloCdkStack +new Bucket(this, "MyFirstBucket", new BucketProps +{ + Versioned = true +}); +``` + +------ +#### [ Go ] + +``` +import ( + "github.com/aws/aws-cdk-go/awscdk/v2/awss3" + "github.com/aws/jsii-runtime-go" +) + +// stack is HelloCdkStack +awss3.NewBucket(stack, jsii.String("MyFirstBucket"), &awss3.BucketProps{ + Versioned: jsii.Bool(true), + })> +``` + +------ + +The [AWS Construct Library](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-construct-library.html) includes constructs that represent many AWS resources\. + +**Note** +`MyFirstBucket` is not the name of the bucket that AWS CloudFormation creates\. It is a logical identifier given to the new construct\. See [Physical Names](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Resource.html#physicalname) for details\. + +## Configuration<a name="constructs_config"></a> + +Most constructs accept `props` as their third argument \(or in Python, keyword arguments\), a name/value collection that defines the construct's configuration\. The following example defines a bucket with AWS Key Management Service \(AWS KMS\) encryption and static website hosting enabled\. Since it does not explicitly specify an encryption key, the `Bucket` construct defines a new `kms.Key` and associates it with the bucket\. + +------ +#### [ TypeScript ] + +``` +new s3.Bucket(this, 'MyEncryptedBucket', { + encryption: s3.BucketEncryption.KMS, + websiteIndexDocument: 'index.html' +}); +``` + +------ +#### [ JavaScript ] + +``` +new s3.Bucket(this, 'MyEncryptedBucket', { + encryption: s3.BucketEncryption.KMS, + websiteIndexDocument: 'index.html' +}); +``` + +------ +#### [ Python ] + +``` +s3.Bucket(self, "MyEncryptedBucket", encryption=s3.BucketEncryption.KMS, + website_index_document="index.html") +``` + +------ +#### [ Java ] + +``` +Bucket.Builder.create(this, "MyEncryptedBucket") + .encryption(BucketEncryption.KMS_MANAGED) + .websiteIndexDocument("index.html").build(); +``` + +------ +#### [ C\# ] + +``` +new Bucket(this, "MyEncryptedBucket", new BucketProps +{ + Encryption = BucketEncryption.KMS_MANAGED, + WebsiteIndexDocument = "index.html" +}); +``` + +------ +#### [ Go ] + +``` + awss3.NewBucket(stack, jsii.String("MyEncryptedBucket"), &awss3.BucketProps{ + Encryption: awss3.BucketEncryption_KMS, + WebsiteIndexDocument: jsii.String("index.html"), + }) +``` + +------ + + AWS constructs are designed around the concept of "sensible defaults\." Most constructs have a minimal required configuration, enabling you to quickly get started while also providing full control over the configuration when you need it\. + +## Interacting with constructs<a name="constructs_interact"></a> + +Constructs are classes that extend the base [Construct](https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html) class\. After you instantiate a construct, the construct object exposes a set of methods and properties that let you interact with the construct and pass it around as a reference to other parts of the system\. + +The AWS CDK framework doesn't put any restrictions on the APIs of constructs\. Authors can define any API they want\. However, the AWS constructs that are included with the AWS Construct Library, such as `s3.Bucket`, follow guidelines and common patterns\. This provides a consistent experience across all AWS resources\. + +Most AWS constructs have a set of [grant](permissions.md#permissions_grants) methods that you can use to grant AWS Identity and Access Management \(IAM\) permissions on that construct to a principal\. The following example grants the IAM group `data-science` permission to read from the Amazon S3 bucket `raw-data`\. + +------ +#### [ TypeScript ] + +``` +const rawData = new s3.Bucket(this, 'raw-data'); +const dataScience = new iam.Group(this, 'data-science'); +rawData.grantRead(dataScience); +``` + +------ +#### [ JavaScript ] + +``` +const rawData = new s3.Bucket(this, 'raw-data'); +const dataScience = new iam.Group(this, 'data-science'); +rawData.grantRead(dataScience); +``` + +------ +#### [ Python ] + +``` +raw_data = s3.Bucket(self, 'raw-data') +data_science = iam.Group(self, 'data-science') +raw_data.grant_read(data_science) +``` + +------ +#### [ Java ] + +``` +Bucket rawData = new Bucket(this, "raw-data"); +Group dataScience = new Group(this, "data-science"); +rawData.grantRead(dataScience); +``` + +------ +#### [ C\# ] + +``` +var rawData = new Bucket(this, "raw-data"); +var dataScience = new Group(this, "data-science"); +rawData.GrantRead(dataScience); +``` + +------ +#### [ Go ] + +``` + rawData := awss3.NewBucket(stack, jsii.String("raw-data"), nil) + dataScience := awsiam.NewGroup(stack, jsii.String("data-science"), nil) + rawData.GrantRead(dataScience, nil) +``` + +------ + +Another common pattern is for AWS constructs to set one of the resource's attributes from data supplied elsewhere\. Attributes can include Amazon Resource Names \(ARNs\), names, or URLs\. + +The following code defines an AWS Lambda function and associates it with an Amazon Simple Queue Service \(Amazon SQS\) queue through the queue's URL in an environment variable\. + +------ +#### [ TypeScript ] + +``` +const jobsQueue = new sqs.Queue(this, 'jobs'); +const createJobLambda = new lambda.Function(this, 'create-job', { + runtime: lambda.Runtime.NODEJS_14_X, + handler: 'index.handler', + code: lambda.Code.fromAsset('./create-job-lambda-code'), + environment: { + QUEUE_URL: jobsQueue.queueUrl + } +}); +``` + +------ +#### [ JavaScript ] + +``` +const jobsQueue = new sqs.Queue(this, 'jobs'); +const createJobLambda = new lambda.Function(this, 'create-job', { + runtime: lambda.Runtime.NODEJS_14_X, + handler: 'index.handler', + code: lambda.Code.fromAsset('./create-job-lambda-code'), + environment: { + QUEUE_URL: jobsQueue.queueUrl + } +}); +``` + +------ +#### [ Python ] + +``` +jobs_queue = sqs.Queue(self, "jobs") +create_job_lambda = lambda_.Function(self, "create-job", + runtime=lambda_.Runtime.NODEJS_14_X, + handler="index.handler", + code=lambda_.Code.from_asset("./create-job-lambda-code"), + environment=dict( + QUEUE_URL=jobs_queue.queue_url + ) +) +``` + +------ +#### [ Java ] + +``` +final Queue jobsQueue = new Queue(this, "jobs"); +Function createJobLambda = Function.Builder.create(this, "create-job") + .handler("index.handler") + .code(Code.fromAsset("./create-job-lambda-code")) + .environment(java.util.Map.of( // Map.of is Java 9 or later + "QUEUE_URL", jobsQueue.getQueueUrl()) + .build(); +``` + +------ +#### [ C\# ] + +``` +var jobsQueue = new Queue(this, "jobs"); +var createJobLambda = new Function(this, "create-job", new FunctionProps +{ + Runtime = Runtime.NODEJS_14_X, + Handler = "index.handler", + Code = Code.FromAsset(@".\create-job-lambda-code"), + Environment = new Dictionary<string, string> + { + ["QUEUE_URL"] = jobsQueue.QueueUrl + } +}); +``` + +------ +#### [ Go ] + +``` + createJobLambda := awslambda.NewFunction(stack, jsii.String("create-job"), &awslambda.FunctionProps{ + Runtime: awslambda.Runtime_NODEJS_14_X(), + Handler: jsii.String("index.handler"), + Code: awslambda.Code_FromAsset(jsii.String(".\\create-job-lambda-code"), nil), + Environment: &map[string]*string{ + "QUEUE_URL": jsii.String(*jobsQueue.QueueUrl()), + }, + }) +``` + +------ + +For information about the most common API patterns in the AWS Construct Library, see [Resources](resources.md)\. + +## Writing your own constructs<a name="constructs_author"></a> + +In addition to using existing constructs like `s3.Bucket`, you can also write your own constructs, and then anyone can use them in their apps\. All constructs are equal in the AWS CDK\. An AWS CDK construct \(such as `s3.Bucket` or `sns.Topic`\) behaves the same as a construct from a third\-party library published via NPM, Maven, or PyPI\. Constructs published to your company's internal package repository also behave the same way\. + +To declare a new construct, create a class that extends the [Construct](https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html) base class, in the `constructs` package, then follow the pattern for initializer arguments\. + +The following example shows how to declare a construct that represents an Amazon S3 bucket\. The S3 bucket sends an Amazon Simple Notification Service \(Amazon SNS\) notification every time someone uploads a file into it\. + +------ +#### [ TypeScript ] + +``` +export interface NotifyingBucketProps { + prefix?: string; +} + +export class NotifyingBucket extends Construct { + constructor(scope: Construct, id: string, props: NotifyingBucketProps = {}) { + super(scope, id); + const bucket = new s3.Bucket(this, 'bucket'); + const topic = new sns.Topic(this, 'topic'); + bucket.addObjectCreatedNotification(new s3notify.SnsDestination(topic), + { prefix: props.prefix }); + } +} +``` + +------ +#### [ JavaScript ] + +``` +class NotifyingBucket extends Construct { + constructor(scope, id, props = {}) { + super(scope, id); + const bucket = new s3.Bucket(this, 'bucket'); + const topic = new sns.Topic(this, 'topic'); + bucket.addObjectCreatedNotification(new s3notify.SnsDestination(topic), + { prefix: props.prefix }); + } +} + +module.exports = { NotifyingBucket } +``` + +------ +#### [ Python ] + +``` +class NotifyingBucket(Construct): + + def __init__(self, scope: Construct, id: str, *, prefix=None): + super().__init__(scope, id) + bucket = s3.Bucket(self, "bucket") + topic = sns.Topic(self, "topic") + bucket.add_object_created_notification(s3notify.SnsDestination(topic), + s3.NotificationKeyFilter(prefix=prefix)) +``` + +------ +#### [ Java ] + +``` +public class NotifyingBucket extends Construct { + + public NotifyingBucket(final Construct scope, final String id) { + this(scope, id, null, null); + } + + public NotifyingBucket(final Construct scope, final String id, final BucketProps props) { + this(scope, id, props, null); + } + + public NotifyingBucket(final Construct scope, final String id, final String prefix) { + this(scope, id, null, prefix); + } + + public NotifyingBucket(final Construct scope, final String id, final BucketProps props, final String prefix) { + super(scope, id); + + Bucket bucket = new Bucket(this, "bucket"); + Topic topic = new Topic(this, "topic"); + if (prefix != null) + bucket.addObjectCreatedNotification(new SnsDestination(topic), + NotificationKeyFilter.builder().prefix(prefix).build()); + } +} +``` + +------ +#### [ C\# ] + +``` +public class NotifyingBucketProps : BucketProps +{ + public string Prefix { get; set; } +} + +public class NotifyingBucket : Construct +{ + public NotifyingBucket(Construct scope, string id, NotifyingBucketProps props = null) : base(scope, id) + { + var bucket = new Bucket(this, "bucket"); + var topic = new Topic(this, "topic"); + bucket.AddObjectCreatedNotification(new SnsDestination(topic), new NotificationKeyFilter + { + Prefix = props?.Prefix + }); + } +} +``` + +------ +#### [ Go ] + +``` +type NotifyingBucketProps struct { + awss3.BucketProps + Prefix *string +} + +func NewNotifyingBucket(scope constructs.Construct, id *string, props *NotifyingBucketProps) awss3.Bucket { + var bucket awss3.Bucket + if props == nil { + bucket = awss3.NewBucket(scope, jsii.String(*id+"Bucket"), nil) + } else { + bucket = awss3.NewBucket(scope, jsii.String(*id+"Bucket"), &props.BucketProps) + } + topic := awssns.NewTopic(scope, jsii.String(*id+"Topic"), nil) + if props == nil { + bucket.AddObjectCreatedNotification(awss3notifications.NewSnsDestination(topic)) + } else { + bucket.AddObjectCreatedNotification(awss3notifications.NewSnsDestination(topic), &awss3.NotificationKeyFilter{ + Prefix: props.Prefix, + }) + } + return bucket +} +``` + +------ + +**Note** +Our `NotifyingBucket` construct inherits not from `Bucket` but rather from `Construct`\. We are using composition, not inheritance, to bundle an Amazon S3 bucket and an Amazon SNS topic together\. In general, composition is preferred over inheritance when developing AWS CDK constructs\. + +The `NotifyingBucket` constructor has a typical construct signature: `scope`, `id`, and `props`\. The last argument, `props`, is optional \(gets the default value `{}`\) because all props are optional\. \(The base `Construct` class does not take a `props` argument\.\) You could define an instance of this construct in your app without `props`, for example: + +------ +#### [ TypeScript ] + +``` +new NotifyingBucket(this, 'MyNotifyingBucket'); +``` + +------ +#### [ JavaScript ] + +``` +new NotifyingBucket(this, 'MyNotifyingBucket'); +``` + +------ +#### [ Python ] + +``` +NotifyingBucket(self, "MyNotifyingBucket") +``` + +------ +#### [ Java ] + +``` +new NotifyingBucket(this, "MyNotifyingBucket"); +``` + +------ +#### [ C\# ] + +``` +new NotifyingBucket(this, "MyNotifyingBucket"); +``` + +------ +#### [ Go ] + +``` +NewNotifyingBucket(stack, jsii.String("MyNotifyingBucket"), nil) +``` + +------ + +Or you could use `props` \(in Java, an additional parameter\) to specify the path prefix to filter on, for example: + +------ +#### [ TypeScript ] + +``` +new NotifyingBucket(this, 'MyNotifyingBucket', { prefix: 'images/' }); +``` + +------ +#### [ JavaScript ] + +``` +new NotifyingBucket(this, 'MyNotifyingBucket', { prefix: 'images/' }); +``` + +------ +#### [ Python ] + +``` +NotifyingBucket(self, "MyNotifyingBucket", prefix="images/") +``` + +------ +#### [ Java ] + +``` +new NotifyingBucket(this, "MyNotifyingBucket", "/images"); +``` + +------ +#### [ C\# ] + +``` +new NotifyingBucket(this, "MyNotifyingBucket", new NotifyingBucketProps +{ + Prefix = "/images" +}); +``` + +------ +#### [ Go ] + +``` +NewNotifyingBucket(stack, jsii.String("MyNotifyingBucket"), &NotifyingBucketProps{ + Prefix: jsii.String("images/"), +}) +``` + +------ + +Typically, you would also want to expose some properties or methods on your constructs\. It's not very useful to have a topic hidden behind your construct, because users of your construct aren't able to subscribe to it\. Adding a `topic` property lets consumers access the inner topic, as shown in the following example: + +------ +#### [ TypeScript ] + +``` +export class NotifyingBucket extends Construct { + public readonly topic: sns.Topic; + + constructor(scope: Construct, id: string, props: NotifyingBucketProps) { + super(scope, id); + const bucket = new s3.Bucket(this, 'bucket'); + this.topic = new sns.Topic(this, 'topic'); + bucket.addObjectCreatedNotification(new s3notify.SnsDestination(this.topic), { prefix: props.prefix }); + } +} +``` + +------ +#### [ JavaScript ] + +``` +class NotifyingBucket extends Construct { + + constructor(scope, id, props) { + super(scope, id); + const bucket = new s3.Bucket(this, 'bucket'); + this.topic = new sns.Topic(this, 'topic'); + bucket.addObjectCreatedNotification(new s3notify.SnsDestination(this.topic), { prefix: props.prefix }); + } +} + +module.exports = { NotifyingBucket }; +``` + +------ +#### [ Python ] + +``` +class NotifyingBucket(Construct): + + def __init__(self, scope: Construct, id: str, *, prefix=None, **kwargs): + super().__init__(scope, id) + bucket = s3.Bucket(self, "bucket") + self.topic = sns.Topic(self, "topic") + bucket.add_object_created_notification(s3notify.SnsDestination(self.topic), + s3.NotificationKeyFilter(prefix=prefix)) +``` + +------ +#### [ Java ] + +``` +public class NotifyingBucket extends Construct { + + public Topic topic = null; + + public NotifyingBucket(final Construct scope, final String id) { + this(scope, id, null, null); + } + + public NotifyingBucket(final Construct scope, final String id, final BucketProps props) { + this(scope, id, props, null); + } + + public NotifyingBucket(final Construct scope, final String id, final String prefix) { + this(scope, id, null, prefix); + } + + public NotifyingBucket(final Construct scope, final String id, final BucketProps props, final String prefix) { + super(scope, id); + + Bucket bucket = new Bucket(this, "bucket"); + topic = new Topic(this, "topic"); + if (prefix != null) + bucket.addObjectCreatedNotification(new SnsDestination(topic), + NotificationKeyFilter.builder().prefix(prefix).build()); + } +} +``` + +------ +#### [ C\# ] + +``` +public class NotifyingBucket : Construct +{ + public readonly Topic topic; + + public NotifyingBucket(Construct scope, string id, NotifyingBucketProps props = null) : base(scope, id) + { + var bucket = new Bucket(this, "bucket"); + topic = new Topic(this, "topic"); + bucket.AddObjectCreatedNotification(new SnsDestination(topic), new NotificationKeyFilter + { + Prefix = props?.Prefix + }); + } +} +``` + +------ +#### [ Go ] + +To do this in Go, we'll need a little extra plumbing\. Our original `NewNotifyingBucket` function returned an `awss3.Bucket`\. We'll need to extend `Bucket` to include a `topic` member by creating a `NotifyingBucket` struct\. Our function will then return this type\. + +``` +type NotifyingBucket struct { + awss3.Bucket + topic awssns.Topic +} + +func NewNotifyingBucket(scope constructs.Construct, id *string, props *NotifyingBucketProps) NotifyingBucket { + var bucket awss3.Bucket + if props == nil { + bucket = awss3.NewBucket(scope, jsii.String(*id+"Bucket"), nil) + } else { + bucket = awss3.NewBucket(scope, jsii.String(*id+"Bucket"), &props.BucketProps) + } + topic := awssns.NewTopic(scope, jsii.String(*id+"Topic"), nil) + if props == nil { + bucket.AddObjectCreatedNotification(awss3notifications.NewSnsDestination(topic)) + } else { + bucket.AddObjectCreatedNotification(awss3notifications.NewSnsDestination(topic), &awss3.NotificationKeyFilter{ + Prefix: props.Prefix, + }) + } + var nbucket NotifyingBucket + nbucket.Bucket = bucket + nbucket.topic = topic + return nbucket +} +``` + +------ + +Now, consumers can subscribe to the topic, for example: + +------ +#### [ TypeScript ] + +``` +const queue = new sqs.Queue(this, 'NewImagesQueue'); +const images = new NotifyingBucket(this, '/images'); +images.topic.addSubscription(new sns_sub.SqsSubscription(queue)); +``` + +------ +#### [ JavaScript ] + +``` +const queue = new sqs.Queue(this, 'NewImagesQueue'); +const images = new NotifyingBucket(this, '/images'); +images.topic.addSubscription(new sns_sub.SqsSubscription(queue)); +``` + +------ +#### [ Python ] + +``` +queue = sqs.Queue(self, "NewImagesQueue") +images = NotifyingBucket(self, prefix="Images") +images.topic.add_subscription(sns_sub.SqsSubscription(queue)) +``` + +------ +#### [ Java ] + +``` +NotifyingBucket images = new NotifyingBucket(this, "MyNotifyingBucket", "/images"); +images.topic.addSubscription(new SqsSubscription(queue)); +``` + +------ +#### [ C\# ] + +``` +var queue = new Queue(this, "NewImagesQueue"); +var images = new NotifyingBucket(this, "MyNotifyingBucket", new NotifyingBucketProps +{ + Prefix = "/images" +}); +images.topic.AddSubscription(new SqsSubscription(queue)); +``` + +------ +#### [ Go ] + +``` + queue := awssqs.NewQueue(stack, jsii.String("NewImagesQueue"), nil) + images := NewNotifyingBucket(stack, jsii.String("MyNotifyingBucket"), &NotifyingBucketProps{ + Prefix: jsii.String("/images"), + }) + images.topic.AddSubscription(awssnssubscriptions.NewSqsSubscription(queue, nil)) +``` + +------ + +## The construct tree<a name="constructs_tree"></a> + +As we've already seen, in AWS CDK apps, you define constructs "inside" other constructs using the `scope` argument passed to every construct\. In this way, an AWS CDK app defines a hierarchy of constructs known as the *construct tree*\. + +The root of this tree is your app—that is, an instance of the `App` class\. Within the app, you instantiate one or more stacks\. Within stacks, you instantiate either AWS CloudFormation resources or higher\-level constructs, which may themselves instantiate resources or other constructs, and so on down the tree\. + +Constructs are *always* explicitly defined within the scope of another construct, so there is no doubt about the relationships between constructs\. Almost always, you should pass `this` \(in Python, `self`\) as the scope, indicating that the new construct is a child of the current construct\. The intended pattern is that you derive your construct from [https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html](https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html), then instantiate the constructs it uses in its constructor\. + +Passing the scope explicitly allows each construct to add itself to the tree, with this behavior entirely contained within the [`Construct` base class](https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html)\. It works the same way in every language supported by the AWS CDK and does not require introspection or other "magic\." + +**Important** +Technically, it's possible to pass some scope other than `this` when instantiating a construct\. You can add constructs anywhere in the tree, or even in another stack in the same app\. For example, you could write a mixin\-style function that adds constructs to a scope passed in as an argument\. The practical difficulty here is that you can't easily ensure that the IDs you choose for your constructs are unique within someone else's scope\. The practice also makes your code more difficult to understand, maintain, and reuse\. It is almost always better to find a way to express your intent without resorting to abusing the `scope` argument\. + +The AWS CDK uses the IDs of all constructs in the path from the tree's root to each child construct to generate the unique IDs required by AWS CloudFormation\. This approach means that construct IDs only need to be unique within their scope, rather than within the entire stack as in native AWS CloudFormation\. However, if you move a construct to a different scope, its generated stack\-unique ID changes, and AWS CloudFormation won't consider it the same resource\. + +The construct tree is separate from the constructs that you define in your AWS CDK code\. However, it's accessible through any construct's `node` attribute, which is a reference to the node that represents that construct in the tree\. Each node is a [https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Node.html](https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Node.html) instance, the attributes of which provide access to the tree's root and to the node's parent scopes and children\. ++ `node.children` – The direct children of the construct\. ++ `node.id` – The identifier of the construct within its scope\. ++ `node.path` – The full path of the construct including the IDs of all of its parents\. ++ `node.root` – The root of the construct tree \(the app\)\. ++ `node.scope` – The scope \(parent\) of the construct, or undefined if the node is the root\. ++ `node.scopes` – All parents of the construct, up to the root\. ++ `node.uniqueId` – The unique alphanumeric identifier for this construct within the tree \(by default, generated from `node.path` and a hash\)\. + +The construct tree defines an implicit order in which constructs are synthesized to resources in the final AWS CloudFormation template\. Where one resource must be created before another, AWS CloudFormation or the AWS Construct Library generally infers the dependency\. They then make sure that the resources are created in the right order\. + +You can also add an explicit dependency between two nodes by using `node.addDependency()`\. For more information, see [Dependencies](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib-readme.html#dependencies) in the *AWS CDK API Reference*\. + +The AWS CDK provides a simple way to visit every node in the construct tree and perform an operation on each one\. For more information, see [Aspects](aspects.md)\. \ No newline at end of file diff --git a/v2/context.md b/v2/context.md new file mode 100644 index 00000000..8d96edd9 --- /dev/null +++ b/v2/context.md @@ -0,0 +1,333 @@ +# Runtime context<a name="context"></a> + +Context values are key\-value pairs that can be associated with an app, stack, or construct\. They may be supplied to your app from a file \(usually either `cdk.json` or `cdk.context.json` in your project directory\) or on the command line\. + +The CDK Toolkit uses context to cache values retrieved from your AWS account during synthesis\. Values include the Availability Zones in your account or the Amazon Machine Image \(AMI\) IDs currently available for Amazon EC2 instances\. Because these values are provided by your AWS account, they can change between runs of your CDK application\. This makes them a potential source of unintended change\. The CDK Toolkit's caching behavior "freezes" these values for your CDK app until you decide to accept the new values\. + +Imagine the following scenario without context caching\. Let's say you specified "latest Amazon Linux" as the AMI for your Amazon EC2 instances, and a new version of this AMI was released\. Then, the next time you deployed your CDK stack, your already\-deployed instances would be using the outdated \("wrong"\) AMI and would need to be upgraded\. Upgrading would result in replacing all your existing instances with new ones, which would probably be unexpected and undesired\. + +Instead, the CDK records your account's available AMIs in your project's `cdk.context.json` file, and uses the stored value for future synthesis operations\. This way, the list of AMIs is no longer a potential source of change\. You can also be sure that your stacks will always synthesize to the same AWS CloudFormation templates\. + +Not all context values are cached values from your AWS environment\. [Feature flags](featureflags.md) are also context values\. You can also create your own context values for use by your apps or constructs\. + +Context keys are strings\. Values may be any type supported by JSON: numbers, strings, arrays, or objects\. + +**Tip** +If your constructs create their own context values, incorporate your library's package name in its keys so they won't conflict with other packages' context values\. + +Many context values are associated with a particular AWS environment, and a given CDK app can be deployed in more than one environment\. The key for such values includes the AWS account and Region so that values from different environments do not conflict\. + +The following context key illustrates the format used by the AWS CDK, including the account and Region\. + +``` +availability-zones:account=123456789012:region=eu-central-1 +``` + +**Important** +Cached context values are managed by the AWS CDK and its constructs, including constructs you may write\. Do not add or change cached context values by manually editing files\. It can be useful, however, to review `cdk.context.json` occasionally to see what values are being cached\. Context values that don't represent cached values should be stored under the `context` key of `cdk.json`\. This way, they won't be cleared when cached values are cleared\. + +## Sources of context values<a name="context_construct"></a> + +Context values can be provided to your AWS CDK app in six different ways: ++ Automatically from the current AWS account\. ++ Through the \-\-context option to the cdk command\. \(These values are always strings\.\) ++ In the project's `cdk.context.json` file\. ++ In the `context` key of the project's `cdk.json` file\. ++ In the `context` key of your `~/.cdk.json` file\. ++ In your AWS CDK app using the `construct.node.setContext()` method\. + +The project file `cdk.context.json` is where the AWS CDK caches context values retrieved from your AWS account\. This practice avoids unexpected changes to your deployments when, for example, a new Availability Zone is introduced\. The AWS CDK does not write context data to any of the other files listed\. + +**Important** +Because they're part of your application's state, `cdk.json` and `cdk.context.json` must be committed to source control along with the rest of your app's source code\. Otherwise, deployments in other environments \(for example, a CI pipeline\) might produce inconsistent results\. + +Context values are scoped to the construct that created them; they are visible to child constructs, but not to parents or siblings\. Context values that are set by the AWS CDK Toolkit \(the cdk command\) can be set automatically, from a file, or from the \-\-context option\. Context values from these sources are implicitly set on the `App` construct\. Therefore, they're visible to every construct in every stack in the app\. + +Your app can read a context value using the `construct.node.tryGetContext` method\. If the requested entry isn't found on the current construct or any of its parents, the result is `undefined`\. \(Alternatively, the result could be your language's equivalent, such as `None` in Python\.\) + +## Context methods<a name="context_methods"></a> + +The AWS CDK supports several context methods that enable AWS CDK apps to obtain contextual information from the AWS environment\. For example, you can get a list of Availability Zones that are available in a given AWS account and Region, using the [stack\.availabilityZones](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html#availabilityzones) method\. + +The following are the context methods: + +[HostedZone\.fromLookup](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_route53.HostedZone.html#static-fromwbrlookupscope-id-query) +Gets the hosted zones in your account\. + +[stack\.availabilityZones](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html#availabilityzones) +Gets the supported Availability Zones\. + +[StringParameter\.valueFromLookup](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ssm.StringParameter.html#static-valuewbrfromwbrlookupscope-parametername) +Gets a value from the current Region's Amazon EC2 Systems Manager Parameter Store\. + +[Vpc\.fromLookup](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.Vpc.html#static-fromwbrlookupscope-id-options) +Gets the existing Amazon Virtual Private Clouds in your accounts\. + +[LookupMachineImage](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.LookupMachineImage.html) +Looks up a machine image for use with a NAT instance in an Amazon Virtual Private Cloud\. + +If a required context value isn't available, the AWS CDK app notifies the CDK Toolkit that the context information is missing\. Next, the CLI queries the current AWS account for the information and stores the resulting context information in the `cdk.context.json` file\. Then, it executes the AWS CDK app again with the context values\. + +## Viewing and managing context<a name="context_viewing"></a> + +Use the cdk context command to view and manage the information in your `cdk.context.json` file\. To see this information, use the cdk context command without any options\. The output should be something like the following\. + +``` +Context found in cdk.json: + +┌───┬─────────────────────────────────────────────────────────────┬─────────────────────────────────────────────────────────┐ +│ # │ Key │ Value │ +├───┼─────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────┤ +│ 1 │ availability-zones:account=123456789012:region=eu-central-1 │ [ "eu-central-1a", "eu-central-1b", "eu-central-1c" ] │ +├───┼─────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────┤ +│ 2 │ availability-zones:account=123456789012:region=eu-west-1 │ [ "eu-west-1a", "eu-west-1b", "eu-west-1c" ] │ +└───┴─────────────────────────────────────────────────────────────┴─────────────────────────────────────────────────────────┘ + +Run cdk context --reset KEY_OR_NUMBER to remove a context key. If it is a cached value, it will be refreshed on the next cdk synth. +``` + +To remove a context value, run cdk context \-\-reset, specifying the value's corresponding key or number\. The following example removes the value that corresponds to the second key in the preceding example\. This value represents the list of Availability Zones in the Europe \(Ireland\) Region\. + +``` +cdk context --reset 2 +``` + +``` +Context value +availability-zones:account=123456789012:region=eu-west-1 +reset. It will be refreshed on the next SDK synthesis run. +``` + +Therefore, if you want to update to the latest version of the Amazon Linux AMI, use the preceding example to do a controlled update of the context value and reset it\. Then, synthesize and deploy your app again\. + +``` +cdk synth +``` + +To clear all of the stored context values for your app, run cdk context \-\-clear, as follows\. + +``` +cdk context --clear +``` + +Only context values stored in `cdk.context.json` can be reset or cleared\. The AWS CDK does not touch other context values\. Therefore, to protect a context value from being reset using these commands, you might copy the value to `cdk.json`\. + +## AWS CDK Toolkit `--context` flag<a name="context_cli"></a> + +Use the `--context` \(`-c` for short\) option to pass runtime context values to your CDK app during synthesis or deployment\. + +``` +cdk synth --context key=value MyStack +``` + +To specify multiple context values, repeat the \-\-context option any number of times, providing one key\-value pair each time\. + +``` +cdk synth --context key1=value1 --context key2=value2 MyStack +``` + +When synthesizing multiple stacks, the specified context values are passed to all stacks\. To provide different context values to individual stacks, either use different keys for the values, or use multiple cdk synth or cdk deploy commands\. + +Context values passed from the command line are always strings\. If a value is usually of some other type, your code must be prepared to convert or parse the value\. You might have non\-string context values provided in other ways \(for example, in `cdk.context.json`\)\. To make sure this kind of value works as expected, confirm that the value is a string before converting it\. + +## Example<a name="context_example"></a> + +Following is an example of using an existing Amazon VPC using AWS CDK context\. + +------ +#### [ TypeScript ] + +``` +import * as cdk from 'aws-cdk-lib'; +import * as ec2 from 'aws-cdk-lib/aws-ec2'; +import { Construct } from 'constructs'; + +export class ExistsVpcStack extends cdk.Stack { + + constructor(scope: Construct, id: string, props?: cdk.StackProps) { + + super(scope, id, props); + + const vpcid = this.node.tryGetContext('vpcid'); + const vpc = ec2.Vpc.fromLookup(this, 'VPC', { + vpcId: vpcid, + }); + + const pubsubnets = vpc.selectSubnets({subnetType: ec2.SubnetType.PUBLIC}); + + new cdk.CfnOutput(this, 'publicsubnets', { + value: pubsubnets.subnetIds.toString(), + }); + } +} +``` + +------ +#### [ JavaScript ] + +``` +const cdk = require('aws-cdk-lib'); +const ec2 = require('aws-cdk-lib/aws-ec2'); + +class ExistsVpcStack extends cdk.Stack { + + constructor(scope, id, props) { + + super(scope, id, props); + + const vpcid = this.node.tryGetContext('vpcid'); + const vpc = ec2.Vpc.fromLookup(this, 'VPC', { + vpcId: vpcid + }); + + const pubsubnets = vpc.selectSubnets({subnetType: ec2.SubnetType.PUBLIC}); + + new cdk.CfnOutput(this, 'publicsubnets', { + value: pubsubnets.subnetIds.toString() + }); + } +} + +module.exports = { ExistsVpcStack } +``` + +------ +#### [ Python ] + +``` +import aws_cdk as cdk +import aws_cdk.aws_ec2 as ec2 +from constructs import Construct + +class ExistsVpcStack(cdk.Stack): + + def __init__(scope: Construct, id: str, **kwargs): + + super().__init__(scope, id, **kwargs) + + vpcid = self.node.try_get_context("vpcid") + vpc = ec2.Vpc.from_lookup(self, "VPC", vpc_id=vpcid) + + pubsubnets = vpc.select_subnets(subnetType=ec2.SubnetType.PUBLIC) + + cdk.CfnOutput(self, "publicsubnets", + value=pubsubnets.subnet_ids.to_string()) +``` + +------ +#### [ Java ] + +``` +import software.amazon.awscdk.CfnOutput; + +import software.amazon.awscdk.services.ec2.Vpc; +import software.amazon.awscdk.services.ec2.VpcLookupOptions; +import software.amazon.awscdk.services.ec2.SelectedSubnets; +import software.amazon.awscdk.services.ec2.SubnetSelection; +import software.amazon.awscdk.services.ec2.SubnetType; +import software.constructs.Construct; + +public class ExistsVpcStack extends Stack { + public ExistsVpcStack(Construct context, String id) { + this(context, id, null); + } + + public ExistsVpcStack(Construct context, String id, StackProps props) { + super(context, id, props); + + String vpcId = (String)this.getNode().tryGetContext("vpcid"); + Vpc vpc = (Vpc)Vpc.fromLookup(this, "VPC", VpcLookupOptions.builder() + .vpcId(vpcId).build()); + + SelectedSubnets pubSubNets = vpc.selectSubnets(SubnetSelection.builder() + .subnetType(SubnetType.PUBLIC).build()); + + CfnOutput.Builder.create(this, "publicsubnets") + .value(pubSubNets.getSubnetIds().toString()).build(); + } +} +``` + +------ +#### [ C\# ] + +``` +using Amazon.CDK; +using Amazon.CDK.AWS.EC2; +using Constructs; + +class ExistsVpcStack : Stack +{ + public ExistsVpcStack(Construct scope, string id, StackProps props) : base(scope, id, props) + { + var vpcId = (string)this.Node.TryGetContext("vpcid"); + var vpc = Vpc.FromLookup(this, "VPC", new VpcLookupOptions + { + VpcId = vpcId + }); + + SelectedSubnets pubSubNets = vpc.SelectSubnets([new SubnetSelection + { + SubnetType = SubnetType.PUBLIC + }]); + + new CfnOutput(this, "publicsubnets", new CfnOutputProps { + Value = pubSubNets.SubnetIds.ToString() + }); + } +} +``` + +------ + +You can use cdk diff to see the effects of passing in a context value on the command line: + +``` +cdk diff -c vpcid=vpc-0cb9c31031d0d3e22 +``` + +``` +Stack ExistsvpcStack +Outputs +[+] Output publicsubnets publicsubnets: {"Value":"subnet-06e0ea7dd302d3e8f,subnet-01fc0acfb58f3128f"} +``` + +The resulting context values can be viewed as shown here\. + +``` +cdk context -j +``` + +``` +{ + "vpc-provider:account=123456789012:filter.vpc-id=vpc-0cb9c31031d0d3e22:region=us-east-1": { + "vpcId": "vpc-0cb9c31031d0d3e22", + "availabilityZones": [ + "us-east-1a", + "us-east-1b" + ], + "privateSubnetIds": [ + "subnet-03ecfc033225be285", + "subnet-0cded5da53180ebfa" + ], + "privateSubnetNames": [ + "Private" + ], + "privateSubnetRouteTableIds": [ + "rtb-0e955393ced0ada04", + "rtb-05602e7b9f310e5b0" + ], + "publicSubnetIds": [ + "subnet-06e0ea7dd302d3e8f", + "subnet-01fc0acfb58f3128f" + ], + "publicSubnetNames": [ + "Public" + ], + "publicSubnetRouteTableIds": [ + "rtb-00d1fdfd823c82289", + "rtb-04bb1969b42969bcb" + ] + } +} +``` \ No newline at end of file diff --git a/v2/core_concepts.md b/v2/core_concepts.md new file mode 100644 index 00000000..f0a6eb5b --- /dev/null +++ b/v2/core_concepts.md @@ -0,0 +1,5 @@ +# Concepts<a name="core_concepts"></a> + +This topic describes some of the concepts \(the why and how\) behind the AWS CDK\. It also discusses the AWS Construct Library\. + +AWS CDK apps are composed of building blocks known as [Constructs](constructs.md), which are composed together to form [stacks](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html) and [apps](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.App.html)\. \ No newline at end of file diff --git a/v2/disaster-recovery-resiliency.md b/v2/disaster-recovery-resiliency.md new file mode 100644 index 00000000..c99d21f9 --- /dev/null +++ b/v2/disaster-recovery-resiliency.md @@ -0,0 +1,11 @@ +# Resilience for the AWS Cloud Development Kit \(AWS CDK\)<a name="disaster-recovery-resiliency"></a> + +The Amazon Web Services \(AWS\) global infrastructure is built around AWS Regions and Availability Zones\. + +AWS Regions provide multiple physically separated and isolated Availability Zones, which are connected with low\-latency, high\-throughput, and highly redundant networking\. + +With Availability Zones, you can design and operate applications and databases that automatically fail over between Availability Zones without interruption\. Availability Zones are more highly available, fault tolerant, and scalable than traditional single or multiple data center infrastructures\. + +For more information about AWS Regions and Availability Zones, see [AWS Global Infrastructure](https://aws.amazon.com/about-aws/global-infrastructure/)\. + +The AWS CDK follows the [shared responsibility model](https://aws.amazon.com/compliance/shared-responsibility-model/) through the specific Amazon Web Services \(AWS\) services it supports\. For AWS service security information, see the [AWS service security documentation page](https://docs.aws.amazon.com/security/?id=docs_gateway#aws-security) and [AWS services that are in scope of AWS compliance efforts by compliance program](https://aws.amazon.com/compliance/services-in-scope/)\. \ No newline at end of file diff --git a/v2/doc-history.md b/v2/doc-history.md new file mode 100644 index 00000000..58aba4d6 --- /dev/null +++ b/v2/doc-history.md @@ -0,0 +1,13 @@ +# AWS CDK Developer Guide history<a name="doc-history"></a> + +See [Releases](https://github.com/awslabs/aws-cdk/releases) for information about AWS CDK releases\. The AWS CDK is updated approximately once a week\. Maintenance versions may be released between weekly releases to address critical issues\. Each release includes a matched AWS CDK Toolkit \(CDK CLI\), AWS Construct Library, and API Reference\. Updates to this Guide generally do not synchronize with AWS CDK releases\. + +**Note** +The table below represents significant documentation milestones\. We fix errors and improve content on an ongoing basis\. + +| Change | Description | Date | +| --- |--- |--- | +| [Document `cdk.json`](#doc-history) | Add documentation of `cdk.json` configuration values\. | April 20, 2022 | +| [Dependency management](#doc-history) | Add topic on managing dependencies with the AWS CDK\. | April 7, 2022 | +| [Remove double\-braces from Java examples](#doc-history) | Replace this anti\-pattern with Java 9 `Map.of` throughout\. | March 9, 2022 | +| [AWS CDK v2 release](#doc-history) | Version 2 of the AWS CDK Developer Guide is released\. [Document history](../../v1/guide/doc-history.html) for CDK v1\. | December 4, 2021 | \ No newline at end of file diff --git a/v2/ecs_example.md b/v2/ecs_example.md new file mode 100644 index 00000000..a3fb5945 --- /dev/null +++ b/v2/ecs_example.md @@ -0,0 +1,309 @@ +# Creating an AWS Fargate service using the AWS CDK<a name="ecs_example"></a> + +This example walks you through how to create an AWS Fargate service running on an Amazon Elastic Container Service \(Amazon ECS\) cluster that's fronted by an internet\-facing Application Load Balancer from an image on Amazon ECR\. + +Amazon ECS is a highly scalable, fast, container management service that makes it easy to run, stop, and manage Docker containers on a cluster\. You can host your cluster on a serverless infrastructure that's managed by Amazon ECS by launching your services or tasks using the Fargate launch type\. For more control, you can host your tasks on a cluster of Amazon Elastic Compute Cloud \(Amazon EC2\) instances that you manage by using the Amazon EC2 launch type\. + +This tutorial shows you how to launch some services using the Fargate launch type\. If you've used the AWS Management Console to create a Fargate service, you know that there are many steps to follow to accomplish that task\. AWS has several tutorials and documentation topics that walk you through creating a Fargate service, including: ++ [How to Deploy Docker Containers \- AWS](https://aws.amazon.com/getting-started/tutorials/deploy-docker-containers) ++ [Setting Up with Amazon ECS](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/get-set-up-for-amazon-ecs.html) ++ [Getting Started with Amazon ECS Using Fargate](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ECS_GetStarted.html) + +This example creates a similar Fargate service in AWS CDK code\. + +The Amazon ECS construct used in this tutorial helps you use AWS services by providing the following benefits: ++ Automatically configures a load balancer\. ++ Automatically opens a security group for load balancers\. This enables load balancers to communicate with instances without you explicitly creating a security group\. ++ Automatically orders dependency between the service and the load balancer attaching to a target group, where the AWS CDK enforces the correct order of creating the listener before an instance is created\. ++ Automatically configures user data on automatically scaling groups\. This creates the correct configuration to associate a cluster to AMIs\. ++ Validates parameter combinations early\. This exposes AWS CloudFormation issues earlier, thus saving you deployment time\. For example, depending on the task, it's easy to misconfigure the memory settings\. Previously, you would not encounter an error until you deployed your app\. But now the AWS CDK can detect a misconfiguration and emit an error when you synthesize your app\. ++ Automatically adds permissions for Amazon Elastic Container Registry \(Amazon ECR\) if you use an image from Amazon ECR\. ++ Automatically scales\. The AWS CDK supplies a method so you can autoscalinginstances when you use an Amazon EC2 cluster\. This happens automatically when you use an instance in a Fargate cluster\. + + In addition, the AWS CDK prevents an instance from being deleted when automatic scaling tries to kill an instance, but either a task is running or is scheduled on that instance\. + + Previously, you had to create a Lambda function to have this functionality\. ++ Provides asset support, so that you can deploy a source from your machine to Amazon ECS in one step\. Previously, to use an application source you had to perform several manual steps, such as uploading to Amazon ECR and creating a Docker image\. + +See [ECS](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs-readme.html) for details\. + +**Important** +The `ApplicationLoadBalancedFargateService` constructs we'll be using includes numerous AWS components, some of which have non\-trivial costs if left provisioned in your AWS account, even if you don't use them\. Be sure to clean up \(cdk destroy\) after completing this example\. + +## Creating the directory and initializing the AWS CDK<a name="ecs_example_initialize"></a> + +Let's start by creating a directory to hold the AWS CDK code, and then creating a AWS CDK app in that directory\. + +------ +#### [ TypeScript ] + +``` +mkdir MyEcsConstruct +cd MyEcsConstruct +cdk init --language typescript +``` + +------ +#### [ JavaScript ] + +``` +mkdir MyEcsConstruct +cd MyEcsConstruct +cdk init --language javascript +``` + +------ +#### [ Python ] + +``` +mkdir MyEcsConstruct +cd MyEcsConstruct +cdk init --language python +source .venv/bin/activate +pip install -r requirements.txt +``` + +------ +#### [ Java ] + +``` +mkdir MyEcsConstruct +cd MyEcsConstruct +cdk init --language java +``` + +You may now import the Maven project into your IDE\. + +------ +#### [ C\# ] + +``` +mkdir MyEcsConstruct +cd MyEcsConstruct +cdk init --language csharp +``` + +You may now open `src/MyEcsConstruct.sln` in Visual Studio\. + +------ + +Run the app and confirm that it creates an empty stack\. + +``` +cdk synth +``` + +## Create a Fargate service<a name="ecs_example_create_fargate_service"></a> + +There are two different ways to run your container tasks with Amazon ECS: ++ Use the `Fargate` launch type, where Amazon ECS manages the physical machines that your containers are running on for you\. ++ Use the `EC2` launch type, where you do the managing, such as specifying automatic scaling\. + +For this example, we'll create a Fargate service running on an ECS cluster fronted by an internet\-facing Application Load Balancer\. + +Add the following AWS Construct Library module imports to the indicated file\. + +------ +#### [ TypeScript ] + +File: `lib/my_ecs_construct-stack.ts` + +``` +import * as ec2 from "aws-cdk-lib/aws-ec2"; +import * as ecs from "aws-cdk-lib/aws-ecs"; +import * as ecs_patterns from "aws-cdk-lib/aws-ecs-patterns"; +``` + +------ +#### [ JavaScript ] + +File: `lib/my_ecs_construct-stack.js` + +``` +const ec2 = require("aws-cdk-lib/aws-ec2"); +const ecs = require("aws-cdk-lib/aws-ecs"); +const ecs_patterns = require("aws-cdk-lib/aws-ecs-patterns"); +``` + +------ +#### [ Python ] + +File: `my_ecs_construct/my_ecs_construct_stack.py` + +``` +from aws_cdk import (aws_ec2 as ec2, aws_ecs as ecs, + aws_ecs_patterns as ecs_patterns) +``` + +------ +#### [ Java ] + +File: `src/main/java/com/myorg/MyEcsConstructStack.java` + +``` +import software.amazon.awscdk.services.ec2.*; +import software.amazon.awscdk.services.ecs.*; +import software.amazon.awscdk.services.ecs.patterns.*; +``` + +------ +#### [ C\# ] + +File: `src/MyEcsConstruct/MyEcsConstructStack.cs` + +``` +using Amazon.CDK.AWS.EC2; +using Amazon.CDK.AWS.ECS; +using Amazon.CDK.AWS.ECS.Patterns; +``` + +------ + +Replace the comment at the end of the constructor with the following code\. + +------ +#### [ TypeScript ] + +``` + const vpc = new ec2.Vpc(this, "MyVpc", { + maxAzs: 3 // Default is all AZs in region + }); + + const cluster = new ecs.Cluster(this, "MyCluster", { + vpc: vpc + }); + + // Create a load-balanced Fargate service and make it public + new ecs_patterns.ApplicationLoadBalancedFargateService(this, "MyFargateService", { + cluster: cluster, // Required + cpu: 512, // Default is 256 + desiredCount: 6, // Default is 1 + taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample") }, + memoryLimitMiB: 2048, // Default is 512 + publicLoadBalancer: true // Default is true + }); +``` + +------ +#### [ JavaScript ] + +``` + const vpc = new ec2.Vpc(this, "MyVpc", { + maxAzs: 3 // Default is all AZs in region + }); + + const cluster = new ecs.Cluster(this, "MyCluster", { + vpc: vpc + }); + + // Create a load-balanced Fargate service and make it public + new ecs_patterns.ApplicationLoadBalancedFargateService(this, "MyFargateService", { + cluster: cluster, // Required + cpu: 512, // Default is 256 + desiredCount: 6, // Default is 1 + taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample") }, + memoryLimitMiB: 2048, // Default is 512 + publicLoadBalancer: true // Default is true + }); +``` + +------ +#### [ Python ] + +``` + vpc = ec2.Vpc(self, "MyVpc", max_azs=3) # default is all AZs in region + + cluster = ecs.Cluster(self, "MyCluster", vpc=vpc) + + ecs_patterns.ApplicationLoadBalancedFargateService(self, "MyFargateService", + cluster=cluster, # Required + cpu=512, # Default is 256 + desired_count=6, # Default is 1 + task_image_options=ecs_patterns.ApplicationLoadBalancedTaskImageOptions( + image=ecs.ContainerImage.from_registry("amazon/amazon-ecs-sample")), + memory_limit_mib=2048, # Default is 512 + public_load_balancer=True) # Default is True +``` + +------ +#### [ Java ] + +``` + Vpc vpc = Vpc.Builder.create(this, "MyVpc") + .maxAzs(3) // Default is all AZs in region + .build(); + + Cluster cluster = Cluster.Builder.create(this, "MyCluster") + .vpc(vpc).build(); + + // Create a load-balanced Fargate service and make it public + ApplicationLoadBalancedFargateService.Builder.create(this, "MyFargateService") + .cluster(cluster) // Required + .cpu(512) // Default is 256 + .desiredCount(6) // Default is 1 + .taskImageOptions( + ApplicationLoadBalancedTaskImageOptions.builder() + .image(ContainerImage.fromRegistry("amazon/amazon-ecs-sample")) + .build()) + .memoryLimitMiB(2048) // Default is 512 + .publicLoadBalancer(true) // Default is true + .build(); +``` + +------ +#### [ C\# ] + +``` + var vpc = new Vpc(this, "MyVpc", new VpcProps + { + MaxAzs = 3 // Default is all AZs in region + }); + + var cluster = new Cluster(this, "MyCluster", new ClusterProps + { + Vpc = vpc + }); + + // Create a load-balanced Fargate service and make it public + new ApplicationLoadBalancedFargateService(this, "MyFargateService", + new ApplicationLoadBalancedFargateServiceProps + { + Cluster = cluster, // Required + DesiredCount = 6, // Default is 1 + TaskImageOptions = new ApplicationLoadBalancedTaskImageOptions + { + Image = ContainerImage.FromRegistry("amazon/amazon-ecs-sample") + }, + MemoryLimitMiB = 2048, // Default is 256 + PublicLoadBalancer = true // Default is true + } + ); +``` + +------ + +Save it and make sure it runs and creates a stack\. + +``` +cdk synth +``` + +The stack is hundreds of lines, so we won't show it here\. The stack should contain one default instance, a private subnet and a public subnet for the three Availability Zones, and a security group\. + +Deploy the stack\. + +``` +cdk deploy +``` + +AWS CloudFormation displays information about the dozens of steps that it takes as it deploys your app\. + +That's how easy it is to create a Fargate\-powered Amazon ECS service to run a Docker image\. + +## Clean up<a name="ecs_example_destroy"></a> + +To avoid unexpected AWS charges, destroy your AWS CDK stack after you're done with this exercise\. + +``` +cdk destroy +``` \ No newline at end of file diff --git a/v2/environments.md b/v2/environments.md new file mode 100644 index 00000000..8e2b0b9c --- /dev/null +++ b/v2/environments.md @@ -0,0 +1,397 @@ +# Environments<a name="environments"></a> + +Each `Stack` instance in your AWS CDK app is explicitly or implicitly associated with an environment \(`env`\)\. An environment is the target AWS account and Region into which the stack is intended to be deployed\. The Region is specified using a Region code\. For a list, see [Regional endpoints](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints)\. + +**Note** +You must [bootstrap](bootstrapping.md) each environment you will deploy CDK stacks into\. Bootstrapping provisions certain AWS resources that are used during deployment\. + +If you don't specify an environment when you instantiate a stack, the stack is said to be *environment\-agnostic*\. AWS CloudFormation templates synthesized from such a stack will try to use deploy\-time resolution on environment\-related attributes such as `stack.account`, `stack.region`, and `stack.availabilityZones` \(Python: `availability_zones`\)\. + +**Tip** +If you're using the standard AWS CDK development template, your stacks are instantiated in the same file where you instantiate the `App` object\. +The file named after your project \(for example, `hello-cdk.ts`\) in your project's `bin` folder\. +The file named after your project \(for example, `hello-cdk.js`\) in your project's `bin` folder\. +The file `app.py` in your project's main directory\. +The file named `ProjectNameApp.java`, for example `HelloCdkApp.java`, nested deep under the `src/main` directory\. +The file named `Program.cs` under `src\ProjectName`, for example `src\HelloCdk\Program.cs`\. + +In an environment\-agnostic stack, any constructs that use Availability Zones will see two AZs, allowing the stack to be deployed to any Region\. + +When using cdk deploy to deploy environment\-agnostic stacks, the AWS CDK CLI uses the specified AWS CLI profile to determine where to deploy\. If no profile is specified, the default profile is used\. The AWS CDK CLI follows a protocol similar to the AWS CLI to determine which AWS credentials to use when performing operations in your AWS account\. See [AWS CDK Toolkit \(`cdk` command\)](cli.md) for details\. + +For production stacks, we recommend that you explicitly specify the environment for each stack in your app using the `env` property\. The following example specifies different environments for its two different stacks\. + +------ +#### [ TypeScript ] + +``` +const envEU = { account: '2383838383', region: 'eu-west-1' }; +const envUSA = { account: '8373873873', region: 'us-west-2' }; + +new MyFirstStack(app, 'first-stack-us', { env: envUSA }); +new MyFirstStack(app, 'first-stack-eu', { env: envEU }); +``` + +------ +#### [ JavaScript ] + +``` +const envEU = { account: '2383838383', region: 'eu-west-1' }; +const envUSA = { account: '8373873873', region: 'us-west-2' }; + +new MyFirstStack(app, 'first-stack-us', { env: envUSA }); +new MyFirstStack(app, 'first-stack-eu', { env: envEU }); +``` + +------ +#### [ Python ] + +``` +env_EU = cdk.Environment(account="8373873873", region="eu-west-1") +env_USA = cdk.Environment(account="2383838383", region="us-west-2") + +MyFirstStack(app, "first-stack-us", env=env_USA) +MyFirstStack(app, "first-stack-eu", env=env_EU) +``` + +------ +#### [ Java ] + +``` +public class MyApp { + + // Helper method to build an environment + static Environment makeEnv(String account, String region) { + return Environment.builder() + .account(account) + .region(region) + .build(); + } + + public static void main(final String argv[]) { + App app = new App(); + + Environment envEU = makeEnv("8373873873", "eu-west-1"); + Environment envUSA = makeEnv("2383838383", "us-west-2"); + + new MyFirstStack(app, "first-stack-us", StackProps.builder() + .env(envUSA).build()); + new MyFirstStack(app, "first-stack-eu", StackProps.builder() + .env(envEU).build()); + + app.synth(); + } +} +``` + +------ +#### [ C\# ] + +``` +Amazon.CDK.Environment makeEnv(string account, string region) +{ + return new Amazon.CDK.Environment + { + Account = account, + Region = region + }; +} + +var envEU = makeEnv(account: "8373873873", region: "eu-west-1"); +var envUSA = makeEnv(account: "2383838383", region: "us-west-2"); + +new MyFirstStack(app, "first-stack-us", new StackProps { Env=envUSA }); +new MyFirstStack(app, "first-stack-eu", new StackProps { Env=envEU }); +``` + +------ + +When you hardcode the target account and Region as shown in the preceding example, the stack is always deployed to that specific account and Region\. To make the stack deployable to a different target, but to determine the target at synthesis time, your stack can use two environment variables provided by the AWS CDK CLI: `CDK_DEFAULT_ACCOUNT` and `CDK_DEFAULT_REGION`\. These variables are set based on the AWS profile specified using the \-\-profile option, or the default AWS profile if you don't specify one\. + +The following code fragment shows how to access the account and Region passed from the AWS CDK CLI in your stack\. + +------ +#### [ TypeScript ] + +Access environment variables via Node's `process` object\. + +**Note** + You need the `DefinitelyTyped` module to use `process` in TypeScript\. `cdk init` installs this module for you\. However, you should install this module manually if you are working with a project created before it was added, or if you didn't set up your project using `cdk init`\. + +``` +npm install @types/node +``` + +``` +new MyDevStack(app, 'dev', { + env: { + account: process.env.CDK_DEFAULT_ACCOUNT, + region: process.env.CDK_DEFAULT_REGION +}}); +``` + +------ +#### [ JavaScript ] + +Access environment variables via Node's `process` object\. + +``` +new MyDevStack(app, 'dev', { + env: { + account: process.env.CDK_DEFAULT_ACCOUNT, + region: process.env.CDK_DEFAULT_REGION +}}); +``` + +------ +#### [ Python ] + +Use the `os` module's `environ` dictionary to access environment variables\. + +``` +import os +MyDevStack(app, "dev", env=cdk.Environment( + account=os.environ["CDK_DEFAULT_ACCOUNT"], + region=os.environ["CDK_DEFAULT_REGION"])) +``` + +------ +#### [ Java ] + +Use `System.getenv()` to get the value of an environment variable\. + +``` +public class MyApp { + + // Helper method to build an environment + static Environment makeEnv(String account, String region) { + account = (account == null) ? System.getenv("CDK_DEFAULT_ACCOUNT") : account; + region = (region == null) ? System.getenv("CDK_DEFAULT_REGION") : region; + + return Environment.builder() + .account(account) + .region(region) + .build(); + } + + public static void main(final String argv[]) { + App app = new App(); + + Environment envEU = makeEnv(null, null); + Environment envUSA = makeEnv(null, null); + + new MyDevStack(app, "first-stack-us", StackProps.builder() + .env(envUSA).build()); + new MyDevStack(app, "first-stack-eu", StackProps.builder() + .env(envEU).build()); + + app.synth(); + } +} +``` + +------ +#### [ C\# ] + +Use `System.Environment.GetEnvironmentVariable()` to get the value of an environment variable\. + +``` +Amazon.CDK.Environment makeEnv(string account=null, string region=null) +{ + return new Amazon.CDK.Environment + { + Account = account ?? System.Environment.GetEnvironmentVariable("CDK_DEFAULT_ACCOUNT"), + Region = region ?? System.Environment.GetEnvironmentVariable("CDK_DEFAULT_REGION") + }; +} + +new MyDevStack(app, "dev", new StackProps { Env = makeEnv() }); +``` + +------ + +The AWS CDK distinguishes between not specifying the `env` property at all and specifying it using `CDK_DEFAULT_ACCOUNT` and `CDK_DEFAULT_REGION`\. The former implies that the stack should synthesize an environment\-agnostic template\. Constructs that are defined in such a stack cannot use any information about their environment\. For example, you can't write code like `if (stack.region === 'us-east-1')` or use framework facilities like [Vpc\.fromLookup](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.Vpc.html#static-fromwbrlookupscope-id-options) \(Python: `from_lookup`\), which need to query your AWS account\. These features don't work at all until you specify an explicit environment; to use them, you must specify `env`\. + +When you pass in your environment using `CDK_DEFAULT_ACCOUNT` and `CDK_DEFAULT_REGION`, the stack will be deployed in the account and Region determined by the AWS CDK CLI at the time of synthesis\. This lets environment\-dependent code work, but it also means that the synthesized template could be different based on the machine, user, or session that it's synthesized under\. This behavior is often acceptable or even desirable during development, but it would probably be an anti\-pattern for production use\. + +You can set `env` however you like, using any valid expression\. For example, you might write your stack to support two additional environment variables to let you override the account and Region at synthesis time\. We'll call these `CDK_DEPLOY_ACCOUNT` and `CDK_DEPLOY_REGION` here, but you could name them anything you like, as they are not set by the AWS CDK\. In the following stack's environment, alternative environment variables are used if they're set\. If they're not set, they fall back to the default environment provided by the AWS CDK\. + +------ +#### [ TypeScript ] + +``` +new MyDevStack(app, 'dev', { + env: { + account: process.env.CDK_DEPLOY_ACCOUNT || process.env.CDK_DEFAULT_ACCOUNT, + region: process.env.CDK_DEPLOY_REGION || process.env.CDK_DEFAULT_REGION +}}); +``` + +------ +#### [ JavaScript ] + +``` +new MyDevStack(app, 'dev', { + env: { + account: process.env.CDK_DEPLOY_ACCOUNT || process.env.CDK_DEFAULT_ACCOUNT, + region: process.env.CDK_DEPLOY_REGION || process.env.CDK_DEFAULT_REGION +}}); +``` + +------ +#### [ Python ] + +``` +MyDevStack(app, "dev", env=cdk.Environment( + account=os.environ.get("CDK_DEPLOY_ACCOUNT", os.environ["CDK_DEFAULT_ACCOUNT"]), + region=os.environ.get("CDK_DEPLOY_REGION", os.environ["CDK_DEFAULT_REGION"]) +``` + +------ +#### [ Java ] + +``` +public class MyApp { + + // Helper method to build an environment + static Environment makeEnv(String account, String region) { + account = (account == null) ? System.getenv("CDK_DEPLOY_ACCOUNT") : account; + region = (region == null) ? System.getenv("CDK_DEPLOY_REGION") : region; + account = (account == null) ? System.getenv("CDK_DEFAULT_ACCOUNT") : account; + region = (region == null) ? System.getenv("CDK_DEFAULT_REGION") : region; + + return Environment.builder() + .account(account) + .region(region) + .build(); + } + + public static void main(final String argv[]) { + App app = new App(); + + Environment envEU = makeEnv(null, null); + Environment envUSA = makeEnv(null, null); + + new MyDevStack(app, "first-stack-us", StackProps.builder() + .env(envUSA).build()); + new MyDevStack(app, "first-stack-eu", StackProps.builder() + .env(envEU).build()); + + app.synth(); + } +} +``` + +------ +#### [ C\# ] + +``` +Amazon.CDK.Environment makeEnv(string account=null, string region=null) +{ + return new Amazon.CDK.Environment + { + Account = account ?? + System.Environment.GetEnvironmentVariable("CDK_DEPLOY_ACCOUNT") ?? + System.Environment.GetEnvironmentVariable("CDK_DEFAULT_ACCOUNT"), + Region = region ?? + System.Environment.GetEnvironmentVariable("CDK_DEPLOY_REGION") ?? + System.Environment.GetEnvironmentVariable("CDK_DEFAULT_REGION") + }; +} + +new MyDevStack(app, "dev", new StackProps { Env = makeEnv() }); +``` + +------ + +With your stack's environment declared this way, you can write a short script or batch file like the following to set the variables from command line arguments, then call `cdk deploy`\. Any arguments beyond the first two are passed through to `cdk deploy` and can be used to specify command line options or stacks\. + +------ +#### [ macOS/Linux ] + +``` +#!/usr/bin/env bash +if [[ $# -ge 2 ]]; then + export CDK_DEPLOY_ACCOUNT=$1 + export CDK_DEPLOY_REGION=$2 + shift; shift + npx cdk deploy "$@" + exit $? +else + echo 1>&2 "Provide account and region as first two args." + echo 1>&2 "Additional args are passed through to cdk deploy." + exit 1 +fi +``` + +Save the script as `cdk-deploy-to.sh`, then execute `chmod +x cdk-deploy-to.sh` to make it executable\. + +------ +#### [ Windows ] + +``` +@findstr /B /V @ %~dpnx0 > %~dpn0.ps1 && powershell -ExecutionPolicy Bypass %~dpn0.ps1 %* +@exit /B %ERRORLEVEL% +if ($args.length -ge 2) { + $env:CDK_DEPLOY_ACCOUNT, $args = $args + $env:CDK_DEPLOY_REGION, $args = $args + npx cdk deploy $args + exit $lastExitCode +} else { + [console]::error.writeline("Provide account and region as first two args.") + [console]::error.writeline("Additional args are passed through to cdk deploy.") + exit 1 +} +``` + +The Windows version of the script uses PowerShell to provide the same functionality as the macOS/Linux version\. It also contains instructions to allow it to be run as a batch file so it can be easily invoked from a command line\. It should be saved as `cdk-deploy-to.bat`\. The file `cdk-deploy-to.ps1` will be created when the batch file is invoked\. + +------ + +Then you can write additional scripts that call the "deploy\-to" script to deploy to specific environments \(even multiple environments per script\): + +------ +#### [ macOS/Linux ] + +``` +#!/usr/bin/env bash +# cdk-deploy-to-test.sh +./cdk-deploy-to.sh 123457689 us-east-1 "$@" +``` + +------ +#### [ Windows ] + +``` +@echo off +rem cdk-deploy-to-test.bat +cdk-deploy-to 135792469 us-east-1 %* +``` + +------ + +When deploying to multiple environments, consider whether you want to continue deploying to other environments after a deployment fails\. The following example avoids deploying to the second production environment if the first doesn't succeed\. + +------ +#### [ macOS/Linux ] + +``` +#!/usr/bin/env bash +# cdk-deploy-to-prod.sh +./cdk-deploy-to.sh 135792468 us-west-1 "$@" || exit +./cdk-deploy-to.sh 246813579 eu-west-1 "$@" +``` + +------ +#### [ Windows ] + +``` +@echo off +rem cdk-deploy-to-prod.bat +cdk-deploy-to 135792469 us-west-1 %* || exit /B +cdk-deploy-to 245813579 eu-west-1 %* +``` + +------ + +Developers could still use the normal `cdk deploy` command to deploy to their own AWS environments for development\. \ No newline at end of file diff --git a/v2/examples.md b/v2/examples.md new file mode 100644 index 00000000..873931c2 --- /dev/null +++ b/v2/examples.md @@ -0,0 +1,5 @@ +# Examples<a name="examples"></a> + +This topic contains the following examples: ++ [Creating a serverless application using the AWS CDK](serverless_example.md) Creates a serverless application using Lambda, API Gateway, and Amazon S3\. ++ [Creating an AWS Fargate service using the AWS CDK](ecs_example.md) Creates an Amazon ECS Fargate service from an image on DockerHub\. \ No newline at end of file diff --git a/v2/featureflags.md b/v2/featureflags.md new file mode 100644 index 00000000..a8e1ef4e --- /dev/null +++ b/v2/featureflags.md @@ -0,0 +1,44 @@ +# Feature flags<a name="featureflags"></a> + +The AWS CDK uses *feature flags* to enable potentially breaking behaviors in a release\. Flags are stored as [Runtime context](context.md) values in `cdk.json` \(or `~/.cdk.json`\)\. They are not removed by the cdk context \-\-reset or cdk context \-\-clear commands\. + +Feature flags are disabled by default\. Existing projects that do not specify the flag will continue to work as before with later AWS CDK releases\. New projects created using cdk init include flags enabling all features available in the release that created the project\. Edit `cdk.json` to disable any flags for which you prefer the earlier behavior\. You can also add flags to enable new behaviors after upgrading the AWS CDK\. + +A list of all current feature flags can be found on the AWS CDK GitHub repository in [https://github.com/aws/aws-cdk/blob/main/packages/%40aws-cdk/cx-api/FEATURE_FLAGS.md](https://github.com/aws/aws-cdk/blob/main/packages/%40aws-cdk/cx-api/FEATURE_FLAGS.md)\. See the `CHANGELOG` in a given release for a description of any new feature flags added in that release\. + +## Reverting to v1 behavior<a name="featureflags_disabling"></a> + +In CDK v2, the defaults for some feature flags have been changed with respect to v1\. You can set these back to `false` to revert to specific AWS CDK v1 behavior\. Use the `cdk diff` command to inspect the changes to your synthesized template to see if any of these flags are needed\. + +`@aws-cdk/core:newStyleStackSynthesis` +Use the new stack synthesis method, which assumes bootstrap resources with well\-known names\. Requires [modern bootstrapping](bootstrapping.md), but in turn allows CI/CD via [CDK Pipelines](cdk_pipeline.md) and cross\-account deployments out of the box\. + +`@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId` +If your application uses multiple Amazon API Gateway API keys and associates them to usage plans\. + +`@aws-cdk/aws-rds:lowercaseDbIdentifier` +If your application uses Amazon RDS database instance or database clusters, and explicitly specifies the identifier for these\. + +`@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021` + If your application uses the TLS\_V1\_2\_2019 security policy with Amazon CloudFront distributions\. CDK v2 uses security policy TLSv1\.2\_2021 by default\. + +`@aws-cdk/core:stackRelativeExports` +If your application uses multiple stacks and you refer to resources from one stack in another, this determines whether absolute or relative path is used to construct AWS CloudFormation exports\. + +`@aws-cdk/aws-lambda:recognizeVersionProps` +If set to `false`, the CDK includes metadata when detecting whether a Lambda function has changed\. This can cause deployment failures when only the metadata has changed, since duplicate versions are not allowed\. There is no need to revert this flag if you've made at least one change to all Lambda Functions in your application\. + +The syntax for reverting these flags in `cdk.json` is shown here\. + +``` +{ + "context": { + "@aws-cdk/core:newStyleStackSynthesis": false, + "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": false, + "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": false, + "@aws-cdk/aws-rds:lowercaseDbIdentifier": false, + "@aws-cdk/core:stackRelativeExports": false, + "@aws-cdk/aws-lambda:recognizeVersionProps": false + } +} +``` \ No newline at end of file diff --git a/v2/get_cfn_param.md b/v2/get_cfn_param.md new file mode 100644 index 00000000..12e07b27 --- /dev/null +++ b/v2/get_cfn_param.md @@ -0,0 +1,5 @@ +# Use an AWS CloudFormation value<a name="get_cfn_param"></a> + +See [Parameters](parameters.md) for information about using AWS CloudFormation parameters with the AWS CDK\. + +To get a reference to a resource in an existing AWS CloudFormation template, see [Import or migrate an existing AWS CloudFormation template](use_cfn_template.md)\. \ No newline at end of file diff --git a/v2/get_context_var.md b/v2/get_context_var.md new file mode 100644 index 00000000..94faa194 --- /dev/null +++ b/v2/get_context_var.md @@ -0,0 +1,104 @@ +# Get a value from a context variable<a name="get_context_var"></a> + +You can specify a context variable either as part of an AWS CDK CLI command, or in `cdk.json`\. + +To create a command line context variable, use the **\-\-context** \(**\-c**\) option, as shown in the following example\. + +``` +cdk synth -c bucket_name=mygroovybucket +``` + +To specify the same context variable and value in the `cdk.json` file, use the following code\. + +``` +{ + "context": { + "bucket_name": "myotherbucket" + } +} +``` + +To get the value of a context variable in your app, use the `TryGetContext` method in the context of a construct\. \(That is, when `this`, or `self` in Python, is an instance of some construct\.\) The example gets the context value **bucket\_name**\. If the requested value is not defined, `TryGetContext` returns `undefined` \(`None` in Python; `null` in Java and C\#; `nil` in Go\) rather than raising an exception\. + +------ +#### [ TypeScript ] + +``` +const bucket_name = this.node.tryGetContext('bucket_name'); +``` + +------ +#### [ JavaScript ] + +``` +const bucket_name = this.node.tryGetContext('bucket_name'); +``` + +------ +#### [ Python ] + +``` +bucket_name = self.node.try_get_context("bucket_name") +``` + +------ +#### [ Java ] + +``` +String bucketName = (String)this.getNode().tryGetContext("bucket_name"); +``` + +------ +#### [ C\# ] + +``` +var bucketName = this.Node.TryGetContext("bucket_name"); +``` + +------ + +Outside the context of a construct, you can access the context variable from the app object, like this\. + +------ +#### [ TypeScript ] + +``` +const app = new cdk.App(); +const bucket_name = app.node.tryGetContext('bucket_name') +``` + +------ +#### [ JavaScript ] + +``` +const app = new cdk.App(); +const bucket_name = app.node.tryGetContext('bucket_name'); +``` + +------ +#### [ Python ] + +``` +app = cdk.App() +bucket_name = app.node.try_get_context("bucket_name") +``` + +------ +#### [ Java ] + +``` +App app = App(); +String bucketName = (String)app.getNode().tryGetContext("bucket_name"); +``` + +------ +#### [ C\# ] + +``` +app = App(); +var bucketName = app.Node.TryGetContext("bucket_name"); +``` + +------ + +For more details on working with context variables, see [Runtime context](context.md)\. \ No newline at end of file diff --git a/v2/get_env_var.md b/v2/get_env_var.md new file mode 100644 index 00000000..7d4439eb --- /dev/null +++ b/v2/get_env_var.md @@ -0,0 +1,68 @@ +# Get a value from an environment variable<a name="get_env_var"></a> + +To get the value of an environment variable, use code like the following\. This code gets the value of the environment variable `MYBUCKET`\. + +------ +#### [ TypeScript ] + +``` +// Sets bucket_name to undefined if environment variable not set +var bucket_name = process.env.MYBUCKET; + +// Sets bucket_name to a default if env var doesn't exist +var bucket_name = process.env.MYBUCKET || "DefaultName"; +``` + +------ +#### [ JavaScript ] + +``` +// Sets bucket_name to undefined if environment variable not set +var bucket_name = process.env.MYBUCKET; + +// Sets bucket_name to a default if env var doesn't exist +var bucket_name = process.env.MYBUCKET || "DefaultName"; +``` + +------ +#### [ Python ] + +``` +import os + +# Raises KeyError if environment variable doesn't exist +bucket_name = os.environ["MYBUCKET"] + +# Sets bucket_name to None if environment variable doesn't exist +bucket_name = os.getenv("MYBUCKET") + +# Sets bucket_name to a default if env var doesn't exist +bucket_name = os.getenv("MYBUCKET", "DefaultName") +``` + +------ +#### [ Java ] + +``` +// Sets bucketName to null if environment variable doesn't exist +String bucketName = System.getenv("MYBUCKET"); + +// Sets bucketName to a default if env var doesn't exist +String bucketName = System.getenv("MYBUCKET"); +if (bucketName == null) bucketName = "DefaultName"; +``` + +------ +#### [ C\# ] + +``` +using System; + +// Sets bucket name to null if environment variable doesn't exist +string bucketName = Environment.GetEnvironmentVariable("MYBUCKET"); + +// Sets bucket_name to a default if env var doesn't exist +string bucketName = Environment.GetEnvironmentVariable("MYBUCKET") ?? "DefaultName"; +``` + +------ \ No newline at end of file diff --git a/v2/guide/develop/get-sm-val.adoc b/v2/get_secrets_manager_value.md similarity index 64% rename from v2/guide/develop/get-sm-val.adoc rename to v2/get_secrets_manager_value.md index 64f6be61..2a6ba746 100644 --- a/v2/guide/develop/get-sm-val.adoc +++ b/v2/get_secrets_manager_value.md @@ -1,21 +1,11 @@ -include::../attributes.txt[] +# Get a value from AWS Secrets Manager<a name="get_secrets_manager_value"></a> -// Attributes -[.topic] -[#get-secrets-manager-value] -= Get a value from {aws} Secrets Manager -:info_titleabbrev: Get Secrets Manager value +To use values from AWS Secrets Manager in your AWS CDK app, use the [fromSecretAttributes\(\)](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_secretsmanager.Secret.html#static-fromwbrsecretwbrattributesscope-id-attrs) method\. It represents a value that is retrieved from Secrets Manager and used at AWS CloudFormation deployment time\. -// Content start +------ +#### [ TypeScript ] -To use values from {aws} Secrets Manager in your {aws} CDK app, use the link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_secretsmanager.Secret.html#static-fromwbrsecretwbrattributesscope-id-attrs[`fromSecretAttributes()`] method. It represents a value that is retrieved from Secrets Manager and used at {aws} CloudFormation deployment time. The following is an example: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +``` import * as sm from "aws-cdk-lib/aws-secretsmanager"; export class SecretsManagerStack extends cdk.Stack { @@ -27,16 +17,13 @@ export class SecretsManagerStack extends cdk.Stack { "arn:aws:secretsmanager:<region>:<account-id-number>:secret:<secret-name>-<random-6-characters>" // If the secret is encrypted using a KMS-hosted CMK, either import or reference that key: // encryptionKey: ... - } - ); - } -} ----- + }); +``` + +------ +#### [ JavaScript ] -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +``` const sm = require("aws-cdk-lib/aws-secretsmanager"); class SecretsManagerStack extends cdk.Stack { @@ -53,12 +40,12 @@ class SecretsManagerStack extends cdk.Stack { } module.exports = { SecretsManagerStack } ----- +``` + +------ +#### [ Python ] -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- +``` import aws_cdk.aws_secretsmanager as sm class SecretsManagerStack(cdk.Stack): @@ -70,12 +57,12 @@ class SecretsManagerStack(cdk.Stack): # If the secret is encrypted using a KMS-hosted CMK, either import or reference that key: # encryption_key=.... ) ----- +``` -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- +------ +#### [ Java ] + +``` import software.amazon.awscdk.services.secretsmanager.Secret; import software.amazon.awscdk.services.secretsmanager.SecretAttributes; @@ -94,13 +81,13 @@ public class SecretsManagerStack extends Stack { .build()); } } ----- +``` + +------ +#### [ C\# ] -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -using Amazon.CDK.{aws}.SecretsManager; +``` +using Amazon.CDK.AWS.SecretsManager; public class SecretsManagerStack : Stack { @@ -112,22 +99,16 @@ public class SecretsManagerStack : Stack // encryptionKey = ..., }); } -} ----- -==== +``` -[TIP] -==== +------ -Use the {aws} CLI link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_secretsmanager.Secret.html[`create-secret`] CLI command to create a secret from the command line, such as when testing: +**Tip** +Use the [create\-secret](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_secretsmanager.Secret.html) CLI command to create a secret from the command line, such as when testing: -[source,none,subs="verbatim,attributes"] ----- +``` aws secretsmanager create-secret --name ImportedSecret --secret-string mygroovybucket ----- - -The command returns an ARN that you can use with the preceding example. - -==== +``` +The command returns an ARN that you can use with the preceding example\. -Once you have created a `Secret` instance, you can get the secret's value from the instance's `secretValue` attribute. The value is represented by a link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.SecretValue.html[`SecretValue`] instance, a special type of xref:tokens[Tokens and the {aws} CDK]. Because it's a token, it has meaning only after resolution. Your CDK app does not need to access its actual value. Instead, the app can pass the `SecretValue` instance (or its string or numeric representation) to whatever CDK method needs the value. \ No newline at end of file +Once you have created a `Secret` instance, you can get the secret's value from the instance's `secretValue` attribute\. The value is represented by a `[SecretValue](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.SecretValue.html)` instance, a special type of [Tokens](tokens.md)\. Because it's a token, it has meaning only after resolution\. Your CDK app does not need to access its actual value\. Instead, the app can pass the `SecretValue` instance \(or its string or numeric representation\) to whatever CDK method needs the value\. \ No newline at end of file diff --git a/v2/get_ssm_value.md b/v2/get_ssm_value.md new file mode 100644 index 00000000..c7acc715 --- /dev/null +++ b/v2/get_ssm_value.md @@ -0,0 +1,175 @@ +# Get a value from the Systems Manager Parameter Store<a name="get_ssm_value"></a> + +The AWS CDK can retrieve the value of AWS Systems Manager Parameter Store attributes\. During synthesis, the AWS CDK produces a [token](tokens.md) that is resolved by AWS CloudFormation during deployment\. + +The AWS CDK supports retrieving both plain and secure values\. You may request a specific version of either kind of value\. For plain values only, you may omit the version from your request to receive the latest version\. You must always specify the version when requesting the value of a secure attribute\. + +**Note** +This topic shows how to read attributes from the AWS Systems Manager Parameter Store\. You can also read secrets from the AWS Secrets Manager \(see [Get a value from AWS Secrets Manager](get_secrets_manager_value.md)\)\. + +## Reading Systems Manager values at deployment time<a name="ssm_read_at_deploy"></a> + +To read values from the Systems Manager Parameter Store, use the [valueForStringParameter](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ssm.StringParameter.html#static-valuewbrforwbrstringwbrparameterscope-parametername-version) and [valueForSecureStringParameter](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ssm.StringParameter.html#static-valuewbrforwbrsecurewbrstringwbrparameterscope-parametername-version) methods\. Choose a method based on whether the attribute you want is a plain string or a secure string value\. These methods return [tokens](tokens.md), not the actual value\. The value is resolved by AWS CloudFormation during deployment\. + +A [limited number of AWS services](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/dynamic-references.html#template-parameters-dynamic-patterns-resources) currently support this feature\. + +------ +#### [ TypeScript ] + +``` +import * as ssm from 'aws-cdk-lib/aws-ssm'; + +// Get latest version or specified version of plain string attribute +const latestStringToken = ssm.StringParameter.valueForStringParameter( + this, 'my-plain-parameter-name'); // latest version +const versionOfStringToken = ssm.StringParameter.valueForStringParameter( + this, 'my-plain-parameter-name', 1); // version 1 + +// Get specified version of secure string attribute +const secureStringToken = ssm.StringParameter.valueForSecureStringParameter( + this, 'my-secure-parameter-name', 1); // must specify version +``` + +------ +#### [ JavaScript ] + +``` +const ssm = require('aws-cdk-lib/aws-ssm'); + +// Get latest version or specified version of plain string attribute +const latestStringToken = ssm.StringParameter.valueForStringParameter( + this, 'my-plain-parameter-name'); // latest version +const versionOfStringToken = ssm.StringParameter.valueForStringParameter( + this, 'my-plain-parameter-name', 1); // version 1 + +// Get specified version of secure string attribute +const secureStringToken = ssm.StringParameter.valueForSecureStringParameter( + this, 'my-secure-parameter-name', 1); // must specify version +``` + +------ +#### [ Python ] + +``` +import aws_cdk.aws_ssm as ssm + +# Get latest version or specified version of plain string attribute +latest_string_token = ssm.StringParameter.value_for_string_parameter( + self, "my-plain-parameter-name") +latest_string_token = ssm.StringParameter.value_for_string_parameter( + self, "my-plain-parameter-name", 1) + +# Get specified version of secure string attribute +secure_string_token = ssm.StringParameter.value_for_secure_string_parameter( + self, "my-secure-parameter-name", 1) # must specify version +``` + +------ +#### [ Java ] + +``` +import software.amazon.awscdk.services.ssm.StringParameter; + +//Get latest version or specified version of plain string attribute +String latestStringToken = StringParameter.valueForStringParameter( + this, "my-plain-parameter-name"); // latest version +String versionOfStringToken = StringParameter.valueForStringParameter( + this, "my-plain-parameter-name", 1); // version 1 + +//Get specified version of secure string attribute +String secureStringToken = StringParameter.valueForSecureStringParameter( + this, "my-secure-parameter-name", 1); // must specify version +``` + +------ +#### [ C\# ] + +``` +using Amazon.CDK.AWS.SSM; + +// Get latest version or specified version of plain string attribute +var latestStringToken = StringParameter.ValueForStringParameter( + this, "my-plain-parameter-name"); // latest version +var versionOfStringToken = StringParameter.ValueForStringParameter( + this, "my-plain-parameter-name", 1); // version 1 + +// Get specified version of secure string attribute +var secureStringToken = StringParameter.ValueForSecureStringParameter( + this, "my-secure-parameter-name", 1); // must specify version +``` + +------ + +## Reading Systems Manager values at synthesis time<a name="ssm_read_at_synth"></a> + +It is sometimes useful to "bake in" a parameter at synthesis time\. This way, the resulting AWS CloudFormation template always uses the same value, instead of resolving the value during deployment\. + +To read a value from the Systems Manager Parameter Store at synthesis time, use the [valueFromLookup](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ssm.StringParameter.html#static-valuewbrfromwbrlookupscope-parametername) method \(Python: `value_from_lookup`\)\. This method returns the actual value of the parameter as a [Runtime context](context.md) value\. If the value is not already cached in `cdk.json` or passed on the command line, it is retrieved from the current AWS account\. For this reason, the stack *must* be synthesized with explicit account and Region information\. + +Only plain Systems Manager strings may be retrieved, not secure strings\. It is not possible to request a specific version; the latest version is always returned\. + +**Important** +The retrieved value will end up in your synthesized AWS CloudFormation template\. This might be a security risk, depending on who has access to your AWS CloudFormation templates and what kind of value it is\. Generally, don't use this feature for passwords, keys, or other values you want to keep private\. + +------ +#### [ TypeScript ] + +``` +import * as ssm from 'aws-cdk-lib/aws-ssm'; + +const stringValue = ssm.StringParameter.valueFromLookup(this, 'my-plain-parameter-name'); +``` + +------ +#### [ JavaScript ] + +``` +const ssm = require('aws-cdk-lib/aws-ssm'); + +const stringValue = ssm.StringParameter.valueFromLookup(this, 'my-plain-parameter-name'); +``` + +------ +#### [ Python ] + +``` +import aws_cdk.aws_ssm as ssm + +string_value = ssm.StringParameter.value_from_lookup(self, "my-plain-parameter-name") +``` + +------ +#### [ Java ] + +``` +import software.amazon.awscdk.services.ssm.StringParameter; + +String stringValue = StringParameter.valueFromLookup(this, "my-plain-parameter-name"); +``` + +------ +#### [ C\# ] + +``` +using Amazon.CDK.AWS.SSM; + +var stringValue = StringParameter.ValueFromLookup(this, "my-plain-parameter-name"); +``` + +------ + +## Writing values to Systems Manager<a name="ssm_write"></a> + +You can use the AWS CLI, the AWS Management Console, or an AWS SDK to set Systems Manager parameter values\. The following examples use the [ssm put\-parameter](https://docs.aws.amazon.com/cli/latest/reference/ssm/put-parameter.html) CLI command\. + +``` +aws ssm put-parameter --name "parameter-name" --type "String" --value "parameter-value" +aws ssm put-parameter --name "secure-parameter-name" --type "SecureString" --value "secure-parameter-value" +``` + +When updating an SSM value that already exists, also include the `--overwrite` option\. + +``` +aws ssm put-parameter --overwrite --name "parameter-name" --type "String" --value "parameter-value" +aws ssm put-parameter --overwrite --name "secure-parameter-name" --type "SecureString" --value "secure-parameter-value" +``` \ No newline at end of file diff --git a/v2/getting_started.md b/v2/getting_started.md new file mode 100644 index 00000000..dde955ea --- /dev/null +++ b/v2/getting_started.md @@ -0,0 +1,355 @@ +# Getting started with the AWS CDK<a name="getting_started"></a> + +This topic introduces you to important AWS CDK concepts and describes how to install and configure the AWS CDK\. When you're done, you'll be ready to create [your first AWS CDK app](hello_world.md)\. + +## Your background<a name="getting_started_background"></a> + +The AWS Cloud Development Kit \(AWS CDK\) lets you define your cloud infrastructure as code in one of its supported programming languages\. It is intended for moderately to highly experienced AWS users\. + +Ideally, you already have experience with popular AWS services, particularly [AWS Identity and Access Management](https://aws.amazon.com/iam/) \(IAM\)\. You might already have AWS credentials on your workstation for use with an AWS SDK or the AWS CLI\. You might also have experience working with AWS resources programmatically\. + +Familiarity with [AWS CloudFormation](https://aws.amazon.com/cloudformation/) is also useful, because the output of an AWS CDK program is an AWS CloudFormation template\. + +Finally, you should be proficient in the programming language you intend to use with the AWS CDK\. + +## Key concepts<a name="getting_started_concepts"></a> + +The AWS CDK is designed around a handful of important concepts\. We will introduce a few of these here briefly\. Follow the links to learn more, or see the Concepts topics in this guide's Table of Contents\. + +An AWS CDK [app](apps.md) is an application written in TypeScript, JavaScript, Python, Java, C\# or Go that uses the AWS CDK to define AWS infrastructure\. An app defines one or more [stacks](stacks.md)\. Stacks \(equivalent to AWS CloudFormation stacks\) contain [constructs](constructs.md)\. Each construct defines one or more concrete AWS resources, such as Amazon S3 buckets, Lambda functions, or Amazon DynamoDB tables\. + +Constructs \(and also stacks and apps\) are represented as classes \(types\) in your programming language of choice\. You instantiate constructs within a stack to declare them to AWS, and connect them to each other using well\-defined interfaces\. + +The AWS CDK includes the CDK Toolkit \(also called the CLI\), a command line tool for working with your AWS CDK apps and stacks\. Among other functions, the Toolkit provides the ability to do the following: ++ Convert one or more AWS CDK stacks to AWS CloudFormation templates and related assets \(a process called *synthesis*\) ++ Deploy your stacks to an AWS account and Region + +The AWS CDK includes a library of AWS constructs called the AWS Construct Library, organized into various modules\. The library contains constructs for each AWS service\. The main CDK package is called `aws-cdk-lib`, and it contains the majority of the AWS Construct Library\. It also contains base classes like `Stack` and `App` that are used in most CDK applications\. + +The actual package name of the main CDK package varies by language\. + +------ +#### [ TypeScript ] + +| Install | `npm install aws-cdk-lib` | +| --- |--- | +| Import | `import * as cdk from 'aws-cdk-lib';` | +| --- |--- | + +------ +#### [ JavaScript ] + +| Install | `npm install aws-cdk-lib` | +| --- |--- | +| Import | `const cdk = require('aws-cdk-lib');` | +| --- |--- | + +------ +#### [ Python ] + +| Install | python \-m pip install aws\-cdk\-lib | +| --- |--- | +| Import | `import aws_cdk as cdk` | +| --- |--- | + +------ +#### [ Java ] + +| Add to `pom.xml` | Group `software.amazon.awscdk`; artifact `aws-cdk-lib` | +| --- |--- | +| Import | `import software.amazon.awscdk.App;` \(for example\) | +| --- |--- | + +------ +#### [ C\# ] + +| Install | dotnet add package Amazon\.CDK\.Lib | +| --- |--- | +| Import | `using Amazon.CDK;` | +| --- |--- | + +------ +#### [ Go ] + +| Install | go get github\.com/aws/aws\-cdk\-go/awscdk/v2 | +| --- |--- | +| Import | + +``` +import ( + "github.com/aws/aws-cdk-go/awscdk/v2" +) +``` | +| --- |--- | + +------ + +**Note** +If you created a CDK project using cdk init, you don't need to manually install `aws-cdk-lib`\. + +Constructs come in three fundamental flavors: ++ **AWS CloudFormation\-only** or L1 \(short for "layer 1"\)\. These constructs correspond directly to resource types defined by AWS CloudFormation\. In fact, these constructs are automatically generated from the AWS CloudFormation specification\. Therefore, when a new AWS service is launched, the AWS CDK supports it a short time after AWS CloudFormation does\. + + AWS CloudFormation resources always have names that begin with `Cfn`\. For example, for the Amazon S3 service, `CfnBucket` is the L1 construct for an Amazon S3 bucket\. + + All L1 resources are in `aws-cdk-lib`\. ++ **Curated** or L2\. These constructs are carefully developed by the AWS CDK team to address specific use cases and simplify infrastructure development\. For the most part, they encapsulate L1 resources, providing sensible defaults and best practice security policies\. For example, `Bucket` is the L2 construct for an Amazon S3 bucket\. + + Libraries may also define supporting resources needed by the primary L2 resource\. Some services have more than one L2 namespace in the Construct Library for organizational purposes\. + + `aws-cdk-lib` contains L2 constructs that are designated stable, i\.e\., ready for production use\. If a service's L2 support is still under development, its constructs are designated experimental and provided in a separate module\. ++ **Patterns** or L3\. Patterns declare multiple resources to create entire AWS architectures for particular use cases\. All the plumbing is already hooked up, and configuration is boiled down to a few important parameters\. + + As with L2 constructs, L3 constructs that are ready for production use \(stable\) are included in `aws-cdk-lib`, while those still under development are in separate modules\. + +Finally, the `constructs` package contains the `Construct` base class\. It's in its own package because it's used by other construct\-based tools in addition to the AWS CDK, including CDK for Terraform and CDK for Kubernetes\. + +Numerous third parties have also published constructs compatible with the AWS CDK\. Visit [Construct Hub](https://constructs.dev/search?q=&cdk=aws-cdk&cdkver=2&offset=0) to explore the AWS CDK construct partner ecosystem\. + +## Supported programming languages<a name="getting_started_languages"></a> + +The AWS CDK has first\-class support for TypeScript, JavaScript, Python, Java, C\#, and Go\. Other JVM and \.NET CLR languages may also be used, at least in theory\. However, we are unable to offer support for them at this time\. + +To facilitate supporting so many languages, the AWS CDK is developed in one language \(TypeScript\)\. Language bindings are generated for the other languages through the use of a tool called [JSII](https://github.com/aws/jsii)\. + +We have taken pains to make AWS CDK app development in each language follow that language's usual conventions\. This way, writing AWS CDK apps feels natural, not like writing TypeScript in Python, for example\. Take a look at the following examples: + +------ +#### [ TypeScript ] + +``` +const bucket = new s3.Bucket(this, 'MyBucket', { + bucketName: 'my-bucket', + versioned: true, + websiteRedirect: {hostName: 'aws.amazon.com'}}); +``` + +------ +#### [ JavaScript ] + +``` +const bucket = new s3.Bucket(this, 'MyBucket', { + bucketName: 'my-bucket', + versioned: true, + websiteRedirect: {hostName: 'aws.amazon.com'}}); +``` + +------ +#### [ Python ] + +``` +bucket = s3.Bucket("MyBucket", bucket_name="my-bucket", versioned=True, + website_redirect=s3.RedirectTarget(host_name="aws.amazon.com")) +``` + +------ +#### [ Java ] + +``` +Bucket bucket = Bucket.Builder.create(self, "MyBucket") + .bucketName("my-bucket") + .versioned(true) + .websiteRedirect(new RedirectTarget.Builder() + .hostName("aws.amazon.com").build()) + .build(); +``` + +------ +#### [ C\# ] + +``` +var bucket = new Bucket(this, "MyBucket", new BucketProps { + BucketName = "my-bucket", + Versioned = true, + WebsiteRedirect = new RedirectTarget { + HostName = "aws.amazon.com" + }}); +``` + +------ +#### [ Go ] + +``` +bucket := awss3.NewBucket(scope, jsii.String("MyBucket"), &awss3.BucketProps { + BucketName: jsii.String("my-bucket"), + Versioned: jsii.Bool(true), + WebsiteRedirect: &awss3.RedirectTarget { + HostName: jsii.String("aws.amazon.com"), + }, +}) +``` + +------ + +**Note** +These code snippets are intended for illustration only\. They are incomplete and won't run as they are\. + +The AWS Construct Library is distributed using each language's standard package management tools, including NPM, PyPi, Maven, and NuGet\. There's even a version of the [AWS CDK API Reference](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-construct-library.html) for each language\. + +To help you use the AWS CDK in your favorite language, this guide includes the following topics for supported languages: ++ [Working with the AWS CDK in TypeScript](work-with-cdk-typescript.md) ++ [Working with the AWS CDK in JavaScript](work-with-cdk-javascript.md) ++ [Working with the AWS CDK in Python](work-with-cdk-python.md) ++ [Working with the AWS CDK in Java](work-with-cdk-java.md) ++ [Working with the AWS CDK in C\#](work-with-cdk-csharp.md) ++ [Working with the AWS CDK in Go](work-with-cdk-go.md) + +TypeScript was the first language supported by the AWS CDK, and much AWS CDK example code is written in TypeScript\. This guide includes a topic specifically to show how to adapt TypeScript AWS CDK code for use with the other supported languages\. For more information, see [Translating TypeScript AWS CDK code to other languages](multiple_languages.md)\. + +## Prerequisites<a name="getting_started_prerequisites"></a> + +Here's what you need to install to use the AWS CDK\. + +All AWS CDK developers, even those working in Python, Java, or C\#, need [Node\.js](https://nodejs.org/en/download/) 10\.13\.0 or later\. All supported languages use the same backend, which runs on Node\.js\. We recommend a version in [active long\-term support](https://nodejs.org/en/about/releases/)\. Your organization may have a different recommendation\. + +**Important** +Node\.js versions 13\.0\.0 through 13\.6\.0 are not compatible with the AWS CDK due to compatibility issues with its dependencies\. + +You must configure your workstation with your credentials and an AWS Region, if you have not already done so\. If you have the AWS CLI installed, we recommend running the following command: + +``` +aws configure +``` + +Provide your AWS access key ID, secret access key, and default Region when prompted\. + +You can also manually create or edit the `~/.aws/config` and `~/.aws/credentials` \(macOS/Linux\) or `%USERPROFILE%\.aws\config` and `%USERPROFILE%\.aws\credentials` \(Windows\) files to contain credentials and a default Region\. Use the following format\. ++ In `~/.aws/config` or `%USERPROFILE%\.aws\config` + + ``` + [default] + region=us-west-2 + ``` ++ In `~/.aws/credentials` or `%USERPROFILE%\.aws\credentials` + + ``` + [default] + aws_access_key_id=AKIAI44QH8DHBEXAMPLE + aws_secret_access_key=je7MtGbClwBF/2Zp9Utk/h3yCo8nvbEXAMPLEKEY + ``` + +**Note** +Although the AWS CDK uses credentials from the same configuration files as other AWS tools and SDKs, including the [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html), it might behave somewhat differently from these tools\. In particular, if you use a named profile from the `credentials` file, the `config` must have a profile of the same name specifying the Region\. The AWS CDK does not fall back to reading the Region from the `[default]` section in `config`\. Also, do not use a profile named "default" \(e\.g\. `[profile default]`\)\. See [Setting credentials](https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/setting-credentials.html) for complete details on setting up credentials for the AWS SDK for JavaScript, which the AWS CDK uses under the hood\. +The AWS CDK natively supports AWS IAM Identity Center \(successor to AWS Single Sign\-On\)\. To use IAM Identity Center with the CDK, first create a profile using aws configure sso\. Then log in using aws sso login\. Finally, specify this profile when issuing cdk commands using the \-\-profile option or the `AWS_PROFILE` environment variable\. + +Alternatively, you can set the environment variables `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, and `AWS_DEFAULT_REGION` to appropriate values\. + +**Important** +Using your AWS root account is the fastest way to get started with the AWS CDK\. Once you've worked through a few tutorials, however, we strongly recommend against using your root account for day\-to\-day tasks\. Instead, create a user in IAM and use its credentials with the CDK\. Best practices are to change this account's access key regularly and to use a least\-privileges role\. The AWS CDK includes roles that your account should have permission to assume, for example using the policy here\. + +``` +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "sts:AssumeRole" + ], + "Resource": [ + "arn:aws:iam::*:role/cdk-*" + ] + } + ] +} +``` + +Other prerequisites depend on the language in which you develop AWS CDK applications and are as follows\. + +------ +#### [ TypeScript ] ++ TypeScript 3\.8 or later \(`npm -g install typescript`\) + +------ +#### [ JavaScript ] + +No additional requirements + +------ +#### [ Python ] ++ Python 3\.7 or later including `pip` and `virtualenv` + +------ +#### [ Java ] ++ Java Development Kit \(JDK\) 8 \(a\.k\.a\. 1\.8\) or later ++ Apache Maven 3\.5 or later + +Java IDE recommended \(we use Eclipse in some examples in this guide\)\. IDE must be able to import Maven projects\. Check to make sure that your project is set to use Java 1\.8\. Set the JAVA\_HOME environment variable to the path where you have installed the JDK\. + +------ +#### [ C\# ] + +\.NET Core 3\.1 or later, or \.NET 6\.0 or later\. + +Visual Studio 2019 \(any edition\) or Visual Studio Code recommended\. + +------ +#### [ Go ] + +Go 1\.1\.8 or later\. + +------ + +**Note** +Third\-party language deprecation: each language version is only supported until its EOL \(End Of Life\) shared by the vendor or community and is subject to change with prior notice\. + +## Install the AWS CDK<a name="getting_started_install"></a> + +Install the AWS CDK Toolkit globally using the following Node Package Manager command\. + +``` +npm install -g aws-cdk +``` + +Run the following command to verify correct installation and print the version number of the AWS CDK\. + +``` +cdk --version +``` + +**Note** +CDK Toolkit v2 works with your existing CDK v1 projects\. However, it can't initialize new CDK v1 projects\. See [New prerequisites](migrating-v2.md#migrating-v2-prerequisites) if you need to be able to do that\. + +## Bootstrapping<a name="getting_started_bootstrap"></a> + +Deploying stacks with the AWS CDK requires dedicated Amazon S3 buckets and other containers to be available to AWS CloudFormation during deployment\. Creating these is called [bootstrapping](bootstrapping.md)\. To bootstrap, issue: + +``` +cdk bootstrap aws://ACCOUNT-NUMBER/REGION +``` + +**Tip** +If you don't have your AWS account number handy, you can get it from the AWS Management Console\. Or, if you have the AWS CLI installed, the following command displays your default account information, including the account number\. + +``` +aws sts get-caller-identity +``` +If you created named profiles in your local AWS configuration, you can use the `--profile` option to display the account information for a specific profile\. The following example shows how to display account information for the *prod* profile\. + +``` +aws sts get-caller-identity --profile prod +``` +To display the default Region, use `aws configure get`\. + +``` +aws configure get region +aws configure get region --profile prod +``` + +## AWS CDK tools<a name="getting_started_tools"></a> + +The AWS CDK Toolkit, also known as the Command Line Interface \(CLI\), is the main tool you use to interact with your AWS CDK app\. It executes your code and produces and deploys the AWS CloudFormation templates it generates\. It also has deployment, diff, deletion, and troubleshooting capabilities\. For more information, see cdk \-\-help or [AWS CDK Toolkit \(`cdk` command\)](cli.md)\. + +The [AWS Toolkit for Visual Studio Code](https://aws.amazon.com/visualstudiocode/) is an open source plug\-in for Visual Studio Code that helps you create, debug, and deploy applications on AWS\. The toolkit provides an integrated experience for developing AWS CDK applications\. It includes the AWS CDK Explorer feature to list your AWS CDK projects and browse the various components of the CDK application\. [Install the plug\-in](https://docs.aws.amazon.com/toolkit-for-vscode/latest/userguide/setup-toolkit.html) and learn more about [using the AWS CDK Explorer](https://docs.aws.amazon.com/toolkit-for-vscode/latest/userguide/cdk-explorer.html)\. + +## Next steps<a name="getting_started_next_steps"></a> + +Where do you go now that you've dipped your toes in the AWS CDK? ++ Come on in; the water's fine\! Build [your first AWS CDK app](hello_world.md)\. ++ Try the [CDK Workshop](https://cdkworkshop.com/) for a more in\-depth tour involving a more complex project\. ++ See the [API reference](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-construct-library.html) to begin exploring the provided constructs available for your favorite AWS services\. ++ Visit the [Construct Hub](https://constructs.dev/search?q=&cdk=aws-cdk&cdkver=2&sort=downloadsDesc&offset=0) to find constructs from the CDK community and also from AWS\. ++ Dig deeper into concepts like [Environments](environments.md), [Assets](assets.md), [Bootstrapping](bootstrapping.md), [Permissions](permissions.md), [Runtime context](context.md), [Parameters](parameters.md), and [Abstractions and escape hatches](cfn_layer.md)\. ++ Explore [Examples](https://github.com/aws-samples/aws-cdk-examples) of using the AWS CDK\. + +The AWS CDK is an open\-source project\. Want to [contribute](https://github.com/aws/aws-cdk)? \ No newline at end of file diff --git a/v2/guide/CDK_Project.xpr b/v2/guide/CDK_Project.xpr deleted file mode 100644 index 129faa06..00000000 --- a/v2/guide/CDK_Project.xpr +++ /dev/null @@ -1,40 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<project version="20.1"> - <meta> - <filters directoryPatterns="" filePatterns="" positiveFilePatterns="" - showHiddenFiles="false"/> - <options> - <serialized version="20.1" xml:space="preserve"> - <serializableOrderedMap> - <entry> - <String>editor.detect.indent.on.open</String> - <Boolean>false</Boolean> - </entry> - <entry> - <String>editor.hard.line.wrap</String> - <Boolean>true</Boolean> - </entry> - <entry> - <String>editor.indent.size.v9.2</String> - <Integer>2</Integer> - </entry> - <entry> - <String>editor.line.width</String> - <Integer>160</Integer> - </entry> - <entry> - <String>key.editor.format.option.pane.group</String> - <Boolean>true</Boolean> - </entry> - <entry> - <String>validation.scenarios</String> - <validationScenario-array/> - </entry> - </serializableOrderedMap> - </serialized> - </options> - </meta> - <projectTree name="CDK_Project.xpr"> - <folder name="All Files" path="./"/> - </projectTree> -</project> diff --git a/v2/guide/attributes.txt b/v2/guide/attributes.txt deleted file mode 100644 index 39276e28..00000000 --- a/v2/guide/attributes.txt +++ /dev/null @@ -1,4 +0,0 @@ -// Entities that differ depending on the AWS Region build such as China -:arn-aws: pass:q[[.shared]``region.arn``] -:aws: pass:q[[.shared]``AWS``] -:aws-management-console: pass:q[[.shared]``consolelong``] diff --git a/v2/guide/best-practices/best-practices-security.adoc b/v2/guide/best-practices/best-practices-security.adoc deleted file mode 100644 index 03868b27..00000000 --- a/v2/guide/best-practices/best-practices-security.adoc +++ /dev/null @@ -1,133 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[[best-practices-security,best-practices-security.title]] -= {aws} CDK security best practices -:info_titleabbrev: Security -:keywords: {aws} CDK, IAM, security, permissions, infrastructure, {aws} CloudFormation, {aws} CDK deployments - -[abstract] --- -The {aws} Cloud Development Kit ({aws} CDK) is a powerful tool that developers can use to configure {aws} services and provision infrastructure on {aws}. With any tool that provides such control and capabilities, organizations will need to establish policies and practices to ensure that the tool is being used in safe and secure ways. For example, organizations may want to restrict developer access to specific services to ensure that they can't tamper with compliance or cost control measures that are configured in the account. --- - -// Content start - -The {aws} Cloud Development Kit ({aws} CDK) is a powerful tool that developers can use to configure {aws} services and provision infrastructure on {aws}. With any tool that provides such control and capabilities, organizations will need to establish policies and practices to ensure that the tool is being used in safe and secure ways. For example, organizations may want to restrict developer access to specific services to ensure that they can't tamper with compliance or cost control measures that are configured in the account. - -Often, there can be a tension between security and productivity, and each organization needs to establish the proper balance for themselves. This topic provides security best practices for the {aws} CDK that you can consider as you create and implement your own security policies. The following best practices are general guidelines and don`'t represent a complete security solution. Because these best practices might not be appropriate or sufficient for your environment, treat them as helpful considerations rather than prescriptions. - -[#best-practices-security-iam] -== Follow IAM security best practices - -{aws} Identity and Access Management (IAM) is a web service that helps you securely control access to {aws} resources. Organizations, individuals, and the {aws} CDK use IAM to manage permissions that determine the actions that can be performed on {aws} resources. When using IAM, follow the IAM security best practices. For more information, see https://docs.aws.amazon.com/IAM/latest/UserGuide/IAMBestPracticesAndUseCases.html[Security best practices and use cases in {aws} Identity and Access Management] in the _IAM User Guide_. - -[#best-practices-security-permissions] -== Manage permissions for the {aws} CDK - -When you use the {aws} CDK across your organization to develop and manage your infrastructure, you'll want to consider the following scenarios where managing permissions will be important: - -* *Permissions for {aws} CDK deployments* – These permissions determine who can make changes to your {aws} resources and what changes they can make. -* *Permissions between resources* – These are the permissions that allow interactions between the {aws} resources that you create and manage with the {aws} CDK. - -[#best-practices-security-permissions-deployments] -=== Manage permissions for {aws} CDK deployments - -Developers use the {aws} CDK to define infrastructure locally on their development machines. This infrastructure is implemented in {aws} environments through deployments that typically involve using the {aws} CDK Command Line Interface ({aws} CDK CLI). With deployments, you may want to control what changes developers can make in your environments. For example, you might have an Amazon Virtual Private Cloud (Amazon VPC) resource that you don't want developers to modify. - -By default, the CDK CLI uses a combination of the actor's security credentials and IAM roles that are created during bootstrapping to receive permissions for deployments. The actor's security credentials are first used for authentication and IAM roles are then assumed to perform various actions during deployment, such as using the {aws} CloudFormation service to create resources. For more information on how CDK deployments work, including the IAM roles that are used, see xref:deploy[Deploy {aws} CDK applications]. - -To restrict who can perform deployments and the actions that can be performed during deployment, consider the following: - -* The actor's security credentials are the first set of credentials used to authenticate to {aws}. From here, the permissions used to perform actions during deployment are granted to the IAM roles that are assumed during the deployment workflow. You can restrict who can perform deployments by limiting who can assume these roles. You can also restrict the actions that can be performed during deployment by replacing these IAM roles with your own. -* Permissions for performing deployments are given to the `DeploymentActionRole`. You can control permissions for who can perform deployments by limiting who can assume this role. By using a role for deployments, you can perform cross-account deployments since the role can be assumed by {aws} identities in a different account. By default, all identities in the same {aws} account with the appropriate `AssumeRole` policy statement can assume this role. -* Permissions for creating and modifying resources through {aws} CloudFormation are given to the `CloudFormationExecutionRole`. This role also requires permission to read from the bootstrap resources. You control the permissions that CDK deployments have by using a managed policy for the `CloudFormationExecutionRole` and optionally by configuring a permissions boundary. By default, this role has `AdministratorAccess` permissions with no permission boundary. -* Permissions for interacting with bootstrap resources are given to the `FilePublishingRole` and `ImagePublishingRole`. The actor performing deployments must have permission to assume these roles. By default, all identities in the same {aws} account with the appropriate `AssumeRole` policy statement can assume this role. -* Permissions for accessing bootstrap resources to perform lookups are given to the `LookupRole`. The actor performing deployments must have permission to assume this role. By default, this role has `readOnly` access to the bootstrap resources. By default, all identities in the same {aws} account with the appropriate `AssumeRole` policy statement can assume this role. - -To configure the IAM identities in your {aws} account with permission to assume these roles, add a policy with the following policy statement to the identities: - -[source,json,subs="verbatim,attributes"] ----- -{ - "Version": "2012-10-17", - "Statement": [{ - "Sid": "AssumeCDKRoles", - "Effect": "Allow", - "Action": "sts:AssumeRole", - "Resource": "*", - "Condition": { - "StringEquals": { - "iam:ResourceTag/aws-cdk:bootstrap-role": [ - "image-publishing", - "file-publishing", - "deploy", - "lookup" - ] - } - } - }] -} ----- - -[#best-practices-security-permissions-deployments-roles] -==== Modify the permissions for the roles assumed during deployment - -By modifying permissions for the roles assumed during deployment, you can manage the actions that can be performed during deployment. To modify permissions, you create your own IAM roles and specify them when bootstrapping your environment. When you customize bootstrapping, you will have to customize synthesis. For general instructions, see xref:bootstrapping-customizing[Customize {aws} CDK bootstrapping]. - -[#best-practices-security-permissions-deployments-creds] -==== Modify the security credentials and roles used during deployment - -The roles and bootstrap resources that are used during deployments are determined by the CDK stack synthesizer that you use. To modify this behavior, you can customize synthesis. For more information, see xref:configure-synth[Configure and perform CDK stack synthesis]. - -[#best-practices-security-permissions-deployments-least] -==== Considerations for granting least privilege access - -Granting least privilege access is a security best practice that we recommend that you consider as you develop your security strategy. For more information, see link:https://docs.aws.amazon.com/wellarchitected/latest/security-pillar/sec_permissions_least_privileges.html[SEC03-BP02 Grant least privilege access] in the _{aws} Well-Architected Framework Guide_. - -Often, granting least privilege access involves restricting IAM policies to the minimum access necessary to perform a given task. Attempting to grant least privilege access through fine-grained permissions with the CDK using this approach can impact CDK deployments and cause you to have to create wider-scoped permissions than you`'d like. The following are a few things to consider when using this approach: - -* Determining an exhaustive list of permissions that allow developers to use the {aws} CDK to provision infrastructure through CloudFormation is difficult and complex. -* If you want to be fine-grained, permissions may become too long to fit within the maximum length of IAM policy documents. -* Providing an incomplete set of permissions can severely impact developer productivity and deployments. - -With the CDK, deployments are performed using CloudFormation. CloudFormation initiates a set of {aws} API calls in order using the permissions that are provided. The permissions necessary at any point in time depends on many factors: - -* The {aws} services that are being modified. Specifically, the resources and properties that are being used and changed. -* The current state of the CloudFormation stack. -* Issues that may occur during deployments and if rollbacks are needed, which will require `Delete` permissions in addition to `Create`. - -When the provided permissions are incomplete, manual intervention will be required. The following are a few examples: - -* If you discover incomplete permissions during roll forward, you'll need to pause deployment, and take time to discuss and provision new permissions before continuing. -* If deployment rolls back and the permissions to apply the roll back are missing, it may leave your CloudFormation stack in a state that will require a lot of manual work to recover from. - -Since this approach can result in complications and severely limit developer productivity, we don't recommend it. Instead, we recommend implementing guardrails and preventing bypass. - -[#best-practices-security-permissions-deployments-guardrails] -==== Implementing guardrails and preventing bypass - -You can implement guardrails, compliance rules, auditing, and monitoring by using services such as {aws} Control Tower, {aws} Config, {aws} CloudTrail, {aws} Security Hub, and others. With this approach, you grant developers permission to do everything, except tampering with the existing validation mechanisms. Developers have the freedom to implement changes quickly, as long as they stay within policy. This is the approach we recommend when using the {aws} CDK. For more information on guardrails, see https://docs.aws.amazon.com/wellarchitected/latest/management-and-governance-guide/controls.html[Controls] in the _Management and Governance Cloud Environment Guide_. - -We also recommend using _permissions boundaries_ or _service control policies (SCPs)_ as a way of implementing guardrails. For more information on implementing permissions boundaries with the {aws} CDK, see xref:customize-permissions-boundaries[Create and apply permissions boundaries for the {aws} CDK]. - -If you are using any compliance control mechanisms, set them up during the bootstrapping phase. Make sure that the `CloudFormationExecutionRole` or developer-accessible identities have policies or permissions boundaries attached that prevent bypass of the mechanisms that you put in place. The appropriate policies depends on the specific mechanisms that you use. - -[#best-practices-security-permissions-resources] -=== Manage permissions between resources provisioned by the {aws} CDK - -How you manage permissions between resources that are provisioned by the {aws} CDK depends on whether you allow the CDK to create roles and policies. - -When you use L2 constructs from the {aws} Construct Library to define your infrastructure, you can use the provided `grant` methods to provision permissions between resources. With `grant` methods, you specify the type of access you want between resources and the {aws} CDK provisions least privilege IAM roles to accomplish your intent. This approach meets security requirements for most organizations while being efficient for developers. For more information, see xref:define-iam-l2[Define permissions for L2 constructs with the {aws} CDK]. - -If you want to work around this feature by replacing the automatically generated roles with manually created ones, consider the following: - -* Your IAM roles will need to be manually created, slowing down application development. -* When IAM roles need to be manually created and managed, people will often combine multiple logical roles into a single role to make them easier to manage. This runs counter to the least privilege principle. -* Since these roles will need to be created before deployment, the resources that need to be referenced will not yet exist. Therefore, you`'ll need to use wildcards, which runs counter to the least privilege principle. -* A common workaround to using wildcards is to mandate that all resources be given a predictable name. However, this interferes with CloudFormation`'s ability to replace resources when necessary and may slow down or block development. Because of this, we recommend that you allow CloudFormation to create unique resource names for you. -* It will be impossible to perform continuous delivery since manual actions must be performed prior to every deployment. - -When organizations want to prevent the CDK from creating roles, it is usually to prevent developers from being able to create IAM roles. The concern is that by giving developers permission to create IAM roles using the {aws} CDK, they could possibly elevate their own privileges. To mitigate against this, we recommend using _permission boundaries_ or _service control policies (SCPs)_. With permission boundaries, you can set limits for what developers and the CDK are allowed to do. For more information on using permission boundaries with the CDK, see xref:customize-permissions-boundaries[Create and apply permissions boundaries for the {aws} CDK]. \ No newline at end of file diff --git a/v2/guide/best-practices/best-practices.adoc b/v2/guide/best-practices/best-practices.adoc deleted file mode 100644 index 3ba838e6..00000000 --- a/v2/guide/best-practices/best-practices.adoc +++ /dev/null @@ -1,241 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[#best-practices] -= Best practices for developing and deploying cloud infrastructure with the {aws} CDK -:info_titleabbrev: Best practices - -// Content start - -With the {aws} CDK, developers or administrators can define their cloud infrastructure by using a supported programming language. CDK applications should be organized into logical units, such as API, database, and monitoring resources, and optionally have a pipeline for automated deployments. The logical units should be implemented as constructs including the following: - -* Infrastructure (such as Amazon S3 buckets, Amazon RDS databases, or an Amazon VPC network) -* Runtime code (such as {aws} Lambda functions) -* Configuration code - -Stacks define the deployment model of these logical units. For a more detailed introduction to the concepts behind the CDK, see xref:getting-started[Getting started with the {aws} CDK]. - -The {aws} CDK reflects careful consideration of the needs of our customers and internal teams and of the failure patterns that often arise during the deployment and ongoing maintenance of complex cloud applications. We discovered that failures are often related to "out-of-band" changes to an application that aren't fully tested, such as configuration changes. Therefore, we developed the {aws} CDK around a model in which your entire application is defined in code, not only business logic but also infrastructure and configuration. That way, proposed changes can be carefully reviewed, comprehensively tested in environments resembling production to varying degrees, and fully rolled back if something goes wrong. - -image::images/all-in-one.jpg["Software development lifecycle icons representing infrastructure, application, source code, configuration, and deployment.",scaledwidth=100%] - -At deployment time, the {aws} CDK synthesizes a cloud assembly that contains the following: - -* {aws} CloudFormation templates that describe your infrastructure in all target environments -* File assets that contain your runtime code and their supporting files - -With the CDK, every commit in your application's main version control branch can represent a complete, consistent, deployable version of your application. Your application can then be deployed automatically whenever a change is made. - -The philosophy behind the {aws} CDK leads to our recommended best practices, which we have divided into four broad categories. - -* xref:best-practices-organization[Organization best practices] -* xref:best-practices-code[Coding best practices] -* xref:best-practices-constructs[Construct best practices] -* xref:best-practices-apps[Application best practices] - -[TIP] -==== - -Also consider https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/best-practices.html[best practices for {aws} CloudFormation] and the individual {aws} services that you use, where applicable to CDK-defined infrastructure. - -==== - -[#best-practices-organization] -== Organization best practices - -In the beginning stages of {aws} CDK adoption, it's important to consider how to set up your organization for success. It's a best practice to have a team of experts responsible for training and guiding the rest of the company as they adopt the CDK. The size of this team might vary, from one or two people at a small company to a full-fledged Cloud Center of Excellence (CCoE) at a larger company. This team is responsible for setting standards and policies for cloud infrastructure at your company, and also for training and mentoring developers. - -The CCoE might provide guidance on what programming languages should be used for cloud infrastructure. Details will vary from one organization to the next, but a good policy helps make sure that developers can understand and maintain the company's cloud infrastructure. - -The CCoE also creates a "landing zone" that defines your organizational units within {aws}. A landing zone is a pre-configured, secure, scalable, multi-account {aws} environment based on best practice blueprints. To tie together the services that make up your landing zone, you can use https://aws.amazon.com/controltower/[{aws} Control Tower], which configures and manages your entire multi-account system from a single user interface. - -Development teams should be able to use their own accounts for testing and deploy new resources in these accounts as needed. Individual developers can treat these resources as extensions of their own development workstation. Using xref:cdk-pipeline[CDK Pipelines], the {aws} CDK applications can then be deployed via a CI/CD account to testing, integration, and production environments (each isolated in its own {aws} Region or account). This is done by merging the developers' code into your organization's canonical repository. - -image::images/best-practice-deploy-to-multiple-accounts.png[Diagram showing deployment process from developer accounts to multiple target accounts via CI/CD pipeline.,scaledwidth=100%] - -[#best-practices-code] -== Coding best practices - -This section presents best practices for organizing your {aws} CDK code. The following diagram shows the relationship between a team and that team's code repositories, packages, applications, and construct libraries. - -image::images/code-organization.jpg["Diagram showing team's code organization: repository, package, CDK app or construct library.",scaledwidth=100%] - -[#best-practices-code-kiss] -*Start simple and add complexity only when you need it*:: -+ -The guiding principle for most of our best practices is to keep things simple as possible--but no simpler. Add complexity only when your requirements dictate a more complicated solution. With the {aws} CDK, you can refactor your code as necessary to support new requirements. You don't have to architect for all possible scenarios upfront. - -[#best-practices-code-well-architected] -*Align with the {aws} Well-Architected Framework*:: -+ -The https://aws.amazon.com/architecture/well-architected/[{aws} Well-Architected] Framework defines a _component_ as the code, configuration, and {aws} resources that together deliver against a requirement. A component is often the unit of technical ownership, and is decoupled from other components. The term _workload_ is used to identify a set of components that together deliver business value. A workload is usually the level of detail that business and technology leaders communicate about. -+ -An {aws} CDK application maps to a component as defined by the {aws} Well-Architected Framework. {aws} CDK apps are a mechanism to codify and deliver Well-Architected cloud application best practices. You can also create and share components as reusable code libraries through artifact repositories, such as {aws} CodeArtifact. - -[#best-practices-code-package] -*Every application starts with a single package in a single repository*:: -+ -A single package is the entry point of your {aws} CDK app. Here, you define how and where to deploy the different logical units of your application. You also define the CI/CD pipeline to deploy the application. The app's constructs define the logical units of your solution. -+ -Use additional packages for constructs that you use in more than one application. (Shared constructs should also have their own lifecycle and testing strategy.) Dependencies between packages in the same repository are managed by your repo's build tooling. -+ -Although it's possible, we don't recommend putting multiple applications in the same repository, especially when using automated deployment pipelines. Doing this increases the "blast radius" of changes during deployment. When there are multiple applications in a repository, changes to one application trigger deployment of the others (even if the others haven't changed). Furthermore, a break in one application prevents the other applications from being deployed. - -[#best-practices-code-repo] -*Move code into repositories based on code lifecycle or team ownership*:: -+ -When packages begin to be used in multiple applications, move them to their own repository. This way, the packages can be referenced by application build systems that use them, and they can also be updated on cadences independent of the application lifecycles. However, at first it might make sense to put all shared constructs in one repository. -+ -Also, move packages to their own repository when different teams are working on them. This helps enforce access control. -+ -To consume packages across repository boundaries, you need a private package repository--similar to NPM, PyPi, or Maven Central, but internal to your organization. You also need a release process that builds, tests, and publishes the package to the private package repository. https://docs.aws.amazon.com/codeartifact/latest/ug/[CodeArtifact] can host packages for most popular programming languages. -+ -Dependencies on packages in the package repository are managed by your language's package manager, such as NPM for TypeScript or JavaScript applications. Your package manager helps to make sure that builds are repeatable. It does this by recording the specific versions of every package that your application depends on. It also lets you upgrade those dependencies in a controlled manner. -+ -Shared packages need a different testing strategy. For a single application, it might be good enough to deploy the application to a testing environment and confirm that it still works. But shared packages must be tested independently of the consuming application, as if they were being released to the public. (Your organization might choose to actually release some shared packages to the public.) -+ -Keep in mind that a construct can be arbitrarily simple or complex. A `Bucket` is a construct, but `CameraShopWebsite` could be a construct, too. - -[#best-practices-code-all] -*Infrastructure and runtime code live in the same package*:: -+ -In addition to generating {aws} CloudFormation templates for deploying infrastructure, the {aws} CDK also bundles runtime assets like Lambda functions and Docker images and deploys them alongside your infrastructure. This makes it possible to combine the code that defines your infrastructure and the code that implements your runtime logic into a single construct. It's a best practice to do this. These two kinds of code don't need to live in separate repositories or even in separate packages. -+ -To evolve the two kinds of code together, you can use a self-contained construct that completely describes a piece of functionality, including its infrastructure and logic. With a self-contained construct, you can test the two kinds of code in isolation, share and reuse the code across projects, and version all the code in sync. - -[#best-practices-constructs] -== Construct best practices - -This section contains best practices for developing constructs. Constructs are reusable, composable modules that encapsulate resources. They're the building blocks of {aws} CDK apps. - -[#best-practices-constructs-model] -*Model with constructs, deploy with stacks*:: -+ -Stacks are the unit of deployment: everything in a stack is deployed together. So when building your application's higher-level logical units from multiple {aws} resources, represent each logical unit as a https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html[Construct], not as a https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html[Stack]. Use stacks only to describe how your constructs should be composed and connected for your various deployment scenarios. -+ -For example, if one of your logical units is a website, the constructs that make it up (such as an Amazon S3 bucket, API Gateway, Lambda functions, or Amazon RDS tables) should be composed into a single high-level construct. Then that construct should be instantiated in one or more stacks for deployment. -+ -By using constructs for building and stacks for deploying, you improve reuse potential of your infrastructure and give yourself more flexibility in how it's deployed. - -[#best-practices-constructs-config] -*Configure with properties and methods, not environment variables*:: -+ -Environment variable lookups inside constructs and stacks are a common anti-pattern. Both constructs and stacks should accept a properties object to allow for full configurability completely in code. Doing otherwise introduces a dependency on the machine that the code will run on, which creates yet more configuration information that you have to track and manage. -+ -In general, environment variable lookups should be limited to the top level of an {aws} CDK app. They should also be used to pass in information that's needed for running in a development environment. For more information, see xref:environments[Environments for the {aws} CDK]. - -[#best-practices-constructs-test] -*Unit test your infrastructure*:: -+ -To consistently run a full suite of unit tests at build time in all environments, avoid network lookups during synthesis and model all your production stages in code. (These best practices are covered later.) If any single commit always results in the same generated template, you can trust the unit tests that you write to confirm that the generated templates look the way you expect. For more information, see xref:testing[Test {aws} CDK applications]. - -[#best-practices-constructs-logicalid] -*Don't change the logical ID of stateful resources*:: -+ -Changing the logical ID of a resource results in the resource being replaced with a new one at the next deployment. For stateful resources like databases and S3 buckets, or persistent infrastructure like an Amazon VPC, this is seldom what you want. Be careful about any refactoring of your {aws} CDK code that could cause the ID to change. Write unit tests that assert that the logical IDs of your stateful resources remain static. The logical ID is derived from the `id` you specify when you instantiate the construct, and the construct's position in the construct tree. For more information, see xref:identifiers-logical-ids[Logical IDs]. - -[#best-practices-constructs-compliance] -*Constructs aren't enough for compliance*:: -+ -Many enterprise customers write their own wrappers for L2 constructs (the "curated" constructs that represent individual {aws} resources with built-in sane defaults and best practices). These wrappers enforce security best practices such as static encryption and specific IAM policies. For example, you might create a `MyCompanyBucket` that you then use in your applications in place of the usual Amazon S3 `Bucket` construct. This pattern is useful for surfacing security guidance early in the software development lifecycle, but don't rely on it as the sole means of enforcement. -+ -Instead, use {aws} features such as link:https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps.html[service control policies] and link:https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html[permission boundaries] to enforce your security guardrails at the organization level. Use xref:aspects[Aspects and the {aws} CDK] or tools like https://github.com/aws-cloudformation/cloudformation-guard[CloudFormation Guard] to make assertions about the security properties of infrastructure elements before deployment. Use {aws} CDK for what it does best. -+ -Finally, keep in mind that writing your own "L2+" constructs might prevent your developers from taking advantage of {aws} CDK packages such as https://docs.aws.amazon.com/solutions/latest/constructs/welcome.html[{aws} Solutions Constructs] or third-party constructs from Construct Hub. These packages are typically built on standard {aws} CDK constructs and won't be able to use your wrapper constructs. - -[#best-practices-apps] -== Application best practices - -In this section we discuss how to write your {aws} CDK applications, combining constructs to define how your {aws} resources are connected. - -[#best-practices-apps-synth] -*Make decisions at synthesis time*:: -+ -Although {aws} CloudFormation lets you make decisions at deployment time (using `Conditions`, `{ Fn::If }`, and `Parameters`), and the {aws} CDK gives you some access to these mechanisms, we recommend against using them. The types of values that you can use and the types of operations you can perform on them are limited compared to what's available in a general-purpose programming language. -+ -Instead, try to make all decisions, such as which construct to instantiate, in your {aws} CDK application by using your programming language's `if` statements and other features. For example, a common CDK idiom, iterating over a list and instantiating a construct with values from each item in the list, simply isn't possible using {aws} CloudFormation expressions. -+ -Treat {aws} CloudFormation as an implementation detail that the {aws} CDK uses for robust cloud deployments, not as a language target. You're not writing {aws} CloudFormation templates in TypeScript or Python, you're writing CDK code that happens to use CloudFormation for deployment. - -[#best-practices-apps-names] -*Use generated resource names, not physical names*:: -+ -Names are a precious resource. Each name can only be used once. Therefore, if you hardcode a table name or bucket name into your infrastructure and application, you can't deploy that piece of infrastructure twice in the same account. (The name we're talking about here is the name specified by, for example, the `bucketName` property on an Amazon S3 bucket construct.) -+ -What's worse, you can't make changes to the resource that require it to be replaced. If a property can only be set at resource creation, such as the `KeySchema` of an Amazon DynamoDB table, then that property is immutable. Changing this property requires a new resource. However, the new resource must have the same name in order to be a true replacement. But it can't have the same name while the existing resource is still using that name. -+ -A better approach is to specify as few names as possible. If you omit resource names, the {aws} CDK will generate them for you in a way that won't cause problems. Suppose you have a table as a resource. You can then pass the generated table name as an environment variable into your {aws} Lambda function. In your {aws} CDK application, you can reference the table name as `table.tableName`. Alternatively, you can generate a configuration file on your Amazon EC2 instance on startup, or write the actual table name to the {aws} Systems Manager Parameter Store so your application can read it from there. -+ -If the place you need it is another {aws} CDK stack, that's even more straightforward. Supposing that one stack defines the resource and another stack needs to use it, the following applies: -+ -* If the two stacks are in the same {aws} CDK app, pass a reference between the two stacks. For example, save a reference to the resource's construct as an attribute of the defining stack (`this.stack.uploadBucket = amzn-s3-demo-bucket`). Then, pass that attribute to the constructor of the stack that needs the resource. -* When the two stacks are in different {aws} CDK apps, use a static `from` method to use an externally defined resource based on its ARN, name, or other attributes. (For example, use `Table.fromArn()` for a DynamoDB table). Use the `CfnOutput` construct to print the ARN or other required value in the output of `cdk deploy`, or look in the {aws} Management Console. Alternatively, the second app can read the CloudFormation template generated by the first app and retrieve that value from the `Outputs` section. - -[#best-practices-apps-removal-logs] -*Define removal policies and log retention*:: -+ -The {aws} CDK attempts to keep you from losing data by defaulting to policies that retain everything you create. For example, the default removal policy on resources that contain data (such as Amazon S3 buckets and database tables) is not to delete the resource when it is removed from the stack. Instead, the resource is orphaned from the stack. Similarly, the CDK's default is to retain all logs forever. In production environments, these defaults can quickly result in the storage of large amounts of data that you don't actually need, and a corresponding {aws} bill. -+ -Consider carefully what you want these policies to be for each production resource and specify them accordingly. Use xref:aspects[Aspects and the {aws} CDK] to validate the removal and logging policies in your stack. - -[#best-practices-apps-separate] -*Separate your application into multiple stacks as dictated by deployment requirements*:: -+ -There is no hard and fast rule to how many stacks your application needs. You'll usually end up basing the decision on your deployment patterns. Keep in mind the following guidelines: -+ -* It's typically more straightforward to keep as many resources in the same stack as possible, so keep them together unless you know you want them separated. -* Consider keeping stateful resources (like databases) in a separate stack from stateless resources. You can then turn on termination protection on the stateful stack. This way, you can freely destroy or create multiple copies of the stateless stack without risk of data loss. -* Stateful resources are more sensitive to construct renaming--renaming leads to resource replacement. Therefore, don't nest stateful resources inside constructs that are likely to be moved around or renamed (unless the state can be rebuilt if lost, like a cache). This is another good reason to put stateful resources in their own stack. - -[#best-practices-apps-context] -*Commit `cdk.context.json` to avoid non-deterministic behavior*:: -+ -Determinism is key to successful {aws} CDK deployments. An {aws} CDK app should have essentially the same result whenever it is deployed to a given environment. -+ -Since your {aws} CDK app is written in a general-purpose programming language, it can execute arbitrary code, use arbitrary libraries, and make arbitrary network calls. For example, you could use an {aws} SDK to retrieve some information from your {aws} account while synthesizing your app. Recognize that doing so will result in additional credential setup requirements, increased latency, and a chance, however small, of failure every time you run `cdk synth`. -+ -Never modify your {aws} account or resources during synthesis. Synthesizing an app should not have side effects. Changes to your infrastructure should happen only in the deployment phase, after the {aws} CloudFormation template has been generated. This way, if there's a problem, {aws} CloudFormation can automatically roll back the change. To make changes that can't be easily made within the {aws} CDK framework, use link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.custom_resources-readme.html[custom resources] to execute arbitrary code at deployment time. -+ -Even strictly read-only calls are not necessarily safe. Consider what happens if the value returned by a network call changes. What part of your infrastructure will that impact? What will happen to already-deployed resources? Following are two example situations in which a sudden change in values might cause a problem. -+ --- -* If you provision an Amazon VPC to all available Availability Zones in a specified Region, and the number of AZs is two on deployment day, then your IP space gets split in half. If {aws} launches a new Availability Zone the next day, the next deployment after that tries to split your IP space into thirds, requiring all subnets to be recreated. This probably won't be possible because your Amazon EC2 instances are still running, and you'll have to clean this up manually. -* If you query for the latest Amazon Linux machine image and deploy an Amazon EC2 instance, and the next day a new image is released, a subsequent deployment picks up the new AMI and replaces all your instances. This might not be what you expected to happen. --- -+ -These situations can be pernicious because the {aws}-side change might occur after months or years of successful deployments. Suddenly your deployments are failing "for no reason" and you long ago forgot what you did and why. -+ -Fortunately, the {aws} CDK includes a mechanism called _context providers_ to record a snapshot of non-deterministic values. This allows future synthesis operations to produce exactly the same template as they did when first deployed. The only changes in the new template are the changes that _you_ made in your code. When you use a construct's `.fromLookup()` method, the result of the call is cached in `cdk.context.json`. You should commit this to version control along with the rest of your code to make sure that future executions of your CDK app use the same value. The CDK Toolkit includes commands to manage the context cache, so you can refresh specific entries when you need to. For more information, see xref:context[Context values and the {aws} CDK]. -+ -If you need some value (from {aws} or elsewhere) for which there is no native CDK context provider, we recommend writing a separate script. The script should retrieve the value and write it to a file, then read that file in your CDK app. Run the script only when you want to refresh the stored value, not as part of your regular build process. - -[#best-practices-apps-roles] -*Let the {aws} CDK manage roles and security groups*:: -+ -With the {aws} CDK construct library's `grant()` convenience methods, you can create {aws} Identity and Access Management roles that grant access to one resource by another using minimally scoped permissions. For example, consider a line like the following: -+ -[source,javascript,subs="verbatim,attributes"] ----- -amzn-s3-demo-bucket.grantRead(myLambda) ----- -+ -This single line adds a policy to the Lambda function's role (which is also created for you). That role and its policies are more than a dozen lines of CloudFormation that you don't have to write. The {aws} CDK grants only the minimal permissions required for the function to read from the bucket. -+ -If you require developers to always use predefined roles that were created by a security team, {aws} CDK coding becomes much more complicated. Your teams could lose a lot of flexibility in how they design their applications. A better alternative is to use link:https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps.html[service control policies] and link:https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html[permission boundaries] to make sure that developers stay within the guardrails. - -[#best-practices-apps-stages] -*Model all production stages in code*:: -+ -In traditional {aws} CloudFormation scenarios, your goal is to produce a single artifact that is parameterized so that it can be deployed to various target environments after applying configuration values specific to those environments. In the CDK, you can, and should, build that configuration into your source code. Create a stack for your production environment, and create a separate stack for each of your other stages. Then, put the configuration values for each stack in the code. Use services like https://aws.amazon.com/secrets-manager/[Secrets Manager] and https://aws.amazon.com/systems-manager/[Systems Manager] Parameter Store for sensitive values that you don't want to check in to source control, using the names or ARNs of those resources. -+ -When you synthesize your application, the cloud assembly created in the `cdk.out` folder contains a separate template for each environment. Your entire build is deterministic. There are no out-of-band changes to your application, and any given commit always yields the exact same {aws} CloudFormation template and accompanying assets. This makes unit testing much more reliable. - -[#best-practices-apps-measure] -*Measure everything*:: -+ -Achieving the goal of full continuous deployment, with no human intervention, requires a high level of automation. That automation is only possible with extensive amounts of monitoring. To measure all aspects of your deployed resources, create metrics, alarms, and dashboards. Don't stop at measuring things like CPU usage and disk space. Also record your business metrics, and use those measurements to automate deployment decisions like rollbacks. Most of the L2 constructs in {aws} CDK have convenience methods to help you create metrics, such as the `metricUserErrors()` method on the link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_dynamodb.Table.html[`dynamodb.Table`] class. - - -include::best-practices-security.adoc[leveloffset=+1] \ No newline at end of file diff --git a/v2/guide/book.adoc b/v2/guide/book.adoc deleted file mode 100644 index c72a145b..00000000 --- a/v2/guide/book.adoc +++ /dev/null @@ -1,76 +0,0 @@ -include::attributes.txt[] - -:doctype: book -:toc: left -:icons: font -:experimental: -:idprefix: -:idseparator: - -:info_subtitle: Developer Guide -:info_edition: 2 -:info_corpauthor: {aws} -:info_publisher: {aws} -:keywords: CDK, {aws} CDK, {aws} Cloud Development Kit -:info_copyright: 2025 Amazon Web Services, Inc. and/or its affiliates. All rights reserved. -:info_legalnotice: Amazon's trademarks and trade dress may not be used in connection with any product or service that is not Amazon's, in any manner that is likely to cause confusion among customers, or in any manner that disparages or discredits Amazon. All other trademarks not owned by Amazon are the property of their respective owners, who may or may not be affiliated with, connected to, or sponsored by Amazon. - -[[top]] -= {aws} Cloud Development Kit ({aws} CDK) v2 - -[abstract] --- -Provides a conceptual overview and practical examples to help you understand the features provided by the {aws} CDK and how to use them. --- - -[.banner.info] -This is the {aws} CDK v2 Developer Guide. The older CDK v1 entered maintenance on June 1, 2022 and ended support on June 1, 2023. - -include::what-is/home.adoc[leveloffset=+1] - -include::concepts/core-concepts.adoc[leveloffset=+1] - -include::getting-started/prerequisites.adoc[leveloffset=+1] - -include::getting-started/getting-started.adoc[leveloffset=+1] - -include::work-with/work-with-cdk.adoc[leveloffset=+1] - -include::best-practices/best-practices.adoc[leveloffset=+1] - -include::migrate/work-with-cdk-v2.adoc[leveloffset=+1] - -include::migrate/migrate.adoc[leveloffset=+1] - -include::configure-access/configure-access.adoc[leveloffset=+1] - -include::configure-env.adoc[leveloffset=+1] - -include::bootstrapping/bootstrapping-env.adoc[leveloffset=+1] - -include::develop/chapter-develop.adoc[leveloffset=+1] - -include::configure-synth/configure-synth.adoc[leveloffset=+1] - -include::deploy/chapter-deploy.adoc[leveloffset=+1] - -include::toolkit-library.adoc[leveloffset=+1] - -include::testing/testing.adoc[leveloffset=+1] - -include::cli.adoc[leveloffset=+1] - -include::ref-cli-cmd/ref-cli-cmd.adoc[leveloffset=+1] - -include::reference/reference.adoc[leveloffset=+1] - -include::how-tos/how-tos.adoc[leveloffset=+1] - -include::tools.adoc[leveloffset=+1] - -include::security/security.adoc[leveloffset=+1] - -include::troubleshooting.adoc[leveloffset=+1] - -include::pgp-keys.adoc[leveloffset=+1] - -include::doc-history.adoc[leveloffset=+1] \ No newline at end of file diff --git a/v2/guide/book.html b/v2/guide/book.html deleted file mode 100644 index b440a268..00000000 --- a/v2/guide/book.html +++ /dev/null @@ -1,48192 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> -<head> -<meta charset="UTF-8"> -<meta http-equiv="X-UA-Compatible" content="IE=edge"> -<meta name="viewport" content="width=device-width, initial-scale=1.0"> -<meta name="generator" content="Asciidoctor 2.0.23"> -<meta name="keywords" content="CDK, AWS CDK, AWS Cloud Development Kit"> -<title>AWS Cloud Development Kit (AWS CDK) v2</title> -<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700"> -<style> -/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */ -/* Uncomment the following line when using as a custom stylesheet */ -/* @import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700"; */ -html{font-family:sans-serif;-webkit-text-size-adjust:100%} -a{background:none} -a:focus{outline:thin dotted} -a:active,a:hover{outline:0} -h1{font-size:2em;margin:.67em 0} -b,strong{font-weight:bold} -abbr{font-size:.9em} -abbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none} -dfn{font-style:italic} -hr{height:0} -mark{background:#ff0;color:#000} -code,kbd,pre,samp{font-family:monospace;font-size:1em} -pre{white-space:pre-wrap} -q{quotes:"\201C" "\201D" "\2018" "\2019"} -small{font-size:80%} -sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline} -sup{top:-.5em} -sub{bottom:-.25em} -img{border:0} -svg:not(:root){overflow:hidden} -figure{margin:0} -audio,video{display:inline-block} -audio:not([controls]){display:none;height:0} -fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em} -legend{border:0;padding:0} -button,input,select,textarea{font-family:inherit;font-size:100%;margin:0} -button,input{line-height:normal} -button,select{text-transform:none} -button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer} -button[disabled],html input[disabled]{cursor:default} -input[type=checkbox],input[type=radio]{padding:0} -button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0} -textarea{overflow:auto;vertical-align:top} -table{border-collapse:collapse;border-spacing:0} -*,::before,::after{box-sizing:border-box} -html,body{font-size:100%} -body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased} -a:hover{cursor:pointer} -img,object,embed{max-width:100%;height:auto} -object,embed{height:100%} -img{-ms-interpolation-mode:bicubic} -.left{float:left!important} -.right{float:right!important} -.text-left{text-align:left!important} -.text-right{text-align:right!important} -.text-center{text-align:center!important} -.text-justify{text-align:justify!important} -.hide{display:none} -img,object,svg{display:inline-block;vertical-align:middle} -textarea{height:auto;min-height:50px} -select{width:100%} -.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em} -div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0} -a{color:#2156a5;text-decoration:underline;line-height:inherit} -a:hover,a:focus{color:#1d4b8f} -a img{border:0} -p{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility} -p aside{font-size:.875em;line-height:1.35;font-style:italic} -h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em} -h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0} -h1{font-size:2.125em} -h2{font-size:1.6875em} -h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em} -h4,h5{font-size:1.125em} -h6{font-size:1em} -hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em} -em,i{font-style:italic;line-height:inherit} -strong,b{font-weight:bold;line-height:inherit} -small{font-size:60%;line-height:inherit} -code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)} -ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit} -ul,ol{margin-left:1.5em} -ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0} -ul.circle{list-style-type:circle} -ul.disc{list-style-type:disc} -ul.square{list-style-type:square} -ul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit} -ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0} -dl dt{margin-bottom:.3125em;font-weight:bold} -dl dd{margin-bottom:1.25em} -blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd} -blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)} -@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2} -h1{font-size:2.75em} -h2{font-size:2.3125em} -h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em} -h4{font-size:1.4375em}} -table{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal} -table thead,table tfoot{background:#f7f8f7} -table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left} -table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)} -table tr.even,table tr.alt{background:#f8f8f7} -table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6} -h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em} -h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400} -.center{margin-left:auto;margin-right:auto} -.stretch{width:100%} -.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:" ";display:table} -.clearfix::after,.float-group::after{clear:both} -:not(pre).nobreak{word-wrap:normal} -:not(pre).nowrap{white-space:nowrap} -:not(pre).pre-wrap{white-space:pre-wrap} -:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed} -pre{color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;line-height:1.45;text-rendering:optimizeSpeed} -pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit} -pre>code{display:block} -pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal} -em em{font-style:normal} -strong strong{font-weight:400} -.keyseq{color:rgba(51,51,51,.8)} -kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap} -.keyseq kbd:first-child{margin-left:0} -.keyseq kbd:last-child{margin-right:0} -.menuseq,.menuref{color:#000} -.menuseq b:not(.caret),.menuref{font-weight:inherit} -.menuseq{word-spacing:-.02em} -.menuseq b.caret{font-size:1.25em;line-height:.8} -.menuseq i.caret{font-weight:bold;text-align:center;width:.45em} -b.button::before,b.button::after{position:relative;top:-1px;font-weight:400} -b.button::before{content:"[";padding:0 3px 0 2px} -b.button::after{content:"]";padding:0 2px 0 3px} -p a>code:hover{color:rgba(0,0,0,.9)} -#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em} -#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:" ";display:table} -#header::after,#content::after,#footnotes::after,#footer::after{clear:both} -#content{margin-top:1.25em} -#content::before{content:none} -#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0} -#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf} -#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px} -#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap} -#header .details span:first-child{margin-left:-.125em} -#header .details span.email a{color:rgba(0,0,0,.85)} -#header .details br{display:none} -#header .details br+span::before{content:"\00a0\2013\00a0"} -#header .details br+span.author::before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)} -#header .details br+span#revremark::before{content:"\00a0|\00a0"} -#header #revnumber{text-transform:capitalize} -#header #revnumber::after{content:"\00a0"} -#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem} -#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em} -#toc>ul{margin-left:.125em} -#toc ul.sectlevel0>li>a{font-style:italic} -#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0} -#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none} -#toc li{line-height:1.3334;margin-top:.3334em} -#toc a{text-decoration:none} -#toc a:active{text-decoration:underline} -#toctitle{color:#7a2518;font-size:1.2em} -@media screen and (min-width:768px){#toctitle{font-size:1.375em} -body.toc2{padding-left:15em;padding-right:0} -body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px} -#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto} -#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em} -#toc.toc2>ul{font-size:.9em;margin-bottom:0} -#toc.toc2 ul ul{margin-left:0;padding-left:1em} -#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em} -body.toc2.toc-right{padding-left:0;padding-right:15em} -body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}} -@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0} -#toc.toc2{width:20em} -#toc.toc2 #toctitle{font-size:1.375em} -#toc.toc2>ul{font-size:.95em} -#toc.toc2 ul ul{padding-left:1.25em} -body.toc2.toc-right{padding-left:0;padding-right:20em}} -#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px} -#content #toc>:first-child{margin-top:0} -#content #toc>:last-child{margin-bottom:0} -#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em} -#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44} -#content{margin-bottom:.625em} -.sect1{padding-bottom:.625em} -@media screen and (min-width:768px){#content{margin-bottom:1.25em} -.sect1{padding-bottom:1.25em}} -.sect1:last-child{padding-bottom:0} -.sect1+.sect1{border-top:1px solid #e7e7e9} -#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400} -#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em} -#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible} -#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none} -#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221} -details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em} -details{margin-left:1.25rem} -details>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent} -details>summary::-webkit-details-marker{display:none} -details>summary::before{content:"";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)} -details[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)} -details>summary::after{content:"";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem} -.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic} -table.tableblock.fit-content>caption.title{white-space:nowrap;width:0} -.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)} -.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%} -.admonitionblock>table td.icon{text-align:center;width:80px} -.admonitionblock>table td.icon img{max-width:none} -.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase} -.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere} -.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0} -.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px} -.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px} -.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center} -.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0} -.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0} -.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em} -@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}} -@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}} -.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^="highlight "]{background:#f7f7f8} -.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)} -.listingblock>.content{position:relative} -.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5} -.listingblock:hover code[data-lang]::before{display:block} -.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5} -.listingblock.terminal pre .command:not([data-prompt])::before{content:"$"} -.listingblock pre.highlightjs{padding:0} -.listingblock pre.highlightjs>code{padding:1em;border-radius:4px} -.listingblock pre.prettyprint{border-width:0} -.prettyprint{background:#f7f7f8} -pre.prettyprint .linenums{line-height:1.45;margin-left:2em} -pre.prettyprint li{background:none;list-style-type:inherit;padding-left:0} -pre.prettyprint li code[data-lang]::before{opacity:1} -pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none} -table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none} -table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal} -table.linenotable td.code{padding-left:.75em} -table.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none} -pre.pygments span.linenos{display:inline-block;margin-right:.75em} -.quoteblock{margin:0 1em 1.25em 1.5em;display:table} -.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em} -.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify} -.quoteblock blockquote{margin:0;padding:0;border:0} -.quoteblock blockquote::before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)} -.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0} -.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right} -.verseblock{margin:0 1em 1.25em} -.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility} -.verseblock pre strong{font-weight:400} -.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex} -.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic} -.quoteblock .attribution br,.verseblock .attribution br{display:none} -.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)} -.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none} -.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0} -.quoteblock.abstract{margin:0 1em 1.25em;display:block} -.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center} -.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf} -.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0} -.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem} -.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0} -p.tableblock:last-child{margin-bottom:0} -td.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere} -td.tableblock>.content>:last-child{margin-bottom:-1.25em} -table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede} -table.grid-all>*>tr>*{border-width:1px} -table.grid-cols>*>tr>*{border-width:0 1px} -table.grid-rows>*>tr>*{border-width:1px 0} -table.frame-all{border-width:1px} -table.frame-ends{border-width:1px 0} -table.frame-sides{border-width:0 1px} -table.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0} -table.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0} -table.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0} -table.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0} -table.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7} -th.halign-left,td.halign-left{text-align:left} -th.halign-right,td.halign-right{text-align:right} -th.halign-center,td.halign-center{text-align:center} -th.valign-top,td.valign-top{vertical-align:top} -th.valign-bottom,td.valign-bottom{vertical-align:bottom} -th.valign-middle,td.valign-middle{vertical-align:middle} -table thead th,table tfoot th{font-weight:bold} -tbody tr th{background:#f7f8f7} -tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold} -p.tableblock>code:only-child{background:none;padding:0} -p.tableblock{font-size:1em} -ol{margin-left:1.75em} -ul li ol{margin-left:1.5em} -dl dd{margin-left:1.125em} -dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0} -li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em} -ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none} -ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em} -ul.unstyled,ol.unstyled{margin-left:0} -li>p:empty:only-child::before{content:"";display:inline-block} -ul.checklist>li>p:first-child{margin-left:-1em} -ul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em} -ul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em} -ul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em} -ul.inline>li{margin-left:1.25em} -.unstyled dl dt{font-weight:400;font-style:normal} -ol.arabic{list-style-type:decimal} -ol.decimal{list-style-type:decimal-leading-zero} -ol.loweralpha{list-style-type:lower-alpha} -ol.upperalpha{list-style-type:upper-alpha} -ol.lowerroman{list-style-type:lower-roman} -ol.upperroman{list-style-type:upper-roman} -ol.lowergreek{list-style-type:lower-greek} -.hdlist>table,.colist>table{border:0;background:none} -.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none} -td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em} -td.hdlist1{font-weight:bold;padding-bottom:1.25em} -td.hdlist2{word-wrap:anywhere} -.literalblock+.colist,.listingblock+.colist{margin-top:-.5em} -.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top} -.colist td:not([class]):first-child img{max-width:none} -.colist td:not([class]):last-child{padding:.25em 0} -.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd} -.imageblock.left{margin:.25em .625em 1.25em 0} -.imageblock.right{margin:.25em 0 1.25em .625em} -.imageblock>.title{margin-bottom:0} -.imageblock.thumb,.imageblock.th{border-width:6px} -.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em} -.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0} -.image.left{margin-right:.625em} -.image.right{margin-left:.625em} -a.image{text-decoration:none;display:inline-block} -a.image object{pointer-events:none} -sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super} -sup.footnote a,sup.footnoteref a{text-decoration:none} -sup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline} -#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em} -#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0} -#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em} -#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em} -#footnotes .footnote:last-of-type{margin-bottom:0} -#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0} -div.unbreakable{page-break-inside:avoid} -.big{font-size:larger} -.small{font-size:smaller} -.underline{text-decoration:underline} -.overline{text-decoration:overline} -.line-through{text-decoration:line-through} -.aqua{color:#00bfbf} -.aqua-background{background:#00fafa} -.black{color:#000} -.black-background{background:#000} -.blue{color:#0000bf} -.blue-background{background:#0000fa} -.fuchsia{color:#bf00bf} -.fuchsia-background{background:#fa00fa} -.gray{color:#606060} -.gray-background{background:#7d7d7d} -.green{color:#006000} -.green-background{background:#007d00} -.lime{color:#00bf00} -.lime-background{background:#00fa00} -.maroon{color:#600000} -.maroon-background{background:#7d0000} -.navy{color:#000060} -.navy-background{background:#00007d} -.olive{color:#606000} -.olive-background{background:#7d7d00} -.purple{color:#600060} -.purple-background{background:#7d007d} -.red{color:#bf0000} -.red-background{background:#fa0000} -.silver{color:#909090} -.silver-background{background:#bcbcbc} -.teal{color:#006060} -.teal-background{background:#007d7d} -.white{color:#bfbfbf} -.white-background{background:#fafafa} -.yellow{color:#bfbf00} -.yellow-background{background:#fafa00} -span.icon>.fa{cursor:default} -a span.icon>.fa{cursor:inherit} -.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default} -.admonitionblock td.icon .icon-note::before{content:"\f05a";color:#19407c} -.admonitionblock td.icon .icon-tip::before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111} -.admonitionblock td.icon .icon-warning::before{content:"\f071";color:#bf6900} -.admonitionblock td.icon .icon-caution::before{content:"\f06d";color:#bf3400} -.admonitionblock td.icon .icon-important::before{content:"\f06a";color:#bf0000} -.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold} -.conum[data-value] *{color:#fff!important} -.conum[data-value]+b{display:none} -.conum[data-value]::after{content:attr(data-value)} -pre .conum[data-value]{position:relative;top:-.125em} -b.conum *{color:inherit!important} -.conum:not([data-value]):empty{display:none} -dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility} -h1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em} -p strong,td.content strong,div.footnote strong{letter-spacing:-.005em} -p,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem} -p{margin-bottom:1.25rem} -.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em} -.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc} -.print-only{display:none!important} -@page{margin:1.25cm .75cm} -@media print{*{box-shadow:none!important;text-shadow:none!important} -html{font-size:80%} -a{color:inherit!important;text-decoration:underline!important} -a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important} -a[href^="http:"]:not(.bare)::after,a[href^="https:"]:not(.bare)::after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em} -abbr[title]{border-bottom:1px dotted} -abbr[title]::after{content:" (" attr(title) ")"} -pre,blockquote,tr,img,object,svg{page-break-inside:avoid} -thead{display:table-header-group} -svg{max-width:100%} -p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3} -h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid} -#header,#content,#footnotes,#footer{max-width:none} -#toc,.sidebarblock,.exampleblock>.content{background:none!important} -#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important} -body.book #header{text-align:center} -body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em} -body.book #header .details{border:0!important;display:block;padding:0!important} -body.book #header .details span:first-child{margin-left:0!important} -body.book #header .details br{display:block} -body.book #header .details br+span::before{content:none!important} -body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important} -body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always} -.listingblock code[data-lang]::before{display:block} -#footer{padding:0 .9375em} -.hide-on-print{display:none!important} -.print-only{display:block!important} -.hide-for-print{display:none!important} -.show-for-print{display:inherit!important}} -@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem} -.sect1{padding:0!important} -.sect1+.sect1{border:0} -#footer{background:none} -#footer-text{color:rgba(0,0,0,.6);font-size:.9em}} -@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}} -</style> -<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"> -</head> -<body id="top" class="book toc2 toc-left"> -<div id="header"> -<h1>AWS Cloud Development Kit (AWS CDK) v2</h1> -<div id="toc" class="toc2"> -<div id="toctitle">Table of Contents</div> -<ul class="sectlevel1"> -<li><a href="#home">1. What is the AWS CDK?</a> -<ul class="sectlevel2"> -<li><a href="#home-benefits">Benefits of the AWS CDK</a></li> -<li><a href="#home-example">1.1. Example of the AWS CDK</a></li> -<li><a href="#home-features">1.2. AWS CDK features</a></li> -<li><a href="#home-next">1.3. Next steps</a></li> -<li><a href="#home-learn">1.4. Learn more</a></li> -</ul> -</li> -<li><a href="#core-concepts">2. Learn AWS CDK core concepts</a> -<ul class="sectlevel2"> -<li><a href="#concepts-iac">2.1. AWS CDK and <code class="noloc">IaC</code></a></li> -<li><a href="#concepts-cfn">2.2. AWS CDK and AWS CloudFormation</a></li> -<li><a href="#concepts-abstractions">2.3. AWS CDK and abstractions</a></li> -<li><a href="#concepts-learn">2.4. Learn more about core AWS CDK concepts</a></li> -<li><a href="#languages">2.5. Supported programming languages for the AWS CDK</a></li> -<li><a href="#libraries">2.6. The AWS CDK libraries</a></li> -<li><a href="#projects">2.7. AWS CDK projects</a></li> -<li><a href="#apps">2.8. AWS CDK apps</a></li> -<li><a href="#stacks">2.9. Introduction to AWS CDK stacks</a></li> -<li><a href="#stages">2.10. Introduction to AWS CDK stages</a></li> -<li><a href="#constructs">2.11. AWS CDK Constructs</a></li> -<li><a href="#environments">2.12. Environments for the AWS CDK</a></li> -<li><a href="#bootstrapping">2.13. AWS CDK bootstrapping</a></li> -<li><a href="#resources">2.14. Resources and the AWS CDK</a></li> -<li><a href="#identifiers">2.15. Identifiers and the AWS CDK</a></li> -<li><a href="#tokens">2.16. Tokens and the AWS CDK</a></li> -<li><a href="#parameters">2.17. Parameters and the AWS CDK</a></li> -<li><a href="#tagging">2.18. Tags and the AWS CDK</a></li> -<li><a href="#assets">2.19. Assets and the AWS CDK</a></li> -<li><a href="#permissions">2.20. Permissions and the AWS CDK</a></li> -<li><a href="#context">2.21. Context values and the AWS CDK</a></li> -<li><a href="#featureflags">2.22. AWS CDK feature flags</a></li> -<li><a href="#aspects">2.23. Aspects and the AWS CDK</a></li> -</ul> -</li> -<li><a href="#prerequisites">3. AWS CDK prerequisites</a> -<ul class="sectlevel2"> -<li><a href="#prerequisites-account">3.1. Set up your AWS account</a></li> -<li><a href="#prerequisites-cli">3.2. Install and configure the AWS CLI</a></li> -<li><a href="#prerequisites-node">3.3. Install <code class="noloc">Node.js</code> and programming language prerequisites</a></li> -<li><a href="#prerequisites-next">3.4. Next steps</a></li> -</ul> -</li> -<li><a href="#getting-started">4. Getting started with the AWS CDK</a> -<ul class="sectlevel2"> -<li><a href="#getting-started-prerequisites">4.1. Prerequisites</a></li> -<li><a href="#getting-started-install">4.2. Install the AWS CDK <code class="noloc">CLI</code></a></li> -<li><a href="#getting-started-configure">4.3. Configure the AWS CDK <code class="noloc">CLI</code></a></li> -<li><a href="#getting-started-tools">4.4. (Optional) Install additional AWS CDK tools</a></li> -<li><a href="#getting-started-app">4.5. Create your first CDK app</a></li> -<li><a href="#hello-world">4.6. Tutorial: Create your first AWS CDK app</a></li> -</ul> -</li> -<li><a href="#work-with">5. Work with the AWS CDK library</a> -<ul class="sectlevel2"> -<li><a href="#work-with-library">5.1. Import the AWS CDK Library</a></li> -<li><a href="#work-with-library-reference">5.2. Using the AWS CDK API Reference</a></li> -<li><a href="#work-with-cdk-dependencies">5.3. Managing dependencies</a></li> -<li><a href="#work-with-cdk-compare">5.4. Comparing AWS CDK in <code class="noloc">TypeScript</code> with other languages</a></li> -<li><a href="#work-with-cdk-typescript">5.5. Working with the AWS CDK in TypeScript</a></li> -<li><a href="#work-with-cdk-javascript">5.6. Working with the AWS CDK in JavaScript</a></li> -<li><a href="#work-with-cdk-python">5.7. Working with the AWS CDK in Python</a></li> -<li><a href="#work-with-cdk-java">5.8. Working with the AWS CDK in Java</a></li> -<li><a href="#work-with-cdk-csharp">5.9. Working with the AWS CDK in C#</a></li> -<li><a href="#work-with-cdk-go">5.10. Working with the AWS CDK in Go</a></li> -</ul> -</li> -<li><a href="#best-practices">6. Best practices for developing and deploying cloud infrastructure with the AWS CDK</a> -<ul class="sectlevel2"> -<li><a href="#best-practices-organization">6.1. Organization best practices</a></li> -<li><a href="#best-practices-code">6.2. Coding best practices</a></li> -<li><a href="#best-practices-constructs">6.3. Construct best practices</a></li> -<li><a href="#best-practices-apps">6.4. Application best practices</a></li> -<li><a href="#best-practices-security">6.5. AWS CDK security best practices</a></li> -</ul> -</li> -<li><a href="#migrating-v2">7. Migrating from AWS CDK v1 to AWS CDK v2</a> -<ul class="sectlevel2"> -<li><a href="#migrating-v2-prerequisites">7.1. New prerequisites</a></li> -<li><a href="#migrating-v2-dp-upgrade">7.2. Upgrading from AWS CDK v2 Developer Preview</a></li> -<li><a href="#migrating-v2-v1-uppgrade">7.3. Migrating from AWS CDK v1 to CDK v2</a></li> -<li><a href="#migrating-v2-diff.title">7.4. Testing your migrated app before deploying</a></li> -<li><a href="#migrating-v2-trouble.title">7.5. Troubleshooting</a></li> -<li><a href="#finding-v1-stacks.title">7.6. Finding v1 stacks</a></li> -</ul> -</li> -<li><a href="#migrate">8. Migrate existing resources and AWS CloudFormation templates to the AWS CDK</a> -<ul class="sectlevel2"> -<li><a href="#migrate-intro">8.1. How migration works</a></li> -<li><a href="#migrate-benefits">8.2. Benefits of CDK Migrate</a></li> -<li><a href="#migrate-considerations">8.3. Considerations</a></li> -<li><a href="#migrate-prerequisites">8.4. Prerequisites</a></li> -<li><a href="#migrate-gs">8.5. Get started with CDK Migrate</a></li> -<li><a href="#migrate-stack">8.6. Migrate from an AWS CloudFormation stack</a></li> -<li><a href="#migrate-template">8.7. Migrate from an AWS CloudFormation template</a></li> -<li><a href="#migrate-resources">8.8. Migrate from deployed resources</a></li> -<li><a href="#migrate-manage">8.9. Manage and deploy your CDK app</a></li> -</ul> -</li> -<li><a href="#configure-access">9. Configure security credentials for the AWS CDK <code class="noloc">CLI</code></a> -<ul class="sectlevel2"> -<li><a href="#configure-access-prerequisites">9.1. Prerequisites</a></li> -<li><a href="#configure-access-how">9.2. How to configure security credentials</a></li> -<li><a href="#configure-access-sso">9.3. Configure and manage security credentials for IAM Identity Center users</a></li> -<li><a href="#configure-access-iam">9.4. Configure and manage security credentials for IAM users</a></li> -<li><a href="#configure-access-info">9.5. Additional information</a></li> -<li><a href="#configure-access-sso-example-cli">9.6. Example: Authenticate with IAM Identity Center automatic token refresh for use with the AWS CDK <code class="noloc">CLI</code></a></li> -</ul> -</li> -<li><a href="#configure-env">10. Configure environments to use with the AWS CDK</a> -<ul class="sectlevel2"> -<li><a href="#configure-env-where">10.1. Where you can specify environments from</a></li> -<li><a href="#configure-env-precedence">10.2. Environment precedence with the AWS CDK</a></li> -<li><a href="#configure-env-when">10.3. When to specify environments</a></li> -<li><a href="#configure-env-how">10.4. How to specify environments with the AWS CDK</a></li> -<li><a href="#configure-env-considerations">10.5. Considerations when configuring environments with the AWS CDK</a></li> -<li><a href="#configure-env-examples">10.6. Examples</a></li> -</ul> -</li> -<li><a href="#bootstrapping-env">11. Bootstrap your environment for use with the AWS CDK</a> -<ul class="sectlevel2"> -<li><a href="#bootstrapping-howto">11.1. How to bootstrap your environment</a></li> -<li><a href="#bootstrapping-env-when">11.2. When to bootstrap your environment</a></li> -<li><a href="#bootstrapping-env-default">11.3. Default resources created during bootstrapping</a></li> -<li><a href="#bootstrapping-env-permissions">11.4. Permissions to use when bootstrapping your environment</a></li> -<li><a href="#bootstrapping-env-customize">11.5. Customize bootstrapping</a></li> -<li><a href="#bootstrapping-env-pipelines">11.6. Bootstrapping with CDK Pipelines</a></li> -<li><a href="#bootstrap-template-history">11.7. Bootstrap template version history</a></li> -<li><a href="#bootstrapping-template">11.8. Upgrade from legacy to modern bootstrap template</a></li> -<li><a href="#bootstrapping-securityhub">11.9. Address Security Hub Findings</a></li> -<li><a href="#bootstrapping-env-considerations">11.10. Considerations</a></li> -<li><a href="#bootstrapping-customizing">11.11. Customize AWS CDK bootstrapping</a></li> -<li><a href="#customize-permissions-boundaries">11.12. Create and apply permissions boundaries for the AWS CDK</a></li> -<li><a href="#bootstrapping-troubleshoot">11.13. Troubleshoot AWS CDK bootstrapping issues</a></li> -</ul> -</li> -<li><a href="#develop">12. Develop AWS CDK applications</a> -<ul class="sectlevel2"> -<li><a href="#develop-prerequisites">12.1. Prerequisites</a></li> -<li><a href="#develop-overview">12.2. Developing AWS CDK applications overview</a></li> -<li><a href="#develop-gs">12.3. Get started with developing CDK applications</a></li> -<li><a href="#develop-library">12.4. Import and use the AWS CDK Library</a></li> -<li><a href="#develop-next">12.5. Next steps</a></li> -<li><a href="#usage-data">12.6. Configure AWS CDK usage data reporting</a></li> -<li><a href="#cfn-layer">12.7. Customize constructs from the AWS Construct Library</a></li> -<li><a href="#get-env-var">12.8. Get a value from an environment variable</a></li> -<li><a href="#get-cfn-param">12.9. Use CloudFormation parameters to get a CloudFormation value</a></li> -<li><a href="#use-cfn-template">12.10. Import an existing AWS CloudFormation template</a></li> -<li><a href="#get-ssm-value">12.11. Get a value from the Systems Manager Parameter Store</a></li> -<li><a href="#get-secrets-manager-value">12.12. Get a value from AWS Secrets Manager</a></li> -<li><a href="#how-to-set-cw-alarm">12.13. Set a CloudWatch alarm</a></li> -<li><a href="#get-context-var">12.14. Save and retrieve context variable values</a></li> -<li><a href="#use-cfn-public-registry">12.15. Use resources from the AWS CloudFormation Public Registry</a></li> -<li><a href="#define-iam-l2">12.16. Define permissions for L2 constructs with the AWS CDK</a></li> -</ul> -</li> -<li><a href="#configure-synth">13. Configure and perform CDK stack synthesis</a> -<ul class="sectlevel2"> -<li><a href="#configure-synth-bootstrap">13.1. How synthesis and bootstrapping work together</a></li> -<li><a href="#bootstrapping-synthesizers">13.2. How to configure CDK stack synthesis</a></li> -<li><a href="#configure-synth-stack">13.3. How to synthesize a CDK stack</a></li> -<li><a href="#how-synth-default">13.4. How synthesis works by default</a></li> -<li><a href="#bootstrapping-custom-synth">13.5. Customize CDK stack synthesis</a></li> -</ul> -</li> -<li><a href="#deploy">14. Deploy AWS CDK applications</a> -<ul class="sectlevel2"> -<li><a href="#deploy-how">14.1. How AWS CDK deployments work</a></li> -<li><a href="#deploy-prerequisites">14.2. Prerequisites for CDK deployments</a></li> -<li><a href="#deploy-how-synth">14.3. CDK app synthesis</a></li> -<li><a href="#deploy-how-deploy">14.4. Deploy your application</a></li> -<li><a href="#policy-validation-synthesis">14.5. AWS CDK policy validation at synthesis time</a></li> -<li><a href="#cdk-pipeline">14.6. Continuous integration and delivery (CI/CD) using CDK Pipelines</a></li> -<li><a href="#build-containers">14.7. Build and deploy container image assets in CDK apps</a></li> -<li><a href="#deploy-troubleshoot">14.8. Troubleshoot AWS CDK deployments</a></li> -</ul> -</li> -<li><a href="#toolkit-library">15. Perform programmatic actions using the CDK Toolkit Library</a> -<ul class="sectlevel2"> -<li><a href="#toolkit-library-intro">15.1. What is the CDK Toolkit Library Library?</a></li> -<li><a href="#toolkit-library-gs">15.2. Get started with the CDK Toolkit Library</a></li> -</ul> -</li> -<li><a href="#testing">16. Test AWS CDK applications</a> -<ul class="sectlevel2"> -<li><a href="#testing-locally">16.1. Locally test and build AWS CDK applications with the AWS SAM <code class="noloc">CLI</code></a></li> -<li><a href="#testing-getting-started">16.2. Getting started</a></li> -<li><a href="#testing-app">16.3. The example stack</a></li> -<li><a href="#testing-lambda">16.4. The Lambda function</a></li> -<li><a href="#testing-running-tests">16.5. Running tests</a></li> -<li><a href="#testing-fine-grained">16.6. Fine-grained assertions</a></li> -<li><a href="#testing-snapshot">16.7. Snapshot tests</a></li> -<li><a href="#testing-tips">16.8. Tips for tests</a></li> -</ul> -</li> -<li><a href="#cli">17. AWS CDK <code class="noloc">CLI</code> reference</a> -<ul class="sectlevel2"> -<li><a href="#cli-commands">17.1. CDK <code class="noloc">CLI</code> commands</a></li> -<li><a href="#cli-options">17.2. Specify options and their values</a></li> -<li><a href="#cli-help">17.3. Built-in help</a></li> -<li><a href="#version-reporting">17.4. Version reporting</a></li> -<li><a href="#cli-auth">17.5. Authentication with AWS</a></li> -<li><a href="#cli-environment">17.6. Specify Region and other configuration</a></li> -<li><a href="#cli-app-command">17.7. Specify the app command</a></li> -<li><a href="#cli-stacks">17.8. Specify stacks</a></li> -<li><a href="#cli-bootstrap">17.9. Bootstrap your AWS environment</a></li> -<li><a href="#cli-init">17.10. Create a new app</a></li> -<li><a href="#cli-list">17.11. List stacks</a></li> -<li><a href="#cli-synth">17.12. Synthesize stacks</a></li> -<li><a href="#cli-deploy">17.13. Deploy stacks</a></li> -<li><a href="#cli-diff">17.14. Compare stacks</a></li> -<li><a href="#cli-import">17.15. Import existing resources into a stack</a></li> -<li><a href="#cli-config">17.16. Configuration (<code class="path">cdk.json</code>)</a></li> -</ul> -</li> -<li><a href="#ref-cli-cmd">18. AWS CDK <code class="noloc">CLI</code> command reference</a> -<ul class="sectlevel2"> -<li><a href="#ref-cli-cmd-usage">18.1. Usage</a></li> -<li><a href="#ref-cli-cmd-commands">18.2. Commands</a></li> -<li><a href="#ref-cli-cmd-options">18.3. Global options</a></li> -<li><a href="#ref-cli-cmd-configure">18.4. Providing and configuring options</a></li> -<li><a href="#ref-cli-cmd-pass">18.5. Passing options at the command line</a></li> -<li><a href="#ref-cli-cmd-ack">18.6. <code class="noloc">cdk acknowledge</code></a></li> -<li><a href="#ref-cli-cmd-bootstrap">18.7. <code class="noloc">cdk bootstrap</code></a></li> -<li><a href="#ref-cli-cmd-context">18.8. <code class="noloc">cdk context</code></a></li> -<li><a href="#ref-cli-cmd-deploy">18.9. <code class="noloc">cdk deploy</code></a></li> -<li><a href="#ref-cli-cmd-destroy">18.10. <code class="noloc">cdk destroy</code></a></li> -<li><a href="#ref-cli-cmd-diff">18.11. <code class="noloc">cdk diff</code></a></li> -<li><a href="#ref-cli-cmd-docs">18.12. <code class="noloc">cdk docs</code></a></li> -<li><a href="#ref-cli-cmd-doctor">18.13. <code class="noloc">cdk doctor</code></a></li> -<li><a href="#ref-cli-cmd-gc">18.14. <code class="noloc">cdk gc</code></a></li> -<li><a href="#ref-cli-cmd-import">18.15. <code class="noloc">cdk import</code></a></li> -<li><a href="#ref-cli-cmd-init">18.16. <code class="noloc">cdk init</code></a></li> -<li><a href="#ref-cli-cmd-list">18.17. <code class="noloc">cdk list</code></a></li> -<li><a href="#ref-cli-cmd-metadata">18.18. <code class="noloc">cdk metadata</code></a></li> -<li><a href="#ref-cli-cdk-migrate">18.19. <code class="noloc">cdk migrate</code></a></li> -<li><a href="#ref-cli-cmd-notices">18.20. <code class="noloc">cdk notices</code></a></li> -<li><a href="#ref-cli-cmd-rollback">18.21. <code class="noloc">cdk rollback</code></a></li> -<li><a href="#ref-cli-cmd-synth">18.22. <code class="noloc">cdk synthesize</code></a></li> -<li><a href="#ref-cli-cmd-watch">18.23. <code class="noloc">cdk watch</code></a></li> -</ul> -</li> -<li><a href="#reference">19. AWS CDK reference</a> -<ul class="sectlevel2"> -<li><a href="#reference-api">19.1. API reference</a></li> -<li><a href="#versioning">19.2. AWS CDK versioning</a></li> -<li><a href="#videos">19.3. AWS CDK video resources</a></li> -</ul> -</li> -<li><a href="#how-tos">20. AWS CDK tutorials and examples</a> -<ul class="sectlevel2"> -<li><a href="#serverless-example">20.1. Tutorial: Create a serverless Hello World application</a></li> -<li><a href="#stack-how-to-create-multiple-stacks">20.2. Example: Create a CDK app with multiple stacks</a></li> -<li><a href="#ecs-example">20.3. Example: Create an AWS Fargate service using the AWS CDK</a></li> -</ul> -</li> -<li><a href="#tools">21. Use other tools with the AWS CDK</a> -<ul class="sectlevel2"> -<li><a href="#vscode">21.1. AWS Toolkit for Visual Studio Code</a></li> -<li><a href="#sam">21.2. AWS SAM integration</a></li> -</ul> -</li> -<li><a href="#security">22. Security for the AWS Cloud Development Kit (AWS CDK)</a> -<ul class="sectlevel2"> -<li><a href="#security-iam">22.1. Identity and access management for the AWS Cloud Development Kit (AWS CDK)</a></li> -<li><a href="#compliance-validation">22.2. Compliance validation for the AWS Cloud Development Kit (AWS CDK)</a></li> -<li><a href="#disaster-recovery-resiliency">22.3. Resilience for the AWS Cloud Development Kit (AWS CDK)</a></li> -<li><a href="#infrastructure-security">22.4. Infrastructure security for the AWS Cloud Development Kit (AWS CDK)</a></li> -</ul> -</li> -<li><a href="#troubleshooting">23. Troubleshooting common AWS CDK issues</a></li> -<li><a href="#pgp-keys">24. OpenPGP keys for the AWS CDK and jsii</a> -<ul class="sectlevel2"> -<li><a href="#pgp-keys-current">24.1. Current keys</a></li> -<li><a href="#pgp-keys-expired">24.2. Historical keys</a></li> -</ul> -</li> -<li><a href="#doc-history">25. AWS CDK Developer Guide history</a> -<ul class="sectlevel2"> -<li><a href="#unknown-title">25.1. Unknown Title!</a></li> -</ul> -</li> -</ul> -</div> -</div> -<div id="content"> -<div id="preamble"> -<div class="sectionbody"> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Provides a conceptual overview and practical examples to help you understand the features provided by the AWS CDK and how to use them.</p> -</div> -</blockquote> -</div> -<div class="paragraph banner info"> -<p>This is the AWS CDK v2 Developer Guide. The older CDK v1 entered maintenance on June 1, 2022 and ended support on June 1, 2023.</p> -</div> -</div> -</div> -<div class="sect1 topic"> -<h2 id="home">1. What is the AWS CDK?</h2> -<div class="sectionbody"> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>The AWS Cloud Development Kit (AWS CDK) is an open-source software development framework for defining cloud infrastructure in code and provisioning it through AWS CloudFormation.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>The AWS Cloud Development Kit (AWS CDK) is an open-source software development framework for defining cloud infrastructure in code and provisioning it through AWS CloudFormation.</p> -</div> -<div class="paragraph"> -<p>The AWS CDK consists of two primary parts:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><strong><a href="#constructs">AWS CDK Construct Library</a></strong> – A collection of pre-written modular and reusable pieces of code, called constructs, that you can use, modify, and integrate to develop your infrastructure quickly. The goal of the AWS CDK Construct Library is to reduce the complexity required to define and integrate AWS services together when building applications on AWS.</p> -</li> -<li> -<p><strong><a href="#cli">AWS CDK Command Line Interface (AWS CDK CLI)</a></strong> – A command line tool for interacting with CDK apps. Use the CDK <code class="noloc">CLI</code> to create, manage, and deploy your AWS CDK projects. The CDK <code class="noloc">CLI</code> is also referred to as the CDK Toolkit.</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>The AWS CDK supports <code class="noloc">TypeScript</code>, <code class="noloc">JavaScript</code>, <code class="noloc">Python</code>, <code class="noloc">Java</code>, <code class="noloc">C#/.Net</code>, and <code class="noloc">Go</code>. You can use any of these supported programming languages to define reusable cloud components known as <a href="#constructs">constructs</a>. You compose these together into <a href="#stacks">stacks</a> and <a href="#apps">apps</a>. Then, you deploy your CDK applications to AWS CloudFormation to provision or update your resources.</p> -</div> -<div class="imageblock"> -<div class="content"> -<img src="images/AppStacks.png" alt="AWS CDK app structure with stacks, constructs, and deployment to CloudFormation."> -</div> -</div> -<div class="sect2"> -<h3 id="home-benefits">Benefits of the AWS CDK</h3> -<div class="paragraph"> -<p>Use the AWS CDK to develop reliable, scalable, cost-effective applications in the cloud with the considerable expressive power of a programming language. This approach yields many benefits, including:</p> -</div> -<div id="home-benefits-iac" class="dlist"> -<dl> -<dt class="hdlist1">Develop and manage your infrastructure as code (IaC)</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Practice <em>infrastructure as code</em> to create, deploy, and maintain infrastructure in a programmatic, descriptive, and declarative way. With IaC, you treat infrastructure the same way developers treat code. This results in a scalable and structured approach to managing infrastructure. To learn more about IaC, see <a href="https://docs.aws.amazon.com/whitepapers/latest/introduction-devops-aws/infrastructure-as-code.html">Infrastructure as code</a> in the <em>Introduction to DevOps on AWS Whitepaper</em>.</p> -<div class="paragraph"> -<p>With the AWS CDK, you can put your infrastructure, application code, and configuration all in one place, ensuring that you have a complete, cloud-deployable system at every milestone. Employ software engineering best practices such as code reviews, unit tests, and source control to make your infrastructure more robust.</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="home-benefits-languages" class="dlist"> -<dl> -<dt class="hdlist1">Define your cloud infrastructure using general-purpose programming languages</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>With the AWS CDK, you can use any of the following programming languages to define your cloud infrastructure: <code class="noloc">TypeScript</code>, <code class="noloc">JavaScript</code>, <code class="noloc">Python</code>, <code class="noloc">Java</code>, <code class="noloc">C#/.Net</code>, and <code class="noloc">Go</code>. Choose your preferred language and use programming elements like parameters, conditionals, loops, composition, and inheritance to define the desired outcome of your infrastructure.</p> -<div class="paragraph"> -<p>Use the same programming language to define your infrastructure and your application logic.</p> -</div> -<div class="paragraph"> -<p>Receive the benefits of developing infrastructure in your preferred IDE (Integrated Development Environment), such as syntax highlighting and intelligent code completion.</p> -</div> -<div class="imageblock"> -<div class="content"> -<img src="images/CodeCompletion.png" alt="Code snippet showing AWS CDK setup for ECS cluster with VPC and Fargate service configuration."> -</div> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="home-benefits-cfn" class="dlist"> -<dl> -<dt class="hdlist1">Deploy infrastructure through AWS CloudFormation</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>AWS CDK integrates with AWS CloudFormation to deploy and provision your infrastructure on AWS. AWS CloudFormation is a managed AWS service that offers extensive support of resource and property configurations for provisioning services on AWS. With AWS CloudFormation, you can perform infrastructure deployments predictably and repeatedly, with rollback on error. If you are already familiar with AWS CloudFormation, you don’t have to learn a new IaC management service when getting started with the AWS CDK.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="home-benefits-constructs" class="dlist"> -<dl> -<dt class="hdlist1">Get started developing your application quickly with constructs</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Develop faster by using and sharing reusable components called constructs. Use low-level constructs to define individual AWS CloudFormation resources and their properties. Use high-level constructs to quickly define larger components of your application, with sensible, secure defaults for your AWS resources, defining more infrastructure with less code.</p> -<div class="paragraph"> -<p>Create your own constructs that are customized for your unique use cases and share them across your organization or even with the public.</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect2"> -<h3 id="home-example">1.1. Example of the AWS CDK</h3> -<div class="paragraph"> -<p>The following is an example of using the AWS CDK Constructs Library to create an Amazon Elastic Container Service (Amazon ECS) service with AWS Fargate launch type. For more details of this example, see <a href="#ecs-example">Example: Create an AWS Fargate service using the AWS CDK</a>.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">export class MyEcsConstructStack extends Stack { - constructor(scope: App, id: string, props?: StackProps) { - super(scope, id, props); - - const vpc = new ec2.Vpc(this, "MyVpc", { - maxAzs: 3 // Default is all AZs in region - }); - - const cluster = new ecs.Cluster(this, "MyCluster", { - vpc: vpc - }); - - // Create a load-balanced Fargate service and make it public - new ecs_patterns.ApplicationLoadBalancedFargateService(this, "MyFargateService", { - cluster: cluster, // Required - cpu: 512, // Default is 256 - desiredCount: 6, // Default is 1 - taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample") }, - memoryLimitMiB: 2048, // Default is 512 - publicLoadBalancer: true // Default is false - }); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">class MyEcsConstructStack extends Stack { - constructor(scope, id, props) { - super(scope, id, props); - - const vpc = new ec2.Vpc(this, "MyVpc", { - maxAzs: 3 // Default is all AZs in region - }); - - const cluster = new ecs.Cluster(this, "MyCluster", { - vpc: vpc - }); - - // Create a load-balanced Fargate service and make it public - new ecs_patterns.ApplicationLoadBalancedFargateService(this, "MyFargateService", { - cluster: cluster, // Required - cpu: 512, // Default is 256 - desiredCount: 6, // Default is 1 - taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample") }, - memoryLimitMiB: 2048, // Default is 512 - publicLoadBalancer: true // Default is false - }); - } -} - -module.exports = { MyEcsConstructStack }</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">class MyEcsConstructStack(Stack): - - def __init__(self, scope: Construct, id: str, **kwargs) -> None: - super().__init__(scope, id, **kwargs) - - vpc = ec2.Vpc(self, "MyVpc", max_azs=3) # default is all AZs in region - - cluster = ecs.Cluster(self, "MyCluster", vpc=vpc) - - ecs_patterns.ApplicationLoadBalancedFargateService(self, "MyFargateService", - cluster=cluster, # Required - cpu=512, # Default is 256 - desired_count=6, # Default is 1 - task_image_options=ecs_patterns.ApplicationLoadBalancedTaskImageOptions( - image=ecs.ContainerImage.from_registry("amazon/amazon-ecs-sample")), - memory_limit_mib=2048, # Default is 512 - public_load_balancer=True) # Default is False</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">public class MyEcsConstructStack extends Stack { - - public MyEcsConstructStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public MyEcsConstructStack(final Construct scope, final String id, - StackProps props) { - super(scope, id, props); - - Vpc vpc = Vpc.Builder.create(this, "MyVpc").maxAzs(3).build(); - - Cluster cluster = Cluster.Builder.create(this, "MyCluster") - .vpc(vpc).build(); - - ApplicationLoadBalancedFargateService.Builder.create(this, "MyFargateService") - .cluster(cluster) - .cpu(512) - .desiredCount(6) - .taskImageOptions( - ApplicationLoadBalancedTaskImageOptions.builder() - .image(ContainerImage - .fromRegistry("amazon/amazon-ecs-sample")) - .build()).memoryLimitMiB(2048) - .publicLoadBalancer(true).build(); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">public class MyEcsConstructStack : Stack -{ - public MyEcsConstructStack(Construct scope, string id, IStackProps props=null) : base(scope, id, props) - { - var vpc = new Vpc(this, "MyVpc", new VpcProps - { - MaxAzs = 3 - }); - - var cluster = new Cluster(this, "MyCluster", new ClusterProps - { - Vpc = vpc - }); - - new ApplicationLoadBalancedFargateService(this, "MyFargateService", - new ApplicationLoadBalancedFargateServiceProps - { - Cluster = cluster, - Cpu = 512, - DesiredCount = 6, - TaskImageOptions = new ApplicationLoadBalancedTaskImageOptions - { - Image = ContainerImage.FromRegistry("amazon/amazon-ecs-sample") - }, - MemoryLimitMiB = 2048, - PublicLoadBalancer = true, - }); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">func NewMyEcsConstructStack(scope constructs.Construct, id string, props *MyEcsConstructStackProps) awscdk.Stack { - - var sprops awscdk.StackProps - - if props != nil { - sprops = props.StackProps - } - - stack := awscdk.NewStack(scope, &id, &sprops) - - vpc := awsec2.NewVpc(stack, jsii.String("MyVpc"), &awsec2.VpcProps{ - MaxAzs: jsii.Number(3), // Default is all AZs in region - }) - - cluster := awsecs.NewCluster(stack, jsii.String("MyCluster"), &awsecs.ClusterProps{ - Vpc: vpc, - }) - - awsecspatterns.NewApplicationLoadBalancedFargateService(stack, jsii.String("MyFargateService"), - &awsecspatterns.ApplicationLoadBalancedFargateServiceProps{ - Cluster: cluster, // required - Cpu: jsii.Number(512), // default is 256 - DesiredCount: jsii.Number(5), // default is 1 - MemoryLimitMiB: jsii.Number(2048), // Default is 512 - TaskImageOptions: &awsecspatterns.ApplicationLoadBalancedTaskImageOptions{ - Image: awsecs.ContainerImage_FromRegistry(jsii.String("amazon/amazon-ecs-sample"), nil), - }, - PublicLoadBalancer: jsii.Bool(true), // Default is false - }) - - return stack - -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>This class produces an AWS CloudFormation <a href="https://github.com/awsdocs/aws-cdk-guide/blob/main/doc_source/my_ecs_construct-stack.yaml">template of more than 500 lines</a>. Deploying the AWS CDK app produces more than 50 resources of the following types.</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-eip.html">AWS::EC2::EIP</a></p> -</li> -<li> -<p><a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-internetgateway.html">AWS::EC2::InternetGateway</a></p> -</li> -<li> -<p><a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-natgateway.html">AWS::EC2::NatGateway</a></p> -</li> -<li> -<p><a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-route.html">AWS::EC2::Route</a></p> -</li> -<li> -<p><a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-routetable.html">AWS::EC2::RouteTable</a></p> -</li> -<li> -<p><a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-security-group.html">AWS::EC2::SecurityGroup</a></p> -</li> -<li> -<p><a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-subnet.html">AWS::EC2::Subnet</a></p> -</li> -<li> -<p><a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-subnet-route-table-assoc.html">AWS::EC2::SubnetRouteTableAssociation</a></p> -</li> -<li> -<p><a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpc-gateway-attachment.html">AWS::EC2::VPCGatewayAttachment</a></p> -</li> -<li> -<p><a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpc.html">AWS::EC2::VPC</a></p> -</li> -<li> -<p><a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ecs-cluster.html">AWS::ECS::Cluster</a></p> -</li> -<li> -<p><a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ecs-service.html">AWS::ECS::Service</a></p> -</li> -<li> -<p><a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ecs-taskdefinition.html">AWS::ECS::TaskDefinition</a></p> -</li> -<li> -<p><a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticloadbalancingv2-listener.html">AWS::ElasticLoadBalancingV2::Listener</a></p> -</li> -<li> -<p><a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticloadbalancingv2-loadbalancer.html">AWS::ElasticLoadBalancingV2::LoadBalancer</a></p> -</li> -<li> -<p><a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticloadbalancingv2-targetgroup.html">AWS::ElasticLoadBalancingV2::TargetGroup</a></p> -</li> -<li> -<p><a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-policy.html">AWS::IAM::Policy</a></p> -</li> -<li> -<p><a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html">AWS::IAM::Role</a></p> -</li> -<li> -<p><a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-logs-loggroup.html">AWS::Logs::LogGroup</a></p> -</li> -</ul> -</div> -</div> -<div class="sect2"> -<h3 id="home-features">1.2. AWS CDK features</h3> -<div class="sect3"> -<h4 id="home-features-repo">1.2.1. The AWS CDK <code class="noloc">GitHub</code> repository</h4> -<div class="paragraph"> -<p>For the official AWS CDK <code class="noloc">GitHub</code> repository, see <a href="https://github.com/aws/aws-cdk">aws-cdk</a>. Here, you can submit <a href="https://github.com/aws/aws-cdk/issues">issues</a>, view our <a href="https://github.com/aws/aws-cdk/blob/main/LICENSE">license</a>, track <a href="https://github.com/aws/aws-cdk/releases">releases</a>, and more.</p> -</div> -<div class="paragraph"> -<p>Because the AWS CDK is open-source, the team encourages you to contribute to make it an even better tool. For details, see <a href="https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md">Contributing to the AWS Cloud Development Kit (AWS CDK)</a>.</p> -</div> -</div> -<div class="sect3"> -<h4 id="home-features-api">1.2.2. The AWS CDK API reference</h4> -<div class="paragraph"> -<p>The AWS CDK Construct Library provides APIs to define your CDK application and add CDK constructs to the application. For more information, see the <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-construct-library.html">AWS CDK API Reference</a>.</p> -</div> -</div> -<div class="sect3"> -<h4 id="home-features-cpm">1.2.3. The Construct Programming Model</h4> -<div class="paragraph"> -<p>The Construct Programming Model (CPM) extends the concepts behind the AWS CDK into additional domains. Other tools using the CPM include:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><a href="https://www.terraform.io/docs/cdktf/index.html">CDK for Terraform</a> (CDKtf)</p> -</li> -<li> -<p><a href="https://cdk8s.io/">CDK for Kubernetes</a> (CDK8s)</p> -</li> -<li> -<p><a href="https://github.com/projen/projen">Projen</a>, for building project configurations</p> -</li> -</ul> -</div> -</div> -<div class="sect3"> -<h4 id="home-features-hub">1.2.4. The Construct Hub</h4> -<div class="paragraph"> -<p>The <a href="https://constructs.dev/">Construct Hub</a> is an online registry where you can find, publish, and share open-source AWS CDK libraries.</p> -</div> -</div> -</div> -<div class="sect2"> -<h3 id="home-next">1.3. Next steps</h3> -<div class="paragraph"> -<p>To get started with using the AWS CDK, see <a href="#getting-started">Getting started with the AWS CDK</a>.</p> -</div> -</div> -<div class="sect2"> -<h3 id="home-learn">1.4. Learn more</h3> -<div class="paragraph"> -<p>To continue learning about the AWS CDK, see the following:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><strong><a href="#core-concepts">Learn AWS CDK core concepts</a></strong> – Important concepts and terms for the AWS CDK.</p> -</li> -<li> -<p><strong><a href="https://cdkworkshop.com/">AWS CDK Workshop</a></strong> – Hands-on workshop to learn and use the AWS CDK.</p> -</li> -<li> -<p><strong><a href="https://cdkpatterns.com/">AWS CDK Patterns</a></strong> – Open-source collection of AWS serverless architecture patterns, built for the AWS CDK by AWS experts.</p> -</li> -<li> -<p><strong><a href="https://github.com/aws-samples/aws-cdk-examples">AWS CDK code examples</a></strong> – <code class="noloc">GitHub</code> repository of example AWS CDK projects.</p> -</li> -<li> -<p><strong><a href="https://cdk.dev/">cdk.dev</a></strong> – Community-driven hub for the AWS CDK, including a community <code class="noloc">Slack</code> workspace.</p> -</li> -<li> -<p><strong><a href="https://github.com/kalaiser/awesome-cdk">Awesome CDK</a></strong> – <code class="noloc">GitHub</code> repository containing a curated list of AWS CDK open-source projects, guides, blogs, and other resources.</p> -</li> -<li> -<p><strong><a href="https://aws.amazon.com/solutions/constructs/">AWS Solutions Constructs</a></strong> – Vetted, configuration infrastructure as code (IaC) patterns that can easily be assembled into production-ready applications.</p> -</li> -<li> -<p><strong><a href="https://aws.amazon.com/blogs/developer/category/developer-tools/aws-cloud-development-kit/">AWS Developer Tools Blog</a></strong> – Blog posts filtered for the AWS CDK.</p> -</li> -<li> -<p><strong><a href="https://stackoverflow.com/questions/tagged/aws-cdk">AWS CDK on Stack Overflow</a></strong> – Questions tagged with * aws-cdk* on <code class="noloc">Stack Overflow</code>.</p> -</li> -<li> -<p><strong><a href="https://docs.aws.amazon.com/cloud9/latest/user-guide/sample-cdk.html">AWS CDK tutorial for AWS Cloud9</a></strong> – Tutorial on using the AWS CDK with the AWS Cloud9 development environment.</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>To learn more about related topics to the AWS CDK, see the following:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><strong><a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-whatis-concepts.html">AWS CloudFormation concepts</a></strong> – Since the AWS CDK is built to work with AWS CloudFormation, we recommend that you learn and understand key AWS CloudFormation concepts.</p> -</li> -<li> -<p><strong><a href="https://docs.aws.amazon.com/general/latest/gr/glos-chap.html">AWS Glossary</a></strong> – Definitions of key terms used across AWS.</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>To learn more about tools related to the AWS CDK that can be used to simplify serverless application development and deployment, see the following:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><strong><a href="https://aws.amazon.com/serverless/sam/">AWS Serverless Application Model</a></strong> – An open-source developer tool that simplifies and improves the experience of building and running serverless applications on AWS.</p> -</li> -<li> -<p><strong><a href="https://github.com/aws/chalice">AWS Chalice</a></strong> – A framework for writing serverless apps in <code class="noloc">Python</code>.</p> -</li> -</ul> -</div> -</div> -</div> -</div> -<div class="sect1 topic"> -<h2 id="core-concepts">2. Learn AWS CDK core concepts</h2> -<div class="sectionbody"> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Learn core concepts behind the AWS Cloud Development Kit (AWS CDK).</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>Learn core concepts behind the AWS Cloud Development Kit (AWS CDK).</p> -</div> -<div class="sect2"> -<h3 id="concepts-iac">2.1. AWS CDK and <code class="noloc">IaC</code></h3> -<div class="paragraph"> -<p>The AWS CDK is an open-source framework that you can use to manage your AWS infrastructure using code. This approach is known as <em>infrastructure as code (<code class="noloc">IaC</code>)</em>. By managing and provisioning your infrastructure as code, you treat your infrastructure in the same way that developers treat code. This provides many benefits, such as version control and scalability. To learn more about IaC, see <a href="https://aws.amazon.com/what-is/iac/">What is Infrastructure as Code?</a></p> -</div> -</div> -<div class="sect2"> -<h3 id="concepts-cfn">2.2. AWS CDK and AWS CloudFormation</h3> -<div class="paragraph"> -<p>The AWS CDK is tightly integrated with AWS CloudFormation. AWS CloudFormation is a fully managed service that you can use to manage and provision your infrastructure on AWS. With AWS CloudFormation, you define your infrastructure in templates and deploy them to AWS CloudFormation. The AWS CloudFormation service then provisions your infrastructure according to the configuration defined on your templates.</p> -</div> -<div class="paragraph"> -<p>AWS CloudFormation templates are <em>declarative</em>, meaning they declare the desired state or outcome of your infrastructure. Using JSON or YAML, you declare your AWS infrastructure by defining AWS <em>resources</em> and <em>properties</em>. Resources represent the many services on AWS and properties represent your desired configuration of those services. When you deploy your template to AWS CloudFormation, your resources and their configured properties are provisioned as described on your template.</p> -</div> -<div class="paragraph"> -<p>With the AWS CDK, you can manage your infrastructure <em>imperatively</em>, using general-purpose programming languages. Instead of just defining a desired state declaratively, you can define the logic or sequence necessary to reach the desired state. For example, you can use <code>if</code> statements or conditional loops that determine how to reach a desired end state for your infrastructure.</p> -</div> -<div class="paragraph"> -<p>Infrastructure created with the AWS CDK is eventually translated, or <em>synthesized</em> into AWS CloudFormation templates and deployed using the AWS CloudFormation service. So while the AWS CDK offers a different approach to creating your infrastructure, you still receive the benefits of AWS CloudFormation, such as extensive AWS resource configuration support and robust deployment processes.</p> -</div> -<div class="paragraph"> -<p>To learn more about AWS CloudFormation, see <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/Welcome.html">What is AWS CloudFormation?</a> in the <em>AWS CloudFormation User Guide</em>.</p> -</div> -</div> -<div class="sect2"> -<h3 id="concepts-abstractions">2.3. AWS CDK and abstractions</h3> -<div class="paragraph"> -<p>With AWS CloudFormation, you must define every detail of how your resources are configured. This provides the benefit of having complete control over your infrastructure. However, this requires you to learn, understand, and create robust templates that contain resource configuration details and relationships between resources, such as permissions and event-driven interactions.</p> -</div> -<div class="paragraph"> -<p>With the AWS CDK, you can have the same control over your resource configurations. However, the AWS CDK also offers powerful abstractions, which can speed up and simplify the infrastructure development process. For example, the AWS CDK includes constructs that provide sensible default configurations and helper methods that generate boilerplate code for you. The AWS CDK also offers tools, such as the AWS CDK Command Line Interface (AWS CDK <code class="noloc">CLI</code>), that perform infrastructure management actions for you.</p> -</div> -</div> -<div class="sect2"> -<h3 id="concepts-learn">2.4. Learn more about core AWS CDK concepts</h3> -<div class="sect3"> -<h4 id="concepts-learn-interact">2.4.1. Interacting with the AWS CDK</h4> -<div class="paragraph"> -<p>When using with the AWS CDK, you will primarily interact with the AWS Construct Library and the AWS CDK <code class="noloc">CLI</code>.</p> -</div> -</div> -<div class="sect3"> -<h4 id="concepts-learn-develop">2.4.2. Developing with the AWS CDK</h4> -<div class="paragraph"> -<p>The AWS CDK can be written in any <a href="#languages">supported programming language</a>. You start with a <a href="#projects">CDK project</a>, which contains a structure of folders and files, including <a href="#assets">assets</a>. Within the project, you create a <a href="#apps">CDK application</a>. Within the app, you define a <a href="#stacks">stack</a>, which directly represents a CloudFormation stack. Within the stack, you define your AWS resources and properties using <a href="#constructs">constructs</a>.</p> -</div> -</div> -<div class="sect3"> -<h4 id="concepts-learn-deploy">2.4.3. Deploying with the AWS CDK</h4> -<div class="paragraph"> -<p>You deploy CDK apps into an AWS <a href="#environments">environment</a>. Before deploying, you must perform a one-time <a href="#bootstrapping">bootstrapping</a> to prepare your environment.</p> -</div> -</div> -<div class="sect3"> -<h4 id="concepts-learn-more">2.4.4. Learn more</h4> -<div class="paragraph"> -<p>To learn more about AWS CDK core concepts, see the topics in this section.</p> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="languages">2.5. Supported programming languages for the AWS CDK</h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>The AWS Cloud Development Kit (AWS CDK) has first-class support for the <code class="noloc">TypeScript</code>, <code class="noloc">JavaScript</code>, <code class="noloc">Python</code>, <code class="noloc">Java</code>, <code class="noloc">C#</code>, and <code class="noloc">Go</code> general-purpose programming languages.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>The AWS Cloud Development Kit (AWS CDK) has first-class support for the following general-purpose programming languages:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><code class="noloc">TypeScript</code></p> -</li> -<li> -<p><code class="noloc">JavaScript</code></p> -</li> -<li> -<p><code class="noloc">Python</code></p> -</li> -<li> -<p><code class="noloc">Java</code></p> -</li> -<li> -<p><code class="noloc">C#</code></p> -</li> -<li> -<p><code class="noloc">Go</code></p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>Other <code class="noloc">JVM</code> and <code class="noloc">.NET</code><code class="noloc">CLR</code> languages may also be used in theory, but we do not offer official support at this time.</p> -</div> -<div class="paragraph"> -<p>The AWS CDK is developed in one language, <code class="noloc">TypeScript</code>. To support the other languages, the AWS CDK utilizes a tool called <a href="https://github.com/aws/jsii">JSII</a> to generate language bindings.</p> -</div> -<div class="paragraph"> -<p>We attempt to offer each language’s usual conventions to make development with the AWS CDK as natural and intuitive as possible. For example, we distribute AWS Construct Library modules using your preferred language’s standard repository, and you install them using the language’s standard package manager. Methods and properties are also named using your language’s recommended naming patterns.</p> -</div> -<div class="paragraph"> -<p>The following are a few code examples:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const bucket = new s3.Bucket(this, 'amzn-s3-demo-bucket', { - bucketName: 'amzn-s3-demo-bucket', - versioned: true, - websiteRedirect: {hostName: 'aws.amazon.com'}});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const bucket = new s3.Bucket(this, 'amzn-s3-demo-bucket', { - bucketName: 'amzn-s3-demo-bucket', - versioned: true, - websiteRedirect: {hostName: 'aws.amazon.com'}});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">bucket = s3.Bucket("amzn-s3-demo-bucket", bucket_name="amzn-s3-demo-bucket", versioned=True, - website_redirect=s3.RedirectTarget(host_name="aws.amazon.com"))</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">Bucket bucket = Bucket.Builder.create(self, "amzn-s3-demo-bucket") - .bucketName("amzn-s3-demo-bucket") - .versioned(true) - .websiteRedirect(new RedirectTarget.Builder() - .hostName("aws.amazon.com").build()) - .build();</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">var bucket = new Bucket(this, "amzn-s3-demo-bucket", new BucketProps { - BucketName = "amzn-s3-demo-bucket", - Versioned = true, - WebsiteRedirect = new RedirectTarget { - HostName = "aws.amazon.com" - }});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">bucket := awss3.NewBucket(scope, jsii.String("amzn-s3-demo-bucket"), &awss3.BucketProps { - BucketName: jsii.String("amzn-s3-demo-bucket"), - Versioned: jsii.Bool(true), - WebsiteRedirect: &awss3.RedirectTarget { - HostName: jsii.String("aws.amazon.com"), - }, -})</code></pre> -</div> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>These code snippets are intended for illustration only. They are incomplete and won’t run as they are.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>The AWS Construct Library is distributed using each language’s standard package management tools, including <code class="noloc">NPM</code>, <code class="noloc">PyPi</code>, <code class="noloc">Maven</code>, and <code class="noloc">NuGet</code>. We also provide a version of the <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-construct-library.html">AWS CDK API Reference</a> for each language.</p> -</div> -<div class="paragraph"> -<p>To help you use the AWS CDK in your preferred language, this guide includes the following topics for supported languages:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><a href="#work-with-cdk-typescript">Working with the AWS CDK in TypeScript</a></p> -</li> -<li> -<p><a href="#work-with-cdk-javascript">Working with the AWS CDK in JavaScript</a></p> -</li> -<li> -<p><a href="#work-with-cdk-python">Working with the AWS CDK in Python</a></p> -</li> -<li> -<p><a href="#work-with-cdk-java">Working with the AWS CDK in Java</a></p> -</li> -<li> -<p><a href="#work-with-cdk-csharp">Working with the AWS CDK in C#</a></p> -</li> -<li> -<p><a href="#work-with-cdk-go">Working with the AWS CDK in Go</a></p> -</li> -</ul> -</div> -<div class="paragraph"> -<p><code class="noloc">TypeScript</code> was the first language supported by the AWS CDK, and much of the AWS CDK example code is written in <code class="noloc">TypeScript</code>. This guide includes a topic specifically to show how to adapt <code class="noloc">TypeScript</code> AWS CDK code for use with the other supported languages. For more information, see <a href="#work-with-cdk-compare">Comparing AWS CDK in TypeScript with other languages</a>.</p> -</div> -</div> -<div class="sect2 topic"> -<h3 id="libraries">2.6. The AWS CDK libraries</h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Learn about the core libraries that you will use with the AWS Cloud Development Kit (AWS CDK).</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>Learn about the core libraries that you will use with the AWS Cloud Development Kit (AWS CDK).</p> -</div> -<div class="sect3"> -<h4 id="libraries-cdk">2.6.1. The AWS CDK Library</h4> -<div class="paragraph"> -<p>The AWS CDK Library, also referred to as <code>aws-cdk-lib</code>, is the main library that you will use to develop applications with the AWS CDK. It is developed and maintained by AWS. This library contains base classes, such as <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.App.html">App</a></code> and <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html">Stack</a></code>. It also contains the libraries you will use to define your infrastructure through constructs.</p> -</div> -</div> -<div class="sect3"> -<h4 id="libraries-construct">2.6.2. The AWS Construct Library</h4> -<div class="paragraph"> -<p>The AWS Construct Library is a part of the AWS CDK Library. It contains a collection of <a href="#constructs">constructs</a> that are developed and maintained by AWS. It is organized into various modules for each AWS service. Each module includes constructs that you can use to define your AWS resources and properties.</p> -</div> -</div> -<div class="sect3"> -<h4 id="libraries-constructs">2.6.3. The Constructs library</h4> -<div class="paragraph"> -<p>The Constructs library, commonly referred to as <code>constructs</code>, is a library for defining and composing cloud infrastructure components. It contains the core <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html">Construct</a></code> class, which represents the construct building block. This class is the foundational base class of all constructs from the AWS Construct Library. The Constructs library is a separate general-purpose library that is used by other construct-based tools such as <em>CDK for <code class="noloc">Terraform</code></em> and <em>CDK for <code class="noloc">Kubernetes</code></em>.</p> -</div> -</div> -<div class="sect3"> -<h4 id="libraries-reference">2.6.4. The AWS CDK API reference</h4> -<div class="paragraph"> -<p>The <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-construct-library.html">AWS CDK API reference</a> contains official reference documentation for the AWS CDK Library, including the AWS Construct Library and Constructs library. A version of the API reference is provided for each supported programming language.</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>For AWS CDK Library (<code>aws-cdk-lib</code>) documentation, see <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib-readme.html">aws-cdk-lib module</a>.</p> -</li> -<li> -<p>Documentation for constructs in the AWS Construct Library are organized by AWS service in the following format: <code>aws-cdk-lib.[replaceable]</code><service>````. For example, construct documentation for Amazon Simple Storage Service (Amazon S3), can be found at <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3-readme.html">aws-cdk-lib.aws_s3 module</a>.</p> -</li> -<li> -<p>For Constructs library (constructs) documentation, see <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/constructs-readme.html">constructs module</a>.</p> -</li> -</ul> -</div> -<div class="sect4"> -<h5 id="libraries-reference-contribute">Contribute to the AWS CDK API reference</h5> -<div class="paragraph"> -<p>The AWS CDK is open-source and we welcome you to contribute. Community contributions positively impact and improve the AWS CDK. For instructions on contributing specifically to AWS CDK API reference documentation, see <a href="https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md#documentation">Documentation</a> in the <em>aws-cdk <code class="noloc">GitHub</code> repository</em>.</p> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="libraries-learn">2.6.5. Learn more</h4> -<div class="paragraph"> -<p>For instructions on importing and using the CDK Library, see <a href="#work-with">Work with the CDK library</a>.</p> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="projects">2.7. AWS CDK projects</h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>An AWS Cloud Development Kit (AWS CDK) project represents the files and folders that contain your CDK code. Contents will vary based on your programming language.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>An AWS Cloud Development Kit (AWS CDK) project represents the files and folders that contain your CDK code. Contents will vary based on your programming language.</p> -</div> -<div class="paragraph"> -<p>You can create your AWS CDK project manually or with the AWS CDK Command Line Interface (AWS CDK <code class="noloc">CLI</code>) <code>cdk init</code> command. In this topic, we will refer to the project structure and naming conventions of files and folders created by the AWS CDK CLI. You can customize and organize your CDK projects to fit your needs.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>Project structure created by the AWS CDK <code class="noloc">CLI</code> may vary across versions over time.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="sect3"> -<h4 id="projects-universal">2.7.1. Universal files and folders</h4> -<div id="projects-universal-git" class="dlist"> -<dl> -<dt class="hdlist1"><code class="noloc">.git</code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>If you have <code>git</code> installed, the AWS CDK <code class="noloc">CLI</code> automatically initializes a <code class="noloc">Git</code> repository for your project. The <code class="path">.git</code> directory contains information about the repository.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="projects-universal-gitignore" class="dlist"> -<dl> -<dt class="hdlist1"><code class="noloc">.gitignore</code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Text file used by <code class="noloc">Git</code> to specify files and folders to ignore.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="projects-universal-readme" class="dlist"> -<dl> -<dt class="hdlist1"><code class="noloc">README.md</code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Text file that provides you with basic guidance and important information for managing your AWS CDK project. Modify this file as necessary to document important information regarding your CDK project.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="projects-universal-cdk" class="dlist"> -<dl> -<dt class="hdlist1"><code class="noloc">cdk.json</code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Configuration file for the AWS CDK. This file provides instruction to the AWS CDK <code class="noloc">CLI</code> regarding how to run your app.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect3"> -<h4 id="projects-specific">2.7.2. Language-specific files and folders</h4> -<div class="paragraph"> -<p>The following files and folders are unique to each supported programming language.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1"><code class="noloc">TypeScript</code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The following is an example project created in the <code class="path">my-cdk-ts-project</code> directory using the <code>cdk init --language typescript</code> command:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">my-cdk-ts-project -├── .git -├── .gitignore -├── .npmignore -├── README.md -├── bin -│ └── my-cdk-ts-project.ts -├── cdk.json -├── jest.config.js -├── lib -│ └── my-cdk-ts-project-stack.ts -├── node_modules -├── package-lock.json -├── package.json -├── test -│ └── my-cdk-ts-project.test.ts -└── tsconfig.json</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">.npmignore</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>File that specifies which files and folders to ignore when publishing a package to the <code class="noloc">npm</code> registry. This file is similar to <code class="path">.gitignore</code>, but is specific to <code class="noloc">npm</code> packages.</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">bin/my-cdk-ts-project.ts</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The <em>application file</em> defines your CDK app. CDK projects can contain one or more application files. Application files are stored in the <code class="path">bin</code> folder.</p> -<div class="paragraph"> -<p>The following is an example of a basic application file that defines a CDK app:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">#!/usr/bin/env node -import 'source-map-support/register'; -import * as cdk from 'aws-cdk-lib'; -import { MyCdkTsProjectStack } from '../lib/my-cdk-ts-project-stack'; - -const app = new cdk.App(); -new MyCdkTsProjectStack(app, 'MyCdkTsProjectStack');</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">jest.config.js</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Configuration file for <code class="noloc">Jest</code>. <em><code class="noloc">Jest</code></em> is a popular <code class="noloc">JavaScript</code> testing framework.</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">lib/my-cdk-ts-project-stack.ts</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The <em>stack file</em> defines your CDK stack. Within your stack, you define AWS resources and properties using constructs.</p> -<div class="paragraph"> -<p>The following is an example of a basic stack file that defines a CDK stack:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as cdk from 'aws-cdk-lib'; -import { Construct } from 'constructs'; - -export class MyCdkTsProjectStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - // code that defines your resources and properties go here - } -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">node_modules</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Common folder in <code class="noloc">Node.js</code> projects that contain dependencies for your project.</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">package-lock.json</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Metadata file that works with the <code class="path">package.json</code> file to manage versions of dependencies.</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">package.json</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Metadata file that is commonly used in <code class="noloc">Node.js</code> projects. This file contains information about your CDK project such as the project name, script definitions, dependencies, and other import project-level information.</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">test/my-cdk-ts-project.test.ts</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>A test folder is created to organize tests for your CDK project. A sample test file is also created.</p> -<div class="paragraph"> -<p>You can write tests in <code class="noloc">TypeScript</code> and use <code class="noloc">Jest</code> to compile your <code class="noloc">TypeScript</code> code before running tests.</p> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">tsconfig.json</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Configuration file used in <code class="noloc">TypeScript</code> projects that specifies compiler options and project settings.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1"><code class="noloc">JavaScript</code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The following is an example project created in the <code class="path">my-cdk-js-project</code> directory using the <code>cdk init --language javascript</code> command:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">my-cdk-js-project -├── .git -├── .gitignore -├── .npmignore -├── README.md -├── bin -│ └── my-cdk-js-project.js -├── cdk.json -├── jest.config.js -├── lib -│ └── my-cdk-js-project-stack.js -├── node_modules -├── package-lock.json -├── package.json -└── test - └── my-cdk-js-project.test.js</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">.npmignore</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>File that specifies which files and folders to ignore when publishing a package to the <code class="noloc">npm</code> registry. This file is similar to <code class="path">.gitignore</code>, but is specific to <code class="noloc">npm</code> packages.</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">bin/my-cdk-js-project.js</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The <em>application file</em> defines your CDK app. CDK projects can contain one or more application files. Application files are stored in the <code class="path">bin</code> folder.</p> -<div class="paragraph"> -<p>The following is an example of a basic application file that defines a CDK app:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">#!/usr/bin/env node - -const cdk = require('aws-cdk-lib'); -const { MyCdkJsProjectStack } = require('../lib/my-cdk-js-project-stack'); - -const app = new cdk.App(); -new MyCdkJsProjectStack(app, 'MyCdkJsProjectStack');</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">jest.config.js</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Configuration file for <code class="noloc">Jest</code>. <em><code class="noloc">Jest</code></em> is a popular <code class="noloc">JavaScript</code> testing framework.</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">lib/my-cdk-js-project-stack.js</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The <em>stack file</em> defines your CDK stack. Within your stack, you define AWS resources and properties using constructs.</p> -<div class="paragraph"> -<p>The following is an example of a basic stack file that defines a CDK stack:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const { Stack, Duration } = require('aws-cdk-lib'); - -class MyCdkJsProjectStack extends Stack { - constructor(scope, id, props) { - super(scope, id, props); - - // code that defines your resources and properties go here - } -} - -module.exports = { MyCdkJsProjectStack }</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">node_modules</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Common folder in <code class="noloc">Node.js</code> projects that contain dependencies for your project.</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">package-lock.json</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Metadata file that works with the <code class="path">package.json</code> file to manage versions of dependencies.</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">package.json</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Metadata file that is commonly used in <code class="noloc">Node.js</code> projects. This file contains information about your CDK project such as the project name, script definitions, dependencies, and other import project-level information.</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">test/my-cdk-js-project.test.js</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>A test folder is created to organize tests for your CDK project. A sample test file is also created.</p> -<div class="paragraph"> -<p>You can write tests in <code class="noloc">JavaScript</code> and use <code class="noloc">Jest</code> to compile your <code class="noloc">JavaScript</code> code before running tests.</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1"><code class="noloc">Python</code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The following is an example project created in the <code class="path">my-cdk-py-project</code> directory using the <code>cdk init --language python</code> command:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">my-cdk-py-project -├── .git -├── .gitignore -├── .venv -├── README.md -├── app.py -├── cdk.json -├── my_cdk_py_project -│ ├── __init__.py -│ └── my_cdk_py_project_stack.py -├── requirements-dev.txt -├── requirements.txt -├── source.bat -└── tests - ├── __init__.py - └── unit</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">.venv</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The CDK <code class="noloc">CLI</code> automatically creates a virtual environment for your project. The <code class="path">.venv</code> directory refers to this virtual environment.</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">app.py</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The <em>application file</em> defines your CDK app. CDK projects can contain one or more application files.</p> -<div class="paragraph"> -<p>The following is an example of a basic application file that defines a CDK app:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">#!/usr/bin/env python3 -import os - -import aws_cdk as cdk - -from my_cdk_py_project.my_cdk_py_project_stack import MyCdkPyProjectStack - -app = cdk.App() -MyCdkPyProjectStack(app, "MyCdkPyProjectStack") - -app.synth()</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">my_cdk_py_project</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Directory that contains your <em>stack files</em>. The CDK <code class="noloc">CLI</code> creates the following here:</p> -<div class="ulist"> -<ul> -<li> -<p><code class="path"><em>init</em>.py </code> – An empty <code class="noloc">Python</code> package definition file.</p> -</li> -<li> -<p><code class="path">my_cdk_py_project</code> – File that defines your CDK stack. You then define AWS resources and properties within the stack using constructs.</p> -</li> -</ul> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</li> -</ul> -</div> -<div class="paragraph"> -<p>The following is an example of a stack file:</p> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">from aws_cdk import Stack - -from constructs import Construct - -class MyCdkPyProjectStack(Stack): - def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: - super().__init__(scope, construct_id, **kwargs) - - # code that defines your resources and properties go here</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">requirements-dev.txt</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>File similar to <code class="path">requirements.txt</code>, but used to manage dependencies specifically for development purposes rather than production.</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">requirements.txt</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Common file used in <code class="noloc">Python</code> projects to specify and manage project dependencies.</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">source.bat</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Batch file for <code class="noloc">Windows</code> that is used to set up the <code class="noloc">Python</code> virtual environment.</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">tests</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Directory that contains tests for your CDK project.</p> -<div class="paragraph"> -<p>The following is an example of a unit test:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">import aws_cdk as core -import aws_cdk.assertions as assertions - -from my_cdk_py_project.my_cdk_py_project_stack import MyCdkPyProjectStack - -def test_sqs_queue_created(): - app = core.App() - stack = MyCdkPyProjectStack(app, "my-cdk-py-project") - template = assertions.Template.from_stack(stack) - - template.has_resource_properties("AWS::SQS::Queue", { - "VisibilityTimeout": 300 - })</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</dd> -<dt class="hdlist1"><code class="noloc">Java</code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The following is an example project created in the <code class="path">my-cdk-java-project</code> directory using the <code>cdk init --language java</code> command:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">my-cdk-java-project -├── .git -├── .gitignore -├── README.md -├── cdk.json -├── pom.xml -└── src - ├── main - └── test</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">pom.xml</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>File that contains configuration information and metadata about your CDK project. This file is a part of <code class="noloc">Maven</code>.</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">src/main</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Directory containing your <em>application</em> and <em>stack</em> files.</p> -<div class="paragraph"> -<p>The following is an example application file:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">package com.myorg; - -import software.amazon.awscdk.App; -import software.amazon.awscdk.Environment; -import software.amazon.awscdk.StackProps; - -import java.util.Arrays; - -public class MyCdkJavaProjectApp { - public static void main(final String[] args) { - App app = new App(); - - new MyCdkJavaProjectStack(app, "MyCdkJavaProjectStack", StackProps.builder() - .build()); - - app.synth(); - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The following is an example stack file:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">package com.myorg; - -import software.constructs.Construct; -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.StackProps; - -public class MyCdkJavaProjectStack extends Stack { - public MyCdkJavaProjectStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public MyCdkJavaProjectStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - // code that defines your resources and properties go here - } -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">src/test</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Directory containing your test files. The following is an example:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">package com.myorg; - -import software.amazon.awscdk.App; -import software.amazon.awscdk.assertions.Template; -import java.io.IOException; - -import java.util.HashMap; - -import org.junit.jupiter.api.Test; - -public class MyCdkJavaProjectTest { - - @Test - public void testStack() throws IOException { - App app = new App(); - MyCdkJavaProjectStack stack = new MyCdkJavaProjectStack(app, "test"); - - Template template = Template.fromStack(stack); - - template.hasResourceProperties("AWS::SQS::Queue", new HashMap<String, Number>() {{ - put("VisibilityTimeout", 300); - }}); - } -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1"><code class="noloc">C#</code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The following is an example project created in the <code class="path">my-cdk-csharp-project</code> directory using the <code>cdk init --language csharp</code> command:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">my-cdk-csharp-project -├── .git -├── .gitignore -├── README.md -├── cdk.json -└── src - ├── MyCdkCsharpProject - └── MyCdkCsharpProject.sln</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">src/MyCdkCsharpProject</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Directory containing your <em>application</em> and <em>stack</em> files.</p> -<div class="paragraph"> -<p>The following is an example application file:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace MyCdkCsharpProject -{ - sealed class Program - { - public static void Main(string[] args) - { - var app = new App(); - new MyCdkCsharpProjectStack(app, "MyCdkCsharpProjectStack", new StackProps{}); - app.Synth(); - } - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The following is an example stack file:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; -using Constructs; - -namespace MyCdkCsharpProject -{ - public class MyCdkCsharpProjectStack : Stack - { - internal MyCdkCsharpProjectStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) - { - // code that defines your resources and properties go here - } - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>This directory also contains the following:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><code class="path">GlobalSuppressions.cs</code> – File used to suppress specific compiler warnings or errors across your project.</p> -</li> -<li> -<p><code class="path">.csproj</code> – XML-based file used to define project settings, dependencies, and build configurations.</p> -</li> -</ul> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">src/MyCdkCsharpProject.sln</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p><code class="noloc">Microsoft Visual Studio Solution File</code> used to organize and manage related projects.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1"><code class="noloc">Go</code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The following is an example project created in the <code class="path">my-cdk-go-project</code> directory using the <code>cdk init --language go</code> command:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">my-cdk-go-project -├── .git -├── .gitignore -├── README.md -├── cdk.json -├── go.mod -├── my-cdk-go-project.go -└── my-cdk-go-project_test.go</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">go.mod</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>File that contains module information and is used to manage dependencies and versioning for your <code class="noloc">Go</code> project.</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">my-cdk-go-project.go</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>File that defines your CDK application and stacks.</p> -<div class="paragraph"> -<p>The following is an example:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">package main -import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/constructs-go/constructs/v10" - "github.com/aws/jsii-runtime-go" -) - -type MyCdkGoProjectStackProps struct { - awscdk.StackProps -} - -func NewMyCdkGoProjectStack(scope constructs.Construct, id string, props *MyCdkGoProjectStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - stack := awscdk.NewStack(scope, &id, &sprops) - // The code that defines your resources and properties go here - - return stack -} - -func main() { - defer jsii.Close() - app := awscdk.NewApp(nil) - NewMyCdkGoProjectStack(app, "MyCdkGoProjectStack", &MyCdkGoProjectStackProps{ - awscdk.StackProps{ - Env: env(), - }, - }) - app.Synth(nil) -} - -func env() *awscdk.Environment { - - return nil -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">my-cdk-go-project_test.go</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>File that defines a sample test.</p> -<div class="paragraph"> -<p>The following is an example:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">package main - -import ( - "testing" - - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/aws-cdk-go/awscdk/v2/assertions" - "github.com/aws/jsii-runtime-go" -) - -func TestMyCdkGoProjectStack(t *testing.T) { - - // GIVEN - app := awscdk.NewApp(nil) - - // WHEN - stack := NewMyCdkGoProjectStack(app, "MyStack", nil) - - // THEN - template := assertions.Template_FromStack(stack, nil) - template.HasResourceProperties(jsii.String("AWS::SQS::Queue"), map[string]interface{}{ - "VisibilityTimeout": 300, - }) -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="apps">2.8. AWS CDK apps</h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>The AWS Cloud Development Kit (AWS CDK) application or <em>app</em> is a collection of one or more CDK <a href="#stacks">stacks</a>. Stacks are a collection of one or more <a href="#constructs">constructs</a>, which define AWS resources and properties. Therefore, the overall grouping of your stacks and constructs are known as your CDK app.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>The AWS Cloud Development Kit (AWS CDK) application or <em>app</em> is a collection of one or more CDK <a href="#stacks">stacks</a>. Stacks are a collection of one or more <a href="#constructs">constructs</a>, which define AWS resources and properties. Therefore, the overall grouping of your stacks and constructs are known as your CDK app.</p> -</div> -<div class="sect3"> -<h4 id="apps-define">2.8.1. How to create a CDK app</h4> -<div class="paragraph"> -<p>You create an app by defining an app instance in the application file of your <a href="#projects">project</a>. To do this, you import and use the <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.App.html">App</a> construct from the AWS Construct Library. The <code>App</code> construct doesn’t require any initialization arguments. It is the only construct that can be used as the root.</p> -</div> -<div class="paragraph"> -<p>The <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.App.html">App</a></code> and <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html">Stack</a></code> classes from the AWS Construct Library are unique constructs. Compared to other constructs, they don’t configure AWS resources on their own. Instead, they are used to provide context for your other constructs. All constructs that represent AWS resources must be defined, directly or indirectly, within the scope of a <code>Stack</code> construct. <code>Stack</code> constructs are defined within the scope of an <code>App</code> construct.</p> -</div> -<div class="paragraph"> -<p>Apps are then synthesized to create AWS CloudFormation templates for your stacks. The following is an example:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const app = new App(); -new MyFirstStack(app, 'hello-cdk'); -app.synth();</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const app = new App(); -new MyFirstStack(app, 'hello-cdk'); -app.synth();</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">app = App() -MyFirstStack(app, "hello-cdk") -app.synth()</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">App app = new App(); -new MyFirstStack(app, "hello-cdk"); -app.synth();</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">var app = new App(); -new MyFirstStack(app, "hello-cdk"); -app.Synth();</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">app := awscdk.NewApp(nil) - -MyFirstStack(app, "MyFirstStack", &MyFirstStackProps{ - awscdk.StackProps{ - Env: env(), - }, -}) - -app.Synth(nil)</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Stacks within a single app can easily refer to each other’s resources and properties. The AWS CDK infers dependencies between stacks so that they can be deployed in the correct order. You can deploy any or all of the stacks within an app with a single <code>cdk deploy</code> command.</p> -</div> -</div> -<div class="sect3"> -<h4 id="apps-tree">2.8.2. The construct tree</h4> -<div class="paragraph"> -<p>Constructs are defined inside of other constructs using the <code>scope</code> argument that is passed to every construct, with the <code>App</code> class as the root. In this way, an AWS CDK app defines a hierarchy of constructs known as the <em>construct tree</em>.</p> -</div> -<div class="paragraph"> -<p>The root of this tree is your app, which is an instance of the <code>App</code> class. Within the app, you instantiate one or more stacks. Within stacks, you instantiate constructs, which may themselves instantiate resources or other constructs, and so on down the tree.</p> -</div> -<div class="paragraph"> -<p>Constructs are <em>always</em> explicitly defined within the scope of another construct, which creates relationships between constructs. Almost always, you should pass <code>this</code> (in Python, <code>self</code>) as the scope, indicating that the new construct is a child of the current construct. The intended pattern is that you derive your construct from <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html">Construct</a>, then instantiate the constructs it uses in its constructor.</p> -</div> -<div class="paragraph"> -<p>Passing the scope explicitly allows each construct to add itself to the tree, with this behavior entirely contained within the <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html">Construct base class</a>. It works the same way in every language supported by the AWS CDK and does not require additional customization.</p> -</div> -<div class="admonitionblock important"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-important" title="Important"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>Technically, it’s possible to pass some scope other than <code>this</code> when instantiating a construct. You can add constructs anywhere in the tree, or even in another stack in the same app. For example, you could write a mixin-style function that adds constructs to a scope passed in as an argument. The practical difficulty here is that you can’t easily ensure that the IDs you choose for your constructs are unique within someone else’s scope. The practice also makes your code more difficult to understand, maintain, and reuse. Therefore, we recommend that you use the general structure of the construct tree.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>The AWS CDK uses the IDs of all constructs in the path from the tree’s root to each child construct to generate the unique IDs required by AWS CloudFormation. This approach means that construct IDs only need to be unique within their scope, rather than within the entire stack as in native AWS CloudFormation. However, if you move a construct to a different scope, its generated stack-unique ID changes, and AWS CloudFormation won’t consider it the same resource.</p> -</div> -<div class="paragraph"> -<p>The construct tree is separate from the constructs that you define in your AWS CDK code. However, it’s accessible through any construct’s <code>node</code> attribute, which is a reference to the node that represents that construct in the tree. Each node is a <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Node.html">Node</a> instance, the attributes of which provide access to the tree’s root and to the node’s parent scopes and children.</p> -</div> -<div class="olist arabic"> -<ol class="arabic"> -<li> -<p><code>node.children</code> – The direct children of the construct.</p> -</li> -<li> -<p><code>node.id</code> – The identifier of the construct within its scope.</p> -</li> -<li> -<p><code>node.path</code> – The full path of the construct including the IDs of all of its parents.</p> -</li> -<li> -<p><code>node.root</code> – The root of the construct tree (the app).</p> -</li> -<li> -<p><code>node.scope</code> – The scope (parent) of the construct, or undefined if the node is the root.</p> -</li> -<li> -<p><code>node.scopes</code> – All parents of the construct, up to the root.</p> -</li> -<li> -<p><code>node.uniqueId</code> – The unique alphanumeric identifier for this construct within the tree (by default, generated from <code>node.path</code> and a hash).</p> -</li> -</ol> -</div> -<div class="paragraph"> -<p>The construct tree defines an implicit order in which constructs are synthesized to resources in the final AWS CloudFormation template. Where one resource must be created before another, AWS CloudFormation or the AWS Construct Library generally infers the dependency. They then make sure that the resources are created in the right order.</p> -</div> -<div class="paragraph"> -<p>You can also add an explicit dependency between two nodes by using <code>node.addDependency()</code>. For more information, see <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib-readme.html#dependencies">Dependencies</a> in the <em>AWS CDK API Reference</em>.</p> -</div> -<div class="paragraph"> -<p>The AWS CDK provides a simple way to visit every node in the construct tree and perform an operation on each one. For more information, see <a href="#aspects">Aspects and the AWS CDK</a>.</p> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="stacks">2.9. Introduction to AWS CDK stacks</h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>An AWS CDK stack is a single unit of deployment. It represents a collection of AWS resources. When you develop CDK applications, you define AWS resources using CDK constructs and organize them within CDK stacks. When you deploy, the resources within a CDK stack are deployed together as an AWS CloudFormation stack.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>An AWS CDK stack is the smallest single unit of deployment. It represents a collection of AWS resources that you define using CDK constructs. When you deploy CDK apps, the resources within a CDK stack are deployed together as an AWS CloudFormation stack. To learn more about AWS CloudFormation stacks, see <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacks.html">Managing AWS resources as a single unit with AWS CloudFormation stacks</a> in the <em>AWS CloudFormation User Guide</em>.</p> -</div> -<div class="paragraph"> -<p>You define a stack by extending or inheriting from the <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html">Stack</a></code> construct. The following example is a common pattern for defining a CDK stack on a separate file, known as a <em>stack file</em>. Here, we extend or inherit the <code>Stack</code> class and define a constructor that accepts <code>scope</code>, <code>id</code>, and <code>props</code>. Then, we invoke the base <code>Stack</code> class constructor using <code>super</code> with the received <code>scope</code>, <code>id</code>, and <code>props</code>:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as cdk from 'aws-cdk-lib'; -import { Construct } from 'constructs'; - -export class MyCdkStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - // Define your constructs here - - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const { Stack } = require('aws-cdk-lib'); - -class MyCdkStack extends Stack { - constructor(scope, id, props) { - super(scope, id, props); - - // Define your constructs here - - } -} - -module.exports = { MyCdkStack }</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">from aws_cdk import ( - Stack, -) -from constructs import Construct - -class MyCdkStack(Stack): - - def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: - super().__init__(scope, construct_id, **kwargs) - - # Define your constructs here</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">package com.myorg; - -import software.constructs.Construct; -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.StackProps; - -public class MyCdkStack extends Stack { - public MyCdkStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public MyCdkStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - // Define your constructs here - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; -using Constructs; - -namespace MyCdk -{ - public class MyCdkStack : Stack - { - internal MyCdkStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) - { - // Define your constructs here - } - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">package main - -import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/constructs-go/constructs/v10" - "github.com/aws/jsii-runtime-go" -) - -type CdkDemoAppStackProps struct { - awscdk.StackProps -} - -func NewCdkDemoAppStack(scope constructs.Construct, id string, props *CdkDemoAppStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - stack := awscdk.NewStack(scope, &id, &sprops) - - // The code that defines your stack goes here - - return stack -} - -func main() { - defer jsii.Close() - - app := awscdk.NewApp(nil) - - NewCdkDemoAppStack(app, "CdkDemoAppStack", &CdkDemoAppStackProps{ - awscdk.StackProps{ - Env: env(), - }, - }) - - app.Synth(nil) -} - -//...</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The previous example has only defined a stack. To create the stack, it must be instantiated within the context of your CDK app. A common pattern is to define your CDK app and initialize your stack on a separate file, known as an <em>application file</em>.</p> -</div> -<div class="paragraph"> -<p>The following is an example that creates a CDK stack named <code>MyCdkStack</code>. Here, the CDK app is created and <code>MyCdkStack</code> is instantiated in the context of the app:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">#!/usr/bin/env node -import 'source-map-support/register'; -import * as cdk from 'aws-cdk-lib'; -import { MyCdkStack } from '../lib/my-cdk-stack'; - -const app = new cdk.App(); -new MyCdkStack(app, 'MyCdkStack', { -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">#!/usr/bin/env node - -const cdk = require('aws-cdk-lib'); -const { MyCdkStack } = require('../lib/my-cdk-stack'); - -const app = new cdk.App(); -new MyCdkStack(app, 'MyCdkStack', { -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">app.py</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">#!/usr/bin/env python3 -import os - -import aws_cdk as cdk - -from my_cdk.my_cdk_stack import MyCdkStack - - -app = cdk.App() -MyCdkStack(app, "MyCdkStack",) - -app.synth()</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">package com.myorg; - -import software.amazon.awscdk.App; -import software.amazon.awscdk.Environment; -import software.amazon.awscdk.StackProps; - -import java.util.Arrays; - -public class MyCdkApp { - public static void main(final String[] args) { - App app = new App(); - - new MyCdkStack(app, "MyCdkStack", StackProps.builder() - .build()); - - app.synth(); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace MyCdk -{ - sealed class Program - { - public static void Main(string[] args) - { - var app = new App(); - new MyCdkStack(app, "MyCdkStack", new StackProps - {}); - app.Synth(); - } - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">package main - -import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/constructs-go/constructs/v10" - "github.com/aws/jsii-runtime-go" -) - -// ... - -func main() { - defer jsii.Close() - - app := awscdk.NewApp(nil) - - NewMyCdkStack(app, "MyCdkStack", &MyCdkStackProps{ - awscdk.StackProps{ - Env: env(), - }, - }) - - app.Synth(nil) -} - -// ...</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The following example creates a CDK app that contains two stacks:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const app = new App(); - -new MyFirstStack(app, 'stack1'); -new MySecondStack(app, 'stack2'); - -app.synth();</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const app = new App(); - -new MyFirstStack(app, 'stack1'); -new MySecondStack(app, 'stack2'); - -app.synth();</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">app = App() - -MyFirstStack(app, 'stack1') -MySecondStack(app, 'stack2') - -app.synth()</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">App app = new App(); - -new MyFirstStack(app, "stack1"); -new MySecondStack(app, "stack2"); - -app.synth();</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">var app = new App(); - -new MyFirstStack(app, "stack1"); -new MySecondStack(app, "stack2"); - -app.Synth();</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">package main - -import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/constructs-go/constructs/v10" - "github.com/aws/jsii-runtime-go" -) - -type MyFirstStackProps struct { - awscdk.StackProps -} - -func NewMyFirstStack(scope constructs.Construct, id string, props *MyFirstStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - myFirstStack := awscdk.NewStack(scope, &id, &sprops) - - // The code that defines your stack goes here - - return myFirstStack -} - -type MySecondStackProps struct { - awscdk.StackProps -} - -func NewMySecondStack(scope constructs.Construct, id string, props *MySecondStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - mySecondStack := awscdk.NewStack(scope, &id, &sprops) - - // The code that defines your stack goes here - - return mySecondStack -} - -func main() { - defer jsii.Close() - - app := awscdk.NewApp(nil) - - NewMyFirstStack(app, "MyFirstStack", &MyFirstStackProps{ - awscdk.StackProps{ - Env: env(), - }, - }) - - NewMySecondStack(app, "MySecondStack", &MySecondStackProps{ - awscdk.StackProps{ - Env: env(), - }, - }) - - app.Synth(nil) -} - -// ...</code></pre> -</div> -</div> -<div class="sect3"> -<h4 id="stack-api">2.9.1. About the stack API</h4> -<div class="paragraph"> -<p>The <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html">Stack</a></code> object provides a rich API, including the following:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><code>Stack.of(construct)</code> – A static method that returns the <strong>Stack</strong> in which a construct is defined. This is useful if you need to interact with a stack from within a reusable construct. The call fails if a stack cannot be found in scope.</p> -</li> -<li> -<p><code>stack.stackName</code> (Python: <code>stack_name</code>) – Returns the physical name of the stack. As mentioned previously, all AWS CDK stacks have a physical name that the AWS CDK can resolve during synthesis.</p> -</li> -<li> -<p><code>stack.region</code> and <code>stack.account</code> – Return the AWS Region and account, respectively, into which this stack will be deployed. These properties return one of the following:</p> -<div class="ulist"> -<ul> -<li> -<p>The account or Region explicitly specified when the stack was defined</p> -</li> -<li> -<p>A string-encoded token that resolves to the AWS CloudFormation pseudo parameters for account and Region to indicate that this stack is environment agnostic</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>For information about how environments are determined for stacks, see <a href="#environments">Environments for the AWS CDK</a>.</p> -</div> -</li> -<li> -<p><code>stack.addDependency(stack)</code> (Python: <code>stack.add_dependency(stack)</code> – Can be used to explicitly define dependency order between two stacks. This order is respected by the <strong class="command">cdk deploy</strong> command when deploying multiple stacks at once.</p> -</li> -<li> -<p><code>stack.tags</code> – Returns a <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.TagManager.html">TagManager</a> that you can use to add or remove stack-level tags. This tag manager tags all resources within the stack, and also tags the stack itself when it’s created through AWS CloudFormation.</p> -</li> -<li> -<p><code>stack.partition</code>, <code>stack.urlSuffix</code> (Python: <code>url_suffix</code>), <code>stack.stackId</code> (Python: <code>stack_id</code>), and <code>stack.notificationArn</code> (Python: <code>notification_arn</code>) – Return tokens that resolve to the respective AWS CloudFormation pseudo parameters, such as <code>{ "Ref": "AWS::Partition" }</code>. These tokens are associated with the specific stack object so that the AWS CDK framework can identify cross-stack references.</p> -</li> -<li> -<p><code>stack.availabilityZones</code> (Python: <code>availability_zones</code>) – Returns the set of Availability Zones available in the environment in which this stack is deployed. For environment-agnostic stacks, this always returns an array with two Availability Zones. For environment-specific stacks, the AWS CDK queries the environment and returns the exact set of Availability Zones available in the Region that you specified.</p> -</li> -<li> -<p><code>stack.parseArn(arn)</code> and <code>stack.formatArn(comps)</code> (Python: <code>parse_arn</code>, <code>format_arn</code>) – Can be used to work with Amazon Resource Names (ARNs).</p> -</li> -<li> -<p><code>stack.toJsonString(obj)</code> (Python: <code>to_json_string</code>) – Can be used to format an arbitrary object as a JSON string that can be embedded in an AWS CloudFormation template. The object can include tokens, attributes, and references, which are only resolved during deployment.</p> -</li> -<li> -<p><code>stack.templateOptions</code> (Python: <code>template_options</code>) – Use to specify AWS CloudFormation template options, such as Transform, Description, and Metadata, for your stack.</p> -</li> -</ul> -</div> -</div> -<div class="sect3"> -<h4 id="stacks-work">2.9.2. Working with stacks</h4> -<div class="paragraph"> -<p>Stacks are deployed as an AWS CloudFormation stack into an AWS <em><a href="#environments">environment</a></em>. The environment covers a specific AWS account and AWS Region.</p> -</div> -<div class="paragraph"> -<p>When you run the <code>cdk synth</code> command for an app with multiple stacks, the cloud assembly includes a separate template for each stack instance. Even if the two stacks are instances of the same class, the AWS CDK emits them as two individual templates.</p> -</div> -<div class="paragraph"> -<p>You can synthesize each template by specifying the stack name in the <code>cdk synth</code> command. The following example synthesizes the template for <code class="path">stack1</code>:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk synth stack1</code></pre> -</div> -</div> -<div class="paragraph"> -<p>This approach is conceptually different from how AWS CloudFormation templates are normally used, where a template can be deployed multiple times and parameterized through <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html">AWS CloudFormation parameters</a>. Although AWS CloudFormation parameters can be defined in the AWS CDK, they are generally discouraged because AWS CloudFormation parameters are resolved only during deployment. This means that you cannot determine their value in your code.</p> -</div> -<div class="paragraph"> -<p>For example, to conditionally include a resource in your app based on a parameter value, you must set up an <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/conditions-section-structure.html">AWS CloudFormation condition</a> and tag the resource with it. The AWS CDK takes an approach where concrete templates are resolved at synthesis time. Therefore, you can use an <code>if</code> statement to check the value to determine whether a resource should be defined or some behavior should be applied.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>The AWS CDK provides as much resolution as possible during synthesis time to enable idiomatic and natural usage of your programming language.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>Like any other construct, stacks can be composed together into groups. The following code shows an example of a service that consists of three stacks: a control plane, a data plane, and monitoring stacks. The service construct is defined twice: once for the beta environment and once for the production environment.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import { App, Stack } from 'aws-cdk-lib'; -import { Construct } from 'constructs'; - -interface EnvProps { - prod: boolean; -} - -// imagine these stacks declare a bunch of related resources -class ControlPlane extends Stack {} -class DataPlane extends Stack {} -class Monitoring extends Stack {} - -class MyService extends Construct { - - constructor(scope: Construct, id: string, props?: EnvProps) { - - super(scope, id); - - // we might use the prod argument to change how the service is configured - new ControlPlane(this, "cp"); - new DataPlane(this, "data"); - new Monitoring(this, "mon"); } -} - -const app = new App(); -new MyService(app, "beta"); -new MyService(app, "prod", { prod: true }); - -app.synth();</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const { App, Stack } = require('aws-cdk-lib'); -const { Construct } = require('constructs'); - -// imagine these stacks declare a bunch of related resources -class ControlPlane extends Stack {} -class DataPlane extends Stack {} -class Monitoring extends Stack {} - -class MyService extends Construct { - - constructor(scope, id, props) { - - super(scope, id); - - // we might use the prod argument to change how the service is configured - new ControlPlane(this, "cp"); - new DataPlane(this, "data"); - new Monitoring(this, "mon"); - } -} - -const app = new App(); -new MyService(app, "beta"); -new MyService(app, "prod", { prod: true }); - -app.synth();</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">from aws_cdk import App, Stack -from constructs import Construct - -# imagine these stacks declare a bunch of related resources -class ControlPlane(Stack): pass -class DataPlane(Stack): pass -class Monitoring(Stack): pass - -class MyService(Construct): - - def __init__(self, scope: Construct, id: str, *, prod=False): - - super().__init__(scope, id) - - # we might use the prod argument to change how the service is configured - ControlPlane(self, "cp") - DataPlane(self, "data") - Monitoring(self, "mon") - -app = App(); -MyService(app, "beta") -MyService(app, "prod", prod=True) - -app.synth()</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">package com.myorg; - -import software.amazon.awscdk.App; -import software.amazon.awscdk.Stack; -import software.constructs.Construct; - -public class MyApp { - - // imagine these stacks declare a bunch of related resources - static class ControlPlane extends Stack { - ControlPlane(Construct scope, String id) { - super(scope, id); - } - } - - static class DataPlane extends Stack { - DataPlane(Construct scope, String id) { - super(scope, id); - } - } - - static class Monitoring extends Stack { - Monitoring(Construct scope, String id) { - super(scope, id); - } - } - - static class MyService extends Construct { - MyService(Construct scope, String id) { - this(scope, id, false); - } - - MyService(Construct scope, String id, boolean prod) { - super(scope, id); - - // we might use the prod argument to change how the service is configured - new ControlPlane(this, "cp"); - new DataPlane(this, "data"); - new Monitoring(this, "mon"); - } - } - - public static void main(final String argv[]) { - App app = new App(); - - new MyService(app, "beta"); - new MyService(app, "prod", true); - - app.synth(); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; -using Constructs; - -// imagine these stacks declare a bunch of related resources -public class ControlPlane : Stack { - public ControlPlane(Construct scope, string id=null) : base(scope, id) { } -} - -public class DataPlane : Stack { - public DataPlane(Construct scope, string id=null) : base(scope, id) { } -} - -public class Monitoring : Stack -{ - public Monitoring(Construct scope, string id=null) : base(scope, id) { } -} - -public class MyService : Construct -{ - public MyService(Construct scope, string id, Boolean prod=false) : base(scope, id) - { - // we might use the prod argument to change how the service is configured - new ControlPlane(this, "cp"); - new DataPlane(this, "data"); - new Monitoring(this, "mon"); - } -} - -class Program -{ - static void Main(string[] args) - { - - var app = new App(); - new MyService(app, "beta"); - new MyService(app, "prod", prod: true); - app.Synth(); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">package main - -import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/constructs-go/constructs/v10" - "github.com/aws/jsii-runtime-go" -) - -type ControlPlaneStackProps struct { - awscdk.StackProps -} - -func NewControlPlaneStack(scope constructs.Construct, id string, props *ControlPlaneStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - ControlPlaneStack := awscdk.NewStack(scope, jsii.String(id), &sprops) - - // The code that defines your stack goes here - - return ControlPlaneStack -} - -type DataPlaneStackProps struct { - awscdk.StackProps -} - -func NewDataPlaneStack(scope constructs.Construct, id string, props *DataPlaneStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - DataPlaneStack := awscdk.NewStack(scope, jsii.String(id), &sprops) - - // The code that defines your stack goes here - - return DataPlaneStack -} - -type MonitoringStackProps struct { - awscdk.StackProps -} - -func NewMonitoringStack(scope constructs.Construct, id string, props *MonitoringStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - MonitoringStack := awscdk.NewStack(scope, jsii.String(id), &sprops) - - // The code that defines your stack goes here - - return MonitoringStack -} - -type MyServiceStackProps struct { - awscdk.StackProps - Prod bool -} - -func NewMyServiceStack(scope constructs.Construct, id string, props *MyServiceStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - MyServiceStack := awscdk.NewStack(scope, jsii.String(id), &sprops) - - NewControlPlaneStack(MyServiceStack, "cp", &ControlPlaneStackProps{ - StackProps: sprops, - }) - NewDataPlaneStack(MyServiceStack, "data", &DataPlaneStackProps{ - StackProps: sprops, - }) - NewMonitoringStack(MyServiceStack, "mon", &MonitoringStackProps{ - StackProps: sprops, - }) - - return MyServiceStack -} - -func main() { - defer jsii.Close() - - app := awscdk.NewApp(nil) - - betaProps := MyServiceStackProps{ - StackProps: awscdk.StackProps{ - Env: env(), - }, - Prod: false, - } - - NewMyServiceStack(app, "beta", &betaProps) - - prodProps := MyServiceStackProps{ - StackProps: awscdk.StackProps{ - Env: env(), - }, - Prod: true, - } - - NewMyServiceStack(app, "prod", &prodProps) - - app.Synth(nil) -} - -// ...</code></pre> -</div> -</div> -<div class="paragraph"> -<p>This AWS CDK app eventually consists of six stacks, three for each environment:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk ls - -betacpDA8372D3 -betadataE23DB2BA -betamon632BD457 -prodcp187264CE -proddataF7378CE5 -prodmon631A1083</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The physical names of the AWS CloudFormation stacks are automatically determined by the AWS CDK based on the stack’s construct path in the tree. By default, a stack’s name is derived from the construct ID of the <code>Stack</code> object. However, you can specify an explicit name by using the <code>stackName</code> prop (in Python, <code>stack_name</code>), as follows.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">new MyStack(this, 'not:a:stack:name', { stackName: 'this-is-stack-name' });</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">new MyStack(this, 'not:a:stack:name', { stackName: 'this-is-stack-name' });</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">MyStack(self, "not:a:stack:name", stack_name="this-is-stack-name")</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">new MyStack(this, "not:a:stack:name", StackProps.builder() - .StackName("this-is-stack-name").build());</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">new MyStack(this, "not:a:stack:name", new StackProps -{ - StackName = "this-is-stack-name" -});</code></pre> -</div> -</div> -<div class="sect4"> -<h5 id="stack-nesting">Working with nested stacks</h5> -<div class="paragraph"> -<p>A <em>nested stack</em> is a CDK stack that you create inside another stack, known as the parent stack. You create nested stacks using the <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.NestedStack.html">NestedStack</a></code> construct.</p> -</div> -<div class="paragraph"> -<p>By using nested stacks, you can organize resources across multiple stacks. Nested stacks also offer a way around the AWS CloudFormation 500-resource limit for stacks. A nested stack counts as only one resource in the stack that contains it. However, it can contain up to 500 resources, including additional nested stacks.</p> -</div> -<div class="paragraph"> -<p>The scope of a nested stack must be a <code>Stack</code> or <code>NestedStack</code> construct. The nested stack doesn’t need to be declared lexically inside its parent stack. It is necessary only to pass the parent stack as the first parameter (<code>scope</code>) when instantiating the nested stack. Aside from this restriction, defining constructs in a nested stack works exactly the same as in an ordinary stack.</p> -</div> -<div class="paragraph"> -<p>At synthesis time, the nested stack is synthesized to its own AWS CloudFormation template, which is uploaded to the AWS CDK staging bucket at deployment. Nested stacks are bound to their parent stack and are not treated as independent deployment artifacts. They aren’t listed by <code>cdk list</code>, and they can’t be deployed by <code>cdk deploy</code>.</p> -</div> -<div class="paragraph"> -<p>References between parent stacks and nested stacks are automatically translated to stack parameters and outputs in the generated AWS CloudFormation templates, as with any <a href="#resource-stack">cross-stack reference</a>.</p> -</div> -<div class="admonitionblock warning"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-warning" title="Warning"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>Changes in security posture are not displayed before deployment for nested stacks. This information is displayed only for top-level stacks.</p> -</div> -</td> -</tr> -</table> -</div> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="stages">2.10. Introduction to AWS CDK stages</h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>An AWS Cloud Development Kit (AWS CDK) <em>stage</em> represents a group of one or more CDK stacks that are configured to deploy together. Use stages to deploy the same grouping of stacks to multiple environments, such as development, testing, and production.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>An AWS Cloud Development Kit (AWS CDK) <em>stage</em> represents a group of one or more CDK stacks that are configured to deploy together. Use stages to deploy the same grouping of stacks to multiple environments, such as development, testing, and production.</p> -</div> -<div class="paragraph"> -<p>To configure a CDK stage, import and use the <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stage.html">Stage</a></code> construct.</p> -</div> -<div class="paragraph"> -<p>The following is a basic example that defines a CDK stage named <code>MyAppStage</code>. We add two CDK stacks, named <code>AppStack</code> and <code>DatabaseStack</code> to our stage. For this example, <code>AppStack</code> contains application resources and <code>DatabaseStack</code> contains database resources. We then create two instances of <code>MyAppStage</code>, for development and production environments:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>In <code class="path">cdk-demo-app/lib/app-stack.ts</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as cdk from 'aws-cdk-lib'; -import { Construct } from 'constructs'; - -// Define the app stack -export class AppStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - // The code that defines your application goes here - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>In <code class="path">cdk-demo-app/lib/database-stack.ts</code>:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as cdk from 'aws-cdk-lib'; -import { Construct } from 'constructs'; - -// Define the database stack -export class DatabaseStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - // The code that defines your database goes here - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>In <code class="path">cdk-demo-app/lib/my-stage.ts</code>:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as cdk from 'aws-cdk-lib'; -import { Construct } from 'constructs'; -import { Stage } from 'aws-cdk-lib'; -import { AppStack } from './app-stack'; -import { DatabaseStack } from './database-stack'; - -// Define the stage -export class MyAppStage extends Stage { - constructor(scope: Construct, id: string, props?: cdk.StageProps) { - super(scope, id, props); - - // Add both stacks to the stage - new AppStack(this, 'AppStack'); - new DatabaseStack(this, 'DatabaseStack'); - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>In <code class="path">cdk-demo-app/bin/cdk-demo-app.ts</code>:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">#!/usr/bin/env node -import 'source-map-support/register'; -import * as cdk from 'aws-cdk-lib'; -import { MyAppStage } from '../lib/my-stage'; - -// Create a CDK app -const app = new cdk.App(); - -// Create the development stage -new MyAppStage(app, 'Dev', { - env: { - account: '123456789012', - region: 'us-east-1' - } -}); - -// Create the production stage -new MyAppStage(app, 'Prod', { - env: { - account: '098765432109', - region: 'us-east-1' - } -});</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">JavaScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>In <code class="path">cdk-demo-app/lib/app-stack.js</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const { Stack } = require('aws-cdk-lib'); - -class AppStack extends Stack { - constructor(scope, id, props) { - super(scope, id, props); - - // The code that defines your application goes here - } -} - -module.exports = { AppStack }</code></pre> -</div> -</div> -<div class="paragraph"> -<p>In <code class="path">cdk-demo-app/lib/database-stack.js</code>:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const { Stack } = require('aws-cdk-lib'); - -class DatabaseStack extends Stack { - constructor(scope, id, props) { - super(scope, id, props); - - // The code that defines your database goes here - } -} - -module.exports = { DatabaseStack }</code></pre> -</div> -</div> -<div class="paragraph"> -<p>In <code class="path">cdk-demo-app/lib/my-stage.js</code>:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const { Stage } = require('aws-cdk-lib'); -const { AppStack } = require('./app-stack'); -const { DatabaseStack } = require('./database-stack'); - -// Define the stage -class MyAppStage extends Stage { - constructor(scope, id, props) { - super(scope, id, props); - - // Add both stacks to the stage - new AppStack(this, 'AppStack'); - new DatabaseStack(this, 'DatabaseStack'); - } -} - -module.exports = { MyAppStage };</code></pre> -</div> -</div> -<div class="paragraph"> -<p>In <code class="path">cdk-demo-app/bin/cdk-demo-app.js</code>:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">#!/usr/bin/env node - -const cdk = require('aws-cdk-lib'); -const { MyAppStage } = require('../lib/my-stage'); - -// Create the CDK app -const app = new cdk.App(); - -// Create the development stage -new MyAppStage(app, 'Dev', { - env: { - account: '123456789012', - region: 'us-east-1', - }, -}); - -// Create the production stage -new MyAppStage(app, 'Prod', { - env: { - account: '098765432109', - region: 'us-east-1', - }, -});</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Python</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>In <code class="path">cdk-demo-app/cdk_demo_app/app_stack.py</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">from aws_cdk import Stack -from constructs import Construct - -# Define the app stack -class AppStack(Stack): - def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: - super().__init__(scope, construct_id, **kwargs) - - # The code that defines your application goes here</code></pre> -</div> -</div> -<div class="paragraph"> -<p>In <code class="path">cdk-demo-app/cdk_demo_app/database_stack.py</code>:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">from aws_cdk import Stack -from constructs import Construct - -# Define the database stack -class DatabaseStack(Stack): - def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: - super().__init__(scope, construct_id, **kwargs) - - # The code that defines your database goes here</code></pre> -</div> -</div> -<div class="paragraph"> -<p>In <code class="path">cdk-demo-app/cdk_demo_app/my_stage.py</code>:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">from aws_cdk import Stage -from constructs import Construct -from .app_stack import AppStack -from .database_stack import DatabaseStack - -# Define the stage -class MyAppStage(Stage): - def __init__(self, scope: Construct, id: str, **kwargs) -> None: - super().__init__(scope, id, **kwargs) - - # Add both stacks to the stage - AppStack(self, "AppStack") - DatabaseStack(self, "DatabaseStack")</code></pre> -</div> -</div> -<div class="paragraph"> -<p>In <code class="path">cdk-demo-app/app.py</code>:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">#!/usr/bin/env python3 -import os - -import aws_cdk as cdk - -from cdk_demo_app.my_stage import MyAppStage - -# Create a CDK app -app = cdk.App() - -# Create the development stage -MyAppStage(app, 'Dev', - env=cdk.Environment(account='123456789012', region='us-east-1'), - ) - -# Create the production stage -MyAppStage(app, 'Prod', - env=cdk.Environment(account='098765432109', region='us-east-1'), - ) - -app.synth()</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Java</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>In <code class="path">cdk-demo-app/src/main/java/com/myorg/AppStack.java</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">package com.myorg; - -import software.constructs.Construct; -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.StackProps; - -public class AppStack extends Stack { - public AppStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public AppStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - // The code that defines your application goes here - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>In <code class="path">cdk-demo-app/src/main/java/com/myorg/DatabaseStack.java</code>:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">package com.myorg; - -import software.constructs.Construct; -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.StackProps; - -public class DatabaseStack extends Stack { - public DatabaseStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public DatabaseStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - // The code that defines your database goes here - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>In <code class="path">cdk-demo-app/src/main/java/com/myorg/MyAppStage.java</code>:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">package com.myorg; - -import software.amazon.awscdk.Stage; -import software.amazon.awscdk.StageProps; -import software.constructs.Construct; - -// Define the stage -public class MyAppStage extends Stage { - public MyAppStage(final Construct scope, final String id, final software.amazon.awscdk.Environment env) { - super(scope, id, StageProps.builder().env(env).build()); - - // Add both stacks to the stage - new AppStack(this, "AppStack"); - new DatabaseStack(this, "DatabaseStack"); - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>In <code class="path">cdk-demo-app/src/main/java/com/myorg/CdkDemoAppApp.java</code>:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">package com.myorg; - -import software.amazon.awscdk.App; -import software.amazon.awscdk.Environment; -import software.amazon.awscdk.StackProps; - -import java.util.Arrays; - -public class CdkDemoAppApp { - public static void main(final String[] args) { - - // Create a CDK app - App app = new App(); - - // Create the development stage - new MyAppStage(app, "Dev", Environment.builder() - .account("123456789012") - .region("us-east-1") - .build()); - - // Create the production stage - new MyAppStage(app, "Prod", Environment.builder() - .account("098765432109") - .region("us-east-1") - .build()); - - app.synth(); - } -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">C#</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>In <code class="path">cdk-demo-app/src/CdkDemoApp/AppStack.cs</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; -using Constructs; - -namespace CdkDemoApp -{ - public class AppStack : Stack - { - internal AppStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) - { - // The code that defines your application goes here - } - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>In <code class="path">cdk-demo-app/src/CdkDemoApp/DatabaseStack.cs</code>:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; -using Constructs; - -namespace CdkDemoApp -{ - public class DatabaseStack : Stack - { - internal DatabaseStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) - { - // The code that defines your database goes here - } - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>In <code class="path">cdk-demo-app/src/CdkDemoApp/MyAppStage.cs</code>:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; -using Constructs; - -namespace CdkDemoApp -{ - // Define the stage - public class MyAppStage : Stage - { - internal MyAppStage(Construct scope, string id, Environment env) : base(scope, id, new StageProps { Env = env }) - { - // Add both stacks to the stage - new AppStack(this, "AppStack"); - new DatabaseStack(this, "DatabaseStack"); - } - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>In <code class="path">cdk-demo-app/src/CdkDemoApp/program.cs</code>:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace CdkDemoApp -{ - sealed class Program - { - public static void Main(string[] args) - { - // Create a CDK app - var app = new App(); - - // Create the development stage - new MyAppStage(app, "Dev", new Amazon.CDK.Environment - { - Account = "123456789012", - Region = "us-east-1" - }); - - // Create the production stage - new MyAppStage(app, "Prod", new Amazon.CDK.Environment - { - Account = "098765432109", - Region = "us-east-1" - }); - - app.Synth(); - } - } -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Go</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>In <code class="path">cdk-demo-app/cdk-demo-app.go</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">package main - -import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/constructs-go/constructs/v10" - "github.com/aws/jsii-runtime-go" -) - -// Define the app stack -type AppStackProps struct { - awscdk.StackProps -} - -func NewAppStack(scope constructs.Construct, id string, props *AppStackProps) awscdk.Stack { - stack := awscdk.NewStack(scope, &id, &props.StackProps) - - // The code that defines your application goes here - - return stack -} - -// Define the database stack -type DatabaseStackProps struct { - awscdk.StackProps -} - -func NewDatabaseStack(scope constructs.Construct, id string, props *DatabaseStackProps) awscdk.Stack { - stack := awscdk.NewStack(scope, &id, &props.StackProps) - - // The code that defines your database goes here - - return stack -} - -// Define the stage -type MyAppStageProps struct { - awscdk.StageProps -} - -func NewMyAppStage(scope constructs.Construct, id string, props *MyAppStageProps) awscdk.Stage { - stage := awscdk.NewStage(scope, &id, &props.StageProps) - - // Add both stacks to the stage - NewAppStack(stage, "AppStack", &AppStackProps{ - StackProps: awscdk.StackProps{ - Env: props.Env, - }, - }) - - NewDatabaseStack(stage, "DatabaseStack", &DatabaseStackProps{ - StackProps: awscdk.StackProps{ - Env: props.Env, - }, - }) - - return stage -} - -func main() { - defer jsii.Close() - - // Create a CDK app - app := awscdk.NewApp(nil) - - // Create the development stage - NewMyAppStage(app, "Dev", &MyAppStageProps{ - StageProps: awscdk.StageProps{ - Env: &awscdk.Environment{ - Account: jsii.String("123456789012"), - Region: jsii.String("us-east-1"), - }, - }, - }) - - // Create the production stage - NewMyAppStage(app, "Prod", &MyAppStageProps{ - StageProps: awscdk.StageProps{ - Env: &awscdk.Environment{ - Account: jsii.String("098765432109"), - Region: jsii.String("us-east-1"), - }, - }, - }) - - app.Synth(nil) -} - -func env() *awscdk.Environment { - return nil -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div class="paragraph"> -<p>When we run <code>cdk synth</code>, two cloud assemblies are created in <code class="path">cdk.out</code>. These two cloud assemblies contain the synthesized AWS CloudFormation template and assets for each stage. The following is snippet of our project directory:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk-demo-app -├── bin -│ └── cdk-demo-app.ts -├── cdk.out -│ ├── assembly-Dev -│ │ ├── DevAppStackunique-hash.assets.json -│ │ ├── DevAppStackunique-hash.template.json -│ │ ├── DevDatabaseStackunique-hash.assets.json -│ │ ├── DevDatabaseStackunique-hash.template.json -│ │ ├── cdk.out -│ │ └── manifest.json -│ ├── assembly-Prod -│ │ ├── ProdAppStackunique-hash.assets.json -│ │ ├── ProdAppStackunique-hash.template.json -│ │ ├── ProdDatabaseStackunique-hash.assets.json -│ │ ├── ProdDatabaseStackunique-hash.template.json -│ │ ├── cdk.out -│ │ └── manifest.json -└── lib - ├── app-stack.ts - ├── database-stack.ts - └── my-stage.ts</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk-demo-app -├── bin -│ └── cdk-demo-app.js -├── cdk.out -│ ├── assembly-Dev -│ │ ├── DevAppStackunique-hash.assets.json -│ │ ├── DevAppStackunique-hash.template.json -│ │ ├── DevDatabaseStackunique-hash.assets.json -│ │ ├── DevDatabaseStackunique-hash.template.json -│ │ ├── cdk.out -│ │ └── manifest.json -│ ├── assembly-Prod -│ │ ├── ProdAppStackunique-hash.assets.json -│ │ ├── ProdAppStackunique-hash.template.json -│ │ ├── ProdDatabaseStackunique-hash.assets.json -│ │ ├── ProdDatabaseStackunique-hash.template.json -│ │ ├── cdk.out -│ │ └── manifest.json -└── lib - ├── app-stack.js - ├── database-stack.js - └── my-stage.js</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk-demo-app -├── app.py -├── cdk.out -│ ├── assembly-Dev -│ │ ├── DevAppStackunique-hash.assets.json -│ │ ├── DevAppStackunique-hash.template.json -│ │ ├── DevDatabaseStackunique-hash.assets.json -│ │ ├── DevDatabaseStackunique-hash.template.json -│ │ ├── cdk.out -│ │ └── manifest.json -│ ├── assembly-Prod -│ │ ├── ProdAppStackunique-hash.assets.json -│ │ ├── ProdAppStackunique-hash.template.json -│ │ ├── ProdDatabaseStackunique-hash.assets.json -│ │ ├── ProdDatabaseStackunique-hash.template.json -│ │ ├── cdk.out -│ │ └── manifest.json -│ ├── cdk.out -│ ├── manifest.json -│ └── tree.json -└── cdk_demo_app - ├── __init__.py - ├── app_stack.py - ├── database_stack.py - └── my_stage.py</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk-demo-app -├── cdk.out -│ ├── assembly-Dev -│ │ ├── DevAppStackunique-hash.assets.json -│ │ ├── DevAppStackunique-hash.template.json -│ │ ├── DevDatabaseStackunique-hash.assets.json -│ │ ├── DevDatabaseStackunique-hash.template.json -│ │ ├── cdk.out -│ │ └── manifest.json -│ ├── assembly-Prod -│ │ ├── ProdAppStackunique-hash.assets.json -│ │ ├── ProdAppStackunique-hash.template.json -│ │ ├── ProdDatabaseStackunique-hash.assets.json -│ │ ├── ProdDatabaseStackunique-hash.template.json -│ │ ├── cdk.out -│ │ └── manifest.json -│ ├── cdk.out -│ ├── manifest.json -│ └── tree.json -└── src - └── main - └── java - └── com - └── myorg - ├── AppStack.java - ├── CdkDemoAppApp.java - ├── DatabaseStack.java - └── MyAppStage.java</code></pre> -</div> -</div> -</dd> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk-demo-app -├── cdk.out -│ ├── assembly-Dev -│ │ ├── DevAppStackunique-hash.assets.json -│ │ ├── DevAppStackunique-hash.template.json -│ │ ├── DevDatabaseStackunique-hash.assets.json -│ │ ├── DevDatabaseStackunique-hash.template.json -│ │ ├── cdk.out -│ │ └── manifest.json -│ ├── assembly-Prod -│ │ ├── ProdAppStackunique-hash.assets.json -│ │ ├── ProdAppStackunique-hash.template.json -│ │ ├── ProdDatabaseStackunique-hash.assets.json -│ │ ├── ProdDatabaseStackunique-hash.template.json -│ │ ├── cdk.out -│ │ └── manifest.json -│ ├── cdk.out -│ ├── manifest.json -│ └── tree.json -└── src - └── CdkDemoApp - ├── AppStack.cs - ├── DatabaseStack.cs - ├── MyAppStage.cs - └── Program.cs</code></pre> -</div> -</div> -</dd> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk-demo-app -├── cdk-demo-app.go -└── cdk.out - ├── assembly-Dev - │ ├── DevAppStackunique-hash.assets.json - │ ├── DevAppStackunique-hash.template.json - │ ├── DevDatabaseStackunique-hash.assets.json - │ ├── DevDatabaseStackunique-hash.template.json - │ ├── cdk.out - │ └── manifest.json - ├── assembly-Prod - │ ├── ProdAppStackunique-hash.assets.json - │ ├── ProdAppStackunique-hash.template.json - │ ├── ProdDatabaseStackunique-hash.assets.json - │ ├── ProdDatabaseStackunique-hash.template.json - │ ├── cdk.out - │ └── manifest.json - ├── cdk.out - ├── manifest.json - └── tree.json</code></pre> -</div> -</div> -</dd> -</dl> -</div> -<div class="paragraph"> -<p>When we list our stacks with <code>cdk list</code>, we see a total of four stacks:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ cdk list -Dev/AppStack (Dev-AppStack) -Dev/DatabaseStack (Dev-DatabaseStack) -Prod/AppStack (Prod-AppStack) -Prod/DatabaseStack (Prod-DatabaseStack)</code></pre> -</div> -</div> -<div class="paragraph"> -<p>To deploy a specific stage, we run <code>cdk deploy</code> and provide the stacks to deploy. The following is an example that uses the <code>\*</code> wildcard to deploy both stacks in our <code>Dev</code> stage:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ cdk deploy "Dev/*" - -✨ Synthesis time: 3.18s - -Dev/AppStack (Dev-AppStack) -Dev/AppStack (Dev-AppStack): deploying... [1/2] - - ✅ Dev/AppStack (Dev-AppStack) - -✨ Deployment time: 1.11s - -Stack ARN: -... - -✨ Total time: 4.29s - -Dev/DatabaseStack (Dev-DatabaseStack) -Dev/DatabaseStack (Dev-DatabaseStack): deploying... [2/2] - - ✅ Dev/DatabaseStack (Dev-DatabaseStack) - -✨ Deployment time: 1.09s - -Stack ARN: -... - -✨ Total time: 4.27s</code></pre> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="constructs">2.11. AWS CDK Constructs</h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Constructs are the basic building blocks of AWS Cloud Development Kit (AWS CDK) applications. A construct is a component within your application that represents one or more AWS CloudFormation resources and their configuration. You build your application, piece by piece, by importing and configuring constructs.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>Constructs are the basic building blocks of AWS Cloud Development Kit (AWS CDK) applications. A construct is a component within your application that represents one or more AWS CloudFormation resources and their configuration. You build your application, piece by piece, by importing and configuring constructs.</p> -</div> -<div class="sect3"> -<h4 id="constructs-import">2.11.1. Import and use constructs</h4> -<div class="paragraph"> -<p>Constructs are classes that you import into your CDK applications from the <a href="#libraries-construct">AWS Construct Library</a>. You can also create and distribute your own constructs, or use constructs created by third-party developers.</p> -</div> -<div class="paragraph"> -<p>Constructs are part of the Construct Programming Model (CPM). They are available to use with other tools such as CDK for <code class="noloc">Terraform</code> (CDKtf), CDK for <code class="noloc">Kubernetes</code> (CDK8s), and <code class="noloc">Projen</code>.</p> -</div> -<div class="paragraph"> -<p>Numerous third parties have also published constructs compatible with the AWS CDK. Visit <a href="https://constructs.dev/search?q=&cdk=aws-cdk&cdkver=2&offset=0">Construct Hub</a> to explore the AWS CDK construct partner ecosystem.</p> -</div> -</div> -<div class="sect3"> -<h4 id="constructs-lib-levels">2.11.2. Construct levels</h4> -<div class="paragraph"> -<p>Constructs from the AWS Construct Library are categorized into three levels. Each level offers an increasing level of abstraction. The higher the abstraction, the easier to configure, requiring less expertise. The lower the abstraction, the more customization available, requiring more expertise.</p> -</div> -<div id="constructs-lib-levels-one" class="dlist"> -<dl> -<dt class="hdlist1">Level 1 (L1) constructs</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>L1 constructs, also known as <em>CFN resources</em>, are the lowest-level construct and offer no abstraction. Each L1 construct maps directly to a single AWS CloudFormation resource. With L1 constructs, you import a construct that represents a specific AWS CloudFormation resource. You then define the resource’s properties within your construct instance.</p> -<div class="paragraph"> -<p>L1 constructs are great to use when you are familiar with AWS CloudFormation and need complete control over defining your AWS resource properties.</p> -</div> -<div class="paragraph"> -<p>In the AWS Construct Library, L1 constructs are named starting with <code>Cfn</code>, followed by an identifier for the AWS CloudFormation resource that it represents. For example, the <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.CfnBucket.html">CfnBucket</a></code> construct is an L1 construct that represents an <code><a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-s3-bucket.html">AWS::S3::Bucket</a></code> AWS CloudFormation resource.</p> -</div> -<div class="paragraph"> -<p>L1 constructs are generated from the <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-resource-specification.html">AWS CloudFormation resource specification</a>. If a resource exists in AWS CloudFormation, it’ll be available in the AWS CDK as an L1 construct. New resources or properties may take up to a week to become available in the AWS Construct Library. For more information, see <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html">AWS resource and property types reference</a> in the <em>AWS CloudFormation User Guide</em>.</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="constructs-lib-levels-two" class="dlist"> -<dl> -<dt class="hdlist1">Level 2 (L2) constructs</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>L2 constructs, also known as <em>curated</em> constructs, are thoughtfully developed by the CDK team and are usually the most widely used construct type. L2 constructs map directly to single AWS CloudFormation resources, similar to L1 constructs. Compared to L1 constructs, L2 constructs provide a higher-level abstraction through an intuitive intent-based API. L2 constructs include sensible default property configurations, best practice security policies, and generate a lot of the boilerplate code and glue logic for you.</p> -<div class="paragraph"> -<p>L2 constructs also provide helper methods for most resources that make it simpler and quicker to define properties, permissions, event-based interactions between resources, and more.</p> -</div> -<div class="paragraph"> -<p>The <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html">s3.Bucket</a></code> class is an example of an L2 construct for an Amazon Simple Storage Service (Amazon S3) bucket resource.</p> -</div> -<div class="paragraph"> -<p>The AWS Construct Library contains L2 constructs that are designated stable and ready for production use. For L2 constructs under development, they are designated as experimental and offered in a separate module.</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="constructs-lib-levels-three" class="dlist"> -<dl> -<dt class="hdlist1">Level 3 (L3) constructs</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>L3 constructs, also known as <em>patterns</em>, are the highest-level of abstraction. Each L3 construct can contain a collection of resources that are configured to work together to accomplish a specific task or service within your application. L3 constructs are used to create entire AWS architectures for particular use cases in your application.</p> -<div class="paragraph"> -<p>To provide complete system designs, or substantial parts of a larger system, L3 constructs offer opinionated default property configurations. They are built around a particular approach toward solving a problem and providing a solution. With L3 constructs, you can create and configure multiple resources quickly, with the fewest amount of input and code.</p> -</div> -<div class="paragraph"> -<p>The <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs_patterns.ApplicationLoadBalancedFargateService.html">ecsPatterns.ApplicationLoadBalancedFargateService</a></code> class is an example of an L3 construct that represents an AWS Fargate service running on an Amazon Elastic Container Service (Amazon ECS) cluster and fronted by an application load balancer.</p> -</div> -<div class="paragraph"> -<p>Similar to L2 constructs, L3 constructs that are ready for production use are included in the AWS Construct Library. Those under development are offered in separate modules.</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect3"> -<h4 id="constructs-define">2.11.3. Defining constructs</h4> -<div class="sect4"> -<h5 id="constructs-composition">Composition</h5> -<div class="paragraph"> -<p><em>Composition</em> is the key pattern for defining higher-level abstractions through constructs. A high-level construct can be composed from any number of lower-level constructs. From a bottom-up perspective, you use constructs to organize the individual AWS resources that you want to deploy. You use whatever abstractions are convenient for your purpose, with as many levels as you need.</p> -</div> -<div class="paragraph"> -<p>With composition, you define reusable components and share them like any other code. For example, a team can define a construct that implements the company’s best practice for an Amazon DynamoDB table, including backup, global replication, automatic scaling, and monitoring. The team can share the construct internally with other teams, or publicly.</p> -</div> -<div class="paragraph"> -<p>Teams can use constructs like any other library package. When the library is updated, developers get access to the new version’s improvements and bug fixes, similar to any other code library.</p> -</div> -</div> -<div class="sect4"> -<h5 id="constructs-init">Initialization</h5> -<div class="paragraph"> -<p>Constructs are implemented in classes that extend the <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html">Construct</a> base class. You define a construct by instantiating the class. All constructs take three parameters when they are initialized:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><strong>scope</strong> – The construct’s parent or owner. This can either be a stack or another construct. Scope determines the construct’s place in the <a href="#apps-tree">construct tree</a>. You should usually pass <code>this</code> (<code>self</code> in <code class="noloc">Python</code>), which represents the current object, for the scope.</p> -</li> -<li> -<p><strong>id</strong> – An <a href="#identifiers">identifier</a> that must be unique within the scope. The identifier serves as a namespace for everything that’s defined within the construct. It’s used to generate unique identifiers, such as <a href="#resources-physical-names">resource names</a> and AWS CloudFormation logical IDs.</p> -<div class="paragraph"> -<p>Identifiers need only be unique within a scope. This lets you instantiate and reuse constructs without concern for the constructs and identifiers they might contain, and enables composing constructs into higher-level abstractions. In addition, scopes make it possible to refer to groups of constructs all at once. Examples include for <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Tag.html">tagging</a>, or specifying where the constructs will be deployed.</p> -</div> -</li> -<li> -<p><strong>props</strong> – A set of properties or keyword arguments, depending on the language, that define the construct’s initial configuration. Higher-level constructs provide more defaults, and if all prop elements are optional, you can omit the props parameter completely.</p> -</li> -</ul> -</div> -</div> -<div class="sect4"> -<h5 id="constructs-config">Configuration</h5> -<div class="paragraph"> -<p>Most constructs accept <code>props</code> as their third argument (or in Python, keyword arguments), a name/value collection that defines the construct’s configuration. The following example defines a bucket with AWS Key Management Service (AWS KMS) encryption and static website hosting enabled. Since it does not explicitly specify an encryption key, the <code>Bucket</code> construct defines a new <code>kms.Key</code> and associates it with the bucket.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">new s3.Bucket(this, 'MyEncryptedBucket', { - encryption: s3.BucketEncryption.KMS, - websiteIndexDocument: 'index.html' -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">new s3.Bucket(this, 'MyEncryptedBucket', { - encryption: s3.BucketEncryption.KMS, - websiteIndexDocument: 'index.html' -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">s3.Bucket(self, "MyEncryptedBucket", encryption=s3.BucketEncryption.KMS, - website_index_document="index.html")</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">Bucket.Builder.create(this, "MyEncryptedBucket") - .encryption(BucketEncryption.KMS_MANAGED) - .websiteIndexDocument("index.html").build();</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">new Bucket(this, "MyEncryptedBucket", new BucketProps -{ - Encryption = BucketEncryption.KMS_MANAGED, - WebsiteIndexDocument = "index.html" -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go"> awss3.NewBucket(stack, jsii.String("MyEncryptedBucket"), &awss3.BucketProps{ - Encryption: awss3.BucketEncryption_KMS, - WebsiteIndexDocument: jsii.String("index.html"), - })</code></pre> -</div> -</div> -</div> -<div class="sect4"> -<h5 id="constructs-interact">Interacting with constructs</h5> -<div class="paragraph"> -<p>Constructs are classes that extend the base <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html">Construct</a> class. After you instantiate a construct, the construct object exposes a set of methods and properties that let you interact with the construct and pass it around as a reference to other parts of the system.</p> -</div> -<div class="paragraph"> -<p>The AWS CDK framework doesn’t put any restrictions on the APIs of constructs. Authors can define any API they want. However, the AWS constructs that are included with the AWS Construct Library, such as <code>s3.Bucket</code>, follow guidelines and common patterns. This provides a consistent experience across all AWS resources.</p> -</div> -<div class="paragraph"> -<p>Most AWS constructs have a set of <a href="#permissions-grants">grant</a> methods that you can use to grant AWS Identity and Access Management (IAM) permissions on that construct to a principal. The following example grants the IAM group <code>data-science</code> permission to read from the Amazon S3 bucket <code>raw-data</code>.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const rawData = new s3.Bucket(this, 'raw-data'); -const dataScience = new iam.Group(this, 'data-science'); -rawData.grantRead(dataScience);</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const rawData = new s3.Bucket(this, 'raw-data'); -const dataScience = new iam.Group(this, 'data-science'); -rawData.grantRead(dataScience);</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">raw_data = s3.Bucket(self, 'raw-data') -data_science = iam.Group(self, 'data-science') -raw_data.grant_read(data_science)</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">Bucket rawData = new Bucket(this, "raw-data"); -Group dataScience = new Group(this, "data-science"); -rawData.grantRead(dataScience);</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">var rawData = new Bucket(this, "raw-data"); -var dataScience = new Group(this, "data-science"); -rawData.GrantRead(dataScience);</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go"> rawData := awss3.NewBucket(stack, jsii.String("raw-data"), nil) - dataScience := awsiam.NewGroup(stack, jsii.String("data-science"), nil) - rawData.GrantRead(dataScience, nil)</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Another common pattern is for AWS constructs to set one of the resource’s attributes from data supplied elsewhere. Attributes can include Amazon Resource Names (ARNs), names, or URLs.</p> -</div> -<div class="paragraph"> -<p>The following code defines an AWS Lambda function and associates it with an Amazon Simple Queue Service (Amazon SQS) queue through the queue’s URL in an environment variable.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const jobsQueue = new sqs.Queue(this, 'jobs'); -const createJobLambda = new lambda.Function(this, 'create-job', { - runtime: lambda.Runtime.NODEJS_18_X, - handler: 'index.handler', - code: lambda.Code.fromAsset('./create-job-lambda-code'), - environment: { - QUEUE_URL: jobsQueue.queueUrl - } -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const jobsQueue = new sqs.Queue(this, 'jobs'); -const createJobLambda = new lambda.Function(this, 'create-job', { - runtime: lambda.Runtime.NODEJS_18_X, - handler: 'index.handler', - code: lambda.Code.fromAsset('./create-job-lambda-code'), - environment: { - QUEUE_URL: jobsQueue.queueUrl - } -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">jobs_queue = sqs.Queue(self, "jobs") -create_job_lambda = lambda_.Function(self, "create-job", - runtime=lambda_.Runtime.NODEJS_18_X, - handler="index.handler", - code=lambda_.Code.from_asset("./create-job-lambda-code"), - environment=dict( - QUEUE_URL=jobs_queue.queue_url - ) -)</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">final Queue jobsQueue = new Queue(this, "jobs"); -Function createJobLambda = Function.Builder.create(this, "create-job") - .handler("index.handler") - .code(Code.fromAsset("./create-job-lambda-code")) - .environment(java.util.Map.of( // Map.of is Java 9 or later - "QUEUE_URL", jobsQueue.getQueueUrl()) - .build();</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">var jobsQueue = new Queue(this, "jobs"); -var createJobLambda = new Function(this, "create-job", new FunctionProps -{ - Runtime = Runtime.NODEJS_18_X, - Handler = "index.handler", - Code = Code.FromAsset(@".\create-job-lambda-code"), - Environment = new Dictionary<string, string> - { - ["QUEUE_URL"] = jobsQueue.QueueUrl - } -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go"> createJobLambda := awslambda.NewFunction(stack, jsii.String("create-job"), &awslambda.FunctionProps{ - Runtime: awslambda.Runtime_NODEJS_18_X(), - Handler: jsii.String("index.handler"), - Code: awslambda.Code_FromAsset(jsii.String(".\\create-job-lambda-code"), nil), - Environment: &map[string]*string{ - "QUEUE_URL": jsii.String(*jobsQueue.QueueUrl()), - }, - })</code></pre> -</div> -</div> -<div class="paragraph"> -<p>For information about the most common API patterns in the AWS Construct Library, see <a href="#resources">Resources and the AWS CDK</a>.</p> -</div> -</div> -<div class="sect4"> -<h5 id="constructs-apps-stacks">The app and stack construct</h5> -<div class="paragraph"> -<p>The <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.App.html">App</a></code> and <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html">Stack</a></code> classes from the AWS Construct Library are unique constructs. Compared to other constructs, they don’t configure AWS resources on their own. Instead, they are used to provide context for your other constructs. All constructs that represent AWS resources must be defined, directly or indirectly, within the scope of a <code>Stack</code> construct. <code>Stack</code> constructs are defined within the scope of an <code>App</code> construct.</p> -</div> -<div class="paragraph"> -<p>To learn more about CDK apps, see <a href="#apps">AWS CDK apps</a>. To learn more about CDK stacks, see <a href="#stacks">Introduction to AWS CDK stacks</a>.</p> -</div> -<div class="paragraph"> -<p>The following example defines an app with a single stack. Within the stack, an L2 construct is used to configure an Amazon S3 bucket resource.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import { App, Stack, StackProps } from 'aws-cdk-lib'; -import * as s3 from 'aws-cdk-lib/aws-s3'; - -class HelloCdkStack extends Stack { - constructor(scope: App, id: string, props?: StackProps) { - super(scope, id, props); - - new s3.Bucket(this, 'MyFirstBucket', { - versioned: true - }); - } -} - -const app = new App(); -new HelloCdkStack(app, "HelloCdkStack");</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const { App , Stack } = require('aws-cdk-lib'); -const s3 = require('aws-cdk-lib/aws-s3'); - -class HelloCdkStack extends Stack { - constructor(scope, id, props) { - super(scope, id, props); - - new s3.Bucket(this, 'MyFirstBucket', { - versioned: true - }); - } -} - -const app = new App(); -new HelloCdkStack(app, "HelloCdkStack");</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">from aws_cdk import App, Stack -import aws_cdk.aws_s3 as s3 -from constructs import Construct - -class HelloCdkStack(Stack): - - def __init__(self, scope: Construct, id: str, **kwargs) -> None: - super().__init__(scope, id, **kwargs) - - s3.Bucket(self, "MyFirstBucket", versioned=True) - -app = App() -HelloCdkStack(app, "HelloCdkStack")</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Stack defined in <code class="path">HelloCdkStack.java</code> file:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">import software.constructs.Construct; -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.StackProps; -import software.amazon.awscdk.services.s3.*; - -public class HelloCdkStack extends Stack { - public HelloCdkStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public HelloCdkStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - Bucket.Builder.create(this, "MyFirstBucket") - .versioned(true).build(); - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>App defined in <code class="path">HelloCdkApp.java</code> file:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">import software.amazon.awscdk.App; -import software.amazon.awscdk.StackProps; - -public class HelloCdkApp { - public static void main(final String[] args) { - App app = new App(); - - new HelloCdkStack(app, "HelloCdkStack", StackProps.builder() - .build()); - - app.synth(); - } -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; -using Amazon.CDK.AWS.S3; - -namespace HelloCdkApp -{ - internal static class Program - { - public static void Main(string[] args) - { - var app = new App(); - new HelloCdkStack(app, "HelloCdkStack"); - app.Synth(); - } - } - - public class HelloCdkStack : Stack - { - public HelloCdkStack(Construct scope, string id, IStackProps props=null) : base(scope, id, props) - { - new Bucket(this, "MyFirstBucket", new BucketProps { Versioned = true }); - } - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">func NewHelloCdkStack(scope constructs.Construct, id string, props *HelloCdkStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - stack := awscdk.NewStack(scope, &id, &sprops) - - awss3.NewBucket(stack, jsii.String("MyFirstBucket"), &awss3.BucketProps{ - Versioned: jsii.Bool(true), - }) - - return stack -}</code></pre> -</div> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="constructs-work">2.11.4. Working with constructs</h4> -<div class="sect4"> -<h5 id="constructs-l1-using">Working with L1 constructs</h5> -<div class="paragraph"> -<p>L1 constructs map directly to individual AWS CloudFormation resources. You must provide the resource’s required configuration.</p> -</div> -<div class="paragraph"> -<p>In this example, we create a <code>bucket</code> object using the <code>CfnBucket</code> L1 construct:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const bucket = new s3.CfnBucket(this, "amzn-s3-demo-bucket", { - bucketName: "amzn-s3-demo-bucket" -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const bucket = new s3.CfnBucket(this, "amzn-s3-demo-bucket", { - bucketName: "amzn-s3-demo-bucket" -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">bucket = s3.CfnBucket(self, "amzn-s3-demo-bucket", bucket_name="amzn-s3-demo-bucket")</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">CfnBucket bucket = new CfnBucket.Builder().bucketName("amzn-s3-demo-bucket").build();</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">var bucket = new CfnBucket(this, "amzn-s3-demo-bucket", new CfnBucketProps -{ - BucketName= "amzn-s3-demo-bucket" -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go"> awss3.NewCfnBucket(stack, jsii.String("amzn-s3-demo-bucket"), &awss3.CfnBucketProps{ - BucketName: jsii.String("amzn-s3-demo-bucket"), - })</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Construct properties that aren’t simple Booleans, strings, numbers, or containers are handled differently in the supported languages.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const bucket = new s3.CfnBucket(this, "amzn-s3-demo-bucket", { - bucketName: "amzn-s3-demo-bucket", - corsConfiguration: { - corsRules: [{ - allowedOrigins: ["*"], - allowedMethods: ["GET"] - }] - } -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const bucket = new s3.CfnBucket(this, "amzn-s3-demo-bucket", { - bucketName: "amzn-s3-demo-bucket", - corsConfiguration: { - corsRules: [{ - allowedOrigins: ["*"], - allowedMethods: ["GET"] - }] - } -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>In Python, these properties are represented by types defined as inner classes of the L1 construct. For example, the optional property <code>cors_configuration</code> of a <code>CfnBucket</code> requires a wrapper of type <code>CfnBucket.CorsConfigurationProperty</code>. Here we are defining <code>cors_configuration</code> on a <code>CfnBucket</code> instance.</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">bucket = CfnBucket(self, "amzn-s3-demo-bucket", bucket_name="amzn-s3-demo-bucket", - cors_configuration=CfnBucket.CorsConfigurationProperty( - cors_rules=[CfnBucket.CorsRuleProperty( - allowed_origins=["*"], - allowed_methods=["GET"] - )] - ) -)</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Java</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>In Java, these properties are represented by types defined as inner classes of the L1 construct. For example, the optional property <code>corsConfiguration</code> of a <code>CfnBucket</code> requires a wrapper of type <code>CfnBucket.CorsConfigurationProperty</code>. Here we are defining <code>corsConfiguration</code> on a <code>CfnBucket</code> instance.</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">CfnBucket bucket = CfnBucket.Builder.create(this, "amzn-s3-demo-bucket") - .bucketName("amzn-s3-demo-bucket") - .corsConfiguration(new CfnBucket.CorsConfigurationProperty.Builder() - .corsRules(Arrays.asList(new CfnBucket.CorsRuleProperty.Builder() - .allowedOrigins(Arrays.asList("*")) - .allowedMethods(Arrays.asList("GET")) - .build())) - .build()) - .build();</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">C#</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>In C#, these properties are represented by types defined as inner classes of the L1 construct. For example, the optional property <code>CorsConfiguration</code> of a <code>CfnBucket</code> requires a wrapper of type <code>CfnBucket.CorsConfigurationProperty</code>. Here we are defining <code>CorsConfiguration</code> on a <code>CfnBucket</code> instance.</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">var bucket = new CfnBucket(this, "amzn-s3-demo-bucket", new CfnBucketProps -{ - BucketName = "amzn-s3-demo-bucket", - CorsConfiguration = new CfnBucket.CorsConfigurationProperty - { - CorsRules = new object[] { - new CfnBucket.CorsRuleProperty - { - AllowedOrigins = new string[] { "*" }, - AllowedMethods = new string[] { "GET" }, - } - } - } -});</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Go</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>In Go, these types are named using the name of the L1 construct, an underscore, and the property name. For example, the optional property <code>CorsConfiguration</code> of a <code>CfnBucket</code> requires a wrapper of type <code>CfnBucket_CorsConfigurationProperty</code>. Here we are defining <code>CorsConfiguration</code> on a <code>CfnBucket</code> instance.</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go"> awss3.NewCfnBucket(stack, jsii.String("amzn-s3-demo-bucket"), &awss3.CfnBucketProps{ - BucketName: jsii.String("amzn-s3-demo-bucket"), - CorsConfiguration: &awss3.CfnBucket_CorsConfigurationProperty{ - CorsRules: []awss3.CorsRule{ - awss3.CorsRule{ - AllowedOrigins: jsii.Strings("*"), - AllowedMethods: &[]awss3.HttpMethods{"GET"}, - }, - }, - }, - })</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div class="admonitionblock important"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-important" title="Important"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>You can’t use L2 property types with L1 constructs, or vice versa. When working with L1 constructs, always use the types defined for the L1 construct you’re using. Do not use types from other L1 constructs (some may have the same name, but they are not the same type).</p> -</div> -<div class="paragraph"> -<p>Some of our language-specific API references currently have errors in the paths to L1 property types, or don’t document these classes at all. We hope to fix this soon. In the meantime, remember that such types are always inner classes of the L1 construct they are used with.</p> -</div> -</td> -</tr> -</table> -</div> -</div> -<div class="sect4"> -<h5 id="constructs-using">Working with L2 constructs</h5> -<div class="paragraph"> -<p>In the following example, we define an Amazon S3 bucket by creating an object from the <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html">Bucket</a> L2 construct:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as s3 from 'aws-cdk-lib/aws-s3'; - -// "this" is HelloCdkStack -new s3.Bucket(this, 'MyFirstBucket', { - versioned: true -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const s3 = require('aws-cdk-lib/aws-s3'); - -// "this" is HelloCdkStack -new s3.Bucket(this, 'MyFirstBucket', { - versioned: true -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">import aws_cdk.aws_s3 as s3 - -# "self" is HelloCdkStack -s3.Bucket(self, "MyFirstBucket", versioned=True)</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">import software.amazon.awscdk.services.s3.*; - -public class HelloCdkStack extends Stack { - public HelloCdkStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public HelloCdkStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - Bucket.Builder.create(this, "MyFirstBucket") - .versioned(true).build(); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK.AWS.S3; - -// "this" is HelloCdkStack -new Bucket(this, "MyFirstBucket", new BucketProps -{ - Versioned = true -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">import ( - "github.com/aws/aws-cdk-go/awscdk/v2/awss3" - "github.com/aws/jsii-runtime-go" -) - -// stack is HelloCdkStack -awss3.NewBucket(stack, jsii.String("MyFirstBucket"), &awss3.BucketProps{ - Versioned: jsii.Bool(true), - })></code></pre> -</div> -</div> -<div class="paragraph"> -<p><code>MyFirstBucket</code> is not the name of the bucket that AWS CloudFormation creates. It is a logical identifier given to the new construct within the context of your CDK app. The <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Resource.html#physicalname">physicalName</a> value will be used to name the AWS CloudFormation resource.</p> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="constructs-work-third">2.11.5. Working with third-party constructs</h4> -<div class="paragraph"> -<p><a href="https://constructs.dev/search?q=&cdk=aws-cdk&cdkver=2&sort=downloadsDesc&offset=0">Construct Hub</a> is a resource to help you discover additional constructs from AWS, third parties, and the open-source CDK community.</p> -</div> -<div class="sect4"> -<h5 id="constructs-author">Writing your own constructs</h5> -<div class="paragraph"> -<p>In addition to using existing constructs, you can also write your own constructs and let anyone use them in their apps. All constructs are equal in the AWS CDK. Constructs from the AWS Construct Library are treated the same as a construct from a third-party library published via <code class="noloc">NPM</code>, <code class="noloc">Maven</code>, or <code class="noloc">PyPI</code>. Constructs published to your company’s internal package repository are also treated in the same way.</p> -</div> -<div class="paragraph"> -<p>To declare a new construct, create a class that extends the <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html">Construct</a> base class, in the <code>constructs</code> package, then follow the pattern for initializer arguments.</p> -</div> -<div class="paragraph"> -<p>The following example shows how to declare a construct that represents an Amazon S3 bucket. The S3 bucket sends an Amazon Simple Notification Service (Amazon SNS) notification every time someone uploads a file into it.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">export interface NotifyingBucketProps { - prefix?: string; -} - -export class NotifyingBucket extends Construct { - constructor(scope: Construct, id: string, props: NotifyingBucketProps = {}) { - super(scope, id); - const bucket = new s3.Bucket(this, 'bucket'); - const topic = new sns.Topic(this, 'topic'); - bucket.addObjectCreatedNotification(new s3notify.SnsDestination(topic), - { prefix: props.prefix }); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">class NotifyingBucket extends Construct { - constructor(scope, id, props = {}) { - super(scope, id); - const bucket = new s3.Bucket(this, 'bucket'); - const topic = new sns.Topic(this, 'topic'); - bucket.addObjectCreatedNotification(new s3notify.SnsDestination(topic), - { prefix: props.prefix }); - } -} - -module.exports = { NotifyingBucket }</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">class NotifyingBucket(Construct): - - def __init__(self, scope: Construct, id: str, *, prefix=None): - super().__init__(scope, id) - bucket = s3.Bucket(self, "bucket") - topic = sns.Topic(self, "topic") - bucket.add_object_created_notification(s3notify.SnsDestination(topic), - s3.NotificationKeyFilter(prefix=prefix))</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">public class NotifyingBucket extends Construct { - - public NotifyingBucket(final Construct scope, final String id) { - this(scope, id, null, null); - } - - public NotifyingBucket(final Construct scope, final String id, final BucketProps props) { - this(scope, id, props, null); - } - - public NotifyingBucket(final Construct scope, final String id, final String prefix) { - this(scope, id, null, prefix); - } - - public NotifyingBucket(final Construct scope, final String id, final BucketProps props, final String prefix) { - super(scope, id); - - Bucket bucket = new Bucket(this, "bucket"); - Topic topic = new Topic(this, "topic"); - if (prefix != null) - bucket.addObjectCreatedNotification(new SnsDestination(topic), - NotificationKeyFilter.builder().prefix(prefix).build()); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">public class NotifyingBucketProps : BucketProps -{ - public string Prefix { get; set; } -} - -public class NotifyingBucket : Construct -{ - public NotifyingBucket(Construct scope, string id, NotifyingBucketProps props = null) : base(scope, id) - { - var bucket = new Bucket(this, "bucket"); - var topic = new Topic(this, "topic"); - bucket.AddObjectCreatedNotification(new SnsDestination(topic), new NotificationKeyFilter - { - Prefix = props?.Prefix - }); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">type NotifyingBucketProps struct { - awss3.BucketProps - Prefix *string -} - -func NewNotifyingBucket(scope constructs.Construct, id *string, props *NotifyingBucketProps) awss3.Bucket { - var bucket awss3.Bucket - if props == nil { - bucket = awss3.NewBucket(scope, jsii.String(*id+"Bucket"), nil) - } else { - bucket = awss3.NewBucket(scope, jsii.String(*id+"Bucket"), &props.BucketProps) - } - topic := awssns.NewTopic(scope, jsii.String(*id+"Topic"), nil) - if props == nil { - bucket.AddObjectCreatedNotification(awss3notifications.NewSnsDestination(topic)) - } else { - bucket.AddObjectCreatedNotification(awss3notifications.NewSnsDestination(topic), &awss3.NotificationKeyFilter{ - Prefix: props.Prefix, - }) - } - return bucket -}</code></pre> -</div> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>Our <code>NotifyingBucket</code> construct inherits not from <code>Bucket</code> but rather from <code>Construct</code>. We are using composition, not inheritance, to bundle an Amazon S3 bucket and an Amazon SNS topic together. In general, composition is preferred over inheritance when developing AWS CDK constructs.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>The <code>NotifyingBucket</code> constructor has a typical construct signature: <code>scope</code>, <code>id</code>, and <code>props</code>. The last argument, <code>props</code>, is optional (gets the default value <code>{}</code>) because all props are optional. (The base <code>Construct</code> class does not take a <code>props</code> argument.) You could define an instance of this construct in your app without <code>props</code>, for example:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">new NotifyingBucket(this, 'MyNotifyingBucket');</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">new NotifyingBucket(this, 'MyNotifyingBucket');</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">NotifyingBucket(self, "MyNotifyingBucket")</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">new NotifyingBucket(this, "MyNotifyingBucket");</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">new NotifyingBucket(this, "MyNotifyingBucket");</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">NewNotifyingBucket(stack, jsii.String("MyNotifyingBucket"), nil)</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Or you could use <code>props</code> (in Java, an additional parameter) to specify the path prefix to filter on, for example:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">new NotifyingBucket(this, 'MyNotifyingBucket', { prefix: 'images/' });</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">new NotifyingBucket(this, 'MyNotifyingBucket', { prefix: 'images/' });</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">NotifyingBucket(self, "MyNotifyingBucket", prefix="images/")</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">new NotifyingBucket(this, "MyNotifyingBucket", "/images");</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">new NotifyingBucket(this, "MyNotifyingBucket", new NotifyingBucketProps -{ - Prefix = "/images" -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">NewNotifyingBucket(stack, jsii.String("MyNotifyingBucket"), &NotifyingBucketProps{ - Prefix: jsii.String("images/"), -})</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Typically, you would also want to expose some properties or methods on your constructs. It’s not very useful to have a topic hidden behind your construct, because users of your construct aren’t able to subscribe to it. Adding a <code>topic</code> property lets consumers access the inner topic, as shown in the following example:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">export class NotifyingBucket extends Construct { - public readonly topic: sns.Topic; - - constructor(scope: Construct, id: string, props: NotifyingBucketProps) { - super(scope, id); - const bucket = new s3.Bucket(this, 'bucket'); - this.topic = new sns.Topic(this, 'topic'); - bucket.addObjectCreatedNotification(new s3notify.SnsDestination(this.topic), { prefix: props.prefix }); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">class NotifyingBucket extends Construct { - - constructor(scope, id, props) { - super(scope, id); - const bucket = new s3.Bucket(this, 'bucket'); - this.topic = new sns.Topic(this, 'topic'); - bucket.addObjectCreatedNotification(new s3notify.SnsDestination(this.topic), { prefix: props.prefix }); - } -} - -module.exports = { NotifyingBucket };</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">class NotifyingBucket(Construct): - - def __init__(self, scope: Construct, id: str, *, prefix=None, **kwargs): - super().__init__(scope, id) - bucket = s3.Bucket(self, "bucket") - self.topic = sns.Topic(self, "topic") - bucket.add_object_created_notification(s3notify.SnsDestination(self.topic), - s3.NotificationKeyFilter(prefix=prefix))</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">public class NotifyingBucket extends Construct { - - public Topic topic = null; - - public NotifyingBucket(final Construct scope, final String id) { - this(scope, id, null, null); - } - - public NotifyingBucket(final Construct scope, final String id, final BucketProps props) { - this(scope, id, props, null); - } - - public NotifyingBucket(final Construct scope, final String id, final String prefix) { - this(scope, id, null, prefix); - } - - public NotifyingBucket(final Construct scope, final String id, final BucketProps props, final String prefix) { - super(scope, id); - - Bucket bucket = new Bucket(this, "bucket"); - topic = new Topic(this, "topic"); - if (prefix != null) - bucket.addObjectCreatedNotification(new SnsDestination(topic), - NotificationKeyFilter.builder().prefix(prefix).build()); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">public class NotifyingBucket : Construct -{ - public readonly Topic topic; - - public NotifyingBucket(Construct scope, string id, NotifyingBucketProps props = null) : base(scope, id) - { - var bucket = new Bucket(this, "bucket"); - topic = new Topic(this, "topic"); - bucket.AddObjectCreatedNotification(new SnsDestination(topic), new NotificationKeyFilter - { - Prefix = props?.Prefix - }); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>To do this in Go, we’ll need a little extra plumbing. Our original <code>NewNotifyingBucket</code> function returned an <code>awss3.Bucket</code>. We’ll need to extend <code>Bucket</code> to include a <code>topic</code> member by creating a <code>NotifyingBucket</code> struct. Our function will then return this type.</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">type NotifyingBucket struct { - awss3.Bucket - topic awssns.Topic -} - -func NewNotifyingBucket(scope constructs.Construct, id *string, props *NotifyingBucketProps) NotifyingBucket { - var bucket awss3.Bucket - if props == nil { - bucket = awss3.NewBucket(scope, jsii.String(*id+"Bucket"), nil) - } else { - bucket = awss3.NewBucket(scope, jsii.String(*id+"Bucket"), &props.BucketProps) - } - topic := awssns.NewTopic(scope, jsii.String(*id+"Topic"), nil) - if props == nil { - bucket.AddObjectCreatedNotification(awss3notifications.NewSnsDestination(topic)) - } else { - bucket.AddObjectCreatedNotification(awss3notifications.NewSnsDestination(topic), &awss3.NotificationKeyFilter{ - Prefix: props.Prefix, - }) - } - var nbucket NotifyingBucket - nbucket.Bucket = bucket - nbucket.topic = topic - return nbucket -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div class="paragraph"> -<p>Now, consumers can subscribe to the topic, for example:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const queue = new sqs.Queue(this, 'NewImagesQueue'); -const images = new NotifyingBucket(this, '/images'); -images.topic.addSubscription(new sns_sub.SqsSubscription(queue));</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const queue = new sqs.Queue(this, 'NewImagesQueue'); -const images = new NotifyingBucket(this, '/images'); -images.topic.addSubscription(new sns_sub.SqsSubscription(queue));</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">queue = sqs.Queue(self, "NewImagesQueue") -images = NotifyingBucket(self, prefix="Images") -images.topic.add_subscription(sns_sub.SqsSubscription(queue))</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">NotifyingBucket images = new NotifyingBucket(this, "MyNotifyingBucket", "/images"); -images.topic.addSubscription(new SqsSubscription(queue));</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">var queue = new Queue(this, "NewImagesQueue"); -var images = new NotifyingBucket(this, "MyNotifyingBucket", new NotifyingBucketProps -{ - Prefix = "/images" -}); -images.topic.AddSubscription(new SqsSubscription(queue));</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go"> queue := awssqs.NewQueue(stack, jsii.String("NewImagesQueue"), nil) - images := NewNotifyingBucket(stack, jsii.String("MyNotifyingBucket"), &NotifyingBucketProps{ - Prefix: jsii.String("/images"), - }) - images.topic.AddSubscription(awssnssubscriptions.NewSqsSubscription(queue, nil))</code></pre> -</div> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="constructs-learn">2.11.6. Learn more</h4> -<div class="paragraph"> -<p>The following video provides a comprehensive overview of CDK constructs, and explains how you can use them in your CDK apps.</p> -</div> -<div class="videoblock text-center"> -<div class="content"> -<iframe width="480" height="390" src="https://www.youtube.com/embed/PzU-i0rJPGw?rel=0" frameborder="0" allowfullscreen></iframe> -</div> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="environments">2.12. Environments for the AWS CDK</h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>An environment consists of the AWS account and AWS Region that you deploy an AWS Cloud Development Kit (AWS CDK) stack to.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>An environment consists of the AWS account and AWS Region that you deploy an AWS Cloud Development Kit (AWS CDK) stack to.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">AWS account</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>When you create an AWS account, you receive an account ID. This ID is a 12-digit number, such as <strong>012345678901</strong>, that uniquely identifies your account. To learn more, see <a href="https://docs.aws.amazon.com/accounts/latest/reference/manage-acct-identifiers.html">View AWS account identifiers</a> in the <em>AWS Account Management Reference Guide</em>.</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">AWS Region</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>AWS Regions are named by using a combination of geographical location and a number that represents an Availability Zone in the Region. For example, <strong><code class="noloc">us-east-1</code></strong> represents an Availability Zone in the US East (N. Virginia) Region. To learn more about AWS Regions, see <a href="https://aws.amazon.com/about-aws/global-infrastructure/regions_az/">Regions and Availability Zones</a>. For a list of Region codes, see <a href="https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints">Regional endpoints</a> in the <em>AWS General Reference</em> Reference Guide.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div class="paragraph"> -<p>The AWS CDK can determine environments from your credentials and configuration files. These files can be created and managed with the AWS Command Line Interface (AWS CLI). The following is a basic example of these files:</p> -</div> -<div class="paragraph"> -<p><strong>Credentials file</strong></p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-toml" data-lang="toml">[default] -aws_access_key_id=ASIAIOSFODNN7EXAMPLE -aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY -aws_session_token = IQoJb3JpZ2luX2IQoJb3JpZ2luX2IQoJb3JpZ2luX2IQoJb3JpZ2luX2IQoJb3JpZVERYLONGSTRINGEXAMPLE - -[user1] -aws_access_key_id=ASIAI44QH8DHBEXAMPLE -aws_secret_access_key=je7MtGbClwBF/2Zp9Utk/h3yCo8nvbEXAMPLEKEY -aws_session_token = fcZib3JpZ2luX2IQoJb3JpZ2luX2IQoJb3JpZ2luX2IQoJb3JpZ2luX2IQoJb3JpZVERYLONGSTRINGEXAMPLE</code></pre> -</div> -</div> -<div class="paragraph"> -<p><strong>Configuration file</strong></p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-toml" data-lang="toml">[default] -region=us-west-2 -output=json - -[profile user1] -region=us-east-1 -output=text</code></pre> -</div> -</div> -<div class="paragraph"> -<p>You can pass environment information from these files in your CDK code through environment variables that are provided by the CDK. When you run a CDK <code class="noloc">CLI</code> command, such as <code>cdk deploy</code>, you then provide the profile from your credentials and configuration files to gather environment information from.</p> -</div> -<div class="paragraph"> -<p>The following is an example of specifying these environment variables in your CDK code:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">new MyDevStack(app, 'dev', { - env: { - account: process.env.CDK_DEFAULT_ACCOUNT, - region: process.env.CDK_DEFAULT_REGION -}});</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The following is an example of passing values associated with the <code>user1</code> profile from your credentials and configuration files to the CDK <code class="noloc">CLI</code> using the <code>--profile</code> option. Values from these files will be passed to your environment variables:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk deploy myStack --profile user1</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Instead of using values from the credentials and configuration files, you can also hard-code environment values in your CDK code. The following is an example:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const envEU = { account: '238383838383', region: 'eu-west-1' }; -const envUSA = { account: '837873873873', region: 'us-west-2' }; - -new MyFirstStack(app, 'first-stack-us', { env: envUSA }); -new MyFirstStack(app, 'first-stack-eu', { env: envEU });</code></pre> -</div> -</div> -<div class="sect3"> -<h4 id="environments-learn">2.12.1. Learn more</h4> -<div class="paragraph"> -<p>To get started with using environments with the AWS CDK, see <a href="#configure-env">Configure environments to use with the AWS CDK</a>.</p> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="bootstrapping">2.13. AWS CDK bootstrapping</h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p><em>Bootstrapping</em> is the process of preparing your AWS environment for usage with the AWS Cloud Development Kit (AWS CDK). Before you deploy a CDK stack into an AWS environment, the environment must first be bootstrapped.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p><em>Bootstrapping</em> is the process of preparing your AWS environment for usage with the AWS Cloud Development Kit (AWS CDK). Before you deploy a CDK stack into an AWS environment, the environment must first be bootstrapped.</p> -</div> -<div class="sect3"> -<h4 id="bootstrapping-what">2.13.1. What is bootstrapping?</h4> -<div class="paragraph"> -<p>Bootstrapping prepares your AWS environment by provisioning specific AWS resources in your environment that are used by the AWS CDK. These resources are commonly referred to as your <em>bootstrap resources</em>. They include the following:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><strong>Amazon Simple Storage Service (Amazon S3) bucket</strong> – Used to store your CDK project files, such as AWS Lambda function code and assets.</p> -</li> -<li> -<p><strong>Amazon Elastic Container Registry (Amazon ECR) repository</strong> – Used primarily to store <code class="noloc">Docker</code> images.</p> -</li> -<li> -<p><strong>AWS Identity and Access Management (IAM) roles</strong> – Configured to grant permissions needed by the AWS CDK to perform deployments. For more information about the IAM roles created during bootstrapping, see <a href="#bootstrapping-env-roles">IAM roles created during bootstrapping</a>.</p> -</li> -</ul> -</div> -</div> -<div class="sect3"> -<h4 id="bootstrapping-how">2.13.2. How does bootstrapping work?</h4> -<div class="paragraph"> -<p><em>Resources and their configuration that are used by the CDK are defined in an AWS CloudFormation template. This template is created and managed by the CDK team. For the latest version of this template, see <code class="path"><a href="https://github.com/aws/aws-cdk-cli/blob/main/packages/aws-cdk/lib/api/bootstrap/bootstrap-template.yaml">bootstrap-template.yaml</a></code> in the aws-cdk-cli <code class="noloc">GitHub</code> repository</em>.</p> -</div> -<div class="paragraph"> -<p>To bootstrap an environment, you use the AWS CDK Command Line Interface (AWS CDK <code class="noloc">CLI</code>) <code>cdk bootstrap</code> command. The CDK <code class="noloc">CLI</code> retrieves the template and deploys it to AWS CloudFormation as a stack, known as the <em>bootstrap stack</em>. By default, the stack name is <code>CDKToolkit</code>. By deploying this template, CloudFormation provisions the resources in your environment. After deployment, the bootstrap stack will appear in the AWS CloudFormation console of your environment.</p> -</div> -<div class="paragraph"> -<p>You can also customize bootstrapping by modifying the template or by using CDK <code class="noloc">CLI</code> options with the <code>cdk bootstrap</code> command.</p> -</div> -<div class="paragraph"> -<p>AWS environments are independent. Each environment that you want to use with the AWS CDK must first be bootstrapped.</p> -</div> -</div> -<div class="sect3"> -<h4 id="bootstrapping-learn">2.13.3. Learn more</h4> -<div class="paragraph"> -<p>For instructions on bootstrapping your environment, see <a href="#bootstrapping-env">Bootstrap your environment for use with the AWS CDK</a>.</p> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="resources">2.14. Resources and the AWS CDK</h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p><em>Resources</em> are what you configure to use AWS services in your applications. Resources are a feature of AWS CloudFormation. By configuring resources and their properties in a CloudFormation template, you can deploy to CloudFormation to provision your resources. With the AWS Cloud Development Kit (AWS CDK), you can configure resources through constructs. You then deploy your CDK app, which involves synthesizing a AWS CloudFormation template and deploying to AWS CloudFormation to provision your resources.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p><em>Resources</em> are what you configure to use AWS services in your applications. Resources are a feature of AWS CloudFormation. By configuring resources and their properties in a AWS CloudFormation template, you can deploy to AWS CloudFormation to provision your resources. With the AWS Cloud Development Kit (AWS CDK), you can configure resources through constructs. You then deploy your CDK app, which involves synthesizing a AWS CloudFormation template and deploying to AWS CloudFormation to provision your resources.</p> -</div> -<div class="sect3"> -<h4 id="resources-configure">2.14.1. Configuring resources using constructs</h4> -<div class="paragraph"> -<p>As described in <a href="#constructs">AWS CDK Constructs</a>, the AWS CDK provides a rich class library of constructs, called <em>AWS constructs</em>, that represent all AWS resources.</p> -</div> -<div class="paragraph"> -<p>To create an instance of a resource using its corresponding construct, pass in the scope as the first argument, the logical ID of the construct, and a set of configuration properties (props). For example, here’s how to create an Amazon SQS queue with AWS KMS encryption using the <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_sqs.Queue.html">sqs.Queue</a> construct from the AWS Construct Library.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as sqs from '@aws-cdk/aws-sqs'; - -new sqs.Queue(this, 'MyQueue', { - encryption: sqs.QueueEncryption.KMS_MANAGED -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const sqs = require('@aws-cdk/aws-sqs'); - -new sqs.Queue(this, 'MyQueue', { - encryption: sqs.QueueEncryption.KMS_MANAGED -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">import aws_cdk.aws_sqs as sqs - -sqs.Queue(self, "MyQueue", encryption=sqs.QueueEncryption.KMS_MANAGED)</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">import software.amazon.awscdk.services.sqs.*; - -Queue.Builder.create(this, "MyQueue").encryption( - QueueEncryption.KMS_MANAGED).build();</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK.AWS.SQS; - -new Queue(this, "MyQueue", new QueueProps -{ - Encryption = QueueEncryption.KMS_MANAGED -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/jsii-runtime-go" - sqs "github.com/aws/aws-cdk-go/awscdk/v2/awssqs" -) - -sqs.NewQueue(stack, jsii.String("MyQueue"), &sqs.QueueProps{ - Encryption: sqs.QueueEncryption_KMS_MANAGED, -})</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Some configuration props are optional, and in many cases have default values. In some cases, all props are optional, and the last argument can be omitted entirely.</p> -</div> -<div class="sect4"> -<h5 id="resources-attributes">Resource attributes</h5> -<div class="paragraph"> -<p>Most resources in the AWS Construct Library expose attributes, which are resolved at deployment time by AWS CloudFormation. Attributes are exposed in the form of properties on the resource classes with the type name as a prefix. The following example shows how to get the URL of an Amazon SQS queue using the <code>queueUrl</code> (Python: <code>queue_url</code>) property.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as sqs from '@aws-cdk/aws-sqs'; - -const queue = new sqs.Queue(this, 'MyQueue'); -const url = queue.queueUrl; // => A string representing a deploy-time value</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const sqs = require('@aws-cdk/aws-sqs'); - -const queue = new sqs.Queue(this, 'MyQueue'); -const url = queue.queueUrl; // => A string representing a deploy-time value</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">import aws_cdk.aws_sqs as sqs - -queue = sqs.Queue(self, "MyQueue") -url = queue.queue_url # => A string representing a deploy-time value</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">Queue queue = new Queue(this, "MyQueue"); -String url = queue.getQueueUrl(); // => A string representing a deploy-time value</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">var queue = new Queue(this, "MyQueue"); -var url = queue.QueueUrl; // => A string representing a deploy-time value</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/jsii-runtime-go" - sqs "github.com/aws/aws-cdk-go/awscdk/v2/awssqs" -) - -queue := sqs.NewQueue(stack, jsii.String("MyQueue"), &sqs.QueueProps{}) -url := queue.QueueUrl() // => A string representing a deploy-time value</code></pre> -</div> -</div> -<div class="paragraph"> -<p>See <a href="#tokens">Tokens and the AWS CDK</a> for information about how the AWS CDK encodes deploy-time attributes as strings.</p> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="resources-referencing">2.14.2. Referencing resources</h4> -<div class="paragraph"> -<p>When configuring resources, you will often have to reference properties of another resource. The following are examples:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>An Amazon Elastic Container Service (Amazon ECS) resource requires a reference to the cluster on which it runs.</p> -</li> -<li> -<p>An Amazon CloudFront distribution requires a reference to the Amazon Simple Storage Service (Amazon S3) bucket containing the source code.</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>You can reference resources in any of the following ways:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>By passing a resource defined in your CDK app, either in the same stack or in a different one</p> -</li> -<li> -<p>By passing a proxy object referencing a resource defined in your AWS account, created from a unique identifier of the resource (such as an ARN)</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>If the property of a construct represents a construct for another resource, its type is that of the interface type of the construct. For example, the Amazon ECS construct takes a property <code>cluster</code> of type <code>ecs.ICluster</code>. Another example, is the CloudFront distribution construct that takes a property <code>sourceBucket</code> (Python: <code>source_bucket</code>) of type <code>s3.IBucket</code>.</p> -</div> -<div class="paragraph"> -<p>You can directly pass any resource object of the proper type defined in the same AWS CDK app. The following example defines an Amazon ECS cluster and then uses it to define an Amazon ECS service.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const cluster = new ecs.Cluster(this, 'Cluster', { /*...*/ }); - -const service = new ecs.Ec2Service(this, 'Service', { cluster: cluster });</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const cluster = new ecs.Cluster(this, 'Cluster', { /*...*/ }); - -const service = new ecs.Ec2Service(this, 'Service', { cluster: cluster });</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">cluster = ecs.Cluster(self, "Cluster") - -service = ecs.Ec2Service(self, "Service", cluster=cluster)</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">Cluster cluster = new Cluster(this, "Cluster"); -Ec2Service service = new Ec2Service(this, "Service", - new Ec2ServiceProps.Builder().cluster(cluster).build());</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">var cluster = new Cluster(this, "Cluster"); -var service = new Ec2Service(this, "Service", new Ec2ServiceProps { Cluster = cluster });</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/jsii-runtime-go" - ecs "github.com/aws/aws-cdk-go/awscdk/v2/awsecs" -) - -cluster := ecs.NewCluster(stack, jsii.String("MyCluster"), &ecs.ClusterProps{}) -service := ecs.NewEc2Service(stack, jsii.String("MyService"), &ecs.Ec2ServiceProps{ - Cluster: cluster, -})</code></pre> -</div> -</div> -<div class="sect4"> -<h5 id="resource-stack">Referencing resources in a different stack</h5> -<div class="paragraph"> -<p>You can refer to resources in a different stack as long as they are defined in the same app and are in the same AWS environment. The following pattern is generally used:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Store a reference to the construct as an attribute of the stack that produces the resource. (To get a reference to the current construct’s stack, use <code>Stack.of(this)</code>.)</p> -</li> -<li> -<p>Pass this reference to the constructor of the stack that consumes the resource as a parameter or a property. The consuming stack then passes it as a property to any construct that needs it.</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>The following example defines a stack <code>stack1</code>. This stack defines an Amazon S3 bucket and stores a reference to the bucket construct as an attribute of the stack. Then the app defines a second stack, <code>stack2</code>, which accepts a bucket at instantiation. <code>stack2</code> might, for example, define an AWS Glue Table that uses the bucket for data storage.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const prod = { account: '123456789012', region: 'us-east-1' }; - -const stack1 = new StackThatProvidesABucket(app, 'Stack1', { env: prod }); - -// stack2 will take a property { bucket: IBucket } -const stack2 = new StackThatExpectsABucket(app, 'Stack2', { - bucket: stack1.bucket, - env: prod -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const prod = { account: '123456789012', region: 'us-east-1' }; - -const stack1 = new StackThatProvidesABucket(app, 'Stack1', { env: prod }); - -// stack2 will take a property { bucket: IBucket } -const stack2 = new StackThatExpectsABucket(app, 'Stack2', { - bucket: stack1.bucket, - env: prod -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">prod = core.Environment(account="123456789012", region="us-east-1") - -stack1 = StackThatProvidesABucket(app, "Stack1", env=prod) - -# stack2 will take a property "bucket" -stack2 = StackThatExpectsABucket(app, "Stack2", bucket=stack1.bucket, env=prod)</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">// Helper method to build an environment -static Environment makeEnv(String account, String region) { - return Environment.builder().account(account).region(region) - .build(); -} - -App app = new App(); - -Environment prod = makeEnv("123456789012", "us-east-1"); - -StackThatProvidesABucket stack1 = new StackThatProvidesABucket(app, "Stack1", - StackProps.builder().env(prod).build()); - -// stack2 will take an argument "bucket" -StackThatExpectsABucket stack2 = new StackThatExpectsABucket(app, "Stack,", - StackProps.builder().env(prod).build(), stack1.bucket);</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">Amazon.CDK.Environment makeEnv(string account, string region) -{ - return new Amazon.CDK.Environment { Account = account, Region = region }; -} - -var prod = makeEnv(account: "123456789012", region: "us-east-1"); - -var stack1 = new StackThatProvidesABucket(app, "Stack1", new StackProps { Env = prod }); - -// stack2 will take a property "bucket" -var stack2 = new StackThatExpectsABucket(app, "Stack2", new StackProps { Env = prod, - bucket = stack1.Bucket});</code></pre> -</div> -</div> -<div class="paragraph"> -<p>If the AWS CDK determines that the resource is in the same environment, but in a different stack, it automatically synthesizes AWS CloudFormation <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-stack-exports.html">exports</a> in the producing stack and an <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-importvalue.html">Fn::ImportValue</a> in the consuming stack to transfer that information from one stack to the other.</p> -</div> -<div class="sect5"> -<h6 id="resources-deadlock">Resolving dependency deadlocks</h6> -<div class="paragraph"> -<p>Referencing a resource from one stack in a different stack creates a dependency between the two stacks. This makes sure that they’re deployed in the right order. After the stacks are deployed, this dependency is concrete. After that, removing the use of the shared resource from the consuming stack can cause an unexpected deployment failure. This happens if there is another dependency between the two stacks that force them to be deployed in the same order. It can also happen without a dependency if the producing stack is simply chosen by the CDK Toolkit to be deployed first. The AWS CloudFormation export is removed from the producing stack because it’s no longer needed, but the exported resource is still being used in the consuming stack because its update is not yet deployed. Therefore, deploying the producer stack fails.</p> -</div> -<div class="paragraph"> -<p>To break this deadlock, remove the use of the shared resource from the consuming stack. (This removes the automatic export from the producing stack.) Next, manually add the same export to the producing stack using exactly the same logical ID as the automatically generated export. Remove the use of the shared resource in the consuming stack and deploy both stacks. Then, remove the manual export (and the shared resource if it’s no longer needed) and deploy both stacks again. The stack’s <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html#exportwbrvalueexportedvalue-options">exportValue()</a></code> method is a convenient way to create the manual export for this purpose. (See the example in the linked method reference.)</p> -</div> -</div> -</div> -<div class="sect4"> -<h5 id="resources-external">Referencing resources in your AWS account</h5> -<div class="paragraph"> -<p>Suppose you want to use a resource already available in your AWS account in your AWS CDK app. This might be a resource that was defined through the console, an AWS SDK, directly with AWS CloudFormation, or in a different AWS CDK application. You can turn the resource’s ARN (or another identifying attribute, or group of attributes) into a proxy object. The proxy object serves as a reference to the resource by calling a static factory method on the resource’s class.</p> -</div> -<div class="paragraph"> -<p>When you create such a proxy, the external resource <strong>does not</strong> become a part of your AWS CDK app. Therefore, changes you make to the proxy in your AWS CDK app do not affect the deployed resource. The proxy can, however, be passed to any AWS CDK method that requires a resource of that type.</p> -</div> -<div class="paragraph"> -<p>The following example shows how to reference a bucket based on an existing bucket with the ARN <strong>arn:aws:s3:::amzn-s3-demo-bucket1</strong>, and an Amazon Virtual Private Cloud based on an existing VPC having a specific ID.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">// Construct a proxy for a bucket by its name (must be same account) -s3.Bucket.fromBucketName(this, 'MyBucket', 'amzn-s3-demo-bucket1'); - -// Construct a proxy for a bucket by its full ARN (can be another account) -s3.Bucket.fromBucketArn(this, 'MyBucket', 'arn:aws:s3:::amzn-s3-demo-bucket1'); - -// Construct a proxy for an existing VPC from its attribute(s) -ec2.Vpc.fromVpcAttributes(this, 'MyVpc', { - vpcId: 'vpc-1234567890abcde', -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">// Construct a proxy for a bucket by its name (must be same account) -s3.Bucket.fromBucketName(this, 'MyBucket', 'amzn-s3-demo-bucket1'); - -// Construct a proxy for a bucket by its full ARN (can be another account) -s3.Bucket.fromBucketArn(this, 'MyBucket', 'arn:aws:s3:::amzn-s3-demo-bucket1'); - -// Construct a proxy for an existing VPC from its attribute(s) -ec2.Vpc.fromVpcAttributes(this, 'MyVpc', { - vpcId: 'vpc-1234567890abcde' -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python"># Construct a proxy for a bucket by its name (must be same account) -s3.Bucket.from_bucket_name(self, "MyBucket", "amzn-s3-demo-bucket1") - -# Construct a proxy for a bucket by its full ARN (can be another account) -s3.Bucket.from_bucket_arn(self, "MyBucket", "arn:aws:s3:::amzn-s3-demo-bucket1") - -# Construct a proxy for an existing VPC from its attribute(s) -ec2.Vpc.from_vpc_attributes(self, "MyVpc", vpc_id="vpc-1234567890abcdef")</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">// Construct a proxy for a bucket by its name (must be same account) -Bucket.fromBucketName(this, "MyBucket", "amzn-s3-demo-bucket1"); - -// Construct a proxy for a bucket by its full ARN (can be another account) -Bucket.fromBucketArn(this, "MyBucket", - "arn:aws:s3:::amzn-s3-demo-bucket1"); - -// Construct a proxy for an existing VPC from its attribute(s) -Vpc.fromVpcAttributes(this, "MyVpc", VpcAttributes.builder() - .vpcId("vpc-1234567890abcdef").build());</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">// Construct a proxy for a bucket by its name (must be same account) -Bucket.FromBucketName(this, "MyBucket", "amzn-s3-demo-bucket1"); - -// Construct a proxy for a bucket by its full ARN (can be another account) -Bucket.FromBucketArn(this, "MyBucket", "arn:aws:s3:::amzn-s3-demo-bucket1"); - -// Construct a proxy for an existing VPC from its attribute(s) -Vpc.FromVpcAttributes(this, "MyVpc", new VpcAttributes -{ - VpcId = "vpc-1234567890abcdef" -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">// Define a proxy for a bucket by its name (must be same account) -s3.Bucket_FromBucketName(stack, jsii.String("MyBucket"), jsii.String("amzn-s3-demo-bucket1")) - -// Define a proxy for a bucket by its full ARN (can be another account) -s3.Bucket_FromBucketArn(stack, jsii.String("MyBucket"), jsii.String("arn:aws:s3:::amzn-s3-demo-bucket1")) - -// Define a proxy for an existing VPC from its attributes -ec2.Vpc_FromVpcAttributes(stack, jsii.String("MyVpc"), &ec2.VpcAttributes{ - VpcId: jsii.String("vpc-1234567890abcde"), -})</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Let’s take a closer look at the <a href="https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-ec2.Vpc.html#static-fromwbrlookupscope-id-options">Vpc.fromLookup()</a> method. Because the <code>ec2.Vpc</code> construct is complex, there are many ways you might want to select the VPC to be used with your CDK app. To address this, the VPC construct has a <code>fromLookup</code> static method (Python: <code>from_lookup</code>) that lets you look up the desired Amazon VPC by querying your AWS account at synthesis time.</p> -</div> -<div class="paragraph"> -<p>To use <code>Vpc.fromLookup()</code>, the system that synthesizes the stack must have access to the account that owns the Amazon VPC. This is because the CDK Toolkit queries the account to find the right Amazon VPC at synthesis time.</p> -</div> -<div class="paragraph"> -<p>Furthermore, <code>Vpc.fromLookup()</code> works only in stacks that are defined with an explicit <strong>account</strong> and <strong>region</strong> (see <a href="#environments">Environments for the AWS CDK</a>). If the AWS CDK tries to look up an Amazon VPC from an <a href="#stack-api">environment-agnostic stack</a>, the CDK Toolkit doesn’t know which environment to query to find the VPC.</p> -</div> -<div class="paragraph"> -<p>You must provide <code>Vpc.fromLookup()</code> attributes sufficient to uniquely identify a VPC in your AWS account. For example, there can only ever be one default VPC, so it’s sufficient to specify the VPC as the default.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">ec2.Vpc.fromLookup(this, 'DefaultVpc', { - isDefault: true -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">ec2.Vpc.fromLookup(this, 'DefaultVpc', { - isDefault: true -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">ec2.Vpc.from_lookup(self, "DefaultVpc", is_default=True)</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">Vpc.fromLookup(this, "DefaultVpc", VpcLookupOptions.builder() - .isDefault(true).build());</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">Vpc.FromLookup(this, id = "DefaultVpc", new VpcLookupOptions { IsDefault = true });</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">ec2.Vpc_FromLookup(this, jsii.String("DefaultVpc"), &ec2.VpcLookupOptions{ - IsDefault: jsii.Bool(true), -})</code></pre> -</div> -</div> -<div class="paragraph"> -<p>You can also use the <code>tags</code> property to query for VPCs by tag. You can add tags to the Amazon VPC at the time of its creation by using AWS CloudFormation or the AWS CDK. You can edit tags at any time after creation by using the AWS Management Console, the AWS CLI, or an AWS SDK. In addition to any tags you add yourself, the AWS CDK automatically adds the following tags to all VPCs it creates.</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><em>Name</em> – The name of the VPC.</p> -</li> -<li> -<p><em>aws-cdk:subnet-name</em> – The name of the subnet.</p> -</li> -<li> -<p><em>aws-cdk:subnet-type</em> – The type of the subnet: Public, Private, or Isolated.</p> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -</li> -</ul> -</div> -<div class="listingblock"> -<div class="content"> -<pre>ec2.Vpc.fromLookup(this, 'PublicVpc', - {tags: {'aws-cdk:subnet-type': "Public"}});</pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">ec2.Vpc.fromLookup(this, 'PublicVpc', - {tags: {'aws-cdk:subnet-type': "Public"}});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">ec2.Vpc.from_lookup(self, "PublicVpc", - tags={"aws-cdk:subnet-type": "Public"})</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">Vpc.fromLookup(this, "PublicVpc", VpcLookupOptions.builder() - .tags(java.util.Map.of("aws-cdk:subnet-type", "Public")) // Java 9 or later - .build());</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">Vpc.FromLookup(this, id = "PublicVpc", new VpcLookupOptions - { Tags = new Dictionary<string, string> { ["aws-cdk:subnet-type"] = "Public" });</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">ec2.Vpc_FromLookup(this, jsii.String("DefaultVpc"), &ec2.VpcLookupOptions{ - Tags: &map[string]*string{"aws-cdk:subnet-type": jsii.String("Public")}, -})</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Results of <code>Vpc.fromLookup()</code> are cached in the project’s <code class="path">cdk.context.json</code> file. (See <a href="#context">Context values and the AWS CDK</a>.) Commit this file to version control so that your app will continue to refer to the same Amazon VPC. This works even if you later change the attributes of your VPCs in a way that would result in a different VPC being selected. This is particularly important if you’re deploying the stack in an environment that doesn’t have access to the AWS account that defines the VPC, such as <a href="#cdk-pipeline">CDK Pipelines</a>.</p> -</div> -<div class="paragraph"> -<p>Although you can use an external resource anywhere you’d use a similar resource defined in your AWS CDK app, you cannot modify it. For example, calling <code>addToResourcePolicy</code> (Python: <code>add_to_resource_policy</code>) on an external <code>s3.Bucket</code> does nothing.</p> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="resources-physical-names">2.14.3. Resource physical names</h4> -<div class="paragraph"> -<p>The logical names of resources in AWS CloudFormation are different from the names of resources that are shown in the AWS Management Console after they’re deployed by AWS CloudFormation. The AWS CDK calls these final names <em>physical names</em>.</p> -</div> -<div class="paragraph"> -<p>For example, AWS CloudFormation might create the Amazon S3 bucket with the logical ID <code>Stack2MyBucket4DD88B4F</code> and the physical name <code>stack2MyBucket4dd88b4f-iuv1rbv9z3to</code>.</p> -</div> -<div class="paragraph"> -<p>You can specify a physical name when creating constructs that represent resources by using the property <code class="replaceable"><resourceType></code>Name. The following example creates an Amazon S3 bucket with the physical name <code>amzn-s3-demo-bucket</code>.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const bucket = new s3.Bucket(this, 'MyBucket', { - bucketName: 'amzn-s3-demo-bucket', -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const bucket = new s3.Bucket(this, 'MyBucket', { - bucketName: 'amzn-s3-demo-bucket' -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">bucket = s3.Bucket(self, "MyBucket", bucket_name="amzn-s3-demo-bucket")</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">Bucket bucket = Bucket.Builder.create(this, "MyBucket") - .bucketName("amzn-s3-demo-bucket").build();</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">var bucket = new Bucket(this, "MyBucket", new BucketProps { BucketName = "amzn-s3-demo-bucket" });</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">bucket := s3.NewBucket(this, jsii.String("MyBucket"), &s3.BucketProps{ - BucketName: jsii.String("amzn-s3-demo-bucket"), -})</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Assigning physical names to resources has some disadvantages in AWS CloudFormation. Most importantly, any changes to deployed resources that require a resource replacement, such as changes to a resource’s properties that are immutable after creation, will fail if a resource has a physical name assigned. If you end up in that state, the only solution is to delete the AWS CloudFormation stack, then deploy the AWS CDK app again. See the <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-name.html">AWS CloudFormation documentation</a> for details.</p> -</div> -<div class="paragraph"> -<p>In some cases, such as when creating an AWS CDK app with cross-environment references, physical names are required for the AWS CDK to function correctly. In those cases, if you don’t want to bother with coming up with a physical name yourself, you can let the AWS CDK name it for you. To do so, use the special value <code>PhysicalName.GENERATE_IF_NEEDED</code>, as follows.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const bucket = new s3.Bucket(this, 'MyBucket', { - bucketName: core.PhysicalName.GENERATE_IF_NEEDED, -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const bucket = new s3.Bucket(this, 'MyBucket', { - bucketName: core.PhysicalName.GENERATE_IF_NEEDED -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">bucket = s3.Bucket(self, "MyBucket", - bucket_name=core.PhysicalName.GENERATE_IF_NEEDED)</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">Bucket bucket = Bucket.Builder.create(this, "MyBucket") - .bucketName(PhysicalName.GENERATE_IF_NEEDED).build();</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">var bucket = new Bucket(this, "MyBucket", new BucketProps - { BucketName = PhysicalName.GENERATE_IF_NEEDED });</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">bucket := s3.NewBucket(this, jsii.String("MyBucket"), &s3.BucketProps{ - BucketName: awscdk.PhysicalName_GENERATE_IF_NEEDED(), -})</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="resources-identifiers">2.14.4. Passing unique resource identifiers</h4> -<div class="paragraph"> -<p>Whenever possible, you should pass resources by reference, as described in the previous section. However, there are cases where you have no other choice but to refer to a resource by one of its attributes. Example use cases include the following:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>When you are using low-level AWS CloudFormation resources.</p> -</li> -<li> -<p>When you need to expose resources to the runtime components of an AWS CDK application, such as when referring to Lambda functions through environment variables.</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>These identifiers are available as attributes on the resources, such as the following.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">bucket.bucketName -lambdaFunc.functionArn -securityGroup.groupArn</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">bucket.bucketName -lambdaFunc.functionArn -securityGroup.groupArn</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">bucket.bucket_name -lambda_func.function_arn -security_group_arn</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The Java AWS CDK binding uses getter methods for attributes.</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">bucket.getBucketName() -lambdaFunc.getFunctionArn() -securityGroup.getGroupArn()</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">bucket.BucketName -lambdaFunc.FunctionArn -securityGroup.GroupArn</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">bucket.BucketName() -fn.FunctionArn()</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The following example shows how to pass a generated bucket name to an AWS Lambda function.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const bucket = new s3.Bucket(this, 'Bucket'); - -new lambda.Function(this, 'MyLambda', { - // ... - environment: { - BUCKET_NAME: bucket.bucketName, - }, -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const bucket = new s3.Bucket(this, 'Bucket'); - -new lambda.Function(this, 'MyLambda', { - // ... - environment: { - BUCKET_NAME: bucket.bucketName - } -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">bucket = s3.Bucket(self, "Bucket") - -lambda.Function(self, "MyLambda", environment=dict(BUCKET_NAME=bucket.bucket_name))</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">final Bucket bucket = new Bucket(this, "Bucket"); - -Function.Builder.create(this, "MyLambda") - .environment(java.util.Map.of( // Java 9 or later - "BUCKET_NAME", bucket.getBucketName())) - .build();</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">var bucket = new Bucket(this, "Bucket"); - -new Function(this, "MyLambda", new FunctionProps -{ - Environment = new Dictionary<string, string> - { - ["BUCKET_NAME"] = bucket.BucketName - } -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">bucket := s3.NewBucket(this, jsii.String("Bucket"), &s3.BucketProps{}) -lambda.NewFunction(this, jsii.String("MyLambda"), &lambda.FunctionProps{ - Environment: &map[string]*string{"BUCKET_NAME": bucket.BucketName()}, -})</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="resources-grants">2.14.5. Granting permissions between resources</h4> -<div class="paragraph"> -<p>Higher-level constructs make least-privilege permissions achievable by offering simple, intent-based APIs to express permission requirements. For example, many L2 constructs offer grant methods that you can use to grant an entity (such as an IAM role or user) permission to work with the resource, without having to manually create IAM permission statements.</p> -</div> -<div class="paragraph"> -<p>The following example creates the permissions to allow a Lambda function’s execution role to read and write objects to a particular Amazon S3 bucket. If the Amazon S3 bucket is encrypted with an AWS KMS key, this method also grants permissions to the Lambda function’s execution role to decrypt with the key.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">if (bucket.grantReadWrite(func).success) { - // ... -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">if ( bucket.grantReadWrite(func).success) { - // ... -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">if bucket.grant_read_write(func).success: - # ...</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">if (bucket.grantReadWrite(func).getSuccess()) { - // ... -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">if (bucket.GrantReadWrite(func).Success) -{ - // ... -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">if *bucket.GrantReadWrite(function, nil).Success() { - // ... -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The grant methods return an <code>iam.Grant</code> object. Use the <code>success</code> attribute of the <code>Grant</code> object to determine whether the grant was effectively applied (for example, it may not have been applied on <a href="#resources-referencing">external resources</a>). You can also use the <code>assertSuccess</code> (Python: <code>assert_success</code>) method of the <code>Grant</code> object to enforce that the grant was successfully applied.</p> -</div> -<div class="paragraph"> -<p>If a specific grant method isn’t available for the particular use case, you can use a generic grant method to define a new grant with a specified list of actions.</p> -</div> -<div class="paragraph"> -<p>The following example shows how to grant a Lambda function access to the Amazon DynamoDB <code>CreateBackup</code> action.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">table.grant(func, 'dynamodb:CreateBackup');</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">table.grant(func, 'dynamodb:CreateBackup');</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">table.grant(func, "dynamodb:CreateBackup")</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">table.grant(func, "dynamodb:CreateBackup");</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">table.Grant(func, "dynamodb:CreateBackup");</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">table := dynamodb.NewTable(this, jsii.String("MyTable"), &dynamodb.TableProps{}) -table.Grant(function, jsii.String("dynamodb:CreateBackup"))</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Many resources, such as Lambda functions, require a role to be assumed when executing code. A configuration property enables you to specify an <code>iam.IRole</code>. If no role is specified, the function automatically creates a role specifically for this use. You can then use grant methods on the resources to add statements to the role.</p> -</div> -<div class="paragraph"> -<p>The grant methods are built using lower-level APIs for handling with IAM policies. Policies are modeled as <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.PolicyDocument.html">PolicyDocument</a> objects. Add statements directly to roles (or a construct’s attached role) using the <code>addToRolePolicy</code> method (Python: <code>add_to_role_policy</code>), or to a resource’s policy (such as a <code>Bucket</code> policy) using the <code>addToResourcePolicy</code> (Python: <code>add_to_resource_policy</code>) method.</p> -</div> -</div> -<div class="sect3"> -<h4 id="resources-metrics">2.14.6. Resource metrics and alarms</h4> -<div class="paragraph"> -<p>Many resources emit CloudWatch metrics that can be used to set up monitoring dashboards and alarms. Higher-level constructs have metric methods that let you access the metrics without looking up the correct name to use.</p> -</div> -<div class="paragraph"> -<p>The following example shows how to define an alarm when the <code>ApproximateNumberOfMessagesNotVisible</code> of an Amazon SQS queue exceeds 100.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as cw from '@aws-cdk/aws-cloudwatch'; -import * as sqs from '@aws-cdk/aws-sqs'; -import { Duration } from '@aws-cdk/core'; - -const queue = new sqs.Queue(this, 'MyQueue'); - -const metric = queue.metricApproximateNumberOfMessagesNotVisible({ - label: 'Messages Visible (Approx)', - period: Duration.minutes(5), - // ... -}); -metric.createAlarm(this, 'TooManyMessagesAlarm', { - comparisonOperator: cw.ComparisonOperator.GREATER_THAN_THRESHOLD, - threshold: 100, - // ... -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const cw = require('@aws-cdk/aws-cloudwatch'); -const sqs = require('@aws-cdk/aws-sqs'); -const { Duration } = require('@aws-cdk/core'); - -const queue = new sqs.Queue(this, 'MyQueue'); - -const metric = queue.metricApproximateNumberOfMessagesNotVisible({ - label: 'Messages Visible (Approx)', - period: Duration.minutes(5) - // ... -}); -metric.createAlarm(this, 'TooManyMessagesAlarm', { - comparisonOperator: cw.ComparisonOperator.GREATER_THAN_THRESHOLD, - threshold: 100 - // ... -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">import aws_cdk.aws_cloudwatch as cw -import aws_cdk.aws_sqs as sqs -from aws_cdk.core import Duration - -queue = sqs.Queue(self, "MyQueue") -metric = queue.metric_approximate_number_of_messages_not_visible( - label="Messages Visible (Approx)", - period=Duration.minutes(5), - # ... -) -metric.create_alarm(self, "TooManyMessagesAlarm", - comparison_operator=cw.ComparisonOperator.GREATER_THAN_THRESHOLD, - threshold=100, - # ... -)</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">import software.amazon.awscdk.core.Duration; -import software.amazon.awscdk.services.sqs.Queue; -import software.amazon.awscdk.services.cloudwatch.Metric; -import software.amazon.awscdk.services.cloudwatch.MetricOptions; -import software.amazon.awscdk.services.cloudwatch.CreateAlarmOptions; -import software.amazon.awscdk.services.cloudwatch.ComparisonOperator; - -Queue queue = new Queue(this, "MyQueue"); - -Metric metric = queue - .metricApproximateNumberOfMessagesNotVisible(MetricOptions.builder() - .label("Messages Visible (Approx)") - .period(Duration.minutes(5)).build()); - -metric.createAlarm(this, "TooManyMessagesAlarm", CreateAlarmOptions.builder() - .comparisonOperator(ComparisonOperator.GREATER_THAN_THRESHOLD) - .threshold(100) - // ... - .build());</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using cdk = Amazon.CDK; -using cw = Amazon.CDK.AWS.CloudWatch; -using sqs = Amazon.CDK.AWS.SQS; - -var queue = new sqs.Queue(this, "MyQueue"); -var metric = queue.MetricApproximateNumberOfMessagesNotVisible(new cw.MetricOptions -{ - Label = "Messages Visible (Approx)", - Period = cdk.Duration.Minutes(5), - // ... -}); -metric.CreateAlarm(this, "TooManyMessagesAlarm", new cw.CreateAlarmOptions -{ - ComparisonOperator = cw.ComparisonOperator.GREATER_THAN_THRESHOLD, - Threshold = 100, - // .. -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/jsii-runtime-go" - cw "github.com/aws/aws-cdk-go/awscdk/v2/awscloudwatch" - sqs "github.com/aws/aws-cdk-go/awscdk/v2/awssqs" -) - -queue := sqs.NewQueue(this, jsii.String("MyQueue"), &sqs.QueueProps{}) -metric := queue.MetricApproximateNumberOfMessagesNotVisible(&cw.MetricOptions{ - Label: jsii.String("Messages Visible (Approx)"), - Period: awscdk.Duration_Minutes(jsii.Number(5)), -}) - -metric.CreateAlarm(this, jsii.String("TooManyMessagesAlarm"), &cw.CreateAlarmOptions{ - ComparisonOperator: cw.ComparisonOperator_GREATER_THAN_THRESHOLD, - Threshold: jsii.Number(100), -})</code></pre> -</div> -</div> -<div class="paragraph"> -<p>If there is no method for a particular metric, you can use the general metric method to specify the metric name manually.</p> -</div> -<div class="paragraph"> -<p>Metrics can also be added to CloudWatch dashboards. See <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_cloudwatch-readme.html">CloudWatch</a>.</p> -</div> -</div> -<div class="sect3"> -<h4 id="resources-traffic">2.14.7. Network traffic</h4> -<div class="paragraph"> -<p>In many cases, you must enable permissions on a network for an application to work, such as when the compute infrastructure needs to access the persistence layer. Resources that establish or listen for connections expose methods that enable traffic flows, including setting security group rules or network ACLs.</p> -</div> -<div class="paragraph"> -<p><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.IConnectable.html">IConnectable</a> resources have a <code>connections</code> property that is the gateway to network traffic rules configuration.</p> -</div> -<div class="paragraph"> -<p>You enable data to flow on a given network path by using <code>allow</code> methods. The following example enables HTTPS connections to the web and incoming connections from the Amazon EC2 Auto Scaling group <code>fleet2</code>.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as asg from '@aws-cdk/aws-autoscaling'; -import * as ec2 from '@aws-cdk/aws-ec2'; - -const fleet1: asg.AutoScalingGroup = asg.AutoScalingGroup(/*...*/); - -// Allow surfing the (secure) web -fleet1.connections.allowTo(new ec2.Peer.anyIpv4(), new ec2.Port({ fromPort: 443, toPort: 443 })); - -const fleet2: asg.AutoScalingGroup = asg.AutoScalingGroup(/*...*/); -fleet1.connections.allowFrom(fleet2, ec2.Port.AllTraffic());</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const asg = require('@aws-cdk/aws-autoscaling'); -const ec2 = require('@aws-cdk/aws-ec2'); - -const fleet1 = asg.AutoScalingGroup(); - -// Allow surfing the (secure) web -fleet1.connections.allowTo(new ec2.Peer.anyIpv4(), new ec2.Port({ fromPort: 443, toPort: 443 })); - -const fleet2 = asg.AutoScalingGroup(); -fleet1.connections.allowFrom(fleet2, ec2.Port.AllTraffic());</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">import aws_cdk.aws_autoscaling as asg -import aws_cdk.aws_ec2 as ec2 - -fleet1 = asg.AutoScalingGroup( ... ) - -# Allow surfing the (secure) web -fleet1.connections.allow_to(ec2.Peer.any_ipv4(), - ec2.Port(PortProps(from_port=443, to_port=443))) - -fleet2 = asg.AutoScalingGroup( ... ) -fleet1.connections.allow_from(fleet2, ec2.Port.all_traffic())</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">import software.amazon.awscdk.services.autoscaling.AutoScalingGroup; -import software.amazon.awscdk.services.ec2.Peer; -import software.amazon.awscdk.services.ec2.Port; - -AutoScalingGroup fleet1 = AutoScalingGroup.Builder.create(this, "MyFleet") - /* ... */.build(); - -// Allow surfing the (secure) Web -fleet1.getConnections().allowTo(Peer.anyIpv4(), - Port.Builder.create().fromPort(443).toPort(443).build()); - -AutoScalingGroup fleet2 = AutoScalingGroup.Builder.create(this, "MyFleet2") - /* ... */.build(); -fleet1.getConnections().allowFrom(fleet2, Port.allTraffic());</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using cdk = Amazon.CDK; -using asg = Amazon.CDK.AWS.AutoScaling; -using ec2 = Amazon.CDK.AWS.EC2; - -// Allow surfing the (secure) Web -var fleet1 = new asg.AutoScalingGroup(this, "MyFleet", new asg.AutoScalingGroupProps { /* ... */ }); -fleet1.Connections.AllowTo(ec2.Peer.AnyIpv4(), new ec2.Port(new ec2.PortProps - { FromPort = 443, ToPort = 443 }); - -var fleet2 = new asg.AutoScalingGroup(this, "MyFleet2", new asg.AutoScalingGroupProps { /* ... */ }); -fleet1.Connections.AllowFrom(fleet2, ec2.Port.AllTraffic());</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/jsii-runtime-go" - autoscaling "github.com/aws/aws-cdk-go/awscdk/v2/awsautoscaling" - ec2 "github.com/aws/aws-cdk-go/awscdk/v2/awsec2" -) - -fleet1 := autoscaling.NewAutoScalingGroup(this, jsii.String("MyFleet1"), &autoscaling.AutoScalingGroupProps{}) -fleet1.Connections().AllowTo(ec2.Peer_AnyIpv4(),ec2.NewPort(&ec2.PortProps{ FromPort: jsii.Number(443), ToPort: jsii.Number(443) }),jsii.String("secure web")) - -fleet2 := autoscaling.NewAutoScalingGroup(this, jsii.String("MyFleet2"), &autoscaling.AutoScalingGroupProps{}) -fleet1.Connections().AllowFrom(fleet2, ec2.Port_AllTraffic(),jsii.String("all traffic"))</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Certain resources have default ports associated with them. Examples include the listener of a load balancer on the public port, and the ports on which the database engine accepts connections for instances of an Amazon RDS database. In such cases, you can enforce tight network control without having to manually specify the port. To do so, use the <code>allowDefaultPortFrom</code> and <code>allowToDefaultPort</code> methods (Python: <code>allow_default_port_from</code>, <code>allow_to_default_port</code>).</p> -</div> -<div class="paragraph"> -<p>The following example shows how to enable connections from any IPV4 address, and a connection from an Auto Scaling group to access a database.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">listener.connections.allowDefaultPortFromAnyIpv4('Allow public access'); - -fleet.connections.allowToDefaultPort(rdsDatabase, 'Fleet can access database');</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">listener.connections.allowDefaultPortFromAnyIpv4('Allow public access'); - -fleet.connections.allowToDefaultPort(rdsDatabase, 'Fleet can access database');</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">listener.connections.allow_default_port_from_any_ipv4("Allow public access") - -fleet.connections.allow_to_default_port(rds_database, "Fleet can access database")</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">listener.getConnections().allowDefaultPortFromAnyIpv4("Allow public access"); - -fleet.getConnections().AllowToDefaultPort(rdsDatabase, "Fleet can access database");</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">listener.Connections.AllowDefaultPortFromAnyIpv4("Allow public access"); - -fleet.Connections.AllowToDefaultPort(rdsDatabase, "Fleet can access database");</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">listener.Connections().AllowDefaultPortFromAnyIpv4(jsii.String("Allow public Access")) -fleet.Connections().AllowToDefaultPort(rdsDatabase, jsii.String("Fleet can access database"))</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="resources-events">2.14.8. Event handling</h4> -<div class="paragraph"> -<p>Some resources can act as event sources. Use the <code>addEventNotification</code> method (Python: <code>add_event_notification</code>) to register an event target to a particular event type emitted by the resource. In addition to this, <code>addXxxNotification</code> methods offer a simple way to register a handler for common event types.</p> -</div> -<div class="paragraph"> -<p>The following example shows how to trigger a Lambda function when an object is added to an Amazon S3 bucket.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as s3nots from '@aws-cdk/aws-s3-notifications'; - -const handler = new lambda.Function(this, 'Handler', { /*…*/ }); -const bucket = new s3.Bucket(this, 'Bucket'); -bucket.addObjectCreatedNotification(new s3nots.LambdaDestination(handler));</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const s3nots = require('@aws-cdk/aws-s3-notifications'); - -const handler = new lambda.Function(this, 'Handler', { /*…*/ }); -const bucket = new s3.Bucket(this, 'Bucket'); -bucket.addObjectCreatedNotification(new s3nots.LambdaDestination(handler));</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">import aws_cdk.aws_s3_notifications as s3_nots - -handler = lambda_.Function(self, "Handler", ...) -bucket = s3.Bucket(self, "Bucket") -bucket.add_object_created_notification(s3_nots.LambdaDestination(handler))</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">import software.amazon.awscdk.services.s3.Bucket; -import software.amazon.awscdk.services.lambda.Function; -import software.amazon.awscdk.services.s3.notifications.LambdaDestination; - -Function handler = Function.Builder.create(this, "Handler")/* ... */.build(); -Bucket bucket = new Bucket(this, "Bucket"); -bucket.addObjectCreatedNotification(new LambdaDestination(handler));</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using lambda = Amazon.CDK.AWS.Lambda; -using s3 = Amazon.CDK.AWS.S3; -using s3Nots = Amazon.CDK.AWS.S3.Notifications; - -var handler = new lambda.Function(this, "Handler", new lambda.FunctionProps { .. }); -var bucket = new s3.Bucket(this, "Bucket"); -bucket.AddObjectCreatedNotification(new s3Nots.LambdaDestination(handler));</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/jsii-runtime-go" - s3 "github.com/aws/aws-cdk-go/awscdk/v2/awss3" - s3nots "github.com/aws/aws-cdk-go/awscdk/v2/awss3notifications" -) - -handler := lambda.NewFunction(this, jsii.String("MyFunction"), &lambda.FunctionProps{}) -bucket := s3.NewBucket(this, jsii.String("Bucket"), &s3.BucketProps{}) -bucket.AddObjectCreatedNotification(s3nots.NewLambdaDestination(handler), nil)</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="resources-removal">2.14.9. Removal policies</h4> -<div class="paragraph"> -<p>Resources that maintain persistent data, such as databases, Amazon S3 buckets, and Amazon ECR registries, have a <em>removal policy</em>. The removal policy indicates whether to delete persistent objects when the AWS CDK stack that contains them is destroyed. The values specifying the removal policy are available through the <code>RemovalPolicy</code> enumeration in the AWS CDK <code>core</code> module.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>Resources besides those that store data persistently might also have a <code>removalPolicy</code> that is used for a different purpose. For example, a Lambda function version uses a <code>removalPolicy</code> attribute to determine whether a given version is retained when a new version is deployed. These have different meanings and defaults compared to the removal policy on an Amazon S3 bucket or DynamoDB table.</p> -</div> -</td> -</tr> -</table> -</div> -<table class="tableblock frame-all grid-all stretch"> -<colgroup> -<col style="width: 50%;"> -<col style="width: 50%;"> -</colgroup> -<thead> -<tr> -<th class="tableblock halign-left valign-top">Value</th> -<th class="tableblock halign-left valign-top">Meaning</th> -</tr> -</thead> -<tbody> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>RemovalPolicy.RETAIN</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Keep the contents of the resource when destroying the stack (default). The resource is orphaned from the stack and must be deleted manually. If you attempt to re-deploy the stack while the resource still exists, you will receive an error message due to a name conflict.</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>RemovalPolicy.DESTROY</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">The resource will be destroyed along with the stack.</p></td> -</tr> -</tbody> -</table> -<div class="paragraph"> -<p>AWS CloudFormation does not remove Amazon S3 buckets that contain files even if their removal policy is set to <code>DESTROY</code>. Attempting to do so is an AWS CloudFormation error. To have the AWS CDK delete all files from the bucket before destroying it, set the bucket’s <code>autoDeleteObjects</code> property to <code>true</code>.</p> -</div> -<div class="paragraph"> -<p>Following is an example of creating an Amazon S3 bucket with <code>RemovalPolicy</code> of <code>DESTROY</code> and <code>autoDeleteOjbects</code> set to <code>true</code>.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as cdk from '@aws-cdk/core'; -import * as s3 from '@aws-cdk/aws-s3'; - -export class CdkTestStack extends cdk.Stack { - constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - const bucket = new s3.Bucket(this, 'Bucket', { - removalPolicy: cdk.RemovalPolicy.DESTROY, - autoDeleteObjects: true - }); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const cdk = require('@aws-cdk/core'); -const s3 = require('@aws-cdk/aws-s3'); - -class CdkTestStack extends cdk.Stack { - constructor(scope, id, props) { - super(scope, id, props); - - const bucket = new s3.Bucket(this, 'Bucket', { - removalPolicy: cdk.RemovalPolicy.DESTROY, - autoDeleteObjects: true - }); - } -} - -module.exports = { CdkTestStack }</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">import aws_cdk.core as cdk -import aws_cdk.aws_s3 as s3 - -class CdkTestStack(cdk.stack): - def __init__(self, scope: cdk.Construct, id: str, **kwargs): - super().__init__(scope, id, **kwargs) - - bucket = s3.Bucket(self, "Bucket", - removal_policy=cdk.RemovalPolicy.DESTROY, - auto_delete_objects=True)</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">software.amazon.awscdk.core.*; -import software.amazon.awscdk.services.s3.*; - -public class CdkTestStack extends Stack { - public CdkTestStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public CdkTestStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - Bucket.Builder.create(this, "Bucket") - .removalPolicy(RemovalPolicy.DESTROY) - .autoDeleteObjects(true).build(); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; -using Amazon.CDK.AWS.S3; - -public CdkTestStack(Construct scope, string id, IStackProps props) : base(scope, id, props) -{ - new Bucket(this, "Bucket", new BucketProps { - RemovalPolicy = RemovalPolicy.DESTROY, - AutoDeleteObjects = true - }); -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/jsii-runtime-go" - s3 "github.com/aws/aws-cdk-go/awscdk/v2/awss3" -) - -s3.NewBucket(this, jsii.String("Bucket"), &s3.BucketProps{ - RemovalPolicy: awscdk.RemovalPolicy_DESTROY, - AutoDeleteObjects: jsii.Bool(true), -})</code></pre> -</div> -</div> -<div class="paragraph"> -<p>You can also apply a removal policy directly to the underlying AWS CloudFormation resource via the <code>applyRemovalPolicy()</code> method. This method is available on some stateful resources that do not have a <code>removalPolicy</code> property in their L2 resource’s props. Examples include the following:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>AWS CloudFormation stacks</p> -</li> -<li> -<p>Amazon Cognito user pools</p> -</li> -<li> -<p>Amazon DocumentDB database instances</p> -</li> -<li> -<p>Amazon EC2 volumes</p> -</li> -<li> -<p>Amazon OpenSearch Service domains</p> -</li> -<li> -<p>Amazon FSx file systems</p> -</li> -<li> -<p>Amazon SQS queues</p> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -</li> -</ul> -</div> -<div class="listingblock"> -<div class="content"> -<pre>const resource = bucket.node.findChild('Resource') as cdk.CfnResource; -resource.applyRemovalPolicy(cdk.RemovalPolicy.DESTROY);</pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const resource = bucket.node.findChild('Resource'); -resource.applyRemovalPolicy(cdk.RemovalPolicy.DESTROY);</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">resource = bucket.node.find_child('Resource') -resource.apply_removal_policy(cdk.RemovalPolicy.DESTROY);</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">CfnResource resource = (CfnResource)bucket.node.findChild("Resource"); -resource.applyRemovalPolicy(cdk.RemovalPolicy.DESTROY);</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">var resource = (CfnResource)bucket.node.findChild('Resource'); -resource.ApplyRemovalPolicy(cdk.RemovalPolicy.DESTROY);</code></pre> -</div> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>The AWS CDK’s <code>RemovalPolicy</code> translates to AWS CloudFormation’s <code>DeletionPolicy</code>. However, the default in AWS CDK is to retain the data, which is the opposite of the AWS CloudFormation default.</p> -</div> -</td> -</tr> -</table> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="identifiers">2.15. Identifiers and the AWS CDK</h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>When building AWS Cloud Development Kit (AWS CDK) apps, you will use many types of identifiers and names. To use the AWS CDK effectively and avoid errors, it is important to understand the types of identifiers.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>When building AWS Cloud Development Kit (AWS CDK) apps, you will use many types of identifiers and names. To use the AWS CDK effectively and avoid errors, it is important to understand the types of identifiers.</p> -</div> -<div class="paragraph"> -<p>Identifiers must be unique within the scope in which they are created; they do not need to be globally unique in your AWS CDK application.</p> -</div> -<div class="paragraph"> -<p>If you attempt to create an identifier with the same value within the same scope, the AWS CDK throws an exception.</p> -</div> -<div class="sect3"> -<h4 id="identifiers-construct-ids">2.15.1. Construct IDs</h4> -<div class="paragraph"> -<p>The most common identifier, <code>id</code>, is the identifier passed as the second argument when instantiating a construct object. This identifier, like all identifiers, only needs to be unique within the scope in which it is created, which is the first argument when instantiating a construct object.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>The <code>id</code> of a stack is also the identifier that you use to refer to it in the <a href="#cli">AWS CDK CLI reference</a>.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>Let’s look at an example where we have two constructs with the identifier <code>MyBucket</code> in our app. The first is defined in the scope of the stack with the identifier <code>Stack1</code>. The second is defined in the scope of a stack with the identifier <code>Stack2</code>. Because they’re defined in different scopes, this doesn’t cause any conflict, and they can coexist in the same app without issues.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import { App, Stack, StackProps } from 'aws-cdk-lib'; -import { Construct } from 'constructs'; -import * as s3 from 'aws-cdk-lib/aws-s3'; - -class MyStack extends Stack { - constructor(scope: Construct, id: string, props: StackProps = {}) { - super(scope, id, props); - - new s3.Bucket(this, 'MyBucket'); - } -} - -const app = new App(); -new MyStack(app, 'Stack1'); -new MyStack(app, 'Stack2');</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const { App , Stack } = require('aws-cdk-lib'); -const s3 = require('aws-cdk-lib/aws-s3'); - -class MyStack extends Stack { - constructor(scope, id, props = {}) { - super(scope, id, props); - - new s3.Bucket(this, 'MyBucket'); - } -} - -const app = new App(); -new MyStack(app, 'Stack1'); -new MyStack(app, 'Stack2');</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">from aws_cdk import App, Construct, Stack, StackProps -from constructs import Construct -from aws_cdk import aws_s3 as s3 - -class MyStack(Stack): - - def __init__(self, scope: Construct, id: str, **kwargs): - - super().__init__(scope, id, **kwargs) - s3.Bucket(self, "MyBucket") - -app = App() -MyStack(app, 'Stack1') -MyStack(app, 'Stack2')</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">// MyStack.java -package com.myorg; - -import software.amazon.awscdk.App; -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.StackProps; -import software.constructs.Construct; -import software.amazon.awscdk.services.s3.Bucket; - -public class MyStack extends Stack { - public MyStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public MyStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - new Bucket(this, "MyBucket"); - } -} - -// Main.java -package com.myorg; - -import software.amazon.awscdk.App; - -public class Main { - public static void main(String[] args) { - App app = new App(); - new MyStack(app, "Stack1"); - new MyStack(app, "Stack2"); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; -using constructs; -using Amazon.CDK.AWS.S3; - -public class MyStack : Stack -{ - public MyStack(Construct scope, string id, IStackProps props) : base(scope, id, props) - { - new Bucket(this, "MyBucket"); - } -} - -class Program -{ - static void Main(string[] args) - { - var app = new App(); - new MyStack(app, "Stack1"); - new MyStack(app, "Stack2"); - } -}</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="identifiers-paths">2.15.2. Paths</h4> -<div class="paragraph"> -<p>The constructs in an AWS CDK application form a hierarchy rooted in the <code>App</code> class. We refer to the collection of IDs from a given construct, its parent construct, its grandparent, and so on to the root of the construct tree, as a <em>path</em>.</p> -</div> -<div class="paragraph"> -<p>The AWS CDK typically displays paths in your templates as a string. The IDs from the levels are separated by slashes, starting at the node immediately under the root <code>App</code> instance, which is usually a stack. For example, the paths of the two Amazon S3 bucket resources in the previous code example are <code class="path">Stack1/MyBucket</code> and <code class="path">Stack2/MyBucket</code>.</p> -</div> -<div class="paragraph"> -<p>You can access the path of any construct programmatically, as shown in the following example. This gets the path of <code>myConstruct</code> (or <code>my_construct</code>, as Python developers would write it). Since IDs must be unique within the scope they are created, their paths are always unique within an AWS CDK application.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const path: string = myConstruct.node.path;</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const path = myConstruct.node.path;</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">path = my_construct.node.path</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">String path = myConstruct.getNode().getPath();</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">string path = myConstruct.Node.Path;</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="identifiers-unique-ids">2.15.3. Unique IDs</h4> -<div class="paragraph"> -<p>AWS CloudFormation requires that all logical IDs in a template be unique. Because of this, the AWS CDK must be able to generate a unique identifier for each construct in an application. Resources have paths that are globally unique (the names of all scopes from the stack to a specific resource). Therefore, the AWS CDK generates the necessary unique identifiers by concatenating the elements of the path and adding an 8-digit hash. (The hash is necessary to distinguish distinct paths, such as <code>A/B/C</code> and <code>A/BC</code>, that would result in the same AWS CloudFormation identifier. AWS CloudFormation identifiers are alphanumeric and cannot contain slashes or other separator characters.) The AWS CDK calls this string the <em>unique ID</em> of the construct.</p> -</div> -<div class="paragraph"> -<p>In general, your AWS CDK app should not need to know about unique IDs. You can, however, access the unique ID of any construct programmatically, as shown in the following example.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const uid: string = Names.uniqueId(myConstruct);</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const uid = Names.uniqueId(myConstruct);</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">uid = Names.unique_id(my_construct)</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">String uid = Names.uniqueId(myConstruct);</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">string uid = Names.Uniqueid(myConstruct);</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The <em>address</em> is another kind of unique identifier that uniquely distinguishes CDK resources. Derived from the SHA-1 hash of the path, it is not human-readable. However, its constant, relatively short length (always 42 hexadecimal characters) makes it useful in situations where the "traditional" unique ID might be too long. Some constructs may use the address in the synthesized AWS CloudFormation template instead of the unique ID. Again, your app generally should not need to know about its constructs' addresses, but you can retrieve a construct’s address as follows.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const addr: string = myConstruct.node.addr;</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const addr = myConstruct.node.addr;</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">addr = my_construct.node.addr</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">String addr = myConstruct.getNode().getAddr();</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">string addr = myConstruct.Node.Addr;</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="identifiers-logical-ids">2.15.4. Logical IDs</h4> -<div class="paragraph"> -<p>Unique IDs serve as the <em>logical identifiers</em> (or <em>logical names</em>) of resources in the generated AWS CloudFormation templates for constructs that represent AWS resources.</p> -</div> -<div class="paragraph"> -<p>For example, the Amazon S3 bucket in the previous example that is created within <code>Stack2</code> results in an <code>AWS::S3::Bucket</code> resource. The resource’s logical ID is <code>Stack2MyBucket4DD88B4F</code> in the resulting AWS CloudFormation template. (For details on how this identifier is generated, see <a href="#identifiers-unique-ids">Unique IDs</a>.)</p> -</div> -<div class="sect4"> -<h5 id="identifiers-logical-id-stability">Logical ID stability</h5> -<div class="paragraph"> -<p>Avoid changing the logical ID of a resource after it has been created. AWS CloudFormation identifies resources by their logical ID. Therefore, if you change the logical ID of a resource, AWS CloudFormation creates a new resource with the new logical ID, then deletes the existing one. Depending on the type of resource, this might cause service interruption, data loss, or both.</p> -</div> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="tokens">2.16. Tokens and the AWS CDK</h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>In the AWS Cloud Development Kit (AWS CDK), <em>tokens</em> are placeholders for values that aren’t known when defining constructs or synthesizing stacks. These values will be fully resolved at deployment, when your actual infrastructure is created. When developing AWS CDK applications, you will work with tokens to manage these values across your application.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>In the AWS Cloud Development Kit (AWS CDK), <em>tokens</em> are placeholders for values that aren’t known when defining constructs or synthesizing stacks. These values will be fully resolved at deployment, when your actual infrastructure is created. When developing AWS CDK applications, you will work with tokens to manage these values across your application.</p> -</div> -<div class="sect3"> -<h4 id="tokens-example">2.16.1. Token example</h4> -<div class="paragraph"> -<p>The following is an example of a CDK stack that defines a construct for an Amazon Simple Storage Service (Amazon S3) bucket. Since the name of our bucket is not yet known, the value for <code>bucketName</code> is stored as a token:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as cdk from 'aws-cdk-lib'; -import { Construct } from 'constructs'; -import * as s3 from 'aws-cdk-lib/aws-s3'; - -export class CdkDemoAppStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - // Define an S3 bucket - const myBucket = new s3.Bucket(this, 'myBucket'); - - // Store value of the S3 bucket name - const myBucketName = myBucket.bucketName; - - // Print the current value for the S3 bucket name at synthesis - console.log("myBucketName: " + bucketName); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const { Stack, Duration } = require('aws-cdk-lib'); -const s3 = require('aws-cdk-lib/aws-s3'); - -class CdkDemoAppStack extends Stack { - constructor(scope, id, props) { - super(scope, id, props); - - // Define an S3 bucket - const myBucket = new s3.Bucket(this, 'myBucket'); - - // Store value of the S3 bucket name - const myBucketName = myBucket.bucketName; - - // Print the current value for the S3 bucket name at synthesis - console.log("myBucketName: " + myBucketName); - } -} - -module.exports = { CdkDemoAppStack }</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">from aws_cdk import ( - Stack -) -from constructs import Construct -from aws_cdk import aws_s3 as s3 - -class CdkDemoAppStack(Stack): - - def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: - super().__init__(scope, construct_id, **kwargs) - - # Define an S3 bucket - my_bucket = s3.Bucket(self, "myBucket") - - # Store the value of the S3 bucket name - my_bucket_name = my_bucket.bucket_name - - # Print the current value for the S3 bucket name at synthesis - print(f"myBucketName: {my_bucket_name}")</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">package com.myorg; - -import software.constructs.Construct; -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.StackProps; -import software.amazon.awscdk.services.s3.Bucket; - -import java.util.Map; - -public class CdkDemoAppStack extends Stack { - public CdkDemoAppStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public CdkDemoAppStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - // Define an S3 bucket - Bucket myBucket = Bucket.Builder.create(this, "myBucket") - .build(); - - // Store the token for the bucket name - String myBucketName = myBucket.getBucketName(); - - // Print the token at synthesis - System.out.println("myBucketName: " + myBucketName); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; -using Constructs; -using Amazon.CDK.AWS.S3; - -namespace CdkDemoApp -{ - public class CdkDemoAppStack : Stack - { - internal CdkDemoAppStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) - { - // Define an S3 bucket - var myBucket = new Bucket(this, "myBucket"); - - // Store the token for the bucket name - var myBucketName = myBucket.BucketName; - - // Print the token at synthesis - System.Console.WriteLine($"myBucketName: {myBucketName}"); - } - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">package main - -import ( - "fmt" - - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/aws-cdk-go/awscdk/v2/awss3" - "github.com/aws/constructs-go/constructs/v10" - "github.com/aws/jsii-runtime-go" -) - -type CdkDemoAppStackProps struct { - awscdk.StackProps -} - -func NewCdkDemoAppStack(scope constructs.Construct, id string, props *CdkDemoAppStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - stack := awscdk.NewStack(scope, &id, &sprops) - - // Define an S3 bucket - myBucket := awss3.NewBucket(stack, jsii.String("myBucket"), &awss3.BucketProps{}) - - // Store the token for the bucket name - myBucketName := myBucket.BucketName() - - // Print the token at synthesis - fmt.Println("myBucketName: ", *myBucketName) - - return stack -} - -// ...</code></pre> -</div> -</div> -<div class="paragraph"> -<p>When we run <code>cdk synth</code> to synthesize our stack, the value for <code>myBucketName</code> will be displayed in the token format of <code>${Token[TOKEN.[replaceable]</code>1234<code>]}</code>. This token format is a result of how the AWS CDK encodes tokens. In this example, the token is encoded as a string:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ cdk synth --quiet -myBucketName: ${Token[TOKEN.21]}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Since the value for our bucket name is not known at synthesis, the token is rendered as <code>myBucket[replaceable]</code><unique-hash>````. Our AWS CloudFormation template uses the <code>Ref</code> intrinsic function to reference its value, which will be known at deployment:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-yaml" data-lang="yaml">Resources: - myBucket5AF9C99B: - # ... -Outputs: - bucketNameOutput: - Description: The name of the S3 bucket - Value: - Ref: myBucket5AF9C99B</code></pre> -</div> -</div> -<div class="paragraph"> -<p>For more information on how the unique hash is generated, see <a href="#how-synth-default-logical-ids">Generated logical IDs in your AWS CloudFormation template</a>.</p> -</div> -</div> -<div class="sect3"> -<h4 id="tokens-passing">2.16.2. Passing tokens</h4> -<div class="paragraph"> -<p>Tokens can be passed around as if they were the actual value they represent. The following is an example that passes the token for our bucket name to a construct for an AWS Lambda function:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as cdk from 'aws-cdk-lib'; -import { Construct } from 'constructs'; -import * as s3 from 'aws-cdk-lib/aws-s3'; -import * as lambda from 'aws-cdk-lib/aws-lambda'; - -export class CdkDemoAppStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - // Define an S3 bucket - const myBucket = new s3.Bucket(this, 'myBucket'); - - // ... - - // Define a Lambda function - const myFunction = new lambda.Function(this, "myFunction", { - runtime: lambda.Runtime.NODEJS_20_X, - handler: "index.handler", - code: lambda.Code.fromInline(` - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello World!'), - }; - }; - `), - functionName: myBucketName + "Function", // Pass token for the S3 bucket name - environment: { - BUCKET_NAME: myBucketName, // Pass token for the S3 bucket name - } - }); - } -}</code></pre> -</div> -</div> -</dd> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const { Stack, Duration } = require('aws-cdk-lib'); -const s3 = require('aws-cdk-lib/aws-s3'); -const lambda = require('aws-cdk-lib/aws-lambda'); - -class CdkDemoAppStack extends Stack { - constructor(scope, id, props) { - super(scope, id, props); - - // Define an S3 bucket - const myBucket = new s3.Bucket(this, 'myBucket'); - - // ... - - // Define a Lambda function - const myFunction = new lambda.Function(this, 'myFunction', { - runtime: lambda.Runtime.NODEJS_20_X, - handler: 'index.handler', - code: lambda.Code.fromInline(` - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello World!'), - }; - }; - `), - functionName: myBucketName + 'Function', // Pass token for the S3 bucket name - environment: { - BUCKET_NAME: myBucketName, // Pass token for the S3 bucket name - } - }); - } -} - -module.exports = { CdkDemoAppStack }</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">from aws_cdk import ( - Stack -) -from constructs import Construct -from aws_cdk import aws_s3 as s3 -from aws_cdk import aws_lambda as _lambda - -class CdkDemoAppStack(Stack): - - def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: - super().__init__(scope, construct_id, **kwargs) - - # Define an S3 bucket - my_bucket = s3.Bucket(self, "myBucket") - - # ... - - # Define a Lambda function - my_function = _lambda.Function(self, "myFunction", - runtime=_lambda.Runtime.NODEJS_20_X, - handler="index.handler", - code=_lambda.Code.from_inline(""" - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello World!'), - }; - }; - """), - function_name=f"{my_bucket_name}Function", # Pass token for the S3 bucket name - environment={ - "BUCKET_NAME": my_bucket_name # Pass token for the S3 bucket name - } - )</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">package com.myorg; - -import software.constructs.Construct; -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.StackProps; -import software.amazon.awscdk.services.s3.Bucket; -import software.amazon.awscdk.services.lambda.Code; -import software.amazon.awscdk.services.lambda.Function; -import software.amazon.awscdk.services.lambda.Runtime; - -import java.util.Map; - -public class CdkDemoAppStack extends Stack { - public CdkDemoAppStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public CdkDemoAppStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - // Define an S3 bucket - Bucket myBucket = Bucket.Builder.create(this, "myBucket") - .build(); - - // ... - - // Define a Lambda function - Function myFunction = Function.Builder.create(this, "myFunction") - .runtime(Runtime.NODEJS_20_X) - .handler("index.handler") - .code(Code.fromInline( - "exports.handler = async function(event) {" + - "return {" + - "statusCode: 200," + - "body: JSON.stringify('Hello World!')," + - "};" + - "};" - )) - .functionName(myBucketName + "Function") // Pass the token for the s3 bucket to the function construct - .environment(Map.of("BUCKET_NAME", myBucketName)) // Pass the bucket name as environment variable - .build(); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; -using Constructs; -using Amazon.CDK.AWS.S3; -using Amazon.CDK.AWS.Lambda; -using System; -using System.Collections.Generic; - -namespace CdkDemoApp -{ - public class CdkDemoAppStack : Stack - { - internal CdkDemoAppStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) - { - // Define an S3 bucket - var myBucket = new Bucket(this, "myBucket"); - - // ... - - // Define a Lambda function - var myFunction = new Function(this, "myFunction", new FunctionProps - { - Runtime = Runtime.NODEJS_20_X, - Handler = "index.handler", - Code = Code.FromInline(@" - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello World!'), - }; - }; - "), - // Pass the token for the S3 bucket name - Environment = new Dictionary<string, string> - { - { "BUCKET_NAME", myBucketName } - }, - FunctionName = $"{myBucketName}Function" // Pass the token for the s3 bucket to the function construct - }); - } - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">package main - -import ( - "fmt" - - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/aws-cdk-go/awscdk/v2/awslambda" - "github.com/aws/aws-cdk-go/awscdk/v2/awss3" - "github.com/aws/constructs-go/constructs/v10" - "github.com/aws/jsii-runtime-go" -) - -type CdkDemoAppStackProps struct { - awscdk.StackProps -} - -func NewCdkDemoAppStack(scope constructs.Construct, id string, props *CdkDemoAppStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - stack := awscdk.NewStack(scope, &id, &sprops) - - // Define an S3 bucket - myBucket := awss3.NewBucket(stack, jsii.String("myBucket"), &awss3.BucketProps{}) - - // ... - - // Define a Lambda function - myFunction := awslambda.NewFunction(stack, jsii.String("myFunction"), &awslambda.FunctionProps{ - Runtime: awslambda.Runtime_NODEJS_20_X(), - Handler: jsii.String("index.handler"), - Code: awslambda.Code_FromInline(jsii.String(` - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello World!'), - }; - }; - `)), - FunctionName: jsii.String(fmt.Sprintf("%sFunction", *myBucketName)), // Pass the token for the S3 bucket to the function name - Environment: &map[string]*string{ - "BUCKET_NAME": myBucketName, - }, - }) - - return stack -} -// ...</code></pre> -</div> -</div> -<div class="paragraph"> -<p>When we synthesize our template, the <code>Ref</code> and <code>Fn::Join</code> intrinsic functions are used to specify the values, which will be known at deployment:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-yaml" data-lang="yaml">Resources: - myBucket5AF9C99B: - Type: AWS::S3::Bucket - # ... - myFunction884E1557: - Type: AWS::Lambda::Function - Properties: - # ... - Environment: - Variables: - BUCKET_NAME: - Ref: myBucket5AF9C99B - FunctionName: - Fn::Join: - - "" - - - Ref: myBucket5AF9C99B - - Function - # ...</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="tokens-work">2.16.3. How token encodings work</h4> -<div class="paragraph"> -<p>Tokens are objects that implement the <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.IResolvable.html">IResolvable</a></code> interface, which contains a single <code>resolve</code> method. During synthesis, the AWS CDK calls this method to produce the final value for tokens in your CloudFormation template.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>You’ll rarely work directly with the <code>IResolvable</code> interface. You will most likely only see string-encoded versions of tokens.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="sect4"> -<h5 id="tokens-work-types">Token encoding types</h5> -<div class="paragraph"> -<p>Tokens participate in the synthesis process to produce arbitrary values of any type. Other functions typically only accept arguments of basic types, such as <code>string</code> or <code>number</code>. To use tokens in these cases, you can encode them into one of three types by using static methods on the <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Token.html">cdk.Token</a></code> class.</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Token.html#static-aswbrstringvalue-options">Token.asString</a> to generate a string encoding (or call <code>.toString()</code> on the token object).</p> -</li> -<li> -<p><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Token.html#static-aswbrlistvalue-options">Token.asList</a> to generate a list encoding.</p> -</li> -<li> -<p><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Token.html#static-aswbrnumbervalue">Token.asNumber</a> to generate a numeric encoding.</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>These take an arbitrary value, which can be an <code>IResolvable</code>, and encode them into a primitive value of the indicated type.</p> -</div> -<div class="admonitionblock important"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-important" title="Important"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>Because any one of the previous types can potentially be an encoded token, be careful when you parse or try to read their contents. For example, if you attempt to parse a string to extract a value from it, and the string is an encoded token, your parsing fails. Similarly, if you try to query the length of an array or perform math operations with a number, you must first verify that they aren’t encoded tokens.</p> -</div> -</td> -</tr> -</table> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="tokens-check">2.16.4. How to check for tokens in your app</h4> -<div class="paragraph"> -<p>To check whether a value has an unresolved token in it, call the <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Token.html#static-iswbrunresolvedobj">Token.isUnresolved</a></code> (Python: <code>is_unresolved</code>) method. The following is an example that checks if the value for our Amazon S3 bucket name is a token. If its not a token, we then validate the length of the bucket name:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">// ... - -export class CdkDemoAppStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - // Define an S3 bucket - const myBucket = new s3.Bucket(this, 'myBucket'); - // ... - - // Check if bucket name is a token. If not, check if length is less than 10 characters - if (cdk.Token.isUnresolved(myBucketName)) { - console.log("Token identified."); - } else if (!cdk.Token.isUnresolved(myBucketName) && myBucketName.length > 10) { - throw new Error('Maximum length for name is 10 characters.'); - }; - - // ...</code></pre> -</div> -</div> -</dd> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const { Stack, Duration, Token, CfnOutput } = require('aws-cdk-lib'); -// ... - -class CdkDemoAppStack extends Stack { - constructor(scope, id, props) { - super(scope, id, props); - - // Define an S3 bucket - const myBucket = new s3.Bucket(this, 'myBucket'); - - // ... - - // Check if bucket name is a token. If not, check if length is less than 10 characters - if (Token.isUnresolved(myBucketName)) { - console.log("Token identified."); - } else if (!Token.isUnresolved(myBucketName) && myBucketName.length > 10) { - throw new Error('Maximum length for name is 10 characters.'); - }; - - // ...</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">from aws_cdk import ( - Stack, - Token -) -# ... - -class CdkDemoAppStack(Stack): - - def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: - super().__init__(scope, construct_id, **kwargs) - - # Define an S3 bucket - my_bucket = s3.Bucket(self, "myBucket") - - # ... - - # Check if bucket name is a token. If not, check if length is less than 10 characters - if Token.is_unresolved(my_bucket_name): - print("Token identified.") - elif not Token.is_unresolved(my_bucket_name) and len(my_bucket_name) < 10: - raise ValueError("Maximum length for name is 10 characters.") - - # ...</code></pre> -</div> -</div> -</dd> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">// ... -import software.amazon.awscdk.Token; -// ... - -public class CdkDemoAppStack extends Stack { - public CdkDemoAppStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public CdkDemoAppStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - // Define an S3 bucket - Bucket myBucket = Bucket.Builder.create(this, "myBucket") - .build(); - - // ... - - // Check if the bucket name is a token. If not, check if length is less than 10 characters - if (Token.isUnresolved(myBucketName)) { - System.out.println("Token identified."); - } else if (!Token.isUnresolved(myBucketName) && myBucketName.length() > 10) { - throw new IllegalArgumentException("Maximum length for name is 10 characters."); - } - - // ... - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; -using Constructs; -using Amazon.CDK.AWS.S3; -using Amazon.CDK.AWS.Lambda; -using System; -using System.Collections.Generic; - -namespace CdkDemoApp -{ - public class CdkDemoAppStack : Stack - { - internal CdkDemoAppStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) - { - // Define an S3 bucket - var myBucket = new Bucket(this, "myBucket"); - - // ... - - // Check if bucket name is a token. If not, check if length is less than 10 characters - if (Token.IsUnresolved(myBucketName)) - { - System.Console.WriteLine("Token identified."); - } - else if (!Token.IsUnresolved(myBucketName) && myBucketName.Length > 10) - { - throw new System.Exception("Maximum length for name is 10 characters."); - } - - // ...</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">// ... - -func NewCdkDemoAppStack(scope constructs.Construct, id string, props *CdkDemoAppStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - stack := awscdk.NewStack(scope, &id, &sprops) - - // Define an S3 bucket - myBucket := awss3.NewBucket(stack, jsii.String("myBucket"), &awss3.BucketProps{}) - - // ... - - // Check if the bucket name is unresolved (a token) - if tokenUnresolved := awscdk.Token_IsUnresolved(myBucketName); tokenUnresolved != nil && *tokenUnresolved { - fmt.Println("Token identified.") - } else if tokenUnresolved != nil && !*tokenUnresolved && len(*myBucketName) > 10 { - panic("Maximum length for name is 10 characters.") - } - - // ...</code></pre> -</div> -</div> -<div class="paragraph"> -<p>When we run <code>cdk synth</code>, <code>myBucketName</code> is identified as a token:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ cdk synth --quiet -Token identified.</code></pre> -</div> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>You can use token encodings to escape the type system. For example, you could string-encode a token that produces a number value at synthesis time. If you use these functions, it’s your responsibility to make sure that your template resolves to a usable state after synthesis.</p> -</div> -</td> -</tr> -</table> -</div> -</div> -<div class="sect3"> -<h4 id="tokens-string">2.16.5. Working with string-encoded tokens</h4> -<div class="paragraph"> -<p>String-encoded tokens look like the following.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">${TOKEN[Bucket.Name.1234]}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>They can be passed around like regular strings, and can be concatenated, as shown in the following example.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const functionName = bucket.bucketName + 'Function';</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const functionName = bucket.bucketName + 'Function';</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">function_name = bucket.bucket_name + "Function"</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">String functionName = bucket.getBucketName().concat("Function");</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">string functionName = bucket.BucketName + "Function";</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">functionName := *bucket.BucketName() + "Function"</code></pre> -</div> -</div> -<div class="paragraph"> -<p>You can also use string interpolation, if your language supports it, as shown in the following example.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const functionName = `${bucket.bucketName}Function`;</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const functionName = `${bucket.bucketName}Function`;</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">function_name = f"{bucket.bucket_name}Function"</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">String functionName = String.format("%sFunction". bucket.getBucketName());</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">string functionName = $"${bucket.bucketName}Function";</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Use <code>fmt.Sprintf</code> for similar functionality:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">functionName := fmt.Sprintf("%sFunction", *bucket.BucketName())</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div class="paragraph"> -<p>Avoid manipulating the string in other ways. For example, taking a substring of a string is likely to break the string token.</p> -</div> -</div> -<div class="sect3"> -<h4 id="tokens-list">2.16.6. Working with list-encoded tokens</h4> -<div class="paragraph"> -<p>List-encoded tokens look like the following:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">["#{TOKEN[Stack.NotificationArns.1234]}"]</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The only safe thing to do with these lists is pass them directly to other constructs. Tokens in string list form cannot be concatenated, nor can an element be taken from the token. The only safe way to manipulate them is by using AWS CloudFormation intrinsic functions like <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-select.html">Fn.select</a>.</p> -</div> -</div> -<div class="sect3"> -<h4 id="tokens-number">2.16.7. Working with number-encoded tokens</h4> -<div class="paragraph"> -<p>Number-encoded tokens are a set of tiny negative floating-point numbers that look like the following.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">-1.8881545897087626e+289</code></pre> -</div> -</div> -<div class="paragraph"> -<p>As with list tokens, you cannot modify the number value, as doing so is likely to break the number token.</p> -</div> -<div class="paragraph"> -<p>The following is an example of a construct that contains a token encoded as a number:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import { Stack, Duration, StackProps } from 'aws-cdk-lib'; -import { Construct } from 'constructs'; -import * as rds from 'aws-cdk-lib/aws-rds'; -import * as ec2 from 'aws-cdk-lib/aws-ec2'; - -export class CdkDemoAppStack extends Stack { - constructor(scope: Construct, id: string, props?: StackProps) { - super(scope, id, props); - - // Define a new VPC - const vpc = new ec2.Vpc(this, 'MyVpc', { - maxAzs: 3, // Maximum number of availability zones to use - }); - - // Define an RDS database cluster - const dbCluster = new rds.DatabaseCluster(this, 'MyRDSCluster', { - engine: rds.DatabaseClusterEngine.AURORA, - instanceProps: { - vpc, - }, - }); - - // Get the port token (this is a token encoded as a number) - const portToken = dbCluster.clusterEndpoint.port; - - // Print the value for our token at synthesis - console.log("portToken: " + portToken); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const { Stack, Duration } = require('aws-cdk-lib'); -const lambda = require('aws-cdk-lib/aws-lambda'); -const rds = require('aws-cdk-lib/aws-rds'); -const ec2 = require('aws-cdk-lib/aws-ec2'); - -class CdkDemoAppStack extends Stack { - constructor(scope, id, props) { - super(scope, id, props); - - // Define a new VPC - const vpc = new ec2.Vpc(this, 'MyVpc', { - maxAzs: 3, // Maximum number of availability zones to use - }); - - // Define an RDS database cluster - const dbCluster = new rds.DatabaseCluster(this, 'MyRDSCluster', { - engine: rds.DatabaseClusterEngine.AURORA, - instanceProps: { - vpc, - }, - }); - - // Get the port token (this is a token encoded as a number) - const portToken = dbCluster.clusterEndpoint.port; - - // Print the value for our token at synthesis - console.log("portToken: " + portToken); - } -} - -module.exports = { CdkDemoAppStack }</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">from aws_cdk import ( - Duration, - Stack, -) -from aws_cdk import aws_rds as rds -from aws_cdk import aws_ec2 as ec2 -from constructs import Construct - -class CdkDemoAppStack(Stack): - - def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: - super().__init__(scope, construct_id, **kwargs) - - # Define a new VPC - vpc = ec2.Vpc(self, 'MyVpc', - max_azs=3 # Maximum number of availability zones to use - ) - - # Define an RDS database cluster - db_cluster = rds.DatabaseCluster(self, 'MyRDSCluster', - engine=rds.DatabaseClusterEngine.AURORA, - instance_props=rds.InstanceProps( - vpc=vpc - ) - ) - - # Get the port token (this is a token encoded as a number) - port_token = db_cluster.cluster_endpoint.port - - # Print the value for our token at synthesis - print(f"portToken: {port_token}")</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">package com.myorg; - -import software.constructs.Construct; -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.StackProps; -import software.amazon.awscdk.services.ec2.Vpc; -import software.amazon.awscdk.services.rds.DatabaseCluster; -import software.amazon.awscdk.services.rds.DatabaseClusterEngine; -import software.amazon.awscdk.services.rds.InstanceProps; - -public class CdkDemoAppStack extends Stack { - public CdkDemoAppStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public CdkDemoAppStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - // Define a new VPC - Vpc vpc = Vpc.Builder.create(this, "MyVpc") - .maxAzs(3) // Maximum number of availability zones to use - .build(); - - // Define an RDS database cluster - DatabaseCluster dbCluster = DatabaseCluster.Builder.create(this, "MyRDSCluster") - .engine(DatabaseClusterEngine.AURORA) - .instanceProps(InstanceProps.builder() - .vpc(vpc) - .build()) - .build(); - - // Get the port token (this is a token encoded as a number) - Number portToken = dbCluster.getClusterEndpoint().getPort(); - - // Print the value for our token at synthesis - System.out.println("portToken: " + portToken); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; -using Constructs; -using Amazon.CDK.AWS.EC2; -using Amazon.CDK.AWS.RDS; -using System; -using System.Collections.Generic; - -namespace CdkDemoApp -{ - public class CdkDemoAppStack : Stack - { - internal CdkDemoAppStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) - { - // Define a new VPC - var vpc = new Vpc(this, "MyVpc", new VpcProps - { - MaxAzs = 3 // Maximum number of availability zones to use - }); - - // Define an RDS database cluster - var dbCluster = new DatabaseCluster(this, "MyRDSCluster", new DatabaseClusterProps - { - Engine = DatabaseClusterEngine.AURORA, // Remove parentheses - InstanceProps = new Amazon.CDK.AWS.RDS.InstanceProps // Specify RDS InstanceProps - { - Vpc = vpc - } - }); - - // Get the port token (this is a token encoded as a number) - var portToken = dbCluster.ClusterEndpoint.Port; - - // Print the value for our token at synthesis - System.Console.WriteLine($"portToken: {portToken}"); - } - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">package main - -import ( - "fmt" - - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/aws-cdk-go/awscdk/v2/awsec2" - "github.com/aws/aws-cdk-go/awscdk/v2/awsrds" - "github.com/aws/constructs-go/constructs/v10" - "github.com/aws/jsii-runtime-go" -) - -type CdkDemoAppStackProps struct { - awscdk.StackProps -} - -func NewCdkDemoAppStack(scope constructs.Construct, id string, props *CdkDemoAppStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - stack := awscdk.NewStack(scope, &id, &sprops) - - // Define a new VPC - vpc := awsec2.NewVpc(stack, jsii.String("MyVpc"), &awsec2.VpcProps{ - MaxAzs: jsii.Number(3), // Maximum number of availability zones to use - }) - - // Define an RDS database cluster - dbCluster := awsrds.NewDatabaseCluster(stack, jsii.String("MyRDSCluster"), &awsrds.DatabaseClusterProps{ - Engine: awsrds.DatabaseClusterEngine_AURORA(), - InstanceProps: &awsrds.InstanceProps{ - Vpc: vpc, - }, - }) - - // Get the port token (this is a token encoded as a number) - portToken := dbCluster.ClusterEndpoint().Port() - - // Print the value for our token at synthesis - fmt.Println("portToken: ", portToken) - - return stack -} - -// ...</code></pre> -</div> -</div> -<div class="paragraph"> -<p>When we run <code>cdk synth</code>, the value for <code>portToken</code> is displayed as a number-encoded token:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ cdk synth --quiet -portToken: -1.8881545897087968e+289</code></pre> -</div> -</div> -<div class="sect4"> -<h5 id="tokens-number-pass">Pass number-encoded tokens</h5> -<div class="paragraph"> -<p>When you pass number-encoded tokens to other constructs, it may make sense to convert them to strings first. For example, if you want to use the value of a number-encoded string as part of a concatenated string, converting it helps with readability.</p> -</div> -<div class="paragraph"> -<p>In the following example, <code>portToken</code> is a number-encoded token that we want to pass to our Lambda function as part of <code>connectionString</code>:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import { Stack, Duration, CfnOutput, StackProps } from 'aws-cdk-lib'; -// ... -import * as lambda from 'aws-cdk-lib/aws-lambda'; - -export class CdkDemoAppStack extends Stack { - constructor(scope: Construct, id: string, props?: StackProps) { - super(scope, id, props); - - // Define a new VPC - // ... - - // Define an RDS database cluster - // ... - - // Get the port token (this is a token encoded as a number) - const portToken = dbCluster.clusterEndpoint.port; - - // ... - - // Example connection string with the port token as a number - const connectionString = `jdbc:mysql://mydb.cluster.amazonaws.com:${portToken}/mydatabase`; - - // Use the connection string as an environment variable in a Lambda function - const myFunction = new lambda.Function(this, 'MyLambdaFunction', { - runtime: lambda.Runtime.NODEJS_20_X, - handler: 'index.handler', - code: lambda.Code.fromInline(` - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello World!'), - }; - }; - `), - environment: { - DATABASE_CONNECTION_STRING: connectionString, // Using the port token as part of the string - }, - }); - - // Output the value of our connection string at synthesis - console.log("connectionString: " + connectionString); - - // Output the connection string - new CfnOutput(this, 'ConnectionString', { - value: connectionString, - }); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const { Stack, Duration, CfnOutput } = require('aws-cdk-lib'); -// ... -const lambda = require('aws-cdk-lib/aws-lambda'); - -class CdkDemoAppStack extends Stack { - constructor(scope, id, props) { - super(scope, id, props); - - // Define a new VPC - // ... - - // Define an RDS database cluster - // ... - - // Get the port token (this is a token encoded as a number) - const portToken = dbCluster.clusterEndpoint.port; - - // ... - - // Example connection string with the port token as a number - const connectionString = `jdbc:mysql://mydb.cluster.amazonaws.com:${portToken}/mydatabase`; - - // Use the connection string as an environment variable in a Lambda function - const myFunction = new lambda.Function(this, 'MyLambdaFunction', { - runtime: lambda.Runtime.NODEJS_20_X, - handler: 'index.handler', - code: lambda.Code.fromInline(` - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello World!'), - }; - }; - `), - environment: { - DATABASE_CONNECTION_STRING: connectionString, // Using the port token as part of the string - }, - }); - - // Output the value of our connection string at synthesis - console.log("connectionString: " + connectionString); - - // Output the connection string - new CfnOutput(this, 'ConnectionString', { - value: connectionString, - }); - } -} - -module.exports = { CdkDemoAppStack }</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">from aws_cdk import ( - Duration, - Stack, - CfnOutput, -) -from aws_cdk import aws_lambda as _lambda -# ... - -class CdkDemoAppStack(Stack): - - def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: - super().__init__(scope, construct_id, **kwargs) - - # Define a new VPC - # ... - - # Define an RDS database cluster - # ... - - # Get the port token (this is a token encoded as a number) - port_token = db_cluster.cluster_endpoint.port - - # ... - - # Example connection string with the port token as a number - connection_string = f"jdbc:mysql://mydb.cluster.amazonaws.com:{port_token}/mydatabase" - - # Use the connection string as an environment variable in a Lambda function - my_function = _lambda.Function(self, 'MyLambdaFunction', - runtime=_lambda.Runtime.NODEJS_20_X, - handler='index.handler', - code=_lambda.Code.from_inline(""" - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello World!'), - }; - }; - """), - environment={ - 'DATABASE_CONNECTION_STRING': connection_string # Using the port token as part of the string - } - ) - - # Output the value of our connection string at synthesis - print(f"connectionString: {connection_string}") - - # Output the connection string - CfnOutput(self, 'ConnectionString', - value=connection_string - )</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">// ... -import software.amazon.awscdk.CfnOutput; -import software.amazon.awscdk.services.lambda.Function; -import software.amazon.awscdk.services.lambda.Runtime; -import software.amazon.awscdk.services.lambda.Code; - -import java.util.Map; - -public class CdkDemoAppStack extends Stack { - public CdkDemoAppStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public CdkDemoAppStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - // Define a new VPC - // ... - - // Define an RDS database cluster - // ... - - // Get the port token (this is a token encoded as a number) - Number portToken = dbCluster.getClusterEndpoint().getPort(); - - // ... - - // Example connection string with the port token as a number - String connectionString = "jdbc:mysql://mydb.cluster.amazonaws.com:" + portToken + "/mydatabase"; - - // Use the connection string as an environment variable in a Lambda function - Function myFunction = Function.Builder.create(this, "MyLambdaFunction") - .runtime(Runtime.NODEJS_20_X) - .handler("index.handler") - .code(Code.fromInline( - "exports.handler = async function(event) {\n" + - " return {\n" + - " statusCode: 200,\n" + - " body: JSON.stringify('Hello World!'),\n" + - " };\n" + - "};")) - .environment(Map.of( - "DATABASE_CONNECTION_STRING", connectionString // Using the port token as part of the string - )) - .build(); - - // Output the value of our connection string at synthesis - System.out.println("connectionString: " + connectionString); - - // Output the connection string - CfnOutput.Builder.create(this, "ConnectionString") - .value(connectionString) - .build(); - } -}</code></pre> -</div> -</div> -</dd> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">// ... -using Amazon.CDK.AWS.Lambda; - -namespace CdkDemoApp -{ - public class CdkDemoAppStack : Stack - { - internal CdkDemoAppStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) - { - // Define a new VPC - // ... - - // Define an RDS database cluster - var dbCluster = new DatabaseCluster(this, "MyRDSCluster", new DatabaseClusterProps - // ... - - // Get the port token (this is a token encoded as a number) - var portToken = dbCluster.ClusterEndpoint.Port; - - // ... - - // Example connection string with the port token as a number - var connectionString = $"jdbc:mysql://mydb.cluster.amazonaws.com:{portToken}/mydatabase"; - - // Use the connection string as an environment variable in a Lambda function - var myFunction = new Function(this, "MyLambdaFunction", new FunctionProps - { - Runtime = Runtime.NODEJS_20_X, - Handler = "index.handler", - Code = Code.FromInline(@" - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello World!'), - }; - }; - "), - Environment = new Dictionary<string, string> - { - { "DATABASE_CONNECTION_STRING", connectionString } // Using the port token as part of the string - } - }); - - // Output the value of our connection string at synthesis - Console.WriteLine($"connectionString: {connectionString}"); - - // Output the connection string - new CfnOutput(this, "ConnectionString", new CfnOutputProps - { - Value = connectionString - }); - } - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">// ... - "github.com/aws/aws-cdk-go/awscdk/v2/awslambda" -) - -type CdkDemoAppStackProps struct { - awscdk.StackProps -} - -func NewCdkDemoAppStack(scope constructs.Construct, id string, props *CdkDemoAppStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - stack := awscdk.NewStack(scope, &id, &sprops) - - // Define a new VPC - // ... - - // Define an RDS database cluster - // ... - - // Get the port token (this is a token encoded as a number) - portToken := dbCluster.ClusterEndpoint().Port() - - // ... - - // Example connection string with the port token as a number - connectionString := fmt.Sprintf("jdbc:mysql://mydb.cluster.amazonaws.com:%s/mydatabase", portToken) - - // Use the connection string as an environment variable in a Lambda function - myFunction := awslambda.NewFunction(stack, jsii.String("MyLambdaFunction"), &awslambda.FunctionProps{ - Runtime: awslambda.Runtime_NODEJS_20_X(), - Handler: jsii.String("index.handler"), - Code: awslambda.Code_FromInline(jsii.String(` - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello World!'), - }; - }; - `)), - Environment: &map[string]*string{ - "DATABASE_CONNECTION_STRING": jsii.String(connectionString), // Using the port token as part of the string - }, - }) - - // Output the value of our connection string at synthesis - fmt.Println("connectionString: ", connectionString) - - // Output the connection string - awscdk.NewCfnOutput(stack, jsii.String("ConnectionString"), &awscdk.CfnOutputProps{ - Value: jsii.String(connectionString), - }) - - return stack -} - -// ...</code></pre> -</div> -</div> -<div class="paragraph"> -<p>If we pass this value to <code>connectionString</code>, the output value when we run <code>cdk synth</code> may be confusing due to the number-encoded string:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ cdk synth --quiet -connectionString: jdbc:mysql://mydb.cluster.amazonaws.com:-1.888154589708796e+289/mydatabase</code></pre> -</div> -</div> -<div class="paragraph"> -<p>To convert a number-encoded token to a string, use <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Tokenization.html#static-stringifywbrnumberx">cdk.Tokenization.stringifyNumber(token)</a></code>. In the following example, we convert the number-encoded token to a string before defining our connection string:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import { Stack, Duration, Tokenization, CfnOutput, StackProps } from 'aws-cdk-lib'; -// ... - -export class CdkDemoAppStack extends Stack { - constructor(scope: Construct, id: string, props?: StackProps) { - super(scope, id, props); - - // Define a new VPC - // ... - - // Define an RDS database cluster - // ... - - // Get the port token (this is a token encoded as a number) - const portToken = dbCluster.clusterEndpoint.port; - - // ... - - // Convert the encoded number to an encoded string for use in the connection string - const portAsString = Tokenization.stringifyNumber(portToken); - - // Example connection string with the port token as a string - const connectionString = `jdbc:mysql://mydb.cluster.amazonaws.com:${portAsString}/mydatabase`; - - // Use the connection string as an environment variable in a Lambda function - const myFunction = new lambda.Function(this, 'MyLambdaFunction', { - // ... - environment: { - DATABASE_CONNECTION_STRING: connectionString, // Using the port token as part of the string - }, - }); - - // Output the value of our connection string at synthesis - console.log("connectionString: " + connectionString); - - // Output the connection string - new CfnOutput(this, 'ConnectionString', { - value: connectionString, - }); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const { Stack, Duration, Tokenization, CfnOutput } = require('aws-cdk-lib'); -// ... - -class CdkDemoAppStack extends Stack { - constructor(scope, id, props) { - super(scope, id, props); - - // Define a new VPC - // ... - - // Define an RDS database cluster - // ... - - // Get the port token (this is a token encoded as a number) - const portToken = dbCluster.clusterEndpoint.port; - - // ... - - // Convert the encoded number to an encoded string for use in the connection string - const portAsString = Tokenization.stringifyNumber(portToken); - - // Example connection string with the port token as a string - const connectionString = `jdbc:mysql://mydb.cluster.amazonaws.com:${portAsString}/mydatabase`; - - // Use the connection string as an environment variable in a Lambda function - const myFunction = new lambda.Function(this, 'MyLambdaFunction', { - // ... - environment: { - DATABASE_CONNECTION_STRING: connectionString, // Using the port token as part of the string - }, - }); - - // Output the value of our connection string at synthesis - console.log("connectionString: " + connectionString); - - // Output the connection string - new CfnOutput(this, 'ConnectionString', { - value: connectionString, - }); - } -} - -module.exports = { CdkDemoAppStack }</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">from aws_cdk import ( - Duration, - Stack, - Tokenization, - CfnOutput, -) -# ... - -class CdkDemoAppStack(Stack): - - def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: - super().__init__(scope, construct_id, **kwargs) - - # Define a new VPC - # ... - - # Define an RDS database cluster - # ... - - # Get the port token (this is a token encoded as a number) - port_token = db_cluster.cluster_endpoint.port - - # Convert the encoded number to an encoded string for use in the connection string - port_as_string = Tokenization.stringify_number(port_token) - - # Example connection string with the port token as a string - connection_string = f"jdbc:mysql://mydb.cluster.amazonaws.com:{port_as_string}/mydatabase" - - # Use the connection string as an environment variable in a Lambda function - my_function = _lambda.Function(self, 'MyLambdaFunction', - # ... - environment={ - 'DATABASE_CONNECTION_STRING': connection_string # Using the port token as part of the string - } - ) - - # Output the value of our connection string at synthesis - print(f"connectionString: {connection_string}") - - # Output the connection string - CfnOutput(self, 'ConnectionString', - value=connection_string - )</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">// ... -import software.amazon.awscdk.Tokenization; - -public class CdkDemoAppStack extends Stack { - public CdkDemoAppStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public CdkDemoAppStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - // Define a new VPC - // ... - - // Define an RDS database cluster - // ... - - // Get the port token (this is a token encoded as a number) - Number portToken = dbCluster.getClusterEndpoint().getPort(); - - // ... - - // Convert the encoded number to an encoded string for use in the connection string - String portAsString = Tokenization.stringifyNumber(portToken); - - // Example connection string with the port token as a string - String connectionString = "jdbc:mysql://mydb.cluster.amazonaws.com:" + portAsString + "/mydatabase"; - - // Use the connection string as an environment variable in a Lambda function - Function myFunction = Function.Builder.create(this, "MyLambdaFunction") - // ... - .environment(Map.of( - "DATABASE_CONNECTION_STRING", connectionString // Using the port token as part of the string - )) - .build(); - - // Output the value of our connection string at synthesis - System.out.println("connectionString: " + connectionString); - - // Output the connection string - CfnOutput.Builder.create(this, "ConnectionString") - .value(connectionString) - .build(); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">// ... - -namespace CdkDemoApp -{ - public class CdkDemoAppStack : Stack - { - internal CdkDemoAppStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) - { - // Define a new VPC - // ... - - // Define an RDS database cluster - // ... - - // Get the port token (this is a token encoded as a number) - var portToken = dbCluster.ClusterEndpoint.Port; - - // ... - - // Convert the encoded number to an encoded string for use in the connection string - var portAsString = Tokenization.StringifyNumber(portToken); - - // Example connection string with the port token as a string - var connectionString = $"jdbc:mysql://mydb.cluster.amazonaws.com:{portAsString}/mydatabase"; - - // Use the connection string as an environment variable in a Lambda function - var myFunction = new Function(this, "MyLambdaFunction", new FunctionProps - { - // ... - Environment = new Dictionary<string, string> - { - { "DATABASE_CONNECTION_STRING", connectionString } // Using the port token as part of the string - } - }); - - // Output the value of our connection string at synthesis - Console.WriteLine($"connectionString: {connectionString}"); - - // Output the connection string - new CfnOutput(this, "ConnectionString", new CfnOutputProps - { - Value = connectionString - }); - } - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">// ... - -func NewCdkDemoAppStack(scope constructs.Construct, id string, props *CdkDemoAppStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - stack := awscdk.NewStack(scope, &id, &sprops) - - // Define a new VPC - // ... - - // Define an RDS database cluster - // ... - - // Get the port token (this is a token encoded as a number) - portToken := dbCluster.ClusterEndpoint().Port() - - // ... - - // Convert the encoded number to an encoded string for use in the connection string - portAsString := awscdk.Tokenization_StringifyNumber(portToken) - - // Example connection string with the port token as a string - connectionString := fmt.Sprintf("jdbc:mysql://mydb.cluster.amazonaws.com:%s/mydatabase", portAsString) - - // Use the connection string as an environment variable in a Lambda function - myFunction := awslambda.NewFunction(stack, jsii.String("MyLambdaFunction"), &awslambda.FunctionProps{ - // ... - Environment: &map[string]*string{ - "DATABASE_CONNECTION_STRING": jsii.String(connectionString), // Using the port token as part of the string - }, - }) - - // Output the value of our connection string at synthesis - fmt.Println("connectionString: ", connectionString) - - // Output the connection string - awscdk.NewCfnOutput(stack, jsii.String("ConnectionString"), &awscdk.CfnOutputProps{ - Value: jsii.String(connectionString), - }) - - fmt.Println(myFunction) - - return stack -} - -// ...</code></pre> -</div> -</div> -<div class="paragraph"> -<p>When we run <code>cdk synth</code>, the value for our connection string is represented in a cleaner and clearer format:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk synth --quiet -connectionString: jdbc:mysql://mydb.cluster.amazonaws.com:${Token[TOKEN.242]}/mydatabase</code></pre> -</div> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="tokens-lazy">2.16.8. Lazy values</h4> -<div class="paragraph"> -<p>In addition to representing deploy-time values, such as AWS CloudFormation <a href="#parameters">parameters</a>, tokens are also commonly used to represent synthesis-time lazy values. These are values for which the final value will be determined before synthesis has completed, but not at the point where the value is constructed. Use tokens to pass a literal string or number value to another construct, while the actual value at synthesis time might depend on some calculation that has yet to occur.</p> -</div> -<div class="paragraph"> -<p>You can construct tokens representing synth-time lazy values using static methods on the <code>Lazy</code> class, such as <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Lazy.html#static-stringproducer-options">Lazy.string</a></code> and <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Lazy.html#static-numberproducer">Lazy.number</a></code>. These methods accept an object whose <code>produce</code> property is a function that accepts a context argument and returns the final value when called.</p> -</div> -<div class="paragraph"> -<p>The following example creates an Auto Scaling group whose capacity is determined after its creation.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">let actualValue: number; - -new AutoScalingGroup(this, 'Group', { - desiredCapacity: Lazy.numberValue({ - produce(context) { - return actualValue; - } - }) -}); - -// At some later point -actualValue = 10;</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">let actualValue; - -new AutoScalingGroup(this, 'Group', { - desiredCapacity: Lazy.numberValue({ - produce(context) { - return (actualValue); - } - }) -}); - -// At some later point -actualValue = 10;</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">class Producer: - def __init__(self, func): - self.produce = func - -actual_value = None - -AutoScalingGroup(self, "Group", - desired_capacity=Lazy.number_value(Producer(lambda context: actual_value)) -) - -# At some later point -actual_value = 10</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">double actualValue = 0; - -class ProduceActualValue implements INumberProducer { - - @Override - public Number produce(IResolveContext context) { - return actualValue; - } -} - -AutoScalingGroup.Builder.create(this, "Group") - .desiredCapacity(Lazy.numberValue(new ProduceActualValue())).build(); - -// At some later point -actualValue = 10;</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">public class NumberProducer : INumberProducer -{ - Func<Double> function; - - public NumberProducer(Func<Double> function) - { - this.function = function; - } - - public Double Produce(IResolveContext context) - { - return function(); - } -} - -double actualValue = 0; - -new AutoScalingGroup(this, "Group", new AutoScalingGroupProps -{ - DesiredCapacity = Lazy.NumberValue(new NumberProducer(() => actualValue)) -}); - -// At some later point -actualValue = 10;</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="tokens-json">2.16.9. Converting to JSON</h4> -<div class="paragraph"> -<p>Sometimes you want to produce a JSON string of arbitrary data, and you may not know whether the data contains tokens. To properly JSON-encode any data structure, regardless of whether it contains tokens, use the method <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html#towbrjsonwbrstringobj-space">stack.toJsonString</a></code>, as shown in the following example.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const stack = Stack.of(this); -const str = stack.toJsonString({ - value: bucket.bucketName -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const stack = Stack.of(this); -const str = stack.toJsonString({ - value: bucket.bucketName -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">stack = Stack.of(self) -string = stack.to_json_string(dict(value=bucket.bucket_name))</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">Stack stack = Stack.of(this); -String stringVal = stack.toJsonString(java.util.Map.of( // Map.of requires Java 9+ - put("value", bucket.getBucketName())));</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">var stack = Stack.Of(this); -var stringVal = stack.ToJsonString(new Dictionary<string, string> -{ - ["value"] = bucket.BucketName -});</code></pre> -</div> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="parameters">2.17. Parameters and the AWS CDK</h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p><em>Parameters</em> are custom values that are supplied at deployment time.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p><em>Parameters</em> are custom values that are supplied at deployment time. <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html">Parameters</a> are a feature of AWS CloudFormation. Since the AWS Cloud Development Kit (AWS CDK) synthesizes AWS CloudFormation templates, it also offers support for deployment-time parameters.</p> -</div> -<div class="sect3"> -<h4 id="parameters-about">2.17.1. About parameters</h4> -<div class="paragraph"> -<p>Using the AWS CDK, you can define parameters, which can then be used in the properties of constructs you create. You can also deploy stacks that contain parameters.</p> -</div> -<div class="paragraph"> -<p>When deploying the AWS CloudFormation template using the AWS CDK <code class="noloc">CLI</code>, you provide the parameter values on the command line. If you deploy the template through the AWS CloudFormation console, you are prompted for the parameter values.</p> -</div> -<div class="paragraph"> -<p>In general, we recommend against using AWS CloudFormation parameters with the AWS CDK. The usual ways to pass values into AWS CDK apps are <a href="#context">context values</a> and environment variables. Because they are not available at synthesis time, parameter values cannot be easily used for flow control and other purposes in your CDK app.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>To do control flow with parameters, you can use <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.CfnCondition.html">CfnCondition</a> constructs, although this is awkward compared to native <code>if</code> statements.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>Using parameters requires you to be mindful of how the code you’re writing behaves at deployment time, and also at synthesis time. This makes it harder to understand and reason about your AWS CDK application, in many cases for little benefit.</p> -</div> -<div class="paragraph"> -<p>Generally, it’s better to have your CDK app accept necessary information in a well-defined way and use it directly to declare constructs in your CDK app. An ideal AWS CDK–generated AWS CloudFormation template is concrete, with no values remaining to be specified at deployment time.</p> -</div> -<div class="paragraph"> -<p>There are, however, use cases to which AWS CloudFormation parameters are uniquely suited. If you have separate teams defining and deploying infrastructure, for example, you can use parameters to make the generated templates more widely useful. Also, because the AWS CDK supports AWS CloudFormation parameters, you can use the AWS CDK with AWS services that use AWS CloudFormation templates (such as Service Catalog). These AWS services use parameters to configure the template that’s being deployed.</p> -</div> -</div> -<div class="sect3"> -<h4 id="parameters-learn">2.17.2. Learn more</h4> -<div class="paragraph"> -<p>For instructions on developing CDK apps with parameters, see <a href="#get-cfn-param">Use CloudFormation parameters to get a CloudFormation value</a>.</p> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="tagging">2.18. Tags and the AWS CDK</h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Tags are informational key-value elements that you can add to constructs in your AWS CDK app. A tag applied to a given construct also applies to all of its taggable children. Tags are included in the AWS CloudFormation template synthesized from your app and are applied to the AWS resources it deploys. You can use tags to identify and categorize resources for the following purposes:</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>Tags are informational key-value elements that you can add to constructs in your AWS CDK app. A tag applied to a given construct also applies to all of its taggable children. Tags are included in the AWS CloudFormation template synthesized from your app and are applied to the AWS resources it deploys. You can use tags to identify and categorize resources for the following purposes:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Simplifying management</p> -</li> -<li> -<p>Cost allocation</p> -</li> -<li> -<p>Access control</p> -</li> -<li> -<p>Any other purposes that you devise</p> -</li> -</ul> -</div> -<div class="admonitionblock tip"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-tip" title="Tip"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>For more information about how you can use tags with your AWS resources, see <a href="https://docs.aws.amazon.com/whitepapers/latest/tagging-best-practices/tagging-best-practices.html">Best Practices for Tagging AWS Resources</a> in the <em>AWS Whitepaper</em>.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="sect3"> -<h4 id="tagging-use">2.18.1. Using tags</h4> -<div class="paragraph"> -<p>The <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Tags.html">Tags</a> class includes the static method <code>of()</code>, through which you can add tags to, or remove tags from, the specified construct.</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Tags.html#addkey-value-props">Tags.of(SCOPE).add()</a> applies a new tag to the given construct and all of its children.</p> -</li> -<li> -<p><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Tags.html#removekey-props">Tags.of(SCOPE).remove()</a> removes a tag from the given construct and any of its children, including tags a child construct may have applied to itself.</p> -</li> -</ul> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>Tagging is implemented using <a href="#aspects">Aspects and the AWS CDK</a>. Aspects are a way to apply an operation (such as tagging) to all constructs in a given scope.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>The following example applies the tag <strong>key</strong> with the value <strong>value</strong> to a construct.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">Tags.of(myConstruct).add('key', 'value');</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">Tags.of(myConstruct).add('key', 'value');</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">Tags.of(my_construct).add("key", "value")</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">Tags.of(myConstruct).add("key", "value");</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">Tags.Of(myConstruct).Add("key", "value");</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">awscdk.Tags_Of(myConstruct).Add(jsii.String("key"), jsii.String("value"), &awscdk.TagProps{})</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The following example deletes the tag <strong>key</strong> from a construct.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">Tags.of(myConstruct).remove('key');</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">Tags.of(myConstruct).remove('key');</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">Tags.of(my_construct).remove("key")</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">Tags.of(myConstruct).remove("key");</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">Tags.Of(myConstruct).Remove("key");</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">awscdk.Tags_Of(myConstruct).Remove(jsii.String("key"), &awscdk.TagProps{})</code></pre> -</div> -</div> -<div class="paragraph"> -<p>If you are using <code>Stage</code> constructs, apply the tag at the <code>Stage</code> level or below. Tags are not applied across <code>Stage</code> boundaries.</p> -</div> -</div> -<div class="sect3"> -<h4 id="w94aac13c77c17">2.18.2. Tag priorities</h4> -<div class="paragraph"> -<p>The AWS CDK applies and removes tags recursively. If there are conflicts, the tagging operation with the highest priority wins. (Priorities are set using the optional <code>priority</code> property.) If the priorities of two operations are the same, the tagging operation closest to the bottom of the construct tree wins. By default, applying a tag has a priority of 100 (except for tags added directly to an AWS CloudFormation resource, which has a priority of 50). The default priority for removing a tag is 200.</p> -</div> -<div class="paragraph"> -<p>The following applies a tag with a priority of 300 to a construct.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">Tags.of(myConstruct).add('key', 'value', { - priority: 300 -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">Tags.of(myConstruct).add('key', 'value', { - priority: 300 -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">Tags.of(my_construct).add("key", "value", priority=300)</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">Tags.of(myConstruct).add("key", "value", TagProps.builder() - .priority(300).build());</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">Tags.Of(myConstruct).Add("key", "value", new TagProps { Priority = 300 });</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">awscdk.Tags_Of(myConstruct).Add(jsii.String("key"), jsii.String("value"), &awscdk.TagProps{ - Priority: jsii.Number(300), -})</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="tagging-props">2.18.3. Optional properties</h4> -<div class="paragraph"> -<p>Tags support <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.TagProps.html">properties</a> that fine-tune how tags are applied to, or removed from, resources. All properties are optional.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1"><code>applyToLaunchedInstances</code> (Python: <code>apply_to_launched_instances</code>)</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Available for add() only. By default, tags are applied to instances launched in an Auto Scaling group. Set this property to <strong>false</strong> to ignore instances launched in an Auto Scaling group.</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1"><code>includeResourceTypes</code>/<code>excludeResourceTypes</code> (Python: <code>include_resource_types</code>/<code>exclude_resource_types</code>)</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Use these to manipulate tags only on a subset of resources, based on AWS CloudFormation resource types. By default, the operation is applied to all resources in the construct subtree, but this can be changed by including or excluding certain resource types. Exclude takes precedence over include, if both are specified.</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1"><code>priority</code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Use this to set the priority of this operation with respect to other <code>Tags.add()</code> and <code>Tags.remove()</code> operations. Higher values take precedence over lower values. The default is 100 for add operations (50 for tags applied directly to AWS CloudFormation resources) and 200 for remove operations.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div class="paragraph"> -<p>The following example applies the tag <strong>tagname</strong> with the value <strong>value</strong> and priority <strong>100</strong> to resources of type <strong>AWS::Xxx::Yyy</strong> in the construct. It doesn’t apply the tag to instances launched in an Amazon EC2 Auto Scaling group or to resources of type <strong>AWS::Xxx::Zzz</strong>. (These are placeholders for two arbitrary but different AWS CloudFormation resource types.)</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">Tags.of(myConstruct).add('tagname', 'value', { - applyToLaunchedInstances: false, - includeResourceTypes: ['AWS::Xxx::Yyy'], - excludeResourceTypes: ['AWS::Xxx::Zzz'], - priority: 100, -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">Tags.of(myConstruct).add('tagname', 'value', { - applyToLaunchedInstances: false, - includeResourceTypes: ['AWS::Xxx::Yyy'], - excludeResourceTypes: ['AWS::Xxx::Zzz'], - priority: 100 -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">Tags.of(my_construct).add("tagname", "value", - apply_to_launched_instances=False, - include_resource_types=["AWS::Xxx::Yyy"], - exclude_resource_types=["AWS::Xxx::Zzz"], - priority=100)</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">Tags.of(myConstruct).add("tagname", "value", TagProps.builder() - .applyToLaunchedInstances(false) - .includeResourceTypes(Arrays.asList("AWS::Xxx::Yyy")) - .excludeResourceTypes(Arrays.asList("AWS::Xxx::Zzz")) - .priority(100).build());</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">Tags.Of(myConstruct).Add("tagname", "value", new TagProps -{ - ApplyToLaunchedInstances = false, - IncludeResourceTypes = ["AWS::Xxx::Yyy"], - ExcludeResourceTypes = ["AWS::Xxx::Zzz"], - Priority = 100 -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">awscdk.Tags_Of(myConstruct).Add(jsii.String("tagname"), jsii.String("value"), &awscdk.TagProps{ - ApplyToLaunchedInstances: jsii.Bool(false), - IncludeResourceTypes: &[]*string{jsii.String("AWS::Xxx:Yyy")}, - ExcludeResourceTypes: &[]*string{jsii.String("AWS::Xxx:Zzz")}, - Priority: jsii.Number(100), -})</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The following example removes the tag <strong>tagname</strong> with priority <strong>200</strong> from resources of type <strong>AWS::Xxx::Yyy</strong> in the construct, but not from resources of type <strong>AWS::Xxx::Zzz</strong>.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">Tags.of(myConstruct).remove('tagname', { - includeResourceTypes: ['AWS::Xxx::Yyy'], - excludeResourceTypes: ['AWS::Xxx::Zzz'], - priority: 200, -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">Tags.of(myConstruct).remove('tagname', { - includeResourceTypes: ['AWS::Xxx::Yyy'], - excludeResourceTypes: ['AWS::Xxx::Zzz'], - priority: 200 -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">Tags.of(my_construct).remove("tagname", - include_resource_types=["AWS::Xxx::Yyy"], - exclude_resource_types=["AWS::Xxx::Zzz"], - priority=200,)</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">Tags.of((myConstruct).remove("tagname", TagProps.builder() - .includeResourceTypes(Arrays.asList("AWS::Xxx::Yyy")) - .excludeResourceTypes(Arrays.asList("AWS::Xxx::Zzz")) - .priority(100).build());</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">Tags.Of(myConstruct).Remove("tagname", new TagProps -{ - IncludeResourceTypes = ["AWS::Xxx::Yyy"], - ExcludeResourceTypes = ["AWS::Xxx::Zzz"], - Priority = 100 -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">awscdk.Tags_Of(myConstruct).Remove(jsii.String("tagname"), &awscdk.TagProps{ - IncludeResourceTypes: &[]*string{jsii.String("AWS::Xxx:Yyy")}, - ExcludeResourceTypes: &[]*string{jsii.String("AWS::Xxx:Zzz")}, - Priority: jsii.Number(200), -})</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="tagging-example">2.18.4. Example</h4> -<div class="paragraph"> -<p>The following example adds the tag key <strong>StackType</strong> with value <strong>TheBest</strong> to any resource created within the <code>Stack</code> named <code>MarketingSystem</code>. Then it removes it again from all resources except Amazon EC2 VPC subnets. The result is that only the subnets have the tag applied.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import { App, Stack, Tags } from 'aws-cdk-lib'; - -const app = new App(); -const theBestStack = new Stack(app, 'MarketingSystem'); - -// Add a tag to all constructs in the stack -Tags.of(theBestStack).add('StackType', 'TheBest'); - -// Remove the tag from all resources except subnet resources -Tags.of(theBestStack).remove('StackType', { - excludeResourceTypes: ['AWS::EC2::Subnet'] -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const { App, Stack, Tags } = require('aws-cdk-lib'); - -const app = new App(); -const theBestStack = new Stack(app, 'MarketingSystem'); - -// Add a tag to all constructs in the stack -Tags.of(theBestStack).add('StackType', 'TheBest'); - -// Remove the tag from all resources except subnet resources -Tags.of(theBestStack).remove('StackType', { - excludeResourceTypes: ['AWS::EC2::Subnet'] -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">from aws_cdk import App, Stack, Tags - -app = App(); -the_best_stack = Stack(app, 'MarketingSystem') - -# Add a tag to all constructs in the stack -Tags.of(the_best_stack).add("StackType", "TheBest") - -# Remove the tag from all resources except subnet resources -Tags.of(the_best_stack).remove("StackType", - exclude_resource_types=["AWS::EC2::Subnet"])</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">import software.amazon.awscdk.App; -import software.amazon.awscdk.Tags; - -// Add a tag to all constructs in the stack -Tags.of(theBestStack).add("StackType", "TheBest"); - -// Remove the tag from all resources except subnet resources -Tags.of(theBestStack).remove("StackType", TagProps.builder() - .excludeResourceTypes(Arrays.asList("AWS::EC2::Subnet")) - .build());</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; - -var app = new App(); -var theBestStack = new Stack(app, 'MarketingSystem'); - -// Add a tag to all constructs in the stack -Tags.Of(theBestStack).Add("StackType", "TheBest"); - -// Remove the tag from all resources except subnet resources -Tags.Of(theBestStack).Remove("StackType", new TagProps -{ - ExcludeResourceTypes = ["AWS::EC2::Subnet"] -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">import "github.com/aws/aws-cdk-go/awscdk/v2" -app := awscdk.NewApp(nil) -theBestStack := awscdk.NewStack(app, jsii.String("MarketingSystem"), &awscdk.StackProps{}) - -// Add a tag to all constructs in the stack -awscdk.Tags_Of(theBestStack).Add(jsii.String("StackType"), jsii.String("TheBest"), &awscdk.TagProps{}) - -// Remove the tag from all resources except subnet resources -awscdk.Tags_Of(theBestStack).Add(jsii.String("StackType"), jsii.String("TheBest"), &awscdk.TagProps{ - ExcludeResourceTypes: &[]*string{jsii.String("AWS::EC2::Subnet")}, -})</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The following code achieves the same result. Consider which approach (inclusion or exclusion) makes your intent clearer.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">Tags.of(theBestStack).add('StackType', 'TheBest', - { includeResourceTypes: ['AWS::EC2::Subnet']});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">Tags.of(theBestStack).add('StackType', 'TheBest', - { includeResourceTypes: ['AWS::EC2::Subnet']});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">Tags.of(the_best_stack).add("StackType", "TheBest", - include_resource_types=["AWS::EC2::Subnet"])</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">Tags.of(theBestStack).add("StackType", "TheBest", TagProps.builder() - .includeResourceTypes(Arrays.asList("AWS::EC2::Subnet")) - .build());</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">Tags.Of(theBestStack).Add("StackType", "TheBest", new TagProps { - IncludeResourceTypes = ["AWS::EC2::Subnet"] -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">awscdk.Tags_Of(theBestStack).Add(jsii.String("StackType"), jsii.String("TheBest"), &awscdk.TagProps{ - IncludeResourceTypes: &[]*string{jsii.String("AWS::EC2::Subnet")}, -})</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="tagging-single">2.18.5. Tagging single constructs</h4> -<div class="paragraph"> -<p><code>Tags.of(scope).add(key, value)</code> is the standard way to add tags to constructs in the AWS CDK. Its tree-walking behavior, which recursively tags all taggable resources under the given scope, is almost always what you want. Sometimes, however, you need to tag a specific, arbitrary construct (or constructs).</p> -</div> -<div class="paragraph"> -<p>One such case involves applying tags whose value is derived from some property of the construct being tagged. The standard tagging approach recursively applies the same key and value to all matching resources in the scope. However, here the value could be different for each tagged construct.</p> -</div> -<div class="paragraph"> -<p>Tags are implemented using <a href="#aspects">aspects</a>, and the CDK calls the tag’s <code>visit()</code> method for each construct under the scope you specified using <code>Tags.of(scope)</code>. We can call <code>Tag.visit()</code> directly to apply a tag to a single construct.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">new cdk.Tag(key, value).visit(scope);</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">new cdk.Tag(key, value).visit(scope);</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">cdk.Tag(key, value).visit(scope)</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">Tag.Builder.create(key, value).build().visit(scope);</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">new Tag(key, value).Visit(scope);</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">awscdk.NewTag(key, value, &awscdk.TagProps{}).Visit(scope)</code></pre> -</div> -</div> -<div class="paragraph"> -<p>You can tag all constructs under a scope but let the values of the tags derive from properties of each construct. To do so, write an aspect and apply the tag in the aspect’s <code>visit()</code> method as shown in the preceding example. Then, add the aspect to the desired scope using <code>Aspects.of(scope).add(aspect)</code>.</p> -</div> -<div class="paragraph"> -<p>The following example applies a tag to each resource in a stack containing the resource’s path.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">class PathTagger implements cdk.IAspect { - visit(node: IConstruct) { - new cdk.Tag("aws-cdk-path", node.node.path).visit(node); - } -} - -stack = new MyStack(app); -cdk.Aspects.of(stack).add(new PathTagger())</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">class PathTagger { - visit(node) { - new cdk.Tag("aws-cdk-path", node.node.path).visit(node); - } -} - -stack = new MyStack(app); -cdk.Aspects.of(stack).add(new PathTagger())</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">@jsii.implements(cdk.IAspect) -class PathTagger: - def visit(self, node: IConstruct): - cdk.Tag("aws-cdk-path", node.node.path).visit(node) - -stack = MyStack(app) -cdk.Aspects.of(stack).add(PathTagger())</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">final class PathTagger implements IAspect { - public void visit(IConstruct node) { - Tag.Builder.create("aws-cdk-path", node.getNode().getPath()).build().visit(node); - } -} - -stack stack = new MyStack(app); -Aspects.of(stack).add(new PathTagger());</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">public class PathTagger : IAspect -{ - public void Visit(IConstruct node) - { - new Tag("aws-cdk-path", node.Node.Path).Visit(node); - } -} - -var stack = new MyStack(app); -Aspects.Of(stack).Add(new PathTagger);</code></pre> -</div> -</div> -<div class="admonitionblock tip"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-tip" title="Tip"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>The logic of conditional tagging, including priorities, resource types, and so on, is built into the <code>Tag</code> class. You can use these features when applying tags to arbitrary resources; the tag is not applied if the conditions aren’t met. Also, the <code>Tag</code> class only tags taggable resources, so you don’t need to test whether a construct is taggable before applying a tag.</p> -</div> -</td> -</tr> -</table> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="assets">2.19. Assets and the AWS CDK</h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Assets are local files, directories, or Docker images.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>Assets are local files, directories, or Docker images that can be bundled into AWS CDK libraries and apps. For example, an asset might be a directory that contains the handler code for an AWS Lambda function. Assets can represent any artifact that the app needs to operate.</p> -</div> -<div class="paragraph"> -<p>The following tutorial video provides a comprehensive overview of CDK assets, and explains how you can use them in your insfrastructure as code (IaC).</p> -</div> -<div class="videoblock text-center"> -<div class="content"> -<iframe width="480" height="390" src="https://www.youtube.com/embed/jHNtXQmkKfw?rel=0" frameborder="0" allowfullscreen></iframe> -</div> -</div> -<div class="paragraph"> -<p>You add assets through APIs that are exposed by specific AWS constructs. For example, when you define a <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.Function.html">lambda.Function</a> construct, the <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.Function.html#code">code</a> property lets you pass an <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.Code.html#static-fromwbrassetpath-options">asset</a> (directory). <code>Function</code> uses assets to bundle the contents of the directory and use it for the function’s code. Similarly, <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs.ContainerImage.html#static-fromwbrassetdirectory-props">ecs.ContainerImage.fromAsset</a> uses a Docker image built from a local directory when defining an Amazon ECS task definition.</p> -</div> -<div class="sect3"> -<h4 id="assets-details">2.19.1. Assets in detail</h4> -<div class="paragraph"> -<p>When you refer to an asset in your app, the <a href="#deploy-how-synth-assemblies">cloud assembly</a> that’s synthesized from your application includes metadata information with instructions for the AWS CDK CLI. The instructions include where to find the asset on the local disk and what type of bundling to perform based on the asset type, such as a directory to compress (zip) or a Docker image to build.</p> -</div> -<div class="paragraph"> -<p>The AWS CDK generates a source hash for assets. This can be used at construction time to determine whether the contents of an asset have changed.</p> -</div> -<div class="paragraph"> -<p>By default, the AWS CDK creates a copy of the asset in the cloud assembly directory, which defaults to <code class="path">cdk.out</code>, under the source hash. This way, the cloud assembly is self-contained, so if it moved over to a different host for deployment, it can still be deployed. See <a href="#deploy-how-synth-assemblies">Cloud assemblies</a> for details.</p> -</div> -<div class="paragraph"> -<p>When the AWS CDK deploys an app that references assets (either directly by the app code or through a library), the AWS CDK CLI first prepares and publishes the assets to an Amazon S3 bucket or Amazon ECR repository. (The S3 bucket or repository is created during bootstrapping.) Only then are the resources defined in the stack deployed.</p> -</div> -<div class="paragraph"> -<p>This section describes the low-level APIs available in the framework.</p> -</div> -</div> -<div class="sect3"> -<h4 id="assets-types">2.19.2. Asset types</h4> -<div class="paragraph"> -<p>The AWS CDK supports the following types of assets:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Amazon S3 assets</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>These are local files and directories that the AWS CDK uploads to Amazon S3.</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Docker Image</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>These are Docker images that the AWS CDK uploads to Amazon ECR.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div class="paragraph"> -<p>These asset types are explained in the following sections.</p> -</div> -</div> -<div class="sect3"> -<h4 id="assets-types-s3">2.19.3. Amazon S3 assets</h4> -<div class="paragraph"> -<p>You can define local files and directories as assets, and the AWS CDK packages and uploads them to Amazon S3 through the <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3_assets-readme.html">aws-s3-assets</a> module.</p> -</div> -<div class="paragraph"> -<p>The following example defines a local directory asset and a file asset.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import { Asset } from 'aws-cdk-lib/aws-s3-assets'; - -// Archived and uploaded to Amazon S3 as a .zip file -const directoryAsset = new Asset(this, "SampleZippedDirAsset", { - path: path.join(__dirname, "sample-asset-directory") -}); - -// Uploaded to Amazon S3 as-is -const fileAsset = new Asset(this, 'SampleSingleFileAsset', { - path: path.join(__dirname, 'file-asset.txt') -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const { Asset } = require('aws-cdk-lib/aws-s3-assets'); - -// Archived and uploaded to Amazon S3 as a .zip file -const directoryAsset = new Asset(this, "SampleZippedDirAsset", { - path: path.join(__dirname, "sample-asset-directory") -}); - -// Uploaded to Amazon S3 as-is -const fileAsset = new Asset(this, 'SampleSingleFileAsset', { - path: path.join(__dirname, 'file-asset.txt') -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">import os.path -dirname = os.path.dirname(__file__) - -from aws_cdk.aws_s3_assets import Asset - -# Archived and uploaded to Amazon S3 as a .zip file -directory_asset = Asset(self, "SampleZippedDirAsset", - path=os.path.join(dirname, "sample-asset-directory") -) - -# Uploaded to Amazon S3 as-is -file_asset = Asset(self, 'SampleSingleFileAsset', - path=os.path.join(dirname, 'file-asset.txt') -)</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">import java.io.File; - -import software.amazon.awscdk.services.s3.assets.Asset; - -// Directory where app was started -File startDir = new File(System.getProperty("user.dir")); - -// Archived and uploaded to Amazon S3 as a .zip file -Asset directoryAsset = Asset.Builder.create(this, "SampleZippedDirAsset") - .path(new File(startDir, "sample-asset-directory").toString()).build(); - -// Uploaded to Amazon S3 as-is -Asset fileAsset = Asset.Builder.create(this, "SampleSingleFileAsset") - .path(new File(startDir, "file-asset.txt").toString()).build();</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using System.IO; -using Amazon.CDK.AWS.S3.Assets; - -// Archived and uploaded to Amazon S3 as a .zip file -var directoryAsset = new Asset(this, "SampleZippedDirAsset", new AssetProps -{ - Path = Path.Combine(Directory.GetCurrentDirectory(), "sample-asset-directory") -}); - -// Uploaded to Amazon S3 as-is -var fileAsset = new Asset(this, "SampleSingleFileAsset", new AssetProps -{ - Path = Path.Combine(Directory.GetCurrentDirectory(), "file-asset.txt") -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">dirName, err := os.Getwd() -if err != nil { - panic(err) -} - -awss3assets.NewAsset(stack, jsii.String("SampleZippedDirAsset"), &awss3assets.AssetProps{ - Path: jsii.String(path.Join(dirName, "sample-asset-directory")), -}) - -awss3assets.NewAsset(stack, jsii.String("SampleSingleFileAsset"), &awss3assets.AssetProps{ - Path: jsii.String(path.Join(dirName, "file-asset.txt")), -})</code></pre> -</div> -</div> -<div class="paragraph"> -<p>In most cases, you don’t need to directly use the APIs in the <code>aws-s3-assets</code> module. Modules that support assets, such as <code>aws-lambda</code>, have convenience methods so that you can use assets. For Lambda functions, the <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.Code.html#static-fromwbrassetpath-options">fromAsset()</a> static method enables you to specify a directory or a .zip file in the local file system.</p> -</div> -<div class="sect4"> -<h5 id="assets-types-s3-lambda">Lambda function example</h5> -<div class="paragraph"> -<p>A common use case is creating Lambda functions with the handler code as an Amazon S3 asset.</p> -</div> -<div class="paragraph"> -<p>The following example uses an Amazon S3 asset to define a Python handler in the local directory <code class="path">handler</code>. It also creates a Lambda function with the local directory asset as the <code>code</code> property. Following is the Python code for the handler.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">def lambda_handler(event, context): - message = 'Hello World!' - return { - 'message': message - }</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The code for the main AWS CDK app should look like the following.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as cdk from 'aws-cdk-lib'; -import { Constructs } from 'constructs'; -import * as lambda from 'aws-cdk-lib/aws-lambda'; -import * as path from 'path'; - -export class HelloAssetStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - new lambda.Function(this, 'myLambdaFunction', { - code: lambda.Code.fromAsset(path.join(__dirname, 'handler')), - runtime: lambda.Runtime.PYTHON_3_6, - handler: 'index.lambda_handler' - }); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const cdk = require('aws-cdk-lib'); -const lambda = require('aws-cdk-lib/aws-lambda'); -const path = require('path'); - -class HelloAssetStack extends cdk.Stack { - constructor(scope, id, props) { - super(scope, id, props); - - new lambda.Function(this, 'myLambdaFunction', { - code: lambda.Code.fromAsset(path.join(__dirname, 'handler')), - runtime: lambda.Runtime.PYTHON_3_6, - handler: 'index.lambda_handler' - }); - } -} - -module.exports = { HelloAssetStack }</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">from aws_cdk import Stack -from constructs import Construct -from aws_cdk import aws_lambda as lambda_ - -import os.path -dirname = os.path.dirname(__file__) - -class HelloAssetStack(Stack): - def __init__(self, scope: Construct, id: str, **kwargs): - super().__init__(scope, id, **kwargs) - - lambda_.Function(self, 'myLambdaFunction', - code=lambda_.Code.from_asset(os.path.join(dirname, 'handler')), - runtime=lambda_.Runtime.PYTHON_3_6, - handler="index.lambda_handler")</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">import java.io.File; - -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.StackProps; -import software.amazon.awscdk.services.lambda.Function; -import software.amazon.awscdk.services.lambda.Runtime; - -public class HelloAssetStack extends Stack { - - public HelloAssetStack(final App scope, final String id) { - this(scope, id, null); - } - - public HelloAssetStack(final App scope, final String id, final StackProps props) { - super(scope, id, props); - - File startDir = new File(System.getProperty("user.dir")); - - Function.Builder.create(this, "myLambdaFunction") - .code(Code.fromAsset(new File(startDir, "handler").toString())) - .runtime(Runtime.PYTHON_3_6) - .handler("index.lambda_handler").build(); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; -using Amazon.CDK.AWS.Lambda; -using System.IO; - -public class HelloAssetStack : Stack -{ - public HelloAssetStack(Construct scope, string id, StackProps props) : base(scope, id, props) - { - new Function(this, "myLambdaFunction", new FunctionProps - { - Code = Code.FromAsset(Path.Combine(Directory.GetCurrentDirectory(), "handler")), - Runtime = Runtime.PYTHON_3_6, - Handler = "index.lambda_handler" - }); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">import ( - "os" - "path" - - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/aws-cdk-go/awscdk/v2/awslambda" - "github.com/aws/aws-cdk-go/awscdk/v2/awss3assets" - "github.com/aws/constructs-go/constructs/v10" - "github.com/aws/jsii-runtime-go" -) - -func HelloAssetStack(scope constructs.Construct, id string, props *HelloAssetStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - stack := awscdk.NewStack(scope, &id, &sprops) - - dirName, err := os.Getwd() - if err != nil { - panic(err) - } - - awslambda.NewFunction(stack, jsii.String("myLambdaFunction"), &awslambda.FunctionProps{ - Code: awslambda.AssetCode_FromAsset(jsii.String(path.Join(dirName, "handler")), &awss3assets.AssetOptions{}), - Runtime: awslambda.Runtime_PYTHON_3_6(), - Handler: jsii.String("index.lambda_handler"), - }) - - return stack -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The <code>Function</code> method uses assets to bundle the contents of the directory and use it for the function’s code.</p> -</div> -<div class="admonitionblock tip"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-tip" title="Tip"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>Java <code class="path">.jar</code> files are ZIP files with a different extension. These are uploaded as-is to Amazon S3, but when deployed as a Lambda function, the files they contain are extracted, which you might not want. To avoid this, place the <code class="path">.jar</code> file in a directory and specify that directory as the asset.</p> -</div> -</td> -</tr> -</table> -</div> -</div> -<div class="sect4"> -<h5 id="assets-types-s3-deploy">Deploy-time attributes example</h5> -<div class="paragraph"> -<p>Amazon S3 asset types also expose <a href="#resources-attributes">deploy-time attributes</a> that can be referenced in AWS CDK libraries and apps. The AWS CDK CLI command <strong class="command">cdk synth</strong> displays asset properties as AWS CloudFormation parameters.</p> -</div> -<div class="paragraph"> -<p>The following example uses deploy-time attributes to pass the location of an image asset into a Lambda function as environment variables. (The kind of file doesn’t matter; the PNG image used here is only an example.)</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import { Asset } from 'aws-cdk-lib/aws-s3-assets'; -import * as path from 'path'; - -const imageAsset = new Asset(this, "SampleAsset", { - path: path.join(__dirname, "images/my-image.png") -}); - -new lambda.Function(this, "myLambdaFunction", { - code: lambda.Code.asset(path.join(__dirname, "handler")), - runtime: lambda.Runtime.PYTHON_3_6, - handler: "index.lambda_handler", - environment: { - 'S3_BUCKET_NAME': imageAsset.s3BucketName, - 'S3_OBJECT_KEY': imageAsset.s3ObjectKey, - 'S3_OBJECT_URL': imageAsset.s3ObjectUrl - } -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const { Asset } = require('aws-cdk-lib/aws-s3-assets'); -const path = require('path'); - -const imageAsset = new Asset(this, "SampleAsset", { - path: path.join(__dirname, "images/my-image.png") -}); - -new lambda.Function(this, "myLambdaFunction", { - code: lambda.Code.asset(path.join(__dirname, "handler")), - runtime: lambda.Runtime.PYTHON_3_6, - handler: "index.lambda_handler", - environment: { - 'S3_BUCKET_NAME': imageAsset.s3BucketName, - 'S3_OBJECT_KEY': imageAsset.s3ObjectKey, - 'S3_OBJECT_URL': imageAsset.s3ObjectUrl - } -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">import os.path - -import aws_cdk.aws_lambda as lambda_ -from aws_cdk.aws_s3_assets import Asset - -dirname = os.path.dirname(__file__) - -image_asset = Asset(self, "SampleAsset", - path=os.path.join(dirname, "images/my-image.png")) - -lambda_.Function(self, "myLambdaFunction", - code=lambda_.Code.asset(os.path.join(dirname, "handler")), - runtime=lambda_.Runtime.PYTHON_3_6, - handler="index.lambda_handler", - environment=dict( - S3_BUCKET_NAME=image_asset.s3_bucket_name, - S3_OBJECT_KEY=image_asset.s3_object_key, - S3_OBJECT_URL=image_asset.s3_object_url))</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">import java.io.File; - -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.StackProps; -import software.amazon.awscdk.services.lambda.Function; -import software.amazon.awscdk.services.lambda.Runtime; -import software.amazon.awscdk.services.s3.assets.Asset; - -public class FunctionStack extends Stack { - public FunctionStack(final App scope, final String id, final StackProps props) { - super(scope, id, props); - - File startDir = new File(System.getProperty("user.dir")); - - Asset imageAsset = Asset.Builder.create(this, "SampleAsset") - .path(new File(startDir, "images/my-image.png").toString()).build()) - - Function.Builder.create(this, "myLambdaFunction") - .code(Code.fromAsset(new File(startDir, "handler").toString())) - .runtime(Runtime.PYTHON_3_6) - .handler("index.lambda_handler") - .environment(java.util.Map.of( // Java 9 or later - "S3_BUCKET_NAME", imageAsset.getS3BucketName(), - "S3_OBJECT_KEY", imageAsset.getS3ObjectKey(), - "S3_OBJECT_URL", imageAsset.getS3ObjectUrl())) - .build(); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; -using Amazon.CDK.AWS.Lambda; -using Amazon.CDK.AWS.S3.Assets; -using System.IO; -using System.Collections.Generic; - -var imageAsset = new Asset(this, "SampleAsset", new AssetProps -{ - Path = Path.Combine(Directory.GetCurrentDirectory(), @"images\my-image.png") -}); - -new Function(this, "myLambdaFunction", new FunctionProps -{ - Code = Code.FromAsset(Path.Combine(Directory.GetCurrentDirectory(), "handler")), - Runtime = Runtime.PYTHON_3_6, - Handler = "index.lambda_handler", - Environment = new Dictionary<string, string> - { - ["S3_BUCKET_NAME"] = imageAsset.S3BucketName, - ["S3_OBJECT_KEY"] = imageAsset.S3ObjectKey, - ["S3_OBJECT_URL"] = imageAsset.S3ObjectUrl - } -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">import ( - "os" - "path" - - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/aws-cdk-go/awscdk/v2/awslambda" - "github.com/aws/aws-cdk-go/awscdk/v2/awss3assets" -) - -dirName, err := os.Getwd() -if err != nil { - panic(err) -} - -imageAsset := awss3assets.NewAsset(stack, jsii.String("SampleAsset"), &awss3assets.AssetProps{ - Path: jsii.String(path.Join(dirName, "images/my-image.png")), -}) - -awslambda.NewFunction(stack, jsii.String("myLambdaFunction"), &awslambda.FunctionProps{ - Code: awslambda.AssetCode_FromAsset(jsii.String(path.Join(dirName, "handler"))), - Runtime: awslambda.Runtime_PYTHON_3_6(), - Handler: jsii.String("index.lambda_handler"), - Environment: &map[string]*string{ - "S3_BUCKET_NAME": imageAsset.S3BucketName(), - "S3_OBJECT_KEY": imageAsset.S3ObjectKey(), - "S3_URL": imageAsset.S3ObjectUrl(), - }, -})</code></pre> -</div> -</div> -</div> -<div class="sect4"> -<h5 id="assets-types-s3-permissions">Permissions</h5> -<div class="paragraph"> -<p>If you use Amazon S3 assets directly through the <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3_assets-readme.html">aws-s3-assets</a> module, IAM roles, users, or groups, and you need to read assets in runtime, then grant those assets IAM permissions through the <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3_assets.Asset.html#grantwbrreadgrantee">asset.grantRead</a> method.</p> -</div> -<div class="paragraph"> -<p>The following example grants an IAM group read permissions on a file asset.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import { Asset } from 'aws-cdk-lib/aws-s3-assets'; -import * as path from 'path'; - -const asset = new Asset(this, 'MyFile', { - path: path.join(__dirname, 'my-image.png') -}); - -const group = new iam.Group(this, 'MyUserGroup'); -asset.grantRead(group);</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const { Asset } = require('aws-cdk-lib/aws-s3-assets'); -const path = require('path'); - -const asset = new Asset(this, 'MyFile', { - path: path.join(__dirname, 'my-image.png') -}); - -const group = new iam.Group(this, 'MyUserGroup'); -asset.grantRead(group);</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">from aws_cdk.aws_s3_assets import Asset -import aws_cdk.aws_iam as iam - -import os.path -dirname = os.path.dirname(__file__) - - asset = Asset(self, "MyFile", - path=os.path.join(dirname, "my-image.png")) - - group = iam.Group(self, "MyUserGroup") - asset.grant_read(group)</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">import java.io.File; - -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.StackProps; -import software.amazon.awscdk.services.iam.Group; -import software.amazon.awscdk.services.s3.assets.Asset; - -public class GrantStack extends Stack { - public GrantStack(final App scope, final String id, final StackProps props) { - super(scope, id, props); - - File startDir = new File(System.getProperty("user.dir")); - - Asset asset = Asset.Builder.create(this, "SampleAsset") - .path(new File(startDir, "images/my-image.png").toString()).build(); - - Group group = new Group(this, "MyUserGroup"); - asset.grantRead(group); } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; -using Amazon.CDK.AWS.IAM; -using Amazon.CDK.AWS.S3.Assets; -using System.IO; - -var asset = new Asset(this, "MyFile", new AssetProps { - Path = Path.Combine(Path.Combine(Directory.GetCurrentDirectory(), @"images\my-image.png")) -}); - -var group = new Group(this, "MyUserGroup"); -asset.GrantRead(group);</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">import ( - "os" - "path" - - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/aws-cdk-go/awscdk/v2/awsiam" - "github.com/aws/aws-cdk-go/awscdk/v2/awss3assets" -) - -dirName, err := os.Getwd() -if err != nil { - panic(err) -} - -asset := awss3assets.NewAsset(stack, jsii.String("MyFile"), &awss3assets.AssetProps{ - Path: jsii.String(path.Join(dirName, "my-image.png")), -}) - -group := awsiam.NewGroup(stack, jsii.String("MyUserGroup"), &awsiam.GroupProps{}) - -asset.GrantRead(group)</code></pre> -</div> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="assets-types-docker">2.19.4. Docker image assets</h4> -<div class="paragraph"> -<p>The AWS CDK supports bundling local Docker images as assets through the <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecr_assets-readme.html">aws-ecr-assets</a> module.</p> -</div> -<div class="paragraph"> -<p>The following example defines a Docker image that is built locally and pushed to Amazon ECR. Images are built from a local Docker context directory (with a Dockerfile) and uploaded to Amazon ECR by the AWS CDK CLI or your app’s CI/CD pipeline. The images can be naturally referenced in your AWS CDK app.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import { DockerImageAsset } from 'aws-cdk-lib/aws-ecr-assets'; - -const asset = new DockerImageAsset(this, 'MyBuildImage', { - directory: path.join(__dirname, 'my-image') -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const { DockerImageAsset } = require('aws-cdk-lib/aws-ecr-assets'); - -const asset = new DockerImageAsset(this, 'MyBuildImage', { - directory: path.join(__dirname, 'my-image') -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">from aws_cdk.aws_ecr_assets import DockerImageAsset - -import os.path -dirname = os.path.dirname(__file__) - -asset = DockerImageAsset(self, 'MyBuildImage', - directory=os.path.join(dirname, 'my-image'))</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">import software.amazon.awscdk.services.ecr.assets.DockerImageAsset; - -File startDir = new File(System.getProperty("user.dir")); - -DockerImageAsset asset = DockerImageAsset.Builder.create(this, "MyBuildImage") - .directory(new File(startDir, "my-image").toString()).build();</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using System.IO; -using Amazon.CDK.AWS.ECR.Assets; - -var asset = new DockerImageAsset(this, "MyBuildImage", new DockerImageAssetProps -{ - Directory = Path.Combine(Directory.GetCurrentDirectory(), "my-image") -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">import ( - "os" - "path" - - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/aws-cdk-go/awscdk/v2/awsecrassets" -) - -dirName, err := os.Getwd() -if err != nil { - panic(err) -} - -asset := awsecrassets.NewDockerImageAsset(stack, jsii.String("MyBuildImage"), &awsecrassets.DockerImageAssetProps{ - Directory: jsii.String(path.Join(dirName, "my-image")), -})</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The <code class="path">my-image</code> directory must include a Dockerfile. The AWS CDK CLI builds a Docker image from <code class="path">my-image</code>, pushes it to an Amazon ECR repository, and specifies the name of the repository as an AWS CloudFormation parameter to your stack. Docker image asset types expose <a href="#resources-attributes">deploy-time attributes</a> that can be referenced in AWS CDK libraries and apps. The AWS CDK CLI command <strong class="command">cdk synth</strong> displays asset properties as AWS CloudFormation parameters.</p> -</div> -<div class="sect4"> -<h5 id="assets-types-docker-ecs">Amazon ECS task definition example</h5> -<div class="paragraph"> -<p>A common use case is to create an Amazon ECS <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs.TaskDefinition.html">TaskDefinition</a> to run Docker containers. The following example specifies the location of a Docker image asset that the AWS CDK builds locally and pushes to Amazon ECR.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as ecs from 'aws-cdk-lib/aws-ecs'; -import * as ecr_assets from 'aws-cdk-lib/aws-ecr-assets'; -import * as path from 'path'; - -const taskDefinition = new ecs.FargateTaskDefinition(this, "TaskDef", { - memoryLimitMiB: 1024, - cpu: 512 -}); - -const asset = new ecr_assets.DockerImageAsset(this, 'MyBuildImage', { - directory: path.join(__dirname, 'my-image') -}); - -taskDefinition.addContainer("my-other-container", { - image: ecs.ContainerImage.fromDockerImageAsset(asset) -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const ecs = require('aws-cdk-lib/aws-ecs'); -const ecr_assets = require('aws-cdk-lib/aws-ecr-assets'); -const path = require('path'); - -const taskDefinition = new ecs.FargateTaskDefinition(this, "TaskDef", { - memoryLimitMiB: 1024, - cpu: 512 -}); - -const asset = new ecr_assets.DockerImageAsset(this, 'MyBuildImage', { - directory: path.join(__dirname, 'my-image') -}); - -taskDefinition.addContainer("my-other-container", { - image: ecs.ContainerImage.fromDockerImageAsset(asset) -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">import aws_cdk.aws_ecs as ecs -import aws_cdk.aws_ecr_assets as ecr_assets - -import os.path -dirname = os.path.dirname(__file__) - -task_definition = ecs.FargateTaskDefinition(self, "TaskDef", - memory_limit_mib=1024, - cpu=512) - -asset = ecr_assets.DockerImageAsset(self, 'MyBuildImage', - directory=os.path.join(dirname, 'my-image')) - -task_definition.add_container("my-other-container", - image=ecs.ContainerImage.from_docker_image_asset(asset))</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">import java.io.File; - -import software.amazon.awscdk.services.ecs.FargateTaskDefinition; -import software.amazon.awscdk.services.ecs.ContainerDefinitionOptions; -import software.amazon.awscdk.services.ecs.ContainerImage; - -import software.amazon.awscdk.services.ecr.assets.DockerImageAsset; - -File startDir = new File(System.getProperty("user.dir")); - -FargateTaskDefinition taskDefinition = FargateTaskDefinition.Builder.create( - this, "TaskDef").memoryLimitMiB(1024).cpu(512).build(); - -DockerImageAsset asset = DockerImageAsset.Builder.create(this, "MyBuildImage") - .directory(new File(startDir, "my-image").toString()).build(); - -taskDefinition.addContainer("my-other-container", - ContainerDefinitionOptions.builder() - .image(ContainerImage.fromDockerImageAsset(asset)) - .build();</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using System.IO; -using Amazon.CDK.AWS.ECS; -using Amazon.CDK.AWS.Ecr.Assets; - -var taskDefinition = new FargateTaskDefinition(this, "TaskDef", new FargateTaskDefinitionProps -{ - MemoryLimitMiB = 1024, - Cpu = 512 -}); - -var asset = new DockerImageAsset(this, "MyBuildImage", new DockerImageAssetProps -{ - Directory = Path.Combine(Directory.GetCurrentDirectory(), "my-image") -}); - -taskDefinition.AddContainer("my-other-container", new ContainerDefinitionOptions -{ - Image = ContainerImage.FromDockerImageAsset(asset) -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">import ( - "os" - "path" - - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/aws-cdk-go/awscdk/v2/awsecrassets" - "github.com/aws/aws-cdk-go/awscdk/v2/awsecs" -) - -dirName, err := os.Getwd() -if err != nil { - panic(err) -} - -taskDefinition := awsecs.NewTaskDefinition(stack, jsii.String("TaskDef"), &awsecs.TaskDefinitionProps{ - MemoryMiB: jsii.String("1024"), - Cpu: jsii.String("512"), -}) - -asset := awsecrassets.NewDockerImageAsset(stack, jsii.String("MyBuildImage"), &awsecrassets.DockerImageAssetProps{ - Directory: jsii.String(path.Join(dirName, "my-image")), -}) - -taskDefinition.AddContainer(jsii.String("MyOtherContainer"), &awsecs.ContainerDefinitionOptions{ - Image: awsecs.ContainerImage_FromDockerImageAsset(asset), -})</code></pre> -</div> -</div> -</div> -<div class="sect4"> -<h5 id="assets-types-docker-deploy">Deploy-time attributes example</h5> -<div class="paragraph"> -<p>The following example shows how to use the deploy-time attributes <code>repository</code> and <code>imageUri</code> to create an Amazon ECS task definition with the AWS Fargate launch type. Note that the Amazon ECR repo lookup requires the image’s tag, not its URI, so we snip it from the end of the asset’s URI.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as ecs from 'aws-cdk-lib/aws-ecs'; -import * as path from 'path'; -import { DockerImageAsset } from 'aws-cdk-lib/aws-ecr-assets'; - -const asset = new DockerImageAsset(this, 'my-image', { - directory: path.join(__dirname, "..", "demo-image") -}); - -const taskDefinition = new ecs.FargateTaskDefinition(this, "TaskDef", { - memoryLimitMiB: 1024, - cpu: 512 -}); - -taskDefinition.addContainer("my-other-container", { - image: ecs.ContainerImage.fromEcrRepository(asset.repository, asset.imageUri.split(":").pop()) -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const ecs = require('aws-cdk-lib/aws-ecs'); -const path = require('path'); -const { DockerImageAsset } = require('aws-cdk-lib/aws-ecr-assets'); - -const asset = new DockerImageAsset(this, 'my-image', { - directory: path.join(__dirname, "..", "demo-image") -}); - -const taskDefinition = new ecs.FargateTaskDefinition(this, "TaskDef", { - memoryLimitMiB: 1024, - cpu: 512 -}); - -taskDefinition.addContainer("my-other-container", { - image: ecs.ContainerImage.fromEcrRepository(asset.repository, asset.imageUri.split(":").pop()) -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">import aws_cdk.aws_ecs as ecs -from aws_cdk.aws_ecr_assets import DockerImageAsset - -import os.path -dirname = os.path.dirname(__file__) - -asset = DockerImageAsset(self, 'my-image', - directory=os.path.join(dirname, "..", "demo-image")) - -task_definition = ecs.FargateTaskDefinition(self, "TaskDef", - memory_limit_mib=1024, cpu=512) - -task_definition.add_container("my-other-container", - image=ecs.ContainerImage.from_ecr_repository( - asset.repository, asset.image_uri.rpartition(":")[-1]))</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">import java.io.File; - -import software.amazon.awscdk.services.ecr.assets.DockerImageAsset; - -import software.amazon.awscdk.services.ecs.FargateTaskDefinition; -import software.amazon.awscdk.services.ecs.ContainerDefinitionOptions; -import software.amazon.awscdk.services.ecs.ContainerImage; - -File startDir = new File(System.getProperty("user.dir")); - -DockerImageAsset asset = DockerImageAsset.Builder.create(this, "my-image") - .directory(new File(startDir, "demo-image").toString()).build(); - -FargateTaskDefinition taskDefinition = FargateTaskDefinition.Builder.create( - this, "TaskDef").memoryLimitMiB(1024).cpu(512).build(); - -// extract the tag from the asset's image URI for use in ECR repo lookup -String imageUri = asset.getImageUri(); -String imageTag = imageUri.substring(imageUri.lastIndexOf(":") + 1); - -taskDefinition.addContainer("my-other-container", - ContainerDefinitionOptions.builder().image(ContainerImage.fromEcrRepository( - asset.getRepository(), imageTag)).build());</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using System.IO; -using Amazon.CDK.AWS.ECS; -using Amazon.CDK.AWS.ECR.Assets; - -var asset = new DockerImageAsset(this, "my-image", new DockerImageAssetProps { - Directory = Path.Combine(Directory.GetCurrentDirectory(), "demo-image") -}); - -var taskDefinition = new FargateTaskDefinition(this, "TaskDef", new FargateTaskDefinitionProps -{ - MemoryLimitMiB = 1024, - Cpu = 512 -}); - -taskDefinition.AddContainer("my-other-container", new ContainerDefinitionOptions -{ - Image = ContainerImage.FromEcrRepository(asset.Repository, asset.ImageUri.Split(":").Last()) -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">import ( - "os" - "path" - - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/aws-cdk-go/awscdk/v2/awsecrassets" - "github.com/aws/aws-cdk-go/awscdk/v2/awsecs" -) - -dirName, err := os.Getwd() -if err != nil { - panic(err) -} - -asset := awsecrassets.NewDockerImageAsset(stack, jsii.String("MyImage"), &awsecrassets.DockerImageAssetProps{ - Directory: jsii.String(path.Join(dirName, "demo-image")), -}) - -taskDefinition := awsecs.NewFargateTaskDefinition(stack, jsii.String("TaskDef"), &awsecs.FargateTaskDefinitionProps{ - MemoryLimitMiB: jsii.Number(1024), - Cpu: jsii.Number(512), -}) - -taskDefinition.AddContainer(jsii.String("MyOtherContainer"), &awsecs.ContainerDefinitionOptions{ - Image: awsecs.ContainerImage_FromEcrRepository(asset.Repository(), asset.ImageTag()), -})</code></pre> -</div> -</div> -</div> -<div class="sect4"> -<h5 id="assets-types-docker-build">Build arguments example</h5> -<div class="paragraph"> -<p>You can provide customized build arguments for the Docker build step through the <code>buildArgs</code> (Python: <code>build_args</code>) property option when the AWS CDK CLI builds the image during deployment.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const asset = new DockerImageAsset(this, 'MyBuildImage', { - directory: path.join(__dirname, 'my-image'), - buildArgs: { - HTTP_PROXY: 'http://10.20.30.2:1234' - } -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const asset = new DockerImageAsset(this, 'MyBuildImage', { - directory: path.join(__dirname, 'my-image'), - buildArgs: { - HTTP_PROXY: 'http://10.20.30.2:1234' - } -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">asset = DockerImageAsset(self, "MyBuildImage", - directory=os.path.join(dirname, "my-image"), - build_args=dict(HTTP_PROXY="http://10.20.30.2:1234"))</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">DockerImageAsset asset = DockerImageAsset.Builder.create(this, "my-image"), - .directory(new File(startDir, "my-image").toString()) - .buildArgs(java.util.Map.of( // Java 9 or later - "HTTP_PROXY", "http://10.20.30.2:1234")) - .build();</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">var asset = new DockerImageAsset(this, "MyBuildImage", new DockerImageAssetProps { - Directory = Path.Combine(Directory.GetCurrentDirectory(), "my-image"), - BuildArgs = new Dictionary<string, string> - { - ["HTTP_PROXY"] = "http://10.20.30.2:1234" - } -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">dirName, err := os.Getwd() -if err != nil { - panic(err) -} - -asset := awsecrassets.NewDockerImageAsset(stack, jsii.String("MyBuildImage"), &awsecrassets.DockerImageAssetProps{ - Directory: jsii.String(path.Join(dirName, "my-image")), - BuildArgs: &map[string]*string{ - "HTTP_PROXY": jsii.String("http://10.20.30.2:1234"), - }, -})</code></pre> -</div> -</div> -</div> -<div class="sect4"> -<h5 id="assets-types-docker-permissions">Permissions</h5> -<div class="paragraph"> -<p>If you use a module that supports Docker image assets, such as <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs-readme.html">aws-ecs</a>, the AWS CDK manages permissions for you when you use assets directly or through <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs.ContainerImage.html#static-fromwbrecrwbrrepositoryrepository-tag">ContainerImage.fromEcrRepository</a> (Python: <code>from_ecr_repository</code>). If you use Docker image assets directly, make sure that the consuming principal has permissions to pull the image.</p> -</div> -<div class="paragraph"> -<p>In most cases, you should use <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecr.Repository.html#grantwbrpullgrantee">asset.repository.grantPull</a> method (Python: <code>grant_pull</code>. This modifies the IAM policy of the principal to enable it to pull images from this repository. If the principal that is pulling the image is not in the same account, or if it’s an AWS service that doesn’t assume a role in your account (such as AWS CodeBuild), you must grant pull permissions on the resource policy and not on the principal’s policy. Use the <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecr.Repository.html#addwbrtowbrresourcewbrpolicystatement">asset.repository.addToResourcePolicy</a> method (Python: <code>add_to_resource_policy</code>) to grant the appropriate principal permissions.</p> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="assets-cfn">2.19.5. AWS CloudFormation resource metadata</h4> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>This section is relevant only for construct authors. In certain situations, tools need to know that a certain CFN resource is using a local asset. For example, you can use the AWS SAM CLI to invoke Lambda functions locally for debugging purposes. See <a href="#sam">AWS SAM integration</a> for details.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>To enable such use cases, external tools consult a set of metadata entries on AWS CloudFormation resources:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><code>aws:asset:path</code> – Points to the local path of the asset.</p> -</li> -<li> -<p><code>aws:asset:property</code> – The name of the resource property where the asset is used.</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>Using these two metadata entries, tools can identify that assets are used by a certain resource, and enable advanced local experiences.</p> -</div> -<div class="paragraph"> -<p>To add these metadata entries to a resource, use the <code>asset.addResourceMetadata</code> (Python: <code>add_resource_metadata</code>) method.</p> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="permissions">2.20. Permissions and the AWS CDK</h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>The AWS Construct Library uses a few common, widely implemented idioms to manage access and permissions. The IAM module provides you with the tools you need to use these idioms.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>The AWS Construct Library uses a few common, widely implemented idioms to manage access and permissions. The IAM module provides you with the tools you need to use these idioms.</p> -</div> -<div class="paragraph"> -<p>AWS CDK uses AWS CloudFormation to deploy changes. Every deployment involves an actor (either a developer, or an automated system) that starts a AWS CloudFormation deployment. In the course of doing this, the actor will assume one or more IAM Identities (user or roles) and optionally pass a role to AWS CloudFormation.</p> -</div> -<div class="paragraph"> -<p>If you use AWS IAM Identity Center to authenticate as a user, then the single sign-on provider supplies short-lived session credentials that authorize you to act as a pre-defined IAM role. To learn how the AWS CDK obtains AWS credentials from IAM Identity Center authentication, see <a href="https://docs.aws.amazon.com/sdkref/latest/guide/understanding-sso.html">Understand IAM Identity Center authentication</a> in the <em>AWS SDKs and Tools Reference Guide</em>.</p> -</div> -<div class="sect3"> -<h4 id="permissions-principals">2.20.1. Principals</h4> -<div class="paragraph"> -<p>An IAM principal is an authenticated AWS entity representing a user, service, or application that can call AWS APIs. The AWS Construct Library supports specifying principals in several flexible ways to grant them access your AWS resources.</p> -</div> -<div class="paragraph"> -<p>In security contexts, the term "principal" refers specifically to authenticated entities such as users. Objects like groups and roles do not <em>represent</em> users (and other authenticated entities) but rather <em>identify</em> them indirectly for the purpose of granting permissions.</p> -</div> -<div class="paragraph"> -<p>For example, if you create an IAM group, you can grant the group (and thus its members) write access to an Amazon RDS table. However, the group itself is not a principal because it doesn’t represent a single entity (also, you cannot log in to a group).</p> -</div> -<div class="paragraph"> -<p>In the CDK’s IAM library, classes that directly or indirectly identify principals implement the <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.IPrincipal.html">IPrincipal</a> interface, allowing these objects to be used interchangeably in access policies. However, not all of them are principals in the security sense. These objects include:</p> -</div> -<div class="olist arabic"> -<ol class="arabic"> -<li> -<p>IAM resources such as <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html">Role</a></code>, <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.User.html">User</a></code>, and <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Group.html">Group</a></code></p> -</li> -<li> -<p>Service principals (<code>new iam.https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.ServicePrincipal.html[ServicePrincipal]('service.amazonaws.com')</code>)</p> -</li> -<li> -<p>Federated principals (<code>new iam.https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.FederatedPrincipal.html[FederatedPrincipal]('cognito-identity.amazonaws.com')</code>)</p> -</li> -<li> -<p>Account principals (<code>new iam.https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.AccountPrincipal.html[AccountPrincipal]('0123456789012'))</code></p> -</li> -<li> -<p>Canonical user principals (<code>new iam.https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.CanonicalUserPrincipal.html[CanonicalUserPrincipal]('79a59d[…​]7ef2be')</code>)</p> -</li> -<li> -<p>AWS Organizations principals (<code>new iam.https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.OrganizationPrincipal.html[OrganizationPrincipal]('org-id')</code>)</p> -</li> -<li> -<p>Arbitrary ARN principals (<code>new iam.https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.ArnPrincipal.html[ArnPrincipal](res.arn)</code>)</p> -</li> -<li> -<p>An <code>iam.https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.CompositePrincipal.html[CompositePrincipal](principal1, principal2, …​)</code> to trust multiple principals</p> -</li> -</ol> -</div> -</div> -<div class="sect3"> -<h4 id="permissions-grants">2.20.2. Grants</h4> -<div class="paragraph"> -<p>Every construct that represents a resource that can be accessed, such as an Amazon S3 bucket or Amazon DynamoDB table, has methods that grant access to another entity. All such methods have names starting with <strong>grant</strong>.</p> -</div> -<div class="paragraph"> -<p>For example, Amazon S3 buckets have the methods <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html#grantwbrreadidentity-objectskeypattern">grantRead</a></code> and <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html#grantwbrreadwbrwriteidentity-objectskeypattern">grantReadWrite</a></code> (Python: <code>grant_read</code>, <code>grant_read_write</code>) to enable read and read/write access, respectively, from an entity to the bucket. The entity doesn’t have to know exactly which Amazon S3 IAM permissions are required to perform these operations.</p> -</div> -<div class="paragraph"> -<p>The first argument of a <strong>grant</strong> method is always of type <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.IGrantable.html">IGrantable</a>. This interface represents entities that can be granted permissions. That is, it represents resources with roles, such as the IAM objects <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html">Role</a></code>, <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.User.html">User</a></code>, and <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.User.html">Group</a></code>.</p> -</div> -<div class="paragraph"> -<p>Other entities can also be granted permissions. For example, later in this topic, we show how to grant a CodeBuild project access to an Amazon S3 bucket. Generally, the associated role is obtained via a <code>role</code> property on the entity being granted access.</p> -</div> -<div class="paragraph"> -<p>Resources that use execution roles, such as <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.Function.html">lambda.Function</a></code>, also implement <code>IGrantable</code>, so you can grant them access directly instead of granting access to their role. For example, if <code>bucket</code> is an Amazon S3 bucket, and <code>function</code> is a Lambda function, the following code grants the function read access to the bucket.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">bucket.grantRead(function);</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">bucket.grantRead(function);</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">bucket.grant_read(function)</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">bucket.grantRead(function);</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">bucket.GrantRead(function);</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Sometimes permissions must be applied while your stack is being deployed. One such case is when you grant an AWS CloudFormation custom resource access to some other resource. The custom resource will be invoked during deployment, so it must have the specified permissions at deployment time.</p> -</div> -<div class="paragraph"> -<p>Another case is when a service verifies that the role you pass to it has the right policies applied. (A number of AWS services do this to make sure that you didn’t forget to set the policies.) In those cases, the deployment might fail if the permissions are applied too late.</p> -</div> -<div class="paragraph"> -<p>To force the grant’s permissions to be applied before another resource is created, you can add a dependency on the grant itself, as shown here. Though the return value of grant methods is commonly discarded, every grant method in fact returns an <code>iam.Grant</code> object.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const grant = bucket.grantRead(lambda); -const custom = new CustomResource(...); -custom.node.addDependency(grant);</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const grant = bucket.grantRead(lambda); -const custom = new CustomResource(...); -custom.node.addDependency(grant);</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">grant = bucket.grant_read(function) -custom = CustomResource(...) -custom.node.add_dependency(grant)</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">Grant grant = bucket.grantRead(function); -CustomResource custom = new CustomResource(...); -custom.node.addDependency(grant);</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">var grant = bucket.GrantRead(function); -var custom = new CustomResource(...); -custom.node.AddDependency(grant);</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="permissions-roles">2.20.3. Roles</h4> -<div class="paragraph"> -<p>The IAM package contains a <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html">Role</a></code> construct that represents IAM roles. The following code creates a new role, trusting the Amazon EC2 service.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as iam from 'aws-cdk-lib/aws-iam'; - -const role = new iam.Role(this, 'Role', { - assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com'), // required -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const iam = require('aws-cdk-lib/aws-iam'); - -const role = new iam.Role(this, 'Role', { - assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com') // required -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">import aws_cdk.aws_iam as iam - -role = iam.Role(self, "Role", - assumed_by=iam.ServicePrincipal("ec2.amazonaws.com")) # required</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">import software.amazon.awscdk.services.iam.Role; -import software.amazon.awscdk.services.iam.ServicePrincipal; - -Role role = Role.Builder.create(this, "Role") - .assumedBy(new ServicePrincipal("ec2.amazonaws.com")).build();</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK.AWS.IAM; - -var role = new Role(this, "Role", new RoleProps -{ - AssumedBy = new ServicePrincipal("ec2.amazonaws.com"), // required -});</code></pre> -</div> -</div> -<div class="paragraph"> -<p>You can add permissions to a role by calling the role’s <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html#addwbrtowbrpolicystatement">addToPolicy</a></code> method (Python: <code>add_to_policy</code>), passing in a <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.PolicyStatement.html">PolicyStatement</a></code> that defines the rule to be added. The statement is added to the role’s default policy; if it has none, one is created.</p> -</div> -<div class="paragraph"> -<p>The following example adds a <code>Deny</code> policy statement to the role for the actions <code>ec2:SomeAction</code> and <code>s3:AnotherAction</code> on the resources <code>bucket</code> and <code>otherRole</code> (Python: <code>other_role</code>), under the condition that the authorized service is AWS CodeBuild.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">role.addToPolicy(new iam.PolicyStatement({ - effect: iam.Effect.DENY, - resources: [bucket.bucketArn, otherRole.roleArn], - actions: ['ec2:SomeAction', 's3:AnotherAction'], - conditions: {StringEquals: { - 'ec2:AuthorizedService': 'codebuild.amazonaws.com', -}}}));</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">role.addToPolicy(new iam.PolicyStatement({ - effect: iam.Effect.DENY, - resources: [bucket.bucketArn, otherRole.roleArn], - actions: ['ec2:SomeAction', 's3:AnotherAction'], - conditions: {StringEquals: { - 'ec2:AuthorizedService': 'codebuild.amazonaws.com' -}}}));</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">role.add_to_policy(iam.PolicyStatement( - effect=iam.Effect.DENY, - resources=[bucket.bucket_arn, other_role.role_arn], - actions=["ec2:SomeAction", "s3:AnotherAction"], - conditions={"StringEquals": { - "ec2:AuthorizedService": "codebuild.amazonaws.com"}} -))</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">role.addToPolicy(PolicyStatement.Builder.create() - .effect(Effect.DENY) - .resources(Arrays.asList(bucket.getBucketArn(), otherRole.getRoleArn())) - .actions(Arrays.asList("ec2:SomeAction", "s3:AnotherAction")) - .conditions(java.util.Map.of( // Map.of requires Java 9 or later - "StringEquals", java.util.Map.of( - "ec2:AuthorizedService", "codebuild.amazonaws.com"))) - .build());</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">role.AddToPolicy(new PolicyStatement(new PolicyStatementProps -{ - Effect = Effect.DENY, - Resources = new string[] { bucket.BucketArn, otherRole.RoleArn }, - Actions = new string[] { "ec2:SomeAction", "s3:AnotherAction" }, - Conditions = new Dictionary<string, object> - { - ["StringEquals"] = new Dictionary<string, string> - { - ["ec2:AuthorizedService"] = "codebuild.amazonaws.com" - } - } -}));</code></pre> -</div> -</div> -<div class="paragraph"> -<p>In the preceding example, we’ve created a new <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.PolicyStatement.html">PolicyStatement</a></code> inline with the <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html#addwbrtowbrpolicystatement">addToPolicy</a></code> (Python: <code>add_to_policy</code>) call. You can also pass in an existing policy statement or one you’ve modified. The <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.PolicyStatement.html">PolicyStatement</a> object has <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.PolicyStatement.html#methods">numerous methods</a> for adding principals, resources, conditions, and actions.</p> -</div> -<div class="paragraph"> -<p>If you’re using a construct that requires a role to function correctly, you can do one of the following:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Pass in an existing role when instantiating the construct object.</p> -</li> -<li> -<p>Let the construct create a new role for you, trusting the appropriate service principal. The following example uses such a construct: a CodeBuild project.</p> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -</li> -</ul> -</div> -<div class="listingblock"> -<div class="content"> -<pre>import * as codebuild from 'aws-cdk-lib/aws-codebuild'; - -// imagine roleOrUndefined is a function that might return a Role object -// under some conditions, and undefined under other conditions -const someRole: iam.IRole | undefined = roleOrUndefined(); - -const project = new codebuild.Project(this, 'Project', { - // if someRole is undefined, the Project creates a new default role, - // trusting the codebuild.amazonaws.com service principal - role: someRole, -});</pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const codebuild = require('aws-cdk-lib/aws-codebuild'); - -// imagine roleOrUndefined is a function that might return a Role object -// under some conditions, and undefined under other conditions -const someRole = roleOrUndefined(); - -const project = new codebuild.Project(this, 'Project', { - // if someRole is undefined, the Project creates a new default role, - // trusting the codebuild.amazonaws.com service principal - role: someRole -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">import aws_cdk.aws_codebuild as codebuild - -# imagine role_or_none is a function that might return a Role object -# under some conditions, and None under other conditions -some_role = role_or_none(); - -project = codebuild.Project(self, "Project", -# if role is None, the Project creates a new default role, -# trusting the codebuild.amazonaws.com service principal -role=some_role)</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">import software.amazon.awscdk.services.iam.Role; -import software.amazon.awscdk.services.codebuild.Project; - -// imagine roleOrNull is a function that might return a Role object -// under some conditions, and null under other conditions -Role someRole = roleOrNull(); - -// if someRole is null, the Project creates a new default role, -// trusting the codebuild.amazonaws.com service principal -Project project = Project.Builder.create(this, "Project") - .role(someRole).build();</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK.AWS.CodeBuild; - -// imagine roleOrNull is a function that might return a Role object -// under some conditions, and null under other conditions -var someRole = roleOrNull(); - -// if someRole is null, the Project creates a new default role, -// trusting the codebuild.amazonaws.com service principal -var project = new Project(this, "Project", new ProjectProps -{ - Role = someRole -});</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Once the object is created, the role (whether the role passed in or the default one created by the construct) is available as the property <code>role</code>. However, this property is not available on external resources. Therefore, these constructs have an <code>addToRolePolicy</code> (Python: <code>add_to_role_policy</code>) method.</p> -</div> -<div class="paragraph"> -<p>The method does nothing if the construct is an external resource, and it calls the <code>addToPolicy</code> (Python: <code>add_to_policy</code>) method of the <code>role</code> property otherwise. This saves you the trouble of handling the undefined case explicitly.</p> -</div> -<div class="paragraph"> -<p>The following example demonstrates:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">// project is imported into the CDK application -const project = codebuild.Project.fromProjectName(this, 'Project', 'ProjectName'); - -// project is imported, so project.role is undefined, and this call has no effect -project.addToRolePolicy(new iam.PolicyStatement({ - effect: iam.Effect.ALLOW, // ... and so on defining the policy -}));</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">// project is imported into the CDK application -const project = codebuild.Project.fromProjectName(this, 'Project', 'ProjectName'); - -// project is imported, so project.role is undefined, and this call has no effect -project.addToRolePolicy(new iam.PolicyStatement({ - effect: iam.Effect.ALLOW // ... and so on defining the policy -}));</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python"># project is imported into the CDK application -project = codebuild.Project.from_project_name(self, 'Project', 'ProjectName') - -# project is imported, so project.role is undefined, and this call has no effect -project.add_to_role_policy(iam.PolicyStatement( - effect=iam.Effect.ALLOW, # ... and so on defining the policy -)</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">// project is imported into the CDK application -Project project = Project.fromProjectName(this, "Project", "ProjectName"); - -// project is imported, so project.getRole() is null, and this call has no effect -project.addToRolePolicy(PolicyStatement.Builder.create() - .effect(Effect.ALLOW) // .. and so on defining the policy - .build();</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">// project is imported into the CDK application -var project = Project.FromProjectName(this, "Project", "ProjectName"); - -// project is imported, so project.role is null, and this call has no effect -project.AddToRolePolicy(new PolicyStatement(new PolicyStatementProps -{ - Effect = Effect.ALLOW, // ... and so on defining the policy -}));</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="permissions-resource-policies">2.20.4. Resource policies</h4> -<div class="paragraph"> -<p>A few resources in AWS, such as Amazon S3 buckets and IAM roles, also have a resource policy. These constructs have an <code>addToResourcePolicy</code> method (Python: <code>add_to_resource_policy</code>), which takes a <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.PolicyStatement.html">PolicyStatement</a></code> as its argument. Every policy statement added to a resource policy must specify at least one principal.</p> -</div> -<div class="paragraph"> -<p>In the following example, the <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html" class="bare">https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html</a><code class="Amazon S3 bucket">bucket</code> grants a role with the <code>s3:SomeAction</code> permission to itself.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">bucket.addToResourcePolicy(new iam.PolicyStatement({ - effect: iam.Effect.ALLOW, - actions: ['s3:SomeAction'], - resources: [bucket.bucketArn], - principals: [role] -}));</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">bucket.addToResourcePolicy(new iam.PolicyStatement({ - effect: iam.Effect.ALLOW, - actions: ['s3:SomeAction'], - resources: [bucket.bucketArn], - principals: [role] -}));</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">bucket.add_to_resource_policy(iam.PolicyStatement( - effect=iam.Effect.ALLOW, - actions=["s3:SomeAction"], - resources=[bucket.bucket_arn], - principals=role))</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">bucket.addToResourcePolicy(PolicyStatement.Builder.create() - .effect(Effect.ALLOW) - .actions(Arrays.asList("s3:SomeAction")) - .resources(Arrays.asList(bucket.getBucketArn())) - .principals(Arrays.asList(role)) - .build());</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">bucket.AddToResourcePolicy(new PolicyStatement(new PolicyStatementProps -{ - Effect = Effect.ALLOW, - Actions = new string[] { "s3:SomeAction" }, - Resources = new string[] { bucket.BucketArn }, - Principals = new IPrincipal[] { role } -}));</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="permissions-existing">2.20.5. Using external IAM objects</h4> -<div class="paragraph"> -<p>If you have defined an IAM user, principal, group, or role outside your AWS CDK app, you can use that IAM object in your AWS CDK app. To do so, create a reference to it using its ARN or its name. (Use the name for users, groups, and roles.) The returned reference can then be used to grant permissions or to construct policy statements as explained previously.</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>For users, call <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.User.html#static-fromwbruserwbrarnscope-id-userarn">User.fromUserArn()</a></code> or <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.User.html#static-fromwbruserwbrnamescope-id-username">User.fromUserName()</a></code>. <code>User.fromUserAttributes()</code> is also available, but currently provides the same functionality as <code>User.fromUserArn()</code>.</p> -</li> -<li> -<p>For principals, instantiate an <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.ArnPrincipal.html">ArnPrincipal</a></code> object.</p> -</li> -<li> -<p>For groups, call <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Group.html#static-fromwbrgroupwbrarnscope-id-grouparn">Group.fromGroupArn()</a></code> or <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Group.html#static-fromwbrgroupwbrnamescope-id-groupname">Group.fromGroupName()</a></code>.</p> -</li> -<li> -<p>For roles, call <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html#static-fromwbrrolewbrarnscope-id-rolearn-options">Role.fromRoleArn()</a></code> or <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html#static-fromwbrrolewbrnamescope-id-rolename">Role.fromRoleName()</a></code>.</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>Policies (including managed policies) can be used in similar fashion using the following methods. You can use references to these objects anywhere an IAM policy is required.</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Policy.html#static-fromwbrpolicywbrnamescope-id-policyname">Policy.fromPolicyName</a></code></p> -</li> -<li> -<p><code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.ManagedPolicy.html#static-fromwbrmanagedwbrpolicywbrarnscope-id-managedpolicyarn">ManagedPolicy.fromManagedPolicyArn</a></code></p> -</li> -<li> -<p><code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.ManagedPolicy.html#static-fromwbrmanagedwbrpolicywbrnamescope-id-managedpolicyname">ManagedPolicy.fromManagedPolicyName</a></code></p> -</li> -<li> -<p><code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.ManagedPolicy.html#static-fromwbrawswbrmanagedwbrpolicywbrnamemanagedpolicyname">ManagedPolicy.fromAwsManagedPolicyName</a></code></p> -</li> -</ul> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>As with all references to external AWS resources, you cannot modify external IAM objects in your CDK app.</p> -</div> -</td> -</tr> -</table> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="context">2.21. Context values and the AWS CDK</h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Context values are key-value pairs that can be associated with an app, stack, or construct. They may be supplied to your app from a file (usually either <code class="path">cdk.json</code> or <code class="path">cdk.context.json</code> in your project directory) or on the command line.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>Context values are key-value pairs that can be associated with an app, stack, or construct. They may be supplied to your app from a file (usually either <code class="path">cdk.json</code> or <code class="path">cdk.context.json</code> in your project directory) or on the command line.</p> -</div> -<div class="paragraph"> -<p>The CDK Toolkit uses context to cache values retrieved from your AWS account during synthesis. Values include the Availability Zones in your account or the Amazon Machine Image (AMI) IDs currently available for Amazon EC2 instances. Because these values are provided by your AWS account, they can change between runs of your CDK application. This makes them a potential source of unintended change. The CDK Toolkit’s caching behavior "freezes" these values for your CDK app until you decide to accept the new values.</p> -</div> -<div class="paragraph"> -<p>Imagine the following scenario without context caching. Let’s say you specified "latest Amazon Linux" as the AMI for your Amazon EC2 instances, and a new version of this AMI was released. Then, the next time you deployed your CDK stack, your already-deployed instances would be using the outdated ("wrong") AMI and would need to be upgraded. Upgrading would result in replacing all your existing instances with new ones, which would probably be unexpected and undesired.</p> -</div> -<div class="paragraph"> -<p>Instead, the CDK records your account’s available AMIs in your project’s <code class="path">cdk.context.json</code> file, and uses the stored value for future synthesis operations. This way, the list of AMIs is no longer a potential source of change. You can also be sure that your stacks will always synthesize to the same AWS CloudFormation templates.</p> -</div> -<div class="paragraph"> -<p>Not all context values are cached values from your AWS environment. <a href="#featureflags">AWS CDK feature flags</a> are also context values. You can also create your own context values for use by your apps or constructs.</p> -</div> -<div class="paragraph"> -<p>Context keys are strings. Values may be any type supported by JSON: numbers, strings, arrays, or objects.</p> -</div> -<div class="admonitionblock tip"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-tip" title="Tip"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>If your constructs create their own context values, incorporate your library’s package name in its keys so they won’t conflict with other packages' context values.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>Many context values are associated with a particular AWS environment, and a given CDK app can be deployed in more than one environment. The key for such values includes the AWS account and Region so that values from different environments do not conflict.</p> -</div> -<div class="paragraph"> -<p>The following context key illustrates the format used by the AWS CDK, including the account and Region.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre>availability-zones:account=123456789012:region=eu-central-1</pre> -</div> -</div> -<div class="admonitionblock important"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-important" title="Important"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>Cached context values are managed by the AWS CDK and its constructs, including constructs you may write. Do not add or change cached context values by manually editing files. It can be useful, however, to review <code>cdk.context.json</code> occasionally to see what values are being cached. Context values that don’t represent cached values should be stored under the <code>context</code> key of <code class="path">cdk.json</code>. This way, they won’t be cleared when cached values are cleared.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="sect3"> -<h4 id="context-construct">2.21.1. Sources of context values</h4> -<div class="paragraph"> -<p>Context values can be provided to your AWS CDK app in six different ways:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Automatically from the current AWS account.</p> -</li> -<li> -<p>Through the <strong class="command">--context</strong> option to the <strong class="command">cdk</strong> command. (These values are always strings.)</p> -</li> -<li> -<p>In the project’s <code class="path">cdk.context.json</code> file.</p> -</li> -<li> -<p>In the <code>context</code> key of the project’s <code class="path">cdk.json</code> file.</p> -</li> -<li> -<p>In the <code>context</code> key of your <code class="path">~/.cdk.json</code> file.</p> -</li> -<li> -<p>In your AWS CDK app using the <code>construct.node.setContext()</code> method.</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>The project file <code class="path">cdk.context.json</code> is where the AWS CDK caches context values retrieved from your AWS account. This practice avoids unexpected changes to your deployments when, for example, a new Availability Zone is introduced. The AWS CDK does not write context data to any of the other files listed.</p> -</div> -<div class="admonitionblock important"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-important" title="Important"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>Because they’re part of your application’s state, <code class="path">cdk.json</code> and <code class="path">cdk.context.json</code> must be committed to source control along with the rest of your app’s source code. Otherwise, deployments in other environments (for example, a CI pipeline) might produce inconsistent results.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>Context values are scoped to the construct that created them; they are visible to child constructs, but not to parents or siblings. Context values that are set by the AWS CDK Toolkit (the <strong class="command">cdk</strong> command) can be set automatically, from a file, or from the <strong class="command">--context</strong> option. Context values from these sources are implicitly set on the <code>App</code> construct. Therefore, they’re visible to every construct in every stack in the app.</p> -</div> -<div class="paragraph"> -<p>Your app can read a context value using the <code>construct.node.tryGetContext</code> method. If the requested entry isn’t found on the current construct or any of its parents, the result is <code>undefined</code>. (Alternatively, the result could be your language’s equivalent, such as <code>None</code> in Python.)</p> -</div> -</div> -<div class="sect3"> -<h4 id="context-methods">2.21.2. Context methods</h4> -<div class="paragraph"> -<p>The AWS CDK supports several context methods that enable AWS CDK apps to obtain contextual information from the AWS environment. For example, you can get a list of Availability Zones that are available in a given AWS account and Region, using the <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html#availabilityzones">stack.availabilityZones</a> method.</p> -</div> -<div class="paragraph"> -<p>The following are the context methods:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1"><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_route53.HostedZone.html#static-fromwbrlookupscope-id-query">HostedZone.fromLookup</a></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Gets the hosted zones in your account.</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1"><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html#availabilityzones">stack.availabilityZones</a></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Gets the supported Availability Zones.</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1"><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ssm.StringParameter.html#static-valuewbrfromwbrlookupscope-parametername">StringParameter.valueFromLookup</a></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Gets a value from the current Region’s Amazon EC2 Systems Manager Parameter Store.</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1"><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.Vpc.html#static-fromwbrlookupscope-id-options">Vpc.fromLookup</a></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Gets the existing Amazon Virtual Private Clouds in your accounts.</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1"><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.LookupMachineImage.html">LookupMachineImage</a></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Looks up a machine image for use with a NAT instance in an Amazon Virtual Private Cloud.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div class="paragraph"> -<p>If a required context value isn’t available, the AWS CDK app notifies the CDK Toolkit that the context information is missing. Next, the CLI queries the current AWS account for the information and stores the resulting context information in the <code class="path">cdk.context.json</code> file. Then, it executes the AWS CDK app again with the context values.</p> -</div> -</div> -<div class="sect3"> -<h4 id="context-viewing">2.21.3. Viewing and managing context</h4> -<div class="paragraph"> -<p>Use the <strong class="command">cdk context</strong> command to view and manage the information in your <code class="path">cdk.context.json</code> file. To see this information, use the <strong class="command">cdk context</strong> command without any options. The output should be something like the following.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre>Context found in cdk.json: - -┌───┬─────────────────────────────────────────────────────────────┬─────────────────────────────────────────────────────────┐ -│ # │ Key │ Value │ -├───┼─────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────┤ -│ 1 │ availability-zones:account=123456789012:region=eu-central-1 │ [ "eu-central-1a", "eu-central-1b", "eu-central-1c" ] │ -├───┼─────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────┤ -│ 2 │ availability-zones:account=123456789012:region=eu-west-1 │ [ "eu-west-1a", "eu-west-1b", "eu-west-1c" ] │ -└───┴─────────────────────────────────────────────────────────────┴─────────────────────────────────────────────────────────┘ - -Runto remove a context key. If it is a cached value, it will be refreshed on the next.</pre> -</div> -</div> -<div class="paragraph"> -<p>To remove a context value, run <strong class="command">cdk context --reset</strong>, specifying the value’s corresponding key or number. The following example removes the value that corresponds to the second key in the preceding example. This value represents the list of Availability Zones in the Europe (Ireland) Region.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk context --reset 2</code></pre> -</div> -</div> -<div class="listingblock"> -<div class="content"> -<pre>Context value -availability-zones:account=123456789012:region=eu-west-1 -reset. It will be refreshed on the next SDK synthesis run.</pre> -</div> -</div> -<div class="paragraph"> -<p>Therefore, if you want to update to the latest version of the Amazon Linux AMI, use the preceding example to do a controlled update of the context value and reset it. Then, synthesize and deploy your app again.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk synth</code></pre> -</div> -</div> -<div class="paragraph"> -<p>To clear all of the stored context values for your app, run <strong class="command">cdk context --clear</strong>, as follows.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk context --clear</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Only context values stored in <code class="path">cdk.context.json</code> can be reset or cleared. The AWS CDK does not touch other context values. Therefore, to protect a context value from being reset using these commands, you might copy the value to <code class="path">cdk.json</code>.</p> -</div> -</div> -<div class="sect3"> -<h4 id="context-cli">2.21.4. AWS CDK Toolkit <code>--context</code> flag</h4> -<div class="paragraph"> -<p>Use the <code>--context</code> (<code>-c</code> for short) option to pass runtime context values to your CDK app during synthesis or deployment.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk synth --context key=value MyStack</code></pre> -</div> -</div> -<div class="paragraph"> -<p>To specify multiple context values, repeat the <strong class="command">--context</strong> option any number of times, providing one key-value pair each time.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk synth --context key1=value1 --context key2=value2 MyStack</code></pre> -</div> -</div> -<div class="paragraph"> -<p>When synthesizing multiple stacks, the specified context values are passed to all stacks. To provide different context values to individual stacks, either use different keys for the values, or use multiple <strong class="command">cdk synth</strong> or <strong class="command">cdk deploy</strong> commands.</p> -</div> -<div class="paragraph"> -<p>Context values passed from the command line are always strings. If a value is usually of some other type, your code must be prepared to convert or parse the value. You might have non-string context values provided in other ways (for example, in <code class="path">cdk.context.json</code>). To make sure this kind of value works as expected, confirm that the value is a string before converting it.</p> -</div> -</div> -<div class="sect3"> -<h4 id="context-example">2.21.5. Example</h4> -<div class="paragraph"> -<p>Following is an example of using an existing Amazon VPC using AWS CDK context.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as cdk from 'aws-cdk-lib'; -import * as ec2 from 'aws-cdk-lib/aws-ec2'; -import { Construct } from 'constructs'; - -export class ExistsVpcStack extends cdk.Stack { - - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - - super(scope, id, props); - - const vpcid = this.node.tryGetContext('vpcid'); - const vpc = ec2.Vpc.fromLookup(this, 'VPC', { - vpcId: vpcid, - }); - - const pubsubnets = vpc.selectSubnets({subnetType: ec2.SubnetType.PUBLIC}); - - new cdk.CfnOutput(this, 'publicsubnets', { - value: pubsubnets.subnetIds.toString(), - }); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const cdk = require('aws-cdk-lib'); -const ec2 = require('aws-cdk-lib/aws-ec2'); - -class ExistsVpcStack extends cdk.Stack { - - constructor(scope, id, props) { - - super(scope, id, props); - - const vpcid = this.node.tryGetContext('vpcid'); - const vpc = ec2.Vpc.fromLookup(this, 'VPC', { - vpcId: vpcid - }); - - const pubsubnets = vpc.selectSubnets({subnetType: ec2.SubnetType.PUBLIC}); - - new cdk.CfnOutput(this, 'publicsubnets', { - value: pubsubnets.subnetIds.toString() - }); - } -} - -module.exports = { ExistsVpcStack }</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">import aws_cdk as cdk -import aws_cdk.aws_ec2 as ec2 -from constructs import Construct - -class ExistsVpcStack(cdk.Stack): - - def __init__(scope: Construct, id: str, **kwargs): - - super().__init__(scope, id, **kwargs) - - vpcid = self.node.try_get_context("vpcid") - vpc = ec2.Vpc.from_lookup(self, "VPC", vpc_id=vpcid) - - pubsubnets = vpc.select_subnets(subnetType=ec2.SubnetType.PUBLIC) - - cdk.CfnOutput(self, "publicsubnets", - value=pubsubnets.subnet_ids.to_string())</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">import software.amazon.awscdk.CfnOutput; - -import software.amazon.awscdk.services.ec2.Vpc; -import software.amazon.awscdk.services.ec2.VpcLookupOptions; -import software.amazon.awscdk.services.ec2.SelectedSubnets; -import software.amazon.awscdk.services.ec2.SubnetSelection; -import software.amazon.awscdk.services.ec2.SubnetType; -import software.constructs.Construct; - -public class ExistsVpcStack extends Stack { - public ExistsVpcStack(Construct context, String id) { - this(context, id, null); - } - - public ExistsVpcStack(Construct context, String id, StackProps props) { - super(context, id, props); - - String vpcId = (String)this.getNode().tryGetContext("vpcid"); - Vpc vpc = (Vpc)Vpc.fromLookup(this, "VPC", VpcLookupOptions.builder() - .vpcId(vpcId).build()); - - SelectedSubnets pubSubNets = vpc.selectSubnets(SubnetSelection.builder() - .subnetType(SubnetType.PUBLIC).build()); - - CfnOutput.Builder.create(this, "publicsubnets") - .value(pubSubNets.getSubnetIds().toString()).build(); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; -using Amazon.CDK.AWS.EC2; -using Constructs; - -class ExistsVpcStack : Stack -{ - public ExistsVpcStack(Construct scope, string id, StackProps props) : base(scope, id, props) - { - var vpcId = (string)this.Node.TryGetContext("vpcid"); - var vpc = Vpc.FromLookup(this, "VPC", new VpcLookupOptions - { - VpcId = vpcId - }); - - SelectedSubnets pubSubNets = vpc.SelectSubnets([new SubnetSelection - { - SubnetType = SubnetType.PUBLIC - }]); - - new CfnOutput(this, "publicsubnets", new CfnOutputProps { - Value = pubSubNets.SubnetIds.ToString() - }); - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>You can use <strong class="command">cdk diff</strong> to see the effects of passing in a context value on the command line:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk diff -c vpcid=vpc-0cb9c31031d0d3e22</code></pre> -</div> -</div> -<div class="listingblock"> -<div class="content"> -<pre>Stack ExistsvpcStack -Outputs -[+] Output publicsubnets publicsubnets: {"Value":"subnet-06e0ea7dd302d3e8f,subnet-01fc0acfb58f3128f"}</pre> -</div> -</div> -<div class="paragraph"> -<p>The resulting context values can be viewed as shown here.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk context -j</code></pre> -</div> -</div> -<div class="listingblock"> -<div class="content"> -<pre>{ - "vpc-provider:account=123456789012:filter.vpc-id=vpc-0cb9c31031d0d3e22:region=us-east-1": { - "vpcId": "vpc-0cb9c31031d0d3e22", - "availabilityZones": [ - "us-east-1a", - "us-east-1b" - ], - "privateSubnetIds": [ - "subnet-03ecfc033225be285", - "subnet-0cded5da53180ebfa" - ], - "privateSubnetNames": [ - "Private" - ], - "privateSubnetRouteTableIds": [ - "rtb-0e955393ced0ada04", - "rtb-05602e7b9f310e5b0" - ], - "publicSubnetIds": [ - "subnet-06e0ea7dd302d3e8f", - "subnet-01fc0acfb58f3128f" - ], - "publicSubnetNames": [ - "Public" - ], - "publicSubnetRouteTableIds": [ - "rtb-00d1fdfd823c82289", - "rtb-04bb1969b42969bcb" - ] - } -}</pre> -</div> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="featureflags">2.22. AWS CDK feature flags</h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>The AWS CDK uses <em>feature flags</em> to enable potentially breaking behaviors in a release. Flags are stored as <a href="#context">Context values and the AWS CDK</a> values in <code class="path">cdk.json</code> (or <code class="path">~/.cdk.json</code>). They are not removed by the <strong class="command">cdk context --reset</strong> or <strong class="command">cdk context --clear</strong> commands.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>The AWS CDK uses <em>feature flags</em> to enable potentially breaking behaviors in a release. Flags are stored as <a href="#context">Context values and the AWS CDK</a> values in <code class="path">cdk.json</code> (or <code class="path">~/.cdk.json</code>). They are not removed by the <strong class="command">cdk context --reset</strong> or <strong class="command">cdk context --clear</strong> commands.</p> -</div> -<div class="paragraph"> -<p>Feature flags are disabled by default. Existing projects that do not specify the flag will continue to work as before with later AWS CDK releases. New projects created using <strong class="command">cdk init</strong> include flags enabling all features available in the release that created the project. Edit <code class="path">cdk.json</code> to disable any flags for which you prefer the earlier behavior. You can also add flags to enable new behaviors after upgrading the AWS CDK.</p> -</div> -<div class="paragraph"> -<p>A list of all current feature flags can be found on the AWS CDK GitHub repository in <a href="https://github.com/aws/aws-cdk/blob/main/packages/aws-cdk-lib/cx-api/FEATURE_FLAGS.md">FEATURE_FLAGS.md</a>. See the <code class="path">CHANGELOG</code> in a given release for a description of any new feature flags added in that release.</p> -</div> -<div class="sect3"> -<h4 id="featureflags-disabling">2.22.1. Reverting to v1 behavior</h4> -<div class="paragraph"> -<p>In CDK v2, the defaults for some feature flags have been changed with respect to v1. You can set these back to <code>false</code> to revert to specific AWS CDK v1 behavior. Use the <code>cdk diff</code> command to inspect the changes to your synthesized template to see if any of these flags are needed.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1"><code>@aws-cdk/core:newStyleStackSynthesis</code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Use the new stack synthesis method, which assumes bootstrap resources with well-known names. Requires <a href="#bootstrapping">modern bootstrapping</a>, but in turn allows CI/CD via <a href="#cdk-pipeline">CDK Pipelines</a> and cross-account deployments out of the box.</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1"><code>@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId</code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>If your application uses multiple Amazon API Gateway API keys and associates them to usage plans.</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1"><code>@aws-cdk/aws-rds:lowercaseDbIdentifier</code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>If your application uses Amazon RDS database instance or database clusters, and explicitly specifies the identifier for these.</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1"><code>@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021</code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>If your application uses the TLS_V1_2_2019 security policy with Amazon CloudFront distributions. CDK v2 uses security policy TLSv1.2_2021 by default.</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1"><code>@aws-cdk/core:stackRelativeExports</code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>If your application uses multiple stacks and you refer to resources from one stack in another, this determines whether absolute or relative path is used to construct AWS CloudFormation exports.</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1"><code>@aws-cdk/aws-lambda:recognizeVersionProps</code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>If set to <code>false</code>, the CDK includes metadata when detecting whether a Lambda function has changed. This can cause deployment failures when only the metadata has changed, since duplicate versions are not allowed. There is no need to revert this flag if you’ve made at least one change to all Lambda Functions in your application.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div class="paragraph"> -<p>The syntax for reverting these flags in <code class="path">cdk.json</code> is shown here.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-json" data-lang="json">{ - "context": { - "@aws-cdk/core:newStyleStackSynthesis": false, - "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": false, - "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": false, - "@aws-cdk/aws-rds:lowercaseDbIdentifier": false, - "@aws-cdk/core:stackRelativeExports": false, - "@aws-cdk/aws-lambda:recognizeVersionProps": false - } -}</code></pre> -</div> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="aspects">2.23. Aspects and the AWS CDK</h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Aspects are a way to apply an operation to all constructs in a given scope. The aspect could modify the constructs, such as by adding tags. Or it could verify something about the state of the constructs, such as making sure that all buckets are encrypted.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>Aspects are a way to apply an operation to all constructs in a given scope. The aspect could modify the constructs, such as by adding tags. Or it could verify something about the state of the constructs, such as making sure that all buckets are encrypted.</p> -</div> -<div class="paragraph"> -<p>To apply an aspect to a construct and all constructs in the same scope, call <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Aspects.html#static-ofscope" class="bare">https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Aspects.html#static-ofscope</a><code class="Aspects">.of([replaceable]</code>SCOPE<code>).add()</code> with a new aspect, as shown in the following example.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">Aspects.of(myConstruct).add(new SomeAspect(...));</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">Aspects.of(myConstruct).add(new SomeAspect(...));</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">Aspects.of(my_construct).add(SomeAspect(...))</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">Aspects.of(myConstruct).add(new SomeAspect(...));</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">Aspects.Of(myConstruct).add(new SomeAspect(...));</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">awscdk.Aspects_Of(stack).Add(awscdk.NewTag(...))</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The AWS CDK uses aspects to <a href="#tagging">tag resources</a>, but the framework can also be used for other purposes. For example, you can use it to validate or change the AWS CloudFormation resources that are defined for you by higher-level constructs.</p> -</div> -<div class="sect3"> -<h4 id="aspects-detail">2.23.1. Aspects in detail</h4> -<div class="paragraph"> -<p>Aspects employ the <a href="https://en.wikipedia.org/wiki/Visitor_pattern">visitor pattern</a>. An aspect is a class that implements the following interface.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">interface IAspect { - visit(node: IConstruct): void;}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>JavaScript doesn’t have interfaces as a language feature. Therefore, an aspect is simply an instance of a class having a <code>visit</code> method that accepts the node to be operated on.</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Python</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Python doesn’t have interfaces as a language feature. Therefore, an aspect is simply an instance of a class having a <code>visit</code> method that accepts the node to be operated on.</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">public interface IAspect { - public void visit(Construct node); -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">public interface IAspect -{ - void Visit(IConstruct node); -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">type IAspect interface { - Visit(node constructs.IConstruct) -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>When you call <code>Aspects.of([replaceable]</code>SCOPE<code>).add(…​)</code>, the construct adds the aspect to an internal list of aspects. You can obtain the list with <code>Aspects.of([replaceable]</code>SCOPE<code>)</code>.</p> -</div> -<div class="paragraph"> -<p>During the <a href="#deploy-how-synth-app">prepare phase</a>, the AWS CDK calls the <code>visit</code> method of the object for the construct and each of its children in top-down order.</p> -</div> -<div class="paragraph"> -<p>The <code>visit</code> method is free to change anything in the construct. In strongly typed languages, cast the received construct to a more specific type before accessing construct-specific properties or methods.</p> -</div> -<div class="paragraph"> -<p>Aspects don’t propagate across <code>Stage</code> construct boundaries, because <code>Stages</code> are self-contained and immutable after definition. Apply aspects on the <code>Stage</code> construct itself (or lower) if you want them to visit constructs inside the <code>Stage</code>.</p> -</div> -</div> -<div class="sect3"> -<h4 id="aspects-example">2.23.2. Example</h4> -<div class="paragraph"> -<p>The following example validates that all buckets created in the stack have versioning enabled. The aspect adds an error annotation to the constructs that fail the validation. This results in the <strong class="command">synth</strong> operation failing and prevents deploying the resulting cloud assembly.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">class BucketVersioningChecker implements IAspect { - public visit(node: IConstruct): void { - // See that we're dealing with a CfnBucket - if (node instanceof s3.CfnBucket) { - - // Check for versioning property, exclude the case where the property - // can be a token (IResolvable). - if (!node.versioningConfiguration - || (!Tokenization.isResolvable(node.versioningConfiguration) - && node.versioningConfiguration.status !== 'Enabled')) { - Annotations.of(node).addError('Bucket versioning is not enabled'); - } - } - } -} - -// Later, apply to the stack -Aspects.of(stack).add(new BucketVersioningChecker());</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">class BucketVersioningChecker { - visit(node) { - // See that we're dealing with a CfnBucket - if ( node instanceof s3.CfnBucket) { - - // Check for versioning property, exclude the case where the property - // can be a token (IResolvable). - if (!node.versioningConfiguration - || !Tokenization.isResolvable(node.versioningConfiguration) - && node.versioningConfiguration.status !== 'Enabled')) { - Annotations.of(node).addError('Bucket versioning is not enabled'); - } - } - } -} - -// Later, apply to the stack -Aspects.of(stack).add(new BucketVersioningChecker());</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">@jsii.implements(cdk.IAspect) -class BucketVersioningChecker: - - def visit(self, node): - # See that we're dealing with a CfnBucket - if isinstance(node, s3.CfnBucket): - - # Check for versioning property, exclude the case where the property - # can be a token (IResolvable). - if (not node.versioning_configuration or - not Tokenization.is_resolvable(node.versioning_configuration) - and node.versioning_configuration.status != "Enabled"): - Annotations.of(node).add_error('Bucket versioning is not enabled') - -# Later, apply to the stack -Aspects.of(stack).add(BucketVersioningChecker())</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">public class BucketVersioningChecker implements IAspect -{ - @Override - public void visit(Construct node) - { - // See that we're dealing with a CfnBucket - if (node instanceof CfnBucket) - { - CfnBucket bucket = (CfnBucket)node; - Object versioningConfiguration = bucket.getVersioningConfiguration(); - if (versioningConfiguration == null || - !Tokenization.isResolvable(versioningConfiguration.toString()) && - !versioningConfiguration.toString().contains("Enabled")) - Annotations.of(bucket.getNode()).addError("Bucket versioning is not enabled"); - } - } -} - - -// Later, apply to the stack -Aspects.of(stack).add(new BucketVersioningChecker());</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">class BucketVersioningChecker : Amazon.Jsii.Runtime.Deputy.DeputyBase, IAspect -{ - public void Visit(IConstruct node) - { - // See that we're dealing with a CfnBucket - if (node is CfnBucket) - { - var bucket = (CfnBucket)node; - if (bucket.VersioningConfiguration is null || - !Tokenization.IsResolvable(bucket.VersioningConfiguration) && - !bucket.VersioningConfiguration.ToString().Contains("Enabled")) - Annotations.Of(bucket.Node).AddError("Bucket versioning is not enabled"); - } - } -} - -// Later, apply to the stack -Aspects.Of(stack).add(new BucketVersioningChecker());</code></pre> -</div> -</div> -</div> -</div> -</div> -</div> -<div class="sect1 topic"> -<h2 id="prerequisites">3. AWS CDK prerequisites</h2> -<div class="sectionbody"> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Complete prerequisites before getting started with the AWS Cloud Development Kit (AWS CDK).</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>Complete all prerequisites before getting started with the AWS Cloud Development Kit (AWS CDK).</p> -</div> -<div class="sect2"> -<h3 id="prerequisites-account">3.1. Set up your AWS account</h3> -<div class="paragraph"> -<p>If you or your organization are new to AWS, you must set up your AWS account. This includes signing up for an AWS account, securing your root user, determining your method of managing users, and creating an administrative user. To manage users, you can use AWS Identity and Access Management (IAM) or AWS IAM Identity Center. We recommend that you use IAM Identity Center. For more information, see the following:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/introduction.html">What is IAM?</a> in the <em>IAM User Guide</em>.</p> -</li> -<li> -<p><a href="https://docs.aws.amazon.com/singlesignon/latest/userguide/what-is.html">What is IAM Identity Center?</a> in the <em>AWS IAM Identity Center User Guide</em>.</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>After setting up an AWS account, you should have an administrative user and the ability to create and manage additional users using IAM or IAM Identity Center.</p> -</div> -<div class="paragraph"> -<p>Before moving forward, we recommend that you take time to learn the recommended best practices in AWS Identity and Access Management. For more information, see <a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/IAMBestPracticesAndUseCases.html">Security best practices and use cases in AWS Identity and Access Management</a> in the <em>IAM User Guide</em>.</p> -</div> -</div> -<div class="sect2"> -<h3 id="prerequisites-cli">3.2. Install and configure the AWS CLI</h3> -<div class="paragraph"> -<p>When you develop AWS CDK applications on your local machine, you will use the AWS Cloud Development Kit (AWS CDK) Command Line Interface (<code class="noloc">CLI</code>) to interact with AWS, such as deploying applications to provision your AWS resources. To interact with AWS outside of the AWS Management Console, you must configure security credentials on your local machine. To do this, we recommend that you install and use the AWS Command Line Interface (AWS CLI).</p> -</div> -<div class="paragraph"> -<p>For instructions on installing the AWS CLI, see <a href="https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html">Install or update to the latest version of the AWS CLI</a> in the <em>AWS Command Line Interface User Guide</em>.</p> -</div> -<div class="paragraph"> -<p>How you configure security credentials will depend on how you or your organization manages users. For instructions, see <a href="https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-authentication.html">Authentication and access credentials</a> in the <em>AWS Command Line Interface User Guide</em>.</p> -</div> -<div class="paragraph"> -<p>After installing and configuring the AWS CLI, you should have the following:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>The AWS CLI installed on your local machine.</p> -</li> -<li> -<p>Credentials configured in a <code class="path">config</code> on your local machine using the AWS CLI.</p> -</li> -</ul> -</div> -</div> -<div class="sect2"> -<h3 id="prerequisites-node">3.3. Install <code class="noloc">Node.js</code> and programming language prerequisites</h3> -<div class="paragraph"> -<p>All AWS CDK developers, regardless of the supported programming language that you will use, require <a href="https://nodejs.org/en/download/">Node.js</a> 14.15.0 or later. All supported programming languages use the same backend, which runs on <code class="noloc">Node.js</code>. We recommend a version in <a href="https://nodejs.org/en/about/releases/">active long-term support</a>. If your organization has a different recommendation, follow their guidance.</p> -</div> -<div class="admonitionblock important"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-important" title="Important"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>Node.js versions 13.0.0 through 13.6.0 are not compatible with the AWS CDK due to compatibility issues with its dependencies.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>Other programming language prerequisites depend on the language that you will use to develop AWS CDK applications:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>TypeScript 3.8 or later (<code>npm -g install typescript</code>)</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">JavaScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>No additional requirements</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Python</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Python 3.7 or later including <code>pip</code> and <code>virtualenv</code></p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -<div class="ulist"> -<ul> -<li> -<p>Java Development Kit (JDK) 8 (a.k.a. 1.8) or later</p> -</li> -<li> -<p>Apache Maven 3.5 or later</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>Java IDE recommended (we use Eclipse in some examples in this guide). IDE must be able to import Maven projects. Check to make sure that your project is set to use Java 1.8. Set the JAVA_HOME environment variable to the path where you have installed the JDK.</p> -</div> -</dd> -<dt class="hdlist1">C#</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>.NET Core 3.1 or later, or .NET 6.0 or later.</p> -<div class="paragraph"> -<p>Visual Studio 2019 (any edition) or Visual Studio Code recommended.</p> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Go</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Go 1.1.8 or later.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="title">Third-party language deprecation</div> -<div class="paragraph"> -<p>Each language version is only supported until it is <code class="noloc">EOL</code> (End Of Life) and is subject to change with prior notice.</p> -</div> -</td> -</tr> -</table> -</div> -</div> -<div class="sect2"> -<h3 id="prerequisites-next">3.4. Next steps</h3> -<div class="paragraph"> -<p>To get started with the AWS CDK, see <a href="#getting-started">Getting started with the AWS CDK</a>.</p> -</div> -</div> -</div> -</div> -<div class="sect1 topic"> -<h2 id="getting-started">4. Getting started with the AWS CDK</h2> -<div class="sectionbody"> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Get started with the AWS Cloud Development Kit (AWS CDK) by installing and configuring the AWS CDK Command Line Interface (AWS CDK <code class="noloc">CLI</code>). Then, use the CDK <code class="noloc">CLI</code> to create your first CDK app, bootstrap your AWS environment, and deploy your application.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>Get started with the AWS Cloud Development Kit (AWS CDK) by installing and configuring the AWS CDK Command Line Interface (AWS CDK <code class="noloc">CLI</code>). Then, use the CDK <code class="noloc">CLI</code> to create your first CDK app, bootstrap your AWS environment, and deploy your application.</p> -</div> -<div class="sect2"> -<h3 id="getting-started-prerequisites">4.1. Prerequisites</h3> -<div class="paragraph"> -<p>Before getting started with the AWS CDK, complete all prerequisites. These prerequisites are required for those that are new to AWS or new to programming. For instructions, see <a href="#prerequisites">AWS CDK prerequisites</a>.</p> -</div> -<div class="paragraph"> -<p>We recommend that you have a basic understanding of what the AWS CDK is. For more information, see <a href="#home">What is the AWS CDK?</a> and <a href="#core-concepts">Learn AWS CDK core concepts</a>.</p> -</div> -</div> -<div class="sect2"> -<h3 id="getting-started-install">4.2. Install the AWS CDK <code class="noloc">CLI</code></h3> -<div class="paragraph"> -<p>Use the <code class="noloc">Node</code> Package Manager to install the CDK <code class="noloc">CLI</code>. We recommend that you install it globally using the following command:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ npm install -g aws-cdk</code></pre> -</div> -</div> -<div class="paragraph"> -<p>To install a specific version of the CDK <code class="noloc">CLI</code>, use the following command structure:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ npm install -g aws-cdk@X.YY.Z</code></pre> -</div> -</div> -<div class="paragraph"> -<p>If you want to use multiple versions of the AWS CDK, consider installing a matching version of the CDK <code class="noloc">CLI</code> in individual CDK projects. To do this, remove the <code>-g</code> option from the <code>npm install</code> command. Then, use <code>npx aws-cdk</code> to invoke the CDK <code class="noloc">CLI</code>. This will run a local version if it exists. Otherwise, the globally installed version will be used.</p> -</div> -<div class="sect3"> -<h4 id="getting-started-install-troubleshoot">4.2.1. Troubleshoot a CDK <code class="noloc">CLI</code> installation</h4> -<div class="paragraph"> -<p>If you get a permission error, and have administrator access on your system, run the following:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ sudo npm install -g aws-cdk</code></pre> -</div> -</div> -<div class="paragraph"> -<p>If you receive an error message, try uninstalling the CDK <code class="noloc">CLI</code> by running the following:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ npm uninstall -g aws-cdk</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Then, repeat steps to reinstall the CDK <code class="noloc">CLI</code>.</p> -</div> -</div> -<div class="sect3"> -<h4 id="getting-started-install-verify">4.2.2. Verify a successful CDK <code class="noloc">CLI</code> installation</h4> -<div class="paragraph"> -<p>Run the following command to verify a successful installation. The AWS CDK <code class="noloc">CLI</code> should output the version number:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ cdk --version</code></pre> -</div> -</div> -</div> -</div> -<div class="sect2"> -<h3 id="getting-started-configure">4.3. Configure the AWS CDK <code class="noloc">CLI</code></h3> -<div class="paragraph"> -<p>After installing the CDK <code class="noloc">CLI</code>, you can start using it to develop applications on your local machine. To interact with AWS, such as deploying applications, you must have security credentials configured on your local machine with permissions to perform any actions that you initiate.</p> -</div> -<div class="paragraph"> -<p>To configure security credentials on your local machine, you use the AWS CLI. How you configure security credentials depends on how you manage users. For instructions, see <a href="https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-authentication.html">Authentication and access credentials</a> in the <em>AWS Command Line Interface User Guide</em>.</p> -</div> -<div class="paragraph"> -<p>The CDK <code class="noloc">CLI</code> will automatically use the security credentials that you configure with the AWS CLI. For example, if you are an IAM Identity Center user, you can use the <code>aws configure sso</code> command to configure security credentials. If you are an IAM user, you can use the <code>aws configure</code> command. The AWS CLI will guide you through configuring security credentials on your local machine and save the necessary information in your <code class="path">config</code> and <code class="path">credentials</code> files. Then, when you use the CDK <code class="noloc">CLI</code>, such as deploying an application with <code>cdk deploy</code>, the CDK <code class="noloc">CLI</code> will use your configured security credentials.</p> -</div> -<div class="paragraph"> -<p>Just like the AWS CLI, the CDK <code class="noloc">CLI</code> will use your <code>default</code> profile by default. You can specify a profile using the CDK <code class="noloc">CLI</code><code><a href="#ref-cli-cmd-options-profile">--profile</a></code> option. For more information on using security credentials with the CDK <code class="noloc">CLI</code>, see <a href="#configure-access">Configure security credentials for the AWS CDK CLI</a>.</p> -</div> -</div> -<div class="sect2"> -<h3 id="getting-started-tools">4.4. (Optional) Install additional AWS CDK tools</h3> -<div class="paragraph"> -<p>The <a href="https://aws.amazon.com/visualstudiocode/">AWS Toolkit for Visual Studio Code</a> is an open source plug-in for Visual Studio Code that helps you create, debug, and deploy applications on AWS. The toolkit provides an integrated experience for developing AWS CDK applications. It includes the AWS CDK Explorer feature to list your AWS CDK projects and browse the various components of the CDK application. For instructions, see the following:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><a href="https://docs.aws.amazon.com/toolkit-for-vscode/latest/userguide/setup-toolkit.html">Installing the AWS Toolkit for Visual Studio Code</a>.</p> -</li> -<li> -<p><a href="https://docs.aws.amazon.com/toolkit-for-vscode/latest/userguide/cdk-explorer.html">AWS CDK for VS Code</a>.</p> -</li> -</ul> -</div> -</div> -<div class="sect2"> -<h3 id="getting-started-app">4.5. Create your first CDK app</h3> -<div class="paragraph"> -<p>You’re now ready to get started with using the AWS CDK by creating your first CDK app. For instructions, see <a href="#hello-world">Tutorial: Create your first AWS CDK app</a>.</p> -</div> -</div> -<div class="sect2 topic"> -<h3 id="hello-world">4.6. Tutorial: Create your first AWS CDK app</h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Get started with the AWS Cloud Development Kit (AWS CDK) by using the AWS CDK Command Line Interface (AWS CDK <code class="noloc">CLI</code>) to develop your first CDK app, bootstrap your AWS environment, and deploy your application on AWS.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>Get started with using the AWS Cloud Development Kit (AWS CDK) by using the AWS CDK Command Line Interface (AWS CDK <code class="noloc">CLI</code>) to develop your first CDK app, bootstrap your AWS environment, and deploy your application on AWS.</p> -</div> -<div class="sect3"> -<h4 id="hello-world-prerequisites">4.6.1. Prerequisites</h4> -<div class="paragraph"> -<p>Before starting this tutorial, complete all set up steps in <a href="#getting-started">Getting started with the AWS CDK</a>.</p> -</div> -</div> -<div class="sect3"> -<h4 id="hello-world-about">4.6.2. About this tutorial</h4> -<div class="paragraph"> -<p>In this tutorial, you will create and deploy a simple application on AWS using the AWS CDK. The application consists of an <a href="https://docs.aws.amazon.com/lambda/latest/dg/welcome.html">AWS Lambda function</a> that returns a <code>Hello World!</code> message when invoked. The function will be invoked through a <a href="https://docs.aws.amazon.com/lambda/latest/dg/lambda-urls.html">Lambda function URL</a> that serves as a dedicated HTTP(S) endpoint for your Lambda function.</p> -</div> -<div class="paragraph"> -<p>Through this tutorial, you will perform the following:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><strong>Create your project</strong> – Create a CDK project using the CDK <code class="noloc">CLI</code><code>cdk init</code> command.</p> -</li> -<li> -<p><strong>Configure your AWS environment</strong> – Configure the AWS environment that you will deploy your application into.</p> -</li> -<li> -<p><strong>Bootstrap your AWS environment</strong> – Prepare your AWS environment for deployment by bootstrapping it using the CDK <code class="noloc">CLI</code><code>cdk bootstrap</code> command.</p> -</li> -<li> -<p><strong>Develop your app</strong> – Use constructs from the AWS Construct Library to define your Lambda function and Lambda function URL resources.</p> -</li> -<li> -<p><strong>Prepare your app for deployment</strong> – Use the CDK <code class="noloc">CLI</code> to build your app and synthesize an AWS CloudFormation template.</p> -</li> -<li> -<p><strong>Deploy your app</strong> – Use the CDK <code class="noloc">CLI</code><code>cdk deploy</code> command to deploy your application and provision your AWS resources.</p> -</li> -<li> -<p><strong>Interact with your application</strong> – Interact with your deployed Lambda function on AWS by invoking it and receiving a response.</p> -</li> -<li> -<p><strong>Modify your app</strong> – Modify your Lambda function and deploy to implement your changes.</p> -</li> -<li> -<p><strong>Delete your app</strong> – Delete all resources that you created by using the CDK <code class="noloc">CLI</code><code>cdk destroy</code> command.</p> -</li> -</ul> -</div> -</div> -<div class="sect3"> -<h4 id="hello-world-create">4.6.3. Step 1: Create your CDK project</h4> -<div class="paragraph"> -<p>In this step, you create a new CDK project. A CDK project should be in its own directory, with its own local module dependencies.</p> -</div> -<div class="olist arabic"> -<ol class="arabic"> -<li> -<p>From a starting directory of your choice, create and navigate to a directory named <code class="path">hello-cdk</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ mkdir hello-cdk && cd hello-cdk</code></pre> -</div> -</div> -<div class="admonitionblock important"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-important" title="Important"></i> -</td> -<td class="content"> -Be sure to name your project directory <code class="path">hello-cdk</code>, <em>exactly as shown here</em>. The CDK <code class="noloc">CLI</code> uses this directory name to name things within your CDK code. If you use a different directory name, you will run into issues during this tutorial. -</td> -</tr> -</table> -</div> -</li> -<li> -<p>From the <code class="path">hello-cdk</code> directory, initialize a new CDK project using the CDK <code class="noloc">CLI</code><code>cdk init</code> command. Specify the <code>app</code> template and your preferred programming language with the <code>--language</code> option:</p> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>**</p> -</dd> -</dl> -</div> -</li> -</ol> -</div> -<div class="listingblock"> -<div class="content"> -<pre>$ cdk init app --language typescript</pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>**</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ cdk init app --language javascript</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>**</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ cdk init app --language python</code></pre> -</div> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p>After the app has been created, also enter the following two commands. These activate the app’s <code class="noloc">Python</code> virtual environment and installs the AWS CDK core dependencies.</p> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ source .venv/bin/activate # On Windows, run `.\venv\Scripts\activate` instead -$ python -m pip install -r requirements.txt</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>**</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ cdk init app --language java</code></pre> -</div> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p>If you are using an IDE, you can now open or import the project. In <code class="noloc">Eclipse</code>, for example, choose <strong>File</strong> > <strong>Import</strong> > <strong>Maven</strong> > <strong>Existing Maven Projects</strong>. Make sure that the project settings are set to use Java 8 (1.8).</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>**</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ cdk init app --language csharp</code></pre> -</div> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p>If you are using Visual Studio, open the solution file in the <code class="path">src</code> directory.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>**</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ cdk init app --language go</code></pre> -</div> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p>After the app has been created, also enter the following command to install the AWS Construct Library modules that the app requires.</p> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ go get</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The <code>cdk init</code> command creates a structure of files and folders within the <code class="path">hello-cdk</code> directory to help organize the source code for your CDK app. This structure of files and folders is called your CDK <em>project</em>. Take a moment to explore your CDK project.</p> -</div> -<div class="paragraph"> -<p>If you have <code class="noloc">Git</code> installed, each project you create using <code>cdk init</code> is also initialized as a <code class="noloc">Git</code> repository.</p> -</div> -<div class="paragraph"> -<p>During project initialization, the CDK <code class="noloc">CLI</code> creates a CDK app containing a single CDK stack. The CDK app instance is created using the <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.App.html">App</a></code> construct. The following is a portion of this code from your CDK application file:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">bin/hello-cdk.ts</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">#!/usr/bin/env node -import 'source-map-support/register'; -import * as cdk from 'aws-cdk-lib'; -import { HelloCdkStack } from '../lib/hello-cdk-stack'; - -const app = new cdk.App(); -new HelloCdkStack(app, 'HelloCdkStack', { -});</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">JavaScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">bin/hello-cdk.js</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">#!/usr/bin/env node - -const cdk = require('aws-cdk-lib'); -const { HelloCdkStack } = require('../lib/hello-cdk-stack'); - -const app = new cdk.App(); -new HelloCdkStack(app, 'HelloCdkStack', { -});</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Python</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">app.py</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">#!/usr/bin/env python3 -import os - -import aws_cdk as cdk - -from hello_cdk.hello_cdk_stack import HelloCdkStack - - -app = cdk.App() -HelloCdkStack(app, "HelloCdkStack",) - -app.synth()</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Java</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">src/main/java/…​/HelloCdkApp.java</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">package com.myorg; - -import software.amazon.awscdk.App; -import software.amazon.awscdk.Environment; -import software.amazon.awscdk.StackProps; - -import java.util.Arrays; - -public class HelloCdkApp { - public static void main(final String[] args) { - App app = new App(); - - new HelloCdkStack(app, "HelloCdkStack", StackProps.builder() - .build()); - - app.synth(); - } -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">C#</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">src/HelloCdk/Program.cs</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace HelloCdk -{ - sealed class Program - { - public static void Main(string[] args) - { - var app = new App(); - new HelloCdkStack(app, "HelloCdkStack", new StackProps - {}); - app.Synth(); - } - } -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Go</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">hello-cdk.go</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">package main - -import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/constructs-go/constructs/v10" - "github.com/aws/jsii-runtime-go" -) - -// ... - -func main() { - defer jsii.Close() - - app := awscdk.NewApp(nil) - - NewHelloCdkStack(app, "HelloCdkStack", &HelloCdkStackProps{ - awscdk.StackProps{ - Env: env(), - }, - }) - - app.Synth(nil) -} - -// ...</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div class="paragraph"> -<p>The CDK stack is created using the <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html">Stack</a></code> construct. The following is a portion of this code from your CDK stack file:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">lib/hello-cdk-stack.ts</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as cdk from 'aws-cdk-lib'; -import { Construct } from 'constructs'; - -export class HelloCdkStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - // Define your constructs here - - } -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">JavaScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">lib/hello-cdk-stack.js</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const { Stack } = require('aws-cdk-lib'); - -class HelloCdkStack extends Stack { - constructor(scope, id, props) { - super(scope, id, props); - - // Define your constructs here - - } -} - -module.exports = { HelloCdkStack }</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Python</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">hello_cdk/hello_cdk_stack.py</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">from aws_cdk import ( - Stack, -) -from constructs import Construct - -class HelloCdkStack(Stack): - - def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: - super().__init__(scope, construct_id, **kwargs) - - # Define your constructs here</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Java</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">src/main/java/…​/HelloCdkStack.java</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">package com.myorg; - -import software.constructs.Construct; -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.StackProps; - -public class HelloCdkStack extends Stack { - public HelloCdkStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public HelloCdkStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - // Define your constructs here - } -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">C#</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">src/HelloCdk/HelloCdkStack.cs</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; -using Constructs; - -namespace HelloCdk -{ - public class HelloCdkStack : Stack - { - internal HelloCdkStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) - { - // Define your constructs here - } - } -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Go</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">hello-cdk.go</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">package main - -import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/constructs-go/constructs/v10" - "github.com/aws/jsii-runtime-go" -) - -type HelloCdkStackProps struct { - awscdk.StackProps -} - -func NewHelloCdkStack(scope constructs.Construct, id string, props *HelloCdkStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - stack := awscdk.NewStack(scope, &id, &sprops) - - return stack -} - -// ...</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect3"> -<h4 id="hello-world-configure">4.6.4. Step 2: Configure your AWS environment</h4> -<div class="paragraph"> -<p>In this step, you configure the AWS environment for your CDK stack. By doing this, you specify which environment your CDK stack will be deployed to.</p> -</div> -<div class="paragraph"> -<p>First, determine the AWS environment that you want to use. An AWS environment consists of an AWS account and AWS Region.</p> -</div> -<div class="paragraph"> -<p>When you use the AWS CLI to configure security credentials on your local machine, you can then use the AWS CLI to obtain AWS environment information for a specific profile.</p> -</div> -<div class="olist arabic"> -<ol class="arabic"> -<li> -<p>Run the following AWS CLI command to get the AWS account ID for your <code>default</code> profile:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ aws sts get-caller-identity --query "Account" --output text</code></pre> -</div> -</div> -</li> -<li> -<p>If you prefer to use a named profile, provide the name of your profile using the <code>--profile</code> option:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ aws sts get-caller-identity --profile your-profile-name --query "Account" --output text</code></pre> -</div> -</div> -</li> -<li> -<p>Run the following AWS CLI command to get the Region that you configured for your <code>default</code> profile:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ aws configure get region</code></pre> -</div> -</div> -</li> -<li> -<p>If you prefer to use a named profile, provide the name of your profile using the <code>--profile</code> option:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ aws configure get region --profile your-profile-name</code></pre> -</div> -</div> -</li> -</ol> -</div> -<div class="paragraph"> -<p>Next, you will configure the AWS environment for your CDK stack by modifying the <code>HelloCdkStack</code> instance in your <em>application file</em>. For this tutorial, you will hard code your AWS environment information. This is recommended for production environments. For information on other ways to configure environments, see <a href="#configure-env">Configure environments to use with the AWS CDK</a>.</p> -</div> -<div class="olist arabic"> -<ol class="arabic"> -<li> -<p>In your <em>application file</em>, use the <code>env</code> property of the <code>Stack</code> construct to configure your environment. The following is an example:</p> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">bin/hello-cdk.ts</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">#!/usr/bin/env node -import 'source-map-support/register'; -import * as cdk from 'aws-cdk-lib'; -import { HelloCdkStack } from '../lib/hello-cdk-stack'; - -const app = new cdk.App(); -new HelloCdkStack(app, 'HelloCdkStack', { - env: { account: '123456789012', region: 'us-east-1' }, -});</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">JavaScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">bin/hello-cdk.js</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">#!/usr/bin/env node - -const cdk = require('aws-cdk-lib'); -const { HelloCdkStack } = require('../lib/hello-cdk-stack'); - -const app = new cdk.App(); -new HelloCdkStack(app, 'HelloCdkStack', { - env: { account: '123456789012', region: 'us-east-1' }, -});</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Python</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">app.py</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">#!/usr/bin/env python3 -import os - -import aws_cdk as cdk - -from hello_cdk.hello_cdk_stack import HelloCdkStack - - -app = cdk.App() -HelloCdkStack(app, "HelloCdkStack", - env=cdk.Environment(account='123456789012', region='us-east-1'), - ) - -app.synth()</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Java</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">src/main/java/…​/HelloCdkApp.java</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">package com.myorg; - -import software.amazon.awscdk.App; -import software.amazon.awscdk.Environment; -import software.amazon.awscdk.StackProps; - -import java.util.Arrays; - -public class HelloCdkApp { - public static void main(final String[] args) { - App app = new App(); - - new HelloCdkStack(app, "HelloCdkStack", StackProps.builder() - .env(Environment.builder() - .account("123456789012") - .region("us-east-1") - .build()) - - .build()); - - app.synth(); - } -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">C#</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">src/HelloCdk/Program.cs</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace HelloCdk -{ - sealed class Program - { - public static void Main(string[] args) - { - var app = new App(); - new HelloCdkStack(app, "HelloCdkStack", new StackProps - { - Env = new Amazon.CDK.Environment - { - Account = "123456789012", - Region = "us-east-1", - } - }); - app.Synth(); - } - } -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Go</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">hello-cdk.go</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">package main - -import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/constructs-go/constructs/v10" - "github.com/aws/jsii-runtime-go" -) - -// ... - -func main() { - defer jsii.Close() - - app := awscdk.NewApp(nil) - - NewHelloCdkStack(app, "HelloCdkStack", &HelloCdkStackProps{ - awscdk.StackProps{ - Env: env(), - }, - }) - - app.Synth(nil) -} - -func env() *awscdk.Environment { - return &awscdk.Environment{ - Account: jsii.String("123456789012"), - Region: jsii.String("us-east-1"), - } -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</li> -</ol> -</div> -</div> -<div class="sect3"> -<h4 id="hello-world-bootstrap">4.6.5. Step 3: Bootstrap your AWS environment</h4> -<div class="paragraph"> -<p>In this step, you bootstrap the AWS environment that you configured in the previous step. This prepares your environment for CDK deployments.</p> -</div> -<div class="paragraph"> -<p>To bootstrap your environment, run the following from the root of your CDK project:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk bootstrap</code></pre> -</div> -</div> -<div class="paragraph"> -<p>By bootstrapping from the root of your CDK project, you don’t have to provide any additional information. The CDK <code class="noloc">CLI</code> obtains environment information from your project. When you bootstrap outside of a CDK project, you must provide environment information with the <code>cdk bootstrap</code> command. For more information, see <a href="#bootstrapping-env">Bootstrap your environment for use with the AWS CDK</a>.</p> -</div> -</div> -<div class="sect3"> -<h4 id="hello-world-build">4.6.6. Step 4: Build your CDK app</h4> -<div class="paragraph"> -<p>In most programming environments, you build or compile code after making changes. This isn’t necessary with the AWS CDK since the CDK <code class="noloc">CLI</code> will automatically perform this step. However, you can still build manually when you want to catch syntax and type errors. The following is an example:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ npm run build - -> hello-cdk@0.1.0 build -> tsc</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>No build step is necessary.</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Python</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>No build step is necessary.</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ mvn compile -q</code></pre> -</div> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p>Or press <code>Control-B</code> in Eclipse (other Java IDEs may vary)</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ dotnet build src</code></pre> -</div> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p>Or press F6 in Visual Studio</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ go build</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="hello-world-list">4.6.7. Step 5: List the CDK stacks in your app</h4> -<div class="paragraph"> -<p>At this point, you should have a CDK app containing a single CDK stack. To verify, use the CDK <code class="noloc">CLI</code><code>cdk list</code> command to display your stacks. The output should display a single stack named <code>HelloCdkStack</code>:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ cdk list -HelloCdkStack</code></pre> -</div> -</div> -<div class="paragraph"> -<p>If you don’t see this output, verify that you are in the correct working directory of your project and try again. If you still don’t see your stack, repeat <a href="#hello-world-create">Step 1: Create your CDK project</a> and try again.</p> -</div> -</div> -<div class="sect3"> -<h4 id="hello-world-function">4.6.8. Step 6: Define your Lambda function</h4> -<div class="paragraph"> -<p>In this step, you import the <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda-readme.html">aws_lambda</a></code> module from the AWS Construct Library and use the <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.Function.html">Function</a></code> L2 construct.</p> -</div> -<div class="paragraph"> -<p>Modify your CDK stack file as follows:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">lib/hello-cdk-stack.ts</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as cdk from 'aws-cdk-lib'; -import { Construct } from 'constructs'; -// Import the Lambda module -import * as lambda from 'aws-cdk-lib/aws-lambda'; - -export class HelloCdkStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - // Define the Lambda function resource - const myFunction = new lambda.Function(this, "HelloWorldFunction", { - runtime: lambda.Runtime.NODEJS_20_X, // Provide any supported Node.js runtime - handler: "index.handler", - code: lambda.Code.fromInline(` - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello World!'), - }; - }; - `), - }); - } -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">JavaScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">lib/hello-cdk-stack.js</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const { Stack } = require('aws-cdk-lib'); -// Import the Lambda module -const lambda = require('aws-cdk-lib/aws-lambda'); - -class HelloCdkStack extends Stack { - constructor(scope, id, props) { - super(scope, id, props); - - // Define the Lambda function resource - const myFunction = new lambda.Function(this, "HelloWorldFunction", { - runtime: lambda.Runtime.NODEJS_20_X, // Provide any supported Node.js runtime - handler: "index.handler", - code: lambda.Code.fromInline(` - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello World!'), - }; - }; - `), - }); - - } -} - -module.exports = { HelloCdkStack }</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Python</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">hello_cdk/hello_cdk_stack.py</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">from aws_cdk import ( - Stack, - aws_lambda as _lambda, # Import the Lambda module -) -from constructs import Construct - -class HelloCdkStack(Stack): - - def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: - super().__init__(scope, construct_id, **kwargs) - - # Define the Lambda function resource - my_function = _lambda.Function( - self, "HelloWorldFunction", - runtime = _lambda.Runtime.NODEJS_20_X, # Provide any supported Node.js runtime - handler = "index.handler", - code = _lambda.Code.from_inline( - """ - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello World!'), - }; - }; - """ - ), - )</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Java</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">src/main/java/…​/HelloCdkStack.java</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">package com.myorg; - -import software.constructs.Construct; -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.StackProps; -// Import Lambda function -import software.amazon.awscdk.services.lambda.Code; -import software.amazon.awscdk.services.lambda.Function; -import software.amazon.awscdk.services.lambda.Runtime; - -public class HelloCdkStack extends Stack { - public HelloCdkStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public HelloCdkStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - // Define the Lambda function resource - Function myFunction = Function.Builder.create(this, "HelloWorldFunction") - .runtime(Runtime.NODEJS_20_X) // Provide any supported Node.js runtime - .handler("index.handler") - .code(Code.fromInline( - "exports.handler = async function(event) {" + - " return {" + - " statusCode: 200," + - " body: JSON.stringify('Hello World!')" + - " };" + - "};")) - .build(); - - } -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">C#</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">src/main/java/…​/HelloCdkStack.java</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; -using Constructs; -// Import the Lambda module -using Amazon.CDK.AWS.Lambda; - -namespace HelloCdk -{ - public class HelloCdkStack : Stack - { - internal HelloCdkStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) - { - // Define the Lambda function resource - var myFunction = new Function(this, "HelloWorldFunction", new FunctionProps - { - Runtime = Runtime.NODEJS_20_X, // Provide any supported Node.js runtime - Handler = "index.handler", - Code = Code.FromInline(@" - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello World!'), - }; - }; - "), - }); - } - } -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Go</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">hello-cdk.go</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">package main - -import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/constructs-go/constructs/v10" - "github.com/aws/jsii-runtime-go" - // Import the Lambda module - "github.com/aws/aws-cdk-go/awscdk/v2/awslambda" -) - -type HelloCdkStackProps struct { - awscdk.StackProps -} - -func NewHelloCdkStack(scope constructs.Construct, id string, props *HelloCdkStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - stack := awscdk.NewStack(scope, &id, &sprops) - - // Define the Lambda function resource - myFunction := awslambda.NewFunction(stack, jsii.String("HelloWorldFunction"), &awslambda.FunctionProps{ - Runtime: awslambda.Runtime_NODEJS_20_X(), // Provide any supported Node.js runtime - Handler: jsii.String("index.handler"), - Code: awslambda.Code_FromInline(jsii.String(` - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello World!'), - }; - }; - `)), - }) - - return stack -} - -// ...</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div class="paragraph"> -<p>Let’s take a closer look at the <code>Function</code> construct. Like all constructs, the <code>Function</code> class takes three parameters:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><strong>scope</strong> – Defines your <code>Stack</code> instance as the parent of the <code>Function</code> construct. All constructs that define AWS resources are created within the scope of a stack. You can define constructs inside of constructs, creating a hierarchy (tree). Here, and in most cases, the scope is <code>this</code> (<code>self</code> in <code class="noloc">Python</code>).</p> -</li> -<li> -<p><strong>Id</strong> – The construct ID of the <code>Function</code> within your AWS CDK app. This ID, plus a hash based on the function’s location within the stack, uniquely identifies the function during deployment. The AWS CDK also references this ID when you update the construct in your app and re-deploy to update the deployed resource. Here, your construct ID is <code>HelloWorldFunction</code>. Functions can also have a name, specified with the <code>functionName</code> property. This is different from the construct ID.</p> -</li> -<li> -<p><strong>props</strong> – A bundle of values that define properties of the function. Here you define the <code>runtime</code>, <code>handler</code>, and <code>code</code> properties.</p> -<div class="paragraph"> -<p>Props are represented differently in the languages supported by the AWS CDK.</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>In <code class="noloc">TypeScript</code> and <code class="noloc">JavaScript</code>, <code>props</code> is a single argument and you pass in an object containing the desired properties.</p> -</li> -<li> -<p>In <code class="noloc">Python</code>, props are passed as keyword arguments.</p> -</li> -<li> -<p>In <code class="noloc">Java</code>, a Builder is provided to pass the props. There are two: one for <code>FunctionProps</code>, and a second for <code>Function</code> to let you build the construct and its props object in one step. This code uses the latter.</p> -</li> -<li> -<p>In <code class="noloc">C#</code>, you instantiate a <code>FunctionProps</code> object using an object initializer and pass it as the third parameter.</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>If a construct’s props are optional, you can omit the <code>props</code> parameter entirely.</p> -</div> -</li> -</ul> -</div> -<div class="paragraph"> -<p>All constructs take these same three arguments, so it’s easy to stay oriented as you learn about new ones. And as you might expect, you can subclass any construct to extend it to suit your needs, or if you want to change its defaults.</p> -</div> -</div> -<div class="sect3"> -<h4 id="hello-world-url">4.6.9. Step 7: Define your Lambda function URL</h4> -<div class="paragraph"> -<p>In this step, you use the <code>addFunctionUrl</code> helper method of the <code>Function</code> construct to define a Lambda function URL. To output the value of this URL at deployment, you will create an AWS CloudFormation output using the <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.CfnOutput.html">CfnOutput</a></code> construct.</p> -</div> -<div class="paragraph"> -<p>Add the following to your CDK stack file:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">lib/hello-cdk-stack.ts</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">// ... - -export class HelloCdkStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - // Define the Lambda function resource - // ... - - // Define the Lambda function URL resource - const myFunctionUrl = myFunction.addFunctionUrl({ - authType: lambda.FunctionUrlAuthType.NONE, - }); - - // Define a CloudFormation output for your URL - new cdk.CfnOutput(this, "myFunctionUrlOutput", { - value: myFunctionUrl.url, - }) - - } -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">JavaScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">lib/hello-cdk-stack.js</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const { Stack, CfnOutput } = require('aws-cdk-lib'); // Import CfnOutput - -class HelloCdkStack extends Stack { - constructor(scope, id, props) { - super(scope, id, props); - - // Define the Lambda function resource - // ... - - // Define the Lambda function URL resource - const myFunctionUrl = myFunction.addFunctionUrl({ - authType: lambda.FunctionUrlAuthType.NONE, - }); - - // Define a CloudFormation output for your URL - new CfnOutput(this, "myFunctionUrlOutput", { - value: myFunctionUrl.url, - }) - - } -} - -module.exports = { HelloCdkStack }</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Python</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">hello_cdk/hello_cdk_stack.py</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">from aws_cdk import ( - # ... - CfnOutput # Import CfnOutput -) -from constructs import Construct - -class HelloCdkStack(Stack): - - def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: - super().__init__(scope, construct_id, **kwargs) - - # Define the Lambda function resource - # ... - - # Define the Lambda function URL resource - my_function_url = my_function.add_function_url( - auth_type = _lambda.FunctionUrlAuthType.NONE, - ) - - # Define a CloudFormation output for your URL - CfnOutput(self, "myFunctionUrlOutput", value=my_function_url.url)</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Java</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">src/main/java/…​/HelloCdkStack.java</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">package com.myorg; - -// ... -// Import Lambda function URL -import software.amazon.awscdk.services.lambda.FunctionUrl; -import software.amazon.awscdk.services.lambda.FunctionUrlAuthType; -import software.amazon.awscdk.services.lambda.FunctionUrlOptions; -// Import CfnOutput -import software.amazon.awscdk.CfnOutput; - -public class HelloCdkStack extends Stack { - public HelloCdkStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public HelloCdkStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - // Define the Lambda function resource - // ... - - // Define the Lambda function URL resource - FunctionUrl myFunctionUrl = myFunction.addFunctionUrl(FunctionUrlOptions.builder() - .authType(FunctionUrlAuthType.NONE) - .build()); - - // Define a CloudFormation output for your URL - CfnOutput.Builder.create(this, "myFunctionUrlOutput") - .value(myFunctionUrl.getUrl()) - .build(); - } -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">C#</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">src/main/java/…​/HelloCdkStack.java</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">// ... - -namespace HelloCdk -{ - public class HelloCdkStack : Stack - { - internal HelloCdkStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) - { - // Define the Lambda function resource - // ... - - // Define the Lambda function URL resource - var myFunctionUrl = myFunction.AddFunctionUrl(new FunctionUrlOptions - { - AuthType = FunctionUrlAuthType.NONE - }); - - // Define a CloudFormation output for your URL - new CfnOutput(this, "myFunctionUrlOutput", new CfnOutputProps - { - Value = myFunctionUrl.Url - }); - } - } -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Go</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">hello-cdk.go</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">// ... - -func NewHelloCdkStack(scope constructs.Construct, id string, props *HelloCdkStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - stack := awscdk.NewStack(scope, &id, &sprops) - - // Define the Lambda function resource - // ... - - // Define the Lambda function URL resource - myFunctionUrl := myFunction.AddFunctionUrl(&awslambda.FunctionUrlOptions{ - AuthType: awslambda.FunctionUrlAuthType_NONE, - }) - - // Define a CloudFormation output for your URL - awscdk.NewCfnOutput(stack, jsii.String("myFunctionUrlOutput"), &awscdk.CfnOutputProps{ - Value: myFunctionUrl.Url(), - }) - - return stack -} - -// ...</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div class="admonitionblock warning"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-warning" title="Warning"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>To keep this tutorial simple, your Lambda function URL is defined without authentication. When deployed, this creates a publicly accessible endpoint that can be used to invoke your function. When you are done with this tutorial, follow <a href="#hello-world-delete">Step 12: Delete your application</a> to delete these resources.</p> -</div> -</td> -</tr> -</table> -</div> -</div> -<div class="sect3"> -<h4 id="hello-world-synth">4.6.10. Step 8: Synthesize a CloudFormation template</h4> -<div class="paragraph"> -<p>In this step, you prepare for deployment by synthesizing a CloudFormation template with the CDK <code class="noloc">CLI</code><code>cdk synth</code> command. This command performs basic validation of your CDK code, runs your CDK app, and generates a CloudFormation template from your CDK stack.</p> -</div> -<div class="paragraph"> -<p>If your app contains more than one stack, you must specify which stacks to synthesize. Since your app contains a single stack, the CDK <code class="noloc">CLI</code> automatically detects the stack to synthesize.</p> -</div> -<div class="paragraph"> -<p>If you don’t synthesize a template, the CDK <code class="noloc">CLI</code> will automatically perform this step when you deploy. However, we recommend that you run this step before each deployment to check for synthesis errors.</p> -</div> -<div class="paragraph"> -<p>Before synthesizing a template, you can optionally build your application to catch syntax and type errors. For instructions, see <a href="#hello-world-build">Step 4: Build your CDK app</a>.</p> -</div> -<div class="paragraph"> -<p>To synthesize a CloudFormation template, run the following from the root of your project:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk synth</code></pre> -</div> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>If you receive an error like the following, verify that you are in the <code class="path">hello-cdk</code> directory and try again:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre>--app is required either in command-line, in cdk.json or in ~/.cdk.json</pre> -</div> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>If successful, the CDK <code class="noloc">CLI</code> will output a <code class="noloc">YAML</code>–formatted CloudFormation template to <code>stdout</code> and save a <code class="noloc">JSON</code>–formatted template in the <code class="path">cdk.out</code> directory of your project.</p> -</div> -<div class="paragraph"> -<p>The following is an example output of the CloudFormation template:</p> -</div> -<details id="hello-world-synth-template"> -<summary class="title">AWS CloudFormation template</summary> -<div class="content"> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-yaml" data-lang="yaml">Resources: - HelloWorldFunctionServiceRoleunique-identifier: - Type: AWS::IAM::Role - Properties: - AssumeRolePolicyDocument: - Statement: - - Action: sts:AssumeRole - Effect: Allow - Principal: - Service: lambda.amazonaws.com - Version: "2012-10-17" - ManagedPolicyArns: - - Fn::Join: - - "" - - - "arn:" - - Ref: AWS::Partition - - :iam::aws:policy/service-role/AWSLambdaBasicExecutionRole - Metadata: - aws:cdk:path: HelloCdkStack/HelloWorldFunction/ServiceRole/Resource - HelloWorldFunctionunique-identifier: - Type: AWS::Lambda::Function - Properties: - Code: - ZipFile: " - - \ exports.handler = async function(event) { - - \ return { - - \ statusCode: 200, - - \ body: JSON.stringify('Hello World!'), - - \ }; - - \ }; - - \ " - Handler: index.handler - Role: - Fn::GetAtt: - - HelloWorldFunctionServiceRoleunique-identifier - - Arn - Runtime: nodejs20.x - DependsOn: - - HelloWorldFunctionServiceRoleunique-identifier - Metadata: - aws:cdk:path: HelloCdkStack/HelloWorldFunction/Resource - HelloWorldFunctionFunctionUrlunique-identifier: - Type: AWS::Lambda::Url - Properties: - AuthType: NONE - TargetFunctionArn: - Fn::GetAtt: - - HelloWorldFunctionunique-identifier - - Arn - Metadata: - aws:cdk:path: HelloCdkStack/HelloWorldFunction/FunctionUrl/Resource - HelloWorldFunctioninvokefunctionurlunique-identifier: - Type: AWS::Lambda::Permission - Properties: - Action: lambda:InvokeFunctionUrl - FunctionName: - Fn::GetAtt: - - HelloWorldFunctionunique-identifier - - Arn - FunctionUrlAuthType: NONE - Principal: "*" - Metadata: - aws:cdk:path: HelloCdkStack/HelloWorldFunction/invoke-function-url - CDKMetadata: - Type: AWS::CDK::Metadata - Properties: - Analytics: v2:deflate64:unique-identifier - Metadata: - aws:cdk:path: HelloCdkStack/CDKMetadata/Default - Condition: CDKMetadataAvailable -Outputs: - myFunctionUrlOutput: - Value: - Fn::GetAtt: - - HelloWorldFunctionFunctionUrlunique-identifier - - FunctionUrl -Parameters: - BootstrapVersion: - Type: AWS::SSM::Parameter::Value<String> - Default: /cdk-bootstrap/unique-identifier/version - Description: Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip] -Rules: - CheckBootstrapVersion: - Assertions: - - Assert: - Fn::Not: - - Fn::Contains: - - - "1" - - "2" - - "3" - - "4" - - "5" - - Ref: BootstrapVersion - AssertDescription: CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI.</code></pre> -</div> -</div> -</div> -</details> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>Every generated template contains an <code>AWS::CDK::Metadata</code> resource by default. The AWS CDK team uses this metadata to gain insight into AWS CDK usage and find ways to improve it. For details, including how to opt out of version reporting, see <a href="#version-reporting">Version reporting</a>.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>By defining a single L2 construct, the AWS CDK creates an extensive CloudFormation template containing your Lambda resources, along with the permissions and glue logic required for your resources to interact within your application.</p> -</div> -</div> -<div class="sect3"> -<h4 id="hello-world-deploy">4.6.11. Step 9: Deploy your CDK stack</h4> -<div class="paragraph"> -<p>In this step, you use the CDK <code class="noloc">CLI</code><code>cdk deploy</code> command to deploy your CDK stack. This command retrieves your generated CloudFormation template and deploys it through AWS CloudFormation, which provisions your resources as part of a CloudFormation stack.</p> -</div> -<div class="paragraph"> -<p>From the root of your project, run the following. Confirm changes if prompted:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk deploy - -✨ Synthesis time: 2.69s - -HelloCdkStack: start: Building unique-identifier:current_account-current_region -HelloCdkStack: success: Built unique-identifier:current_account-current_region -HelloCdkStack: start: Publishing unique-identifier:current_account-current_region -HelloCdkStack: success: Published unique-identifier:current_account-current_region -This deployment will make potentially sensitive changes according to your current security approval level (--require-approval broadening). -Please confirm you intend to make the following modifications: - -IAM Statement Changes -┌───┬───────────────────────────────────────┬────────┬──────────────────────────┬──────────────────────────────┬───────────┐ -│ │ Resource │ Effect │ Action │ Principal │ Condition │ -├───┼───────────────────────────────────────┼────────┼──────────────────────────┼──────────────────────────────┼───────────┤ -│ + │ ${HelloWorldFunction.Arn} │ Allow │ lambda:InvokeFunctionUrl │ * │ │ -├───┼───────────────────────────────────────┼────────┼──────────────────────────┼──────────────────────────────┼───────────┤ -│ + │ ${HelloWorldFunction/ServiceRole.Arn} │ Allow │ sts:AssumeRole │ Service:lambda.amazonaws.com │ │ -└───┴───────────────────────────────────────┴────────┴──────────────────────────┴──────────────────────────────┴───────────┘ -IAM Policy Changes -┌───┬───────────────────────────────────┬────────────────────────────────────────────────────────────────────────────────┐ -│ │ Resource │ Managed Policy ARN │ -├───┼───────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────┤ -│ + │ ${HelloWorldFunction/ServiceRole} │ arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole │ -└───┴───────────────────────────────────┴────────────────────────────────────────────────────────────────────────────────┘ -(NOTE: There may be security-related changes not in this list. See https://github.com/aws/aws-cdk/issues/1299) - -Do you wish to deploy these changes (y/n)? y</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Similar to <code>cdk synth</code>, you don’t have to specify the AWS CDK stack since the app contains a single stack.</p> -</div> -<div class="paragraph"> -<p>During deployment, the CDK <code class="noloc">CLI</code> displays progress information as your stack is deployed. When complete, you can go to the <a href="https://console.aws.amazon.com/cloudformation/home">AWS CloudFormation console</a> to view your <code>HelloCdkStack</code> stack. You can also go to the Lambda console to view your <code>HelloWorldFunction</code> resource.</p> -</div> -<div class="paragraph"> -<p>When deployment completes, the CDK <code class="noloc">CLI</code> will output your endpoint URL. Copy this URL for the next step. The following is an example:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>... -HelloCdkStack: deploying... [1/1] -HelloCdkStack: creating CloudFormation changeset... - - ✅ HelloCdkStack - -✨ Deployment time: 41.65s - -Outputs: -HelloCdkStack.myFunctionUrlOutput = https://<api-id>.lambda-url.<Region>.on.aws/ -Stack ARN: -arn:aws:cloudformation:Region:account-id:stack/HelloCdkStack/unique-identifier - -✨ Total time: 44.34s</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="hello-world-interact">4.6.12. Step 10: Interact with your application on AWS</h4> -<div class="paragraph"> -<p>In this step, you interact with your application on AWS by invoking your Lambda function through the function URL. When you access the URL, your Lambda function returns the <code>Hello World!</code> message.</p> -</div> -<div class="paragraph"> -<p>To invoke your function, access the function URL through your browser or from the command line. The following is an example:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ curl https://<api-id>.lambda-url.<Region>.on.aws/ -"Hello World!"%</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="hello-world-modify">4.6.13. Step 11: Modify your application</h4> -<div class="paragraph"> -<p>In this step, you modify the message that the Lambda function returns when invoked. You perform a diff using the CDK <code class="noloc">CLI</code><code>cdk diff</code> command to preview your changes and deploy to update your application. You then interact with your application on AWS to see your new message.</p> -</div> -<div class="paragraph"> -<p>Modify the <code>myFunction</code> instance in your CDK stack file as follows:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">lib/hello-cdk-stack.ts</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">// ... - -export class HelloCdkStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - // Modify the Lambda function resource - const myFunction = new lambda.Function(this, "HelloWorldFunction", { - runtime: lambda.Runtime.NODEJS_20_X, // Provide any supported Node.js runtime - handler: "index.handler", - code: lambda.Code.fromInline(` - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello CDK!'), - }; - }; - `), - }); - - // ...</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">JavaScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">lib/hello-cdk-stack.js</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">// ... - -class HelloCdkStack extends Stack { - constructor(scope, id, props) { - super(scope, id, props); - - // Modify the Lambda function resource - const myFunction = new lambda.Function(this, "HelloWorldFunction", { - runtime: lambda.Runtime.NODEJS_20_X, // Provide any supported Node.js runtime - handler: "index.handler", - code: lambda.Code.fromInline(` - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello CDK!'), - }; - }; - `), - }); - - // ... - - } -} - -module.exports = { HelloCdkStack }</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Python</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">hello_cdk/hello_cdk_stack.py</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python"># ... - -class HelloCdkStack(Stack): - - def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: - super().__init__(scope, construct_id, **kwargs) - - # Modify the Lambda function resource - my_function = _lambda.Function( - self, "HelloWorldFunction", - runtime = _lambda.Runtime.NODEJS_20_X, # Provide any supported Node.js runtime - handler = "index.handler", - code = _lambda.Code.from_inline( - """ - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello CDK!'), - }; - }; - """ - ), - ) - - # ...</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Java</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">src/main/java/…​/HelloCdkStack.java</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">// ... - -public class HelloCdkStack extends Stack { - public HelloCdkStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public HelloCdkStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - // Modify the Lambda function resource - Function myFunction = Function.Builder.create(this, "HelloWorldFunction") - .runtime(Runtime.NODEJS_20_X) // Provide any supported Node.js runtime - .handler("index.handler") - .code(Code.fromInline( - "exports.handler = async function(event) {" + - " return {" + - " statusCode: 200," + - " body: JSON.stringify('Hello CDK!')" + - " };" + - "};")) - .build(); - - // ... - } -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">// ... - -namespace HelloCdk -{ - public class HelloCdkStack : Stack - { - internal HelloCdkStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) - { - // Modify the Lambda function resource - var myFunction = new Function(this, "HelloWorldFunction", new FunctionProps - { - Runtime = Runtime.NODEJS_20_X, // Provide any supported Node.js runtime - Handler = "index.handler", - Code = Code.FromInline(@" - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello CDK!'), - }; - }; - "), - }); - - // ... - } - } -}</code></pre> -</div> -</div> -</dd> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">// ... - -type HelloCdkStackProps struct { - awscdk.StackProps -} - -func NewHelloCdkStack(scope constructs.Construct, id string, props *HelloCdkStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - stack := awscdk.NewStack(scope, &id, &sprops) - - // Modify the Lambda function resource - myFunction := awslambda.NewFunction(stack, jsii.String("HelloWorldFunction"), &awslambda.FunctionProps{ - Runtime: awslambda.Runtime_NODEJS_20_X(), // Provide any supported Node.js runtime - Handler: jsii.String("index.handler"), - Code: awslambda.Code_FromInline(jsii.String(` - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello CDK!'), - }; - }; - `)), - }) - -// ...</code></pre> -</div> -</div> -</dd> -</dl> -</div> -<div class="paragraph"> -<p>Currently, your code changes have not made any direct updates to your deployed Lambda resource. Your code defines the desired state of your resource. To modify your deployed resource, you will use the CDK <code class="noloc">CLI</code> to synthesize the desired state into a new AWS CloudFormation template. Then, you will deploy your new CloudFormation template as a change set. Change sets make only the necessary changes to reach your new desired state.</p> -</div> -<div class="paragraph"> -<p>To preview your changes, run the <code>cdk diff</code> command. The following is an example:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk diff -Stack HelloCdkStack -Hold on while we create a read-only change set to get a diff with accurate replacement information (use --no-change-set to use a less accurate but faster template-only diff) -Resources -[~] AWS::Lambda::Function HelloWorldFunction HelloWorldFunctionunique-identifier - └─ [~] Code - └─ [~] .ZipFile: - ├─ [-] - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello World!'), - }; - }; - - └─ [+] - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello CDK!'), - }; - }; - - -✨ Number of stacks with differences: 1</code></pre> -</div> -</div> -<div class="paragraph"> -<p>To create this diff, the CDK <code class="noloc">CLI</code> queries your AWS account account for the latest AWS CloudFormation template for the <code class="path">HelloCdkStack</code> stack. Then, it compares the latest template with the template it just synthesized from your app.</p> -</div> -<div class="paragraph"> -<p>To implement your changes, run the <code>cdk deploy</code> command. The following is an example:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk deploy - -✨ Synthesis time: 2.12s - -HelloCdkStack: start: Building unique-identifier:current_account-current_region -HelloCdkStack: success: Built unique-identifier:current_account-current_region -HelloCdkStack: start: Publishing unique-identifier:current_account-current_region -HelloCdkStack: success: Published unique-identifier:current_account-current_region -HelloCdkStack: deploying... [1/1] -HelloCdkStack: creating CloudFormation changeset... - - ✅ HelloCdkStack - -✨ Deployment time: 26.96s - -Outputs: -HelloCdkStack.myFunctionUrlOutput = https://unique-identifier.lambda-url.<Region>.on.aws/ -Stack ARN: -arn:aws:cloudformation:Region:account-id:stack/HelloCdkStack/unique-identifier - -✨ Total time: 29.07s</code></pre> -</div> -</div> -<div class="paragraph"> -<p>To interact with your application, repeat <a href="#hello-world-interact">Step 10: Interact with your application on AWS</a>. The following is an example:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ curl https://<api-id>.lambda-url.<Region>.on.aws/ -"Hello CDK!"%</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="hello-world-delete">4.6.14. Step 12: Delete your application</h4> -<div class="paragraph"> -<p>In this step, you use the CDK <code class="noloc">CLI</code><code>cdk destroy</code> command to delete your application. This command deletes the CloudFormation stack associated with your CDK stack, which includes the resources you created.</p> -</div> -<div class="paragraph"> -<p>To delete your application, run the <code>cdk destroy</code> command and confirm your request to delete the application. The following is an example:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk destroy -Are you sure you want to delete: HelloCdkStack (y/n)? y -HelloCdkStack: destroying... [1/1] - - ✅ HelloCdkStack: destroyed</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="hello-world-next-steps">4.6.15. Next steps</h4> -<div class="paragraph"> -<p>Congratulations! You’ve completed this tutorial and have used the AWS CDK to successfully create, modify, and delete resources in the AWS Cloud. You’re now ready to begin using the AWS CDK.</p> -</div> -<div class="paragraph"> -<p>To learn more about using the AWS CDK in your preferred programming language, see <a href="#work-with">Work with the AWS CDK library</a>.</p> -</div> -<div class="paragraph"> -<p>For additional resources, see the following:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Try the <a href="https://cdkworkshop.com/">CDK Workshop</a> for a more in-depth tour involving a more complex project.</p> -</li> -<li> -<p>See the <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-construct-library.html">API reference</a> to begin exploring the CDK constructs available for your favorite AWS services.</p> -</li> -<li> -<p>Visit <a href="https://constructs.dev/search?q=&cdk=aws-cdk&cdkver=2&sort=downloadsDesc&offset=0">Construct Hub</a> to discover constructs created by AWS and others.</p> -</li> -<li> -<p>Explore <a href="https://github.com/aws-samples/aws-cdk-examples">Examples</a> of using the AWS CDK.</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>The AWS CDK is an open-source project. To contribute, see to <a href="https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md">Contributing to the AWS Cloud Development Kit (AWS CDK)</a>.</p> -</div> -</div> -</div> -</div> -</div> -<div class="sect1 topic"> -<h2 id="work-with">5. Work with the AWS CDK library</h2> -<div class="sectionbody"> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Import and use the AWS Cloud Development Kit (AWS CDK) library to define your AWS Cloud infrastructure with a <a href="#languages">supported programming language</a>.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>Import and use the AWS Cloud Development Kit (AWS CDK) library to define your AWS Cloud infrastructure with a <a href="#languages">supported programming language</a>.</p> -</div> -<div class="sect2"> -<h3 id="work-with-library">5.1. Import the AWS CDK Library</h3> -<div class="paragraph"> -<p>The <a href="#libraries">AWS CDK Library</a> is often referred to by its <code class="noloc">TypeScript</code> package name of <code>aws-cdk-lib</code>. The actual package name varies by language. The following is an example of how to install and import the CDK Library:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>​</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">JavaScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>​</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Python</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>​</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Java</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>​</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">C#</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>​</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Go</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>​</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div class="paragraph"> -<p>The <code>construct</code> base class and supporting code is in the <code>constructs</code> library. Experimental constructs, where the API is still undergoing refinement, are distributed as separate modules.</p> -</div> -</div> -<div class="sect2"> -<h3 id="work-with-library-reference">5.2. Using the AWS CDK API Reference</h3> -<div class="paragraph"> -<p>Use the <a href="#libraries-reference">AWS CDK API reference</a> as you develop with the AWS CDK.</p> -</div> -<div class="paragraph"> -<p>Each module’s reference material is broken into the following sections.</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><em>Overview</em>: Introductory material you’ll need to know to work with the service in the AWS CDK, including concepts and examples.</p> -</li> -<li> -<p><em>Constructs</em>: Library classes that represent one or more concrete AWS resources. These are the "curated" (L2) resources or patterns (L3 resources) that provide a high-level interface with sane defaults.</p> -</li> -<li> -<p><em>Classes</em>: Non-construct classes that provide functionality used by constructs in the module.</p> -</li> -<li> -<p><em>Structs</em>: Data structures (attribute bundles) that define the structure of composite values such as properties (the <code>props</code> argument of constructs) and options.</p> -</li> -<li> -<p><em>Interfaces</em>: Interfaces, whose names all begin with "I", define the absolute minimum functionality for the corresponding construct or other class. The CDK uses construct interfaces to represent AWS resources that are defined outside your AWS CDK app and referenced by methods such as <code>Bucket.fromBucketArn()</code>.</p> -</li> -<li> -<p><em>Enums</em>: Collections of named values for use in specifying certain construct parameters. Using an enumerated value allows the CDK to check these values for validity during synthesis.</p> -</li> -<li> -<p><em>CloudFormation Resources</em>: These L1 constructs, whose names begin with "Cfn", represent exactly the resources defined in the CloudFormation specification. They are automatically generated from that specification with each CDK release. Each L2 or L3 construct encapsulates one or more CloudFormation resources.</p> -</li> -<li> -<p><em>CloudFormation Property Types</em>: The collection of named values that define the properties for each CloudFormation Resource.</p> -</li> -</ul> -</div> -<div class="sect3"> -<h4 id="work-with-library-interfaces">5.2.1. Interfaces compared with construct classes</h4> -<div class="paragraph"> -<p>The AWS CDK uses interfaces in a specific way that may not be obvious even if you are familiar with interfaces as a programming concept.</p> -</div> -<div class="paragraph"> -<p>The AWS CDK supports using resources defined outside CDK applications using methods such as <code>Bucket.fromBucketArn()</code>. External resources cannot be modified and may not have all the functionality available with resources defined in your CDK app using e.g. the <code>Bucket</code> class. Interfaces, then, represent the bare minimum functionality available in the CDK for a given AWS resource type, <em>including external resources.</em></p> -</div> -<div class="paragraph"> -<p>When instantiating resources in your CDK app, then, you should always use concrete classes such as <code>Bucket</code>. When specifying the type of an argument you are accepting in one of your own constructs, use the interface type such as <code>IBucket</code> if you are prepared to deal with external resources (that is, you won’t need to change them). If you require a CDK-defined construct, specify the most general type you can use.</p> -</div> -<div class="paragraph"> -<p>Some interfaces are minimum versions of properties or options bundles associated with specific classes, rather than constructs. Such interfaces can be useful when subclassing to accept arguments that you’ll pass on to your parent class. If you require one or more additional properties, you’ll want to implement or derive from this interface, or from a more specific type.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>Some programming languages supported by the AWS CDK don’t have an interface feature. In these languages, interfaces are just ordinary classes. You can identify them by their names, which follow the pattern of an initial "I" followed by the name of some other construct (e.g. <code>IBucket</code>). The same rules apply.</p> -</div> -</td> -</tr> -</table> -</div> -</div> -</div> -<div class="sect2"> -<h3 id="work-with-cdk-dependencies">5.3. Managing dependencies</h3> -<div class="paragraph"> -<p>Dependencies for your AWS CDK app or library are managed using package management tools. These tools are commonly used with the programming languages.</p> -</div> -<div class="paragraph"> -<p>Typically, the AWS CDK supports the language’s standard or official package management tool if there is one. Otherwise, the AWS CDK will support the language’s most popular or widely supported one. You may also be able to use other tools, especially if they work with the supported tools. However, official support for other tools is limited.</p> -</div> -<div class="paragraph"> -<p>The AWS CDK supports the following package managers:</p> -</div> -<table class="tableblock frame-all grid-all stretch"> -<colgroup> -<col style="width: 50%;"> -<col style="width: 50%;"> -</colgroup> -<thead> -<tr> -<th class="tableblock halign-left valign-top">Language</th> -<th class="tableblock halign-left valign-top">Supported package management tool</th> -</tr> -</thead> -<tbody> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">TypeScript/JavaScript</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">NPM (Node Package Manager) or Yarn</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">Python</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">PIP (Package Installer for Python)</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">Java</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Maven</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">C#</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">NuGet</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">Go</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Go modules</p></td> -</tr> -</tbody> -</table> -<div class="paragraph"> -<p>When you create a new project using the AWS CDK <code class="noloc">CLI</code><code>cdk init</code> command, dependencies for the CDK core libraries and stable constructs are automatically specified.</p> -</div> -<div class="paragraph"> -<p>For more information on managing dependencies for supported programming languages, see the following:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><a href="#work-with-cdk-typescript-dependencies">Managing dependencies in TypeScript</a>.</p> -</li> -<li> -<p><a href="#work-with-cdk-javascript-dependencies">Managing dependencies in JavaScript</a>.</p> -</li> -<li> -<p><a href="#work-with-cdk-python-dependencies">Managing dependencies in Python</a>.</p> -</li> -<li> -<p><a href="#work-with-cdk-java-dependencies">Managing dependencies in Java</a>.</p> -</li> -<li> -<p><a href="#work-with-cdk-csharp-dependencies">Managing dependencies in C#</a>.</p> -</li> -<li> -<p><a href="#work-with-cdk-go-dependencies">Managing dependencies in Go</a>.</p> -</li> -</ul> -</div> -</div> -<div class="sect2"> -<h3 id="work-with-cdk-compare">5.4. Comparing AWS CDK in <code class="noloc">TypeScript</code> with other languages</h3> -<div class="paragraph"> -<p>TypeScript was the first language supported for developing AWS CDK applications. Therefore, a substantial amount of example CDK code is written in TypeScript. If you are developing in another language, it might be useful to compare how AWS CDK code is implemented in TypeScript compared to your language of choice. This can help you use the examples throughout documentation.</p> -</div> -<div class="sect3"> -<h4 id="work-with-cdk-compare-import">5.4.1. Importing a module</h4> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript/JavaScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>TypeScript supports importing either an entire namespace, or individual objects from a namespace. Each namespace includes constructs and other classes for use with a given AWS service.</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">// Import main CDK library as cdk -import * as cdk from 'aws-cdk-lib'; // ES6 import preferred in TS -const cdk = require('aws-cdk-lib'); // Node.js require() preferred in JS - -// Import specific core CDK classes -import { Stack, App } from 'aws-cdk-lib'; -const { Stack, App } = require('aws-cdk-lib'); - -// Import AWS S3 namespace as s3 into current namespace -import { aws_s3 as s3 } from 'aws-cdk-lib'; // TypeScript -const s3 = require('aws-cdk-lib/aws-s3'); // JavaScript - -// Having imported cdk already as above, this is also valid -const s3 = cdk.aws_s3; - -// Now use s3 to access the S3 types -const bucket = s3.Bucket(...); - -// Selective import of s3.Bucket -import { Bucket } from 'aws-cdk-lib/aws-s3'; // TypeScript -const { Bucket } = require('aws-cdk-lib/aws-s3'); // JavaScript - -// Now use Bucket to instantiate an S3 bucket -const bucket = Bucket(...);</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Python</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Like TypeScript, Python supports namespaced module imports and selective imports. Namespaces in Python look like <strong>aws_cdk.</strong><em>xxx</em>, where <em>xxx</em> represents an AWS service name, such as <strong>s3</strong> for Amazon S3. (Amazon S3 is used in these examples).</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python"># Import main CDK library as cdk -import aws_cdk as cdk - -# Selective import of specific core classes -from aws_cdk import Stack, App - -# Import entire module as s3 into current namespace -import aws_cdk.aws_s3 as s3 - -# s3 can now be used to access classes it contains -bucket = s3.Bucket(...) - -# Selective import of s3.Bucket into current namespace -from aws_cdk.s3 import Bucket - -# Bucket can now be used to instantiate a bucket -bucket = Bucket(...)</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Java</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Java’s imports work differently from TypeScript’s. Each import statement imports either a single class name from a given package, or all classes defined in that package (using <code>\*</code>). Classes may be accessed using either the class name by itself if it has been imported, or the <em>qualified</em> class name including its package.</p> -<div class="paragraph"> -<p>Libraries are named like <code>software.amazon.awscdk.services.xxx</code> for the AWS Construct Library (the main library is <code>software.amazon.awscdk</code>). The Maven group ID for AWS CDK packages is <code>software.amazon.awscdk</code>.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">// Make certain core classes available -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.App; - -// Make all Amazon S3 construct library classes available -import software.amazon.awscdk.services.s3.*; - -// Make only Bucket and EventType classes available -import software.amazon.awscdk.services.s3.Bucket; -import software.amazon.awscdk.services.s3.EventType; - -// An imported class may now be accessed using the simple class name (assuming that name -// does not conflict with another class) -Bucket bucket = Bucket.Builder.create(...).build(); - -// We can always use the qualified name of a class (including its package) even without an -// import directive -software.amazon.awscdk.services.s3.Bucket bucket = - software.amazon.awscdk.services.s3.Bucket.Builder.create(...) - .build(); - -// Java 10 or later can use var keyword to avoid typing the type twice -var bucket = - software.amazon.awscdk.services.s3.Bucket.Builder.create(...) - .build();</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">C#</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>In C#, you import types with the <code>using</code> directive. There are two styles. One gives you access to all the types in the specified namespace by using their plain names. With the other, you can refer to the namespace itself by using an alias.</p> -<div class="paragraph"> -<p>Packages are named like <code>Amazon.CDK.AWS.xxx</code> for AWS Construct Library packages. (The core module is <code>Amazon.CDK</code>.)</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">// Make CDK base classes available under cdk -using cdk = Amazon.CDK; - -// Make all Amazon S3 construct library classes available -using Amazon.CDK.AWS.S3; - -// Now we can access any S3 type using its name -var bucket = new Bucket(...); - -// Import the S3 namespace under an alias -using s3 = Amazon.CDK.AWS.S3; - -// Now we can access an S3 type through the namespace alias -var bucket = new s3.Bucket(...); - -// We can always use the qualified name of a type (including its namespace) even without a -// using directive -var bucket = new Amazon.CDK.AWS.S3.Bucket(...)</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Go</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Each AWS Construct Library module is provided as a Go package.</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">import ( - "github.com/aws/aws-cdk-go/awscdk/v2" // CDK core package - "github.com/aws/aws-cdk-go/awscdk/v2/awss3" // AWS S3 construct library module -) - -// now instantiate a bucket -bucket := awss3.NewBucket(...) - -// use aliases for brevity/clarity -import ( - cdk "github.com/aws/aws-cdk-go/awscdk/v2" // CDK core package - s3 "github.com/aws/aws-cdk-go/awscdk/v2/awss3" // AWS S3 construct library module -) - -bucket := s3.NewBucket(...)</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect3"> -<h4 id="work-with-cdk-compare-class">5.4.2. Instantiating a construct</h4> -<div class="paragraph"> -<p>AWS CDK construct classes have the same name in all supported languages. Most languages use the <code>new</code> keyword to instantiate a class (Python and Go do not). Also, in most languages, the keyword <code>this</code> refers to the current instance. (Python uses <code>self</code> by convention.) You should pass a reference to the current instance as the <code>scope</code> parameter to every construct you create.</p> -</div> -<div class="paragraph"> -<p>The third argument to an AWS CDK construct is <code>props</code>, an object containing attributes needed to build the construct. This argument may be optional, but when it is required, the supported languages handle it in idiomatic ways. The names of the attributes are also adapted to the language’s standard naming patterns.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript/JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">// Instantiate default Bucket -const bucket = new s3.Bucket(this, 'amzn-s3-demo-bucket'); - -// Instantiate Bucket with bucketName and versioned properties -const bucket = new s3.Bucket(this, 'amzn-s3-demo-bucket', { - bucketName: 'amzn-s3-demo-bucket', - versioned: true, -}); - -// Instantiate Bucket with websiteRedirect, which has its own sub-properties -const bucket = new s3.Bucket(this, 'amzn-s3-demo-bucket', { - websiteRedirect: {host: 'aws.amazon.com'}});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Python doesn’t use a <code>new</code> keyword when instantiating a class. The properties argument is represented using keyword arguments, and the arguments are named using <code>snake_case</code>.</p> -<div class="paragraph"> -<p>If a props value is itself a bundle of attributes, it is represented by a class named after the property, which accepts keyword arguments for the subproperties.</p> -</div> -<div class="paragraph"> -<p>In Python, the current instance is passed to methods as the first argument, which is named <code>self</code> by convention.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python"># Instantiate default Bucket -bucket = s3.Bucket(self, "amzn-s3-demo-bucket") - -# Instantiate Bucket with bucket_name and versioned properties -bucket = s3.Bucket(self, "amzn-s3-demo-bucket", bucket_name="amzn-s3-demo-bucket", versioned=true) - -# Instantiate Bucket with website_redirect, which has its own sub-properties -bucket = s3.Bucket(self, "amzn-s3-demo-bucket", website_redirect=s3.WebsiteRedirect( - host_name="aws.amazon.com"))</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Java</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>In Java, the props argument is represented by a class named <code>XxxxProps</code> (for example, <code>BucketProps</code> for the <code>Bucket</code> construct’s props). You build the props argument using a builder pattern.</p> -<div class="paragraph"> -<p>Each <code>XxxxProps</code> class has a builder. There is also a convenient builder for each construct that builds the props and the construct in one step, as shown in the following example.</p> -</div> -<div class="paragraph"> -<p>Props are named the same as in TypeScript, using <code>camelCase</code>.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">// Instantiate default Bucket -Bucket bucket = Bucket(self, "amzn-s3-demo-bucket"); - -// Instantiate Bucket with bucketName and versioned properties -Bucket bucket = Bucket.Builder.create(self, "amzn-s3-demo-bucket") - .bucketName("amzn-s3-demo-bucket").versioned(true) - .build(); - -# Instantiate Bucket with websiteRedirect, which has its own sub-properties -Bucket bucket = Bucket.Builder.create(self, "amzn-s3-demo-bucket") - .websiteRedirect(new websiteRedirect.Builder() - .hostName("aws.amazon.com").build()) - .build();</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">C#</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>In C#, props are specified using an object initializer to a class named <code>XxxxProps</code> (for example, <code>BucketProps</code> for the <code>Bucket</code> construct’s props).</p> -<div class="paragraph"> -<p>Props are named similarly to TypeScript, except using <code>PascalCase</code>.</p> -</div> -<div class="paragraph"> -<p>It is convenient to use the <code>var</code> keyword when instantiating a construct, so you don’t need to type the class name twice. However, your local code style guide may vary.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">// Instantiate default Bucket -var bucket = Bucket(self, "amzn-s3-demo-bucket"); - -// Instantiate Bucket with BucketName and Versioned properties -var bucket = Bucket(self, "amzn-s3-demo-bucket", new BucketProps { - BucketName = "amzn-s3-demo-bucket", - Versioned = true}); - -// Instantiate Bucket with WebsiteRedirect, which has its own sub-properties -var bucket = Bucket(self, "amzn-s3-demo-bucket", new BucketProps { - WebsiteRedirect = new WebsiteRedirect { - HostName = "aws.amazon.com" - }});</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Go</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>To create a construct in Go, call the function <code>NewXxxxxx</code> where <code>Xxxxxxx</code> is the name of the construct. The constructs' properties are defined as a struct.</p> -<div class="paragraph"> -<p>In Go, all construct parameters are pointers, including values like numbers, Booleans, and strings. Use the convenience functions like <code>jsii.String</code> to create these pointers.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go"> // Instantiate default Bucket - bucket := awss3.NewBucket(stack, jsii.String("amzn-s3-demo-bucket"), nil) - - // Instantiate Bucket with BucketName and Versioned properties - bucket1 := awss3.NewBucket(stack, jsii.String("amzn-s3-demo-bucket"), &awss3.BucketProps{ - BucketName: jsii.String("amzn-s3-demo-bucket"), - Versioned: jsii.Bool(true), - }) - - // Instantiate Bucket with WebsiteRedirect, which has its own sub-properties - bucket2 := awss3.NewBucket(stack, jsii.String("amzn-s3-demo-bucket"), &awss3.BucketProps{ - WebsiteRedirect: &awss3.RedirectTarget{ - HostName: jsii.String("aws.amazon.com"), - }})</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect3"> -<h4 id="work-with-cdk-compare-members">5.4.3. Accessing members</h4> -<div class="paragraph"> -<p>It is common to refer to attributes or properties of constructs and other AWS CDK classes and use these values as, for example, inputs to build other constructs. The naming differences described previously for methods apply here also. Furthermore, in Java, it is not possible to access members directly. Instead, a getter method is provided.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript/JavaScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Names are <code>camelCase</code>.</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">bucket.bucketArn</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Python</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Names are <code>snake_case</code>.</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">bucket.bucket_arn</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Java</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>A getter method is provided for each property; these names are <code>camelCase</code>.</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">bucket.getBucketArn()</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">C#</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Names are <code>PascalCase</code>.</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">bucket.BucketArn</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Go</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Names are <code>PascalCase</code>.</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">bucket.BucketArn</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect3"> -<h4 id="work-with-cdk-compare-enums">5.4.4. Enum constants</h4> -<div class="paragraph"> -<p>Enum constants are scoped to a class, and have uppercase names with underscores in all languages (sometimes referred to as <code>SCREAMING_SNAKE_CASE</code>). Since class names also use the same casing in all supported languages except Go, qualified enum names are also the same in these languages.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">s3.BucketEncryption.KMS_MANAGED</code></pre> -</div> -</div> -<div class="paragraph"> -<p>In Go, enum constants are attributes of the module namespace and are written as follows.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">awss3.BucketEncryption_KMS_MANAGED</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="work-with-cdk-compare-object">5.4.5. Object interfaces</h4> -<div class="paragraph"> -<p>The AWS CDK uses TypeScript object interfaces to indicate that a class implements an expected set of methods and properties. You can recognize an object interface because its name starts with <code>I</code>. A concrete class indicates the interfaces that it implements by using the <code>implements</code> keyword.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript/JavaScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>NOTE: JavaScript doesn’t have an interface feature. You can ignore the <code>implements</code> keyword and the class names following it.</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import { IAspect, IConstruct } from 'aws-cdk-lib'; - -class MyAspect implements IAspect { - public visit(node: IConstruct) { - console.log('Visited', node.node.path); - } -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Python</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Python doesn’t have an interface feature. However, for the AWS CDK you can indicate interface implementation by decorating your class with <code>@jsii.implements(interface)</code>.</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">from aws_cdk import IAspect, IConstruct -import jsii - -@jsii.implements(IAspect) -class MyAspect(): - def visit(self, node: IConstruct) -> None: - print("Visited", node.node.path)</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">import software.amazon.awscdk.IAspect; -import software.amazon.awscdk.IConstruct; - -public class MyAspect implements IAspect { - public void visit(IConstruct node) { - System.out.format("Visited %s", node.getNode().getPath()); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; - -public class MyAspect : IAspect -{ - public void Visit(IConstruct node) - { - System.Console.WriteLine($"Visited ${node.Node.Path}"); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Go structs do not need to explicitly declare which interfaces they implement. The Go compiler determines implementation based on the methods and properties available on the structure. For example, in the following code, <code>MyAspect</code> implements the <code>IAspect</code> interface because it provides a <code>Visit</code> method that takes a construct.</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">type MyAspect struct { -} - -func (a MyAspect) Visit(node constructs.IConstruct) { - fmt.Println("Visited", *node.Node().Path()) -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="work-with-cdk-typescript">5.5. Working with the AWS CDK in TypeScript</h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p><code class="noloc">TypeScript</code> is a fully-supported client language for the AWS CDK and is considered stable.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>TypeScript is a fully-supported client language for the AWS Cloud Development Kit (AWS CDK) and is considered stable. Working with the AWS CDK in TypeScript uses familiar tools, including Microsoft’s TypeScript compiler (<code>tsc</code>), <a href="https://nodejs.org/">Node.js</a> and the Node Package Manager (<code>npm</code>). You may also use <a href="https://yarnpkg.com/">Yarn</a> if you prefer, though the examples in this Guide use NPM. The modules comprising the AWS Construct Library are distributed via the NPM repository, <a href="https://www.npmjs.com/">npmjs.org</a>.</p> -</div> -<div class="paragraph"> -<p>You can use any editor or IDE. Many AWS CDK developers use <a href="https://code.visualstudio.com/">Visual Studio Code</a> (or its open-source equivalent <a href="https://vscodium.com/">VSCodium</a>), which has excellent support for TypeScript.</p> -</div> -<div class="paragraph topiclist"> -<p>[[Topic List]]</p> -</div> -<div class="sect3"> -<h4 id="typescript-prerequisites">5.5.1. Get started with TypeScript</h4> -<div class="paragraph"> -<p>To work with the AWS CDK, you must have an AWS account and credentials and have installed Node.js and the AWS CDK Toolkit. See <a href="#getting-started">Getting started with the AWS CDK</a>.</p> -</div> -<div class="paragraph"> -<p>You also need TypeScript itself (version 3.8 or later). If you don’t already have it, you can install it using <code>npm</code>.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">npm install -g typescript</code></pre> -</div> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>If you get a permission error, and have administrator access on your system, try <code>sudo npm install -g typescript</code>.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>Keep TypeScript up to date with a regular <code>npm update -g typescript</code>.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>Third-party language deprecation: language version is only supported until its EOL (End Of Life) shared by the vendor or community and is subject to change with prior notice.</p> -</div> -</td> -</tr> -</table> -</div> -</div> -<div class="sect3"> -<h4 id="typescript-newproject">5.5.2. Creating a project</h4> -<div class="paragraph"> -<p>You create a new AWS CDK project by invoking <code>cdk init</code> in an empty directory. Use the <code>--language</code> option and specify <code>typescript</code>:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">mkdir my-project -cd my-project -cdk init app --language typescript</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Creating a project also installs the <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib-readme.html">aws-cdk-lib</a> module and its dependencies.</p> -</div> -<div class="paragraph"> -<p><code>cdk init</code> uses the name of the project folder to name various elements of the project, including classes, subfolders, and files. Hyphens in the folder name are converted to underscores. However, the name should otherwise follow the form of a TypeScript identifier; for example, it should not start with a number or contain spaces.</p> -</div> -</div> -<div class="sect3"> -<h4 id="typescript-local">5.5.3. Using local <code>tsc</code> and <code>cdk</code></h4> -<div class="paragraph"> -<p>For the most part, this guide assumes you install TypeScript and the CDK Toolkit globally (<code>npm install -g typescript aws-cdk</code>), and the provided command examples (such as <code>cdk synth</code>) follow this assumption. This approach makes it easy to keep both components up to date, and since both take a strict approach to backward compatibility, there is generally little risk in always using the latest versions.</p> -</div> -<div class="paragraph"> -<p>Some teams prefer to specify all dependencies within each project, including tools like the TypeScript compiler and the CDK Toolkit. This practice lets you pin these components to specific versions and ensure that all developers on your team (and your CI/CD environment) use exactly those versions. This eliminates a possible source of change, helping to make builds and deployments more consistent and repeatable.</p> -</div> -<div class="paragraph"> -<p>The CDK includes dependencies for both TypeScript and the CDK Toolkit in the TypeScript project template’s <code class="path">package.json</code>, so if you want to use this approach, you don’t need to make any changes to your project. All you need to do is use slightly different commands for building your app and for issuing <code>cdk</code> commands.</p> -</div> -<div class="paragraph"> -<p><code>npx aws-cdk</code> runs the version of the CDK Toolkit installed locally in the current project, if one exists, falling back to the global installation, if any. If no global installation exists, <code>npx</code> downloads a temporary copy of the CDK Toolkit and runs that. You may specify an arbitrary version of the CDK Toolkit using the <code>@</code> syntax: <code>npx aws-cdk@2.0 --version</code> prints <code>2.0.0</code>.</p> -</div> -<div class="admonitionblock tip"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-tip" title="Tip"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>Set up an alias so you can use the <code>cdk</code> command with a local CDK Toolkit installation.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">macOS/Linux</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">alias cdk="npx aws-cdk"</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Windows</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">doskey cdk=npx aws-cdk $*</code></pre> -</div> -</div> -</td> -</tr> -</table> -</div> -</div> -<div class="sect3"> -<h4 id="typescript-managemodules">5.5.4. Managing AWS Construct Library modules</h4> -<div class="paragraph"> -<p>Use the Node Package Manager (<code>npm</code>) to install and update AWS Construct Library modules for use by your apps, as well as other packages you need. (You may use <code>yarn</code> instead of <code>npm</code> if you prefer.) <code>npm</code> also installs the dependencies for those modules automatically.</p> -</div> -<div class="paragraph"> -<p>Most AWS CDK constructs are in the main CDK package, named <code>aws-cdk-lib</code>, which is a default dependency in new projects created by <strong class="command">cdk init</strong>. "Experimental" AWS Construct Library modules, where higher-level constructs are still under development, are named like <code>@aws-cdk/[replaceable]</code>SERVICE-NAME<code>-alpha</code>. The service name has an <em>aws-</em> prefix. If you’re unsure of a module’s name, <a href="https://www.npmjs.com/search?q=%40aws-cdk">search for it on NPM</a>.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>The <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-construct-library.html">CDK API Reference</a> also shows the package names.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>For example, the command below installs the experimental module for AWS CodeStar.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">npm install @aws-cdk/aws-codestar-alpha</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Some services' Construct Library support is in more than one namespace. For example, besides <code>aws-route53</code>, there are three additional Amazon Route 53 namespaces, <code>aws-route53-targets</code>, <code>aws-route53-patterns</code>, and <code>aws-route53resolver</code>.</p> -</div> -<div class="paragraph"> -<p>Your project’s dependencies are maintained in <code class="path">package.json</code>. You can edit this file to lock some or all of your dependencies to a specific version or to allow them to be updated to newer versions under certain criteria. To update your project’s NPM dependencies to the latest permitted version according to the rules you specified in <code class="path">package.json</code>:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">npm update</code></pre> -</div> -</div> -<div class="paragraph"> -<p>In TypeScript, you import modules into your code under the same name you use to install them using NPM. We recommend the following practices when importing AWS CDK classes and AWS Construct Library modules in your applications. Following these guidelines will help make your code consistent with other AWS CDK applications as well as easier to understand.</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Use ES6-style <code>import</code> directives, not <code>require()</code>.</p> -</li> -<li> -<p>Generally, import individual classes from <code>aws-cdk-lib</code>.</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import { App, Stack } from 'aws-cdk-lib';</code></pre> -</div> -</div> -</li> -<li> -<p>If you need many classes from <code>aws-cdk-lib</code>, you may use a namespace alias of <code>cdk</code> instead of importing the individual classes. Avoid doing both.</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as cdk from 'aws-cdk-lib';</code></pre> -</div> -</div> -</li> -<li> -<p>Generally, import AWS service constructs using short namespace aliases.</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import { aws_s3 as s3 } from 'aws-cdk-lib';</code></pre> -</div> -</div> -</li> -</ul> -</div> -</div> -<div class="sect3"> -<h4 id="work-with-cdk-typescript-dependencies">5.5.5. Managing dependencies in <code class="noloc">TypeScript</code></h4> -<div class="paragraph"> -<p>In <code class="noloc">TypeScript</code> CDK projects, dependencies are specified in the <code class="path">package.json</code> file in the project’s main directory. The core AWS CDK modules are in a single <code class="noloc">NPM</code> package called <code class="path">aws-cdk-lib</code>.</p> -</div> -<div class="paragraph"> -<p>When you install a package using <strong class="command">npm install</strong>, NPM records the package in <code class="path">package.json</code> for you.</p> -</div> -<div class="paragraph"> -<p>If you prefer, you may use Yarn in place of NPM. However, the CDK does not support Yarn’s plug-and-play mode, which is default mode in Yarn 2. Add the following to your project’s <code class="path">.yarnrc.yml</code> file to turn off this feature.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-yaml" data-lang="yaml">nodeLinker: node-modules</code></pre> -</div> -</div> -<div class="sect4"> -<h5 id="work-with-cdk-typescript-dependencies-apps">CDK applications</h5> -<div class="paragraph"> -<p>The following is an example <code class="path">package.json</code> file generated by the <code>cdk init --language typescript</code> command:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-json" data-lang="json">{ - "name": "my-package", - "version": "0.1.0", - "bin": { - "my-package": "bin/my-package.js" - }, - "scripts": { - "build": "tsc", - "watch": "tsc -w", - "test": "jest", - "cdk": "cdk" - }, - "devDependencies": { - "@types/jest": "^26.0.10", - "@types/node": "10.17.27", - "jest": "^26.4.2", - "ts-jest": "^26.2.0", - "aws-cdk": "2.16.0", - "ts-node": "^9.0.0", - "typescript": "~3.9.7" - }, - "dependencies": { - "aws-cdk-lib": "2.16.0", - "constructs": "^10.0.0", - "source-map-support": "^0.5.16" - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>For deployable CDK apps, <code>aws-cdk-lib</code> must be specified in the <code>dependencies</code> section of <code class="path">package.json</code>. You can use a caret (^) version number specifier to indicate that you will accept later versions than the one specified as long as they are within the same major version.</p> -</div> -<div class="paragraph"> -<p>For experimental constructs, specify exact versions for the alpha construct library modules, which have APIs that may change. Do not use ^ or ~ since later versions of these modules may bring API changes that can break your app.</p> -</div> -<div class="paragraph"> -<p>Specify versions of libraries and tools needed to test your app (for example, the <code class="path">jest</code> testing framework) in the <code>devDependencies</code> section of <code class="path">package.json</code>. Optionally, use ^ to specify that later compatible versions are acceptable.</p> -</div> -</div> -<div class="sect4"> -<h5 id="work-with-cdk-typescript-dependencies-libraries">Third-party construct libraries</h5> -<div class="paragraph"> -<p>If you’re developing a construct library, specify its dependencies using a combination of the <code>peerDependencies</code> and <code>devDependencies</code> sections, as shown in the following example <code class="path">package.json</code> file.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-json" data-lang="json">{ - "name": "my-package", - "version": "0.0.1", - "peerDependencies": { - "aws-cdk-lib": "^2.14.0", - "@aws-cdk/aws-appsync-alpha": "2.10.0-alpha", - "constructs": "^10.0.0" - }, - "devDependencies": { - "aws-cdk-lib": "2.14.0", - "@aws-cdk/aws-appsync-alpha": "2.10.0-alpha", - "constructs": "10.0.0", - "jsii": "^1.50.0", - "aws-cdk": "^2.14.0" - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>In <code>peerDependencies</code>, use a caret (^) to specify the lowest version of <code>aws-cdk-lib</code> that your library works with. This maximizes the compatibility of your library with a range of CDK versions. Specify exact versions for alpha construct library modules, which have APIs that may change. Using <code>peerDependencies</code> makes sure that there is only one copy of all CDK libraries in the <code class="path">node_modules</code> tree.</p> -</div> -<div class="paragraph"> -<p>In <code>devDependencies</code>, specify the tools and libraries you need for testing, optionally with ^ to indicate that later compatible versions are acceptable. Specify exactly (without ^ or ~) the lowest versions of <code>aws-cdk-lib</code> and other CDK packages that you advertise your library be compatible with. This practice makes sure that your tests run against those versions. This way, if you inadvertently use a feature found only in newer versions, your tests can catch it.</p> -</div> -<div class="admonitionblock warning"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-warning" title="Warning"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p><code>peerDependencies</code> are installed automatically only by NPM 7 and later. If you are using NPM 6 or earlier, or if you are using Yarn, you must include the dependencies of your dependencies in <code>devDependencies</code>. Otherwise, they won’t be installed, and you will receive a warning about unresolved peer dependencies.</p> -</div> -</td> -</tr> -</table> -</div> -</div> -<div class="sect4"> -<h5 id="work-with-cdk-typescript-dependencies-install">Installing and updating dependencies</h5> -<div class="paragraph"> -<p>Run the following command to install your project’s dependencies.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">NPM</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none"># Install the latest version of everything that matches the ranges in 'package.json' -npm install - -# Install the same exact dependency versions as recorded in 'package-lock.json' -npm ci</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Yarn</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none"># Install the latest version of everything that matches the ranges in 'package.json' -yarn upgrade - -# Install the same exact dependency versions as recorded in 'yarn.lock' -yarn install --frozen-lockfile</code></pre> -</div> -</div> -<div class="paragraph"> -<p>To update the installed modules, the preceding <strong class="command">npm install</strong> and <strong class="command">yarn upgrade</strong> commands can be used. Either command updates the packages in <code class="path">node_modules</code> to the latest versions that satisfy the rules in <code class="path">package.json</code>. However, they do not update <code class="path">package.json</code> itself, which you might want to do to set a new minimum version. If you host your package on GitHub, you can configure <a href="https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuring-dependabot-version-updates">Dependabot version updates</a> to automatically update <code class="path">package.json</code>. Alternatively, use <a href="https://www.npmjs.com/package/npm-check-updates">npm-check-updates</a>.</p> -</div> -<div class="admonitionblock important"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-important" title="Important"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>By design, when you install or update dependencies, NPM and Yarn choose the latest version of every package that satisfies the requirements specified in <code class="path">package.json</code>. There is always a risk that these versions may be broken (either accidentally or intentionally). Test thoroughly after updating your project’s dependencies.</p> -</div> -</td> -</tr> -</table> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="typescript-cdk-idioms">5.5.6. AWS CDK idioms in TypeScript</h4> -<div class="sect4"> -<h5 id="typescript-props">Props</h5> -<div class="paragraph"> -<p>All AWS Construct Library classes are instantiated using three arguments: the <em>scope</em> in which the construct is being defined (its parent in the construct tree), an <em>id</em>, and <em>props</em>. Argument <em>props</em> is a bundle of key/value pairs that the construct uses to configure the AWS resources it creates. Other classes and methods also use the "bundle of attributes" pattern for arguments.</p> -</div> -<div class="paragraph"> -<p>In TypeScript, the shape of <code>props</code> is defined using an interface that tells you the required and optional arguments and their types. Such an interface is defined for each kind of <code>props</code> argument, usually specific to a single construct or method. For example, the <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html">Bucket</a> construct (in the <code>aws-cdk-lib/aws-s3 module</code>) specifies a <code>props</code> argument conforming to the <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.BucketProps.html">BucketProps</a> interface.</p> -</div> -<div class="paragraph"> -<p>If a property is itself an object, for example the <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.BucketProps.html#websiteredirect">websiteRedirect</a> property of <code>BucketProps</code>, that object will have its own interface to which its shape must conform, in this case <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.RedirectTarget.html">RedirectTarget</a>.</p> -</div> -<div class="paragraph"> -<p>If you are subclassing an AWS Construct Library class (or overriding a method that takes a props-like argument), you can inherit from the existing interface to create a new one that specifies any new props your code requires. When calling the parent class or base method, generally you can pass the entire props argument you received, since any attributes provided in the object but not specified in the interface will be ignored.</p> -</div> -<div class="paragraph"> -<p>A future release of the AWS CDK could coincidentally add a new property with a name you used for your own property. Passing the value you receive up the inheritance chain can then cause unexpected behavior. It’s safer to pass a shallow copy of the props you received with your property removed or set to <code>undefined</code>. For example:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">super(scope, name, {...props, encryptionKeys: undefined});</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Alternatively, name your properties so that it is clear that they belong to your construct. This way, it is unlikely they will collide with properties in future AWS CDK releases. If there are many of them, use a single appropriately-named object to hold them.</p> -</div> -</div> -<div class="sect4"> -<h5 id="typescript-missing-values">Missing values</h5> -<div class="paragraph"> -<p>Missing values in an object (such as props) have the value <code>undefined</code> in TypeScript. Version 3.7 of the language introduced operators that simplify working with these values, making it easier to specify defaults and "short-circuit" chaining when an undefined value is reached. For more information about these features, see the <a href="https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html">TypeScript 3.7 Release Notes</a>, specifically the first two features, Optional Chaining and Nullish Coalescing.</p> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="typescript-running">5.5.7. Build and run CDK apps</h4> -<div class="paragraph"> -<p>Generally, you should be in the project’s root directory when building and running your application.</p> -</div> -<div class="paragraph"> -<p>Node.js cannot run TypeScript directly; instead, your application is converted to JavaScript using the TypeScript compiler, <code>tsc</code>. The resulting JavaScript code is then executed.</p> -</div> -<div class="paragraph"> -<p>The AWS CDK automatically does this whenever it needs to run your app. However, it can be useful to compile manually to check for errors and to run tests. To compile your TypeScript app manually, issue <code>[noloc]</code>npm run build````. You may also issue <code>npm run watch</code> to enter watch mode, in which the TypeScript compiler automatically rebuilds your app whenever you save changes to a source file.</p> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="work-with-cdk-javascript">5.6. Working with the AWS CDK in JavaScript</h3> -<div class="paragraph"> -<p><code class="noloc">JavaScript</code> is a fully-supported client language for the AWS CDK and is considered stable. Working with the AWS Cloud Development Kit (AWS CDK) in JavaScript uses familiar tools, including <a href="https://nodejs.org/">Node.js</a> and the Node Package Manager (<code>npm</code>). You may also use <a href="https://yarnpkg.com/">Yarn</a> if you prefer, though the examples in this Guide use NPM. The modules comprising the AWS Construct Library are distributed via the NPM repository, <a href="https://www.npmjs.com/">npmjs.org</a>.</p> -</div> -<div class="paragraph"> -<p>You can use any editor or IDE. Many AWS CDK developers use <a href="https://code.visualstudio.com/">Visual Studio Code</a> (or its open-source equivalent <a href="https://vscodium.com/">VSCodium</a>), which has good support for JavaScript.</p> -</div> -<div class="paragraph topiclist"> -<p>[[Topic List]]</p> -</div> -<div class="sect3"> -<h4 id="javascript-prerequisites">5.6.1. Get started with <code class="noloc">JavaScript</code></h4> -<div class="paragraph"> -<p>To work with the AWS CDK, you must have an AWS account and credentials and have installed Node.js and the AWS CDK Toolkit. See <a href="#getting-started">Getting started with the AWS CDK</a>.</p> -</div> -<div class="paragraph"> -<p>JavaScript AWS CDK applications require no additional prerequisites beyond these.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>Third-party language deprecation: language version is only supported until its EOL (End Of Life) shared by the vendor or community and is subject to change with prior notice.</p> -</div> -</td> -</tr> -</table> -</div> -</div> -<div class="sect3"> -<h4 id="javascript-newproject">5.6.2. Creating a project</h4> -<div class="paragraph"> -<p>You create a new AWS CDK project by invoking <code>cdk init</code> in an empty directory. Use the <code>--language</code> option and specify <code>javascript</code>:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">mkdir my-project -cd my-project -cdk init app --language javascript</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Creating a project also installs the <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib-readme.html">aws-cdk-lib</a> module and its dependencies.</p> -</div> -<div class="paragraph"> -<p><code>cdk init</code> uses the name of the project folder to name various elements of the project, including classes, subfolders, and files. Hyphens in the folder name are converted to underscores. However, the name should otherwise follow the form of a JavaScript identifier; for example, it should not start with a number or contain spaces.</p> -</div> -</div> -<div class="sect3"> -<h4 id="javascript-local">5.6.3. Using local <code>cdk</code></h4> -<div class="paragraph"> -<p>For the most part, this guide assumes you install the CDK Toolkit globally (<code>npm install -g aws-cdk</code>), and the provided command examples (such as <code>cdk synth</code>) follow this assumption. This approach makes it easy to keep the CDK Toolkit up to date, and since the CDK takes a strict approach to backward compatibility, there is generally little risk in always using the latest version.</p> -</div> -<div class="paragraph"> -<p>Some teams prefer to specify all dependencies within each project, including tools like the CDK Toolkit. This practice lets you pin such components to specific versions and ensure that all developers on your team (and your CI/CD environment) use exactly those versions. This eliminates a possible source of change, helping to make builds and deployments more consistent and repeatable.</p> -</div> -<div class="paragraph"> -<p>The CDK includes a dependency for the CDK Toolkit in the JavaScript project template’s <code class="path">package.json</code>, so if you want to use this approach, you don’t need to make any changes to your project. All you need to do is use slightly different commands for building your app and for issuing <code>cdk</code> commands.</p> -</div> -<div class="paragraph"> -<p><code>npx aws-cdk</code> runs the version of the CDK Toolkit installed locally in the current project, if one exists, falling back to the global installation, if any. If no global installation exists, <code>npx</code> downloads a temporary copy of the CDK Toolkit and runs that. You may specify an arbitrary version of the CDK Toolkit using the <code>@</code> syntax: <code>npx aws-cdk@1.120 --version</code> prints <code>1.120.0</code>.</p> -</div> -<div class="admonitionblock tip"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-tip" title="Tip"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>Set up an alias so you can use the <code>cdk</code> command with a local CDK Toolkit installation.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">macOS/Linux</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">alias cdk="npx aws-cdk"</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Windows</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">doskey cdk=npx aws-cdk $*</code></pre> -</div> -</div> -</td> -</tr> -</table> -</div> -</div> -<div class="sect3"> -<h4 id="javascript-managemodules">5.6.4. Managing AWS Construct Library modules</h4> -<div class="paragraph"> -<p>Use the Node Package Manager (<code>npm</code>) to install and update AWS Construct Library modules for use by your apps, as well as other packages you need. (You may use <code>yarn</code> instead of <code>npm</code> if you prefer.) <code>npm</code> also installs the dependencies for those modules automatically.</p> -</div> -<div class="paragraph"> -<p>Most AWS CDK constructs are in the main CDK package, named <code>aws-cdk-lib</code>, which is a default dependency in new projects created by <strong class="command">cdk init</strong>. "Experimental" AWS Construct Library modules, where higher-level constructs are still under development, are named like <code>aws-cdk-lib/[replaceable]</code>SERVICE-NAME<code>-alpha</code>. The service name has an <em>aws-</em> prefix. If you’re unsure of a module’s name, <a href="https://www.npmjs.com/search?q=%40aws-cdk">search for it on NPM</a>.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>The <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-construct-library.html">CDK API Reference</a> also shows the package names.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>For example, the command below installs the experimental module for AWS CodeStar.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">npm install @aws-cdk/aws-codestar-alpha</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Some services' Construct Library support is in more than one namespace. For example, besides <code>aws-route53</code>, there are three additional Amazon Route 53 namespaces, <code>aws-route53-targets</code>, <code>aws-route53-patterns</code>, and <code>aws-route53resolver</code>.</p> -</div> -<div class="paragraph"> -<p>Your project’s dependencies are maintained in <code class="path">package.json</code>. You can edit this file to lock some or all of your dependencies to a specific version or to allow them to be updated to newer versions under certain criteria. To update your project’s NPM dependencies to the latest permitted version according to the rules you specified in <code class="path">package.json</code>:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">npm update</code></pre> -</div> -</div> -<div class="paragraph"> -<p>In JavaScript, you import modules into your code under the same name you use to install them using NPM. We recommend the following practices when importing AWS CDK classes and AWS Construct Library modules in your applications. Following these guidelines will help make your code consistent with other AWS CDK applications as well as easier to understand.</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Use <code>require()</code>, not ES6-style <code>import</code> directives. Older versions of Node.js do not support ES6 imports, so using the older syntax is more widely compatible. (If you really want to use ES6 imports, use <a href="https://www.npmjs.com/package/esm">esm</a> to ensure your project is compatible with all supported versions of Node.js.)</p> -</li> -<li> -<p>Generally, import individual classes from <code>aws-cdk-lib</code>.</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const { App, Stack } = require('aws-cdk-lib');</code></pre> -</div> -</div> -</li> -<li> -<p>If you need many classes from <code>aws-cdk-lib</code>, you may use a namespace alias of <code>cdk</code> instead of importing the individual classes. Avoid doing both.</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const cdk = require('aws-cdk-lib');</code></pre> -</div> -</div> -</li> -<li> -<p>Generally, import AWS Construct Libraries using short namespace aliases.</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const { s3 } = require('aws-cdk-lib/aws-s3');</code></pre> -</div> -</div> -</li> -</ul> -</div> -</div> -<div class="sect3"> -<h4 id="work-with-cdk-javascript-dependencies">5.6.5. Managing dependencies in <code class="noloc">JavaScript</code></h4> -<div class="paragraph"> -<p>In <code class="noloc">JavaScript</code> CDK projects, dependencies are specified in the <code class="path">package.json</code> file in the project’s main directory. The core AWS CDK modules are in a single <code class="noloc">NPM</code> package called <code class="path">aws-cdk-lib</code>.</p> -</div> -<div class="paragraph"> -<p>When you install a package using <strong class="command">npm install</strong>, NPM records the package in <code class="path">package.json</code> for you.</p> -</div> -<div class="paragraph"> -<p>If you prefer, you may use Yarn in place of NPM. However, the CDK does not support Yarn’s plug-and-play mode, which is default mode in Yarn 2. Add the following to your project’s <code class="path">.yarnrc.yml</code> file to turn off this feature.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-yaml" data-lang="yaml">nodeLinker: node-modules</code></pre> -</div> -</div> -<div class="sect4"> -<h5 id="work-with-cdk-javascript-dependencies-apps">CDK applications</h5> -<div class="paragraph"> -<p>The following is an example <code class="path">package.json</code> file generated by the <code>cdk init --language typescript</code> command. The file generated for JavaScript is similar, only without the TypeScript-related entries.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-json" data-lang="json">{ - "name": "my-package", - "version": "0.1.0", - "bin": { - "my-package": "bin/my-package.js" - }, - "scripts": { - "build": "tsc", - "watch": "tsc -w", - "test": "jest", - "cdk": "cdk" - }, - "devDependencies": { - "@types/jest": "^26.0.10", - "@types/node": "10.17.27", - "jest": "^26.4.2", - "ts-jest": "^26.2.0", - "aws-cdk": "2.16.0", - "ts-node": "^9.0.0", - "typescript": "~3.9.7" - }, - "dependencies": { - "aws-cdk-lib": "2.16.0", - "constructs": "^10.0.0", - "source-map-support": "^0.5.16" - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>For deployable CDK apps, <code>aws-cdk-lib</code> must be specified in the <code>dependencies</code> section of <code class="path">package.json</code>. You can use a caret (^) version number specifier to indicate that you will accept later versions than the one specified as long as they are within the same major version.</p> -</div> -<div class="paragraph"> -<p>For experimental constructs, specify exact versions for the alpha construct library modules, which have APIs that may change. Do not use ^ or ~ since later versions of these modules may bring API changes that can break your app.</p> -</div> -<div class="paragraph"> -<p>Specify versions of libraries and tools needed to test your app (for example, the <code class="path">jest</code> testing framework) in the <code>devDependencies</code> section of <code class="path">package.json</code>. Optionally, use ^ to specify that later compatible versions are acceptable.</p> -</div> -</div> -<div class="sect4"> -<h5 id="work-with-cdk-javascript-dependencies-libraries">Third-party construct libraries</h5> -<div class="paragraph"> -<p>If you’re developing a construct library, specify its dependencies using a combination of the <code>peerDependencies</code> and <code>devDependencies</code> sections, as shown in the following example <code class="path">package.json</code> file.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-json" data-lang="json">{ - "name": "my-package", - "version": "0.0.1", - "peerDependencies": { - "aws-cdk-lib": "^2.14.0", - "@aws-cdk/aws-appsync-alpha": "2.10.0-alpha", - "constructs": "^10.0.0" - }, - "devDependencies": { - "aws-cdk-lib": "2.14.0", - "@aws-cdk/aws-appsync-alpha": "2.10.0-alpha", - "constructs": "10.0.0", - "jsii": "^1.50.0", - "aws-cdk": "^2.14.0" - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>In <code>peerDependencies</code>, use a caret (^) to specify the lowest version of <code>aws-cdk-lib</code> that your library works with. This maximizes the compatibility of your library with a range of CDK versions. Specify exact versions for alpha construct library modules, which have APIs that may change. Using <code>peerDependencies</code> makes sure that there is only one copy of all CDK libraries in the <code class="path">node_modules</code> tree.</p> -</div> -<div class="paragraph"> -<p>In <code>devDependencies</code>, specify the tools and libraries you need for testing, optionally with ^ to indicate that later compatible versions are acceptable. Specify exactly (without ^ or ~) the lowest versions of <code>aws-cdk-lib</code> and other CDK packages that you advertise your library be compatible with. This practice makes sure that your tests run against those versions. This way, if you inadvertently use a feature found only in newer versions, your tests can catch it.</p> -</div> -<div class="admonitionblock warning"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-warning" title="Warning"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p><code>peerDependencies</code> are installed automatically only by NPM 7 and later. If you are using NPM 6 or earlier, or if you are using Yarn, you must include the dependencies of your dependencies in <code>devDependencies</code>. Otherwise, they won’t be installed, and you will receive a warning about unresolved peer dependencies.</p> -</div> -</td> -</tr> -</table> -</div> -</div> -<div class="sect4"> -<h5 id="work-with-cdk-javascript-dependencies-install">Installing and updating dependencies</h5> -<div class="paragraph"> -<p>Run the following command to install your project’s dependencies.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">NPM</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none"># Install the latest version of everything that matches the ranges in 'package.json' -npm install - -# Install the same exact dependency versions as recorded in 'package-lock.json' -npm ci</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Yarn</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none"># Install the latest version of everything that matches the ranges in 'package.json' -yarn upgrade - -# Install the same exact dependency versions as recorded in 'yarn.lock' -yarn install --frozen-lockfile</code></pre> -</div> -</div> -<div class="paragraph"> -<p>To update the installed modules, the preceding <strong class="command">npm install</strong> and <strong class="command">yarn upgrade</strong> commands can be used. Either command updates the packages in <code class="path">node_modules</code> to the latest versions that satisfy the rules in <code class="path">package.json</code>. However, they do not update <code class="path">package.json</code> itself, which you might want to do to set a new minimum version. If you host your package on GitHub, you can configure <a href="https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuring-dependabot-version-updates">Dependabot version updates</a> to automatically update <code class="path">package.json</code>. Alternatively, use <a href="https://www.npmjs.com/package/npm-check-updates">npm-check-updates</a>.</p> -</div> -<div class="admonitionblock important"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-important" title="Important"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>By design, when you install or update dependencies, NPM and Yarn choose the latest version of every package that satisfies the requirements specified in <code class="path">package.json</code>. There is always a risk that these versions may be broken (either accidentally or intentionally). Test thoroughly after updating your project’s dependencies.</p> -</div> -</td> -</tr> -</table> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="javascript-cdk-idioms">5.6.6. AWS CDK idioms in JavaScript</h4> -<div class="sect4"> -<h5 id="javascript-props">Props</h5> -<div class="paragraph"> -<p>All AWS Construct Library classes are instantiated using three arguments: the <em>scope</em> in which the construct is being defined (its parent in the construct tree), an <em>id</em>, and <em>props</em>, a bundle of key/value pairs that the construct uses to configure the AWS resources it creates. Other classes and methods also use the "bundle of attributes" pattern for arguments.</p> -</div> -<div class="paragraph"> -<p>Using an IDE or editor that has good JavaScript autocomplete will help avoid misspelling property names. If a construct is expecting an <code>encryptionKeys</code> property, and you spell it <code>encryptionkeys</code>, when instantiating the construct, you haven’t passed the value you intended. This can cause an error at synthesis time if the property is required, or cause the property to be silently ignored if it is optional. In the latter case, you may get a default behavior you intended to override. Take special care here.</p> -</div> -<div class="paragraph"> -<p>When subclassing an AWS Construct Library class (or overriding a method that takes a props-like argument), you may want to accept additional properties for your own use. These values will be ignored by the parent class or overridden method, because they are never accessed in that code, so you can generally pass on all the props you received.</p> -</div> -<div class="paragraph"> -<p>A future release of the AWS CDK could coincidentally add a new property with a name you used for your own property. Passing the value you receive up the inheritance chain can then cause unexpected behavior. It’s safer to pass a shallow copy of the props you received with your property removed or set to <code>undefined</code>. For example:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">super(scope, name, {...props, encryptionKeys: undefined});</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Alternatively, name your properties so that it is clear that they belong to your construct. This way, it is unlikely they will collide with properties in future AWS CDK releases. If there are many of them, use a single appropriately-named object to hold them.</p> -</div> -</div> -<div class="sect4"> -<h5 id="javascript-missing-values">Missing values</h5> -<div class="paragraph"> -<p>Missing values in an object (such as <code>props</code>) have the value <code>undefined</code> in JavaScript. The usual techniques apply for dealing with these. For example, a common idiom for accessing a property of a value that may be undefined is as follows:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">// a may be undefined, but if it is not, it may have an attribute b -// c is undefined if a is undefined, OR if a doesn't have an attribute b -let c = a && a.b;</code></pre> -</div> -</div> -<div class="paragraph"> -<p>However, if <code>a</code> could have some other "falsy" value besides <code>undefined</code>, it is better to make the test more explicit. Here, we’ll take advantage of the fact that <code>null</code> and <code>undefined</code> are equal to test for them both at once:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">let c = a == null ? a : a.b;</code></pre> -</div> -</div> -<div class="admonitionblock tip"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-tip" title="Tip"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>Node.js 14.0 and later support new operators that can simplify the handling of undefined values. For more information, see the <a href="https://github.com/tc39/proposal-optional-chaining/blob/master/README.md">optional chaining</a> and <a href="https://github.com/tc39/proposal-nullish-coalescing/blob/master/README.md">nullish coalescing</a> proposals.</p> -</div> -</td> -</tr> -</table> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="javascript-using-typescript-examples">5.6.7. Using TypeScript examples with JavaScript</h4> -<div class="paragraph"> -<p><a href="https://www.typescriptlang.org/">TypeScript</a> is the language we use to develop the AWS CDK, and it was the first language supported for developing applications, so many available AWS CDK code examples are written in TypeScript. These code examples can be a good resource for JavaScript developers; you just need to remove the TypeScript-specific parts of the code.</p> -</div> -<div class="paragraph"> -<p>TypeScript snippets often use the newer ECMAScript <code>import</code> and <code>export</code> keywords to import objects from other modules and to declare the objects to be made available outside the current module. Node.js has just begun supporting these keywords in its latest releases. Depending on the version of Node.js you’re using (or wish to support), you might rewrite imports and exports to use the older syntax.</p> -</div> -<div class="paragraph"> -<p>Imports can be replaced with calls to the <code>require()</code> function.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as cdk from 'aws-cdk-lib'; -import { Bucket, BucketPolicy } from 'aws-cdk-lib/aws-s3';</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const cdk = require('aws-cdk-lib'); -const { Bucket, BucketPolicy } = require('aws-cdk-lib/aws-s3');</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Exports can be assigned to the <code>module.exports</code> object.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">export class Stack1 extends cdk.Stack { - // ... -} - -export class Stack2 extends cdk.Stack { - // ... -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">class Stack1 extends cdk.Stack { - // ... -} - -class Stack2 extends cdk.Stack { - // ... -} - -module.exports = { Stack1, Stack2 }</code></pre> -</div> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>An alternative to using the old-style imports and exports is to use the <a href="https://www.npmjs.com/package/esm">esm</a> module.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>Once you’ve got the imports and exports sorted, you can dig into the actual code. You may run into these commonly-used TypeScript features:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Type annotations</p> -</li> -<li> -<p>Interface definitions</p> -</li> -<li> -<p>Type conversions/casts</p> -</li> -<li> -<p>Access modifiers</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>Type annotations may be provided for variables, class members, function parameters, and function return types. For variables, parameters, and members, types are specified by following the identifier with a colon and the type. Function return values follow the function signature and consist of a colon and the type.</p> -</div> -<div class="paragraph"> -<p>To convert type-annotated code to JavaScript, remove the colon and the type. Class members must have some value in JavaScript; set them to <code>undefined</code> if they only have a type annotation in TypeScript.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">var encrypted: boolean = true; - -class myStack extends cdk.Stack { - bucket: s3.Bucket; - // ... -} - -function makeEnv(account: string, region: string) : object { - // ... -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">var encrypted = true; - -class myStack extends cdk.Stack { - bucket = undefined; - // ... -} - -function makeEnv(account, region) { - // ... -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>In TypeScript, interfaces are used to give bundles of required and optional properties, and their types, a name. You can then use the interface name as a type annotation. TypeScript will make sure that the object you use as, for example, an argument to a function has the required properties of the right types.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">interface myFuncProps { - code: lambda.Code, - handler?: string -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>JavaScript does not have an interface feature, so once you’ve removed the type annotations, delete the interface declarations entirely.</p> -</div> -<div class="paragraph"> -<p>When a function or method returns a general-purpose type (such as <code>object</code>), but you want to treat that value as a more specific child type to access properties or methods that are not part of the more general type’s interface, TypeScript lets you <em>cast</em> the value using <code>as</code> followed by a type or interface name. JavaScript doesn’t support (or need) this, so simply remove <code>as</code> and the following identifier. A less-common cast syntax is to use a type name in brackets, <code><LikeThis></code>; these casts, too, must be removed.</p> -</div> -<div class="paragraph"> -<p>Finally, TypeScript supports the access modifiers <code>public</code>, <code>protected</code>, and <code>private</code> for members of classes. All class members in JavaScript are public. Simply remove these modifiers wherever you see them.</p> -</div> -<div class="paragraph"> -<p>Knowing how to identify and remove these TypeScript features goes a long way toward adapting short TypeScript snippets to JavaScript. But it may be impractical to convert longer TypeScript examples in this fashion, since they are more likely to use other TypeScript features. For these situations, we recommend <a href="https://github.com/alangpierce/sucrase">Sucrase</a>. Sucrase won’t complain if code uses an undefined variable, for example, as <code>tsc</code> would. If it is syntactically valid, then with few exceptions, Sucrase can translate it to JavaScript. This makes it particularly valuable for converting snippets that may not be runnable on their own.</p> -</div> -</div> -<div class="sect3"> -<h4 id="javascript-to-typescript">5.6.8. Migrating to TypeScript</h4> -<div class="paragraph"> -<p>Many JavaScript developers move to <a href="https://www.typescriptlang.org/">TypeScript</a> as their projects get larger and more complex. TypeScript is a superset of JavaScript—​all JavaScript code is valid TypeScript code, so no changes to your code are required—​and it is also a supported AWS CDK language. Type annotations and other TypeScript features are optional and can be added to your AWS CDK app as you find value in them. TypeScript also gives you early access to new JavaScript features, such as optional chaining and nullish coalescing, before they’re finalized—​and without requiring that you upgrade Node.js.</p> -</div> -<div class="paragraph"> -<p>TypeScript’s "shape-based" interfaces, which define bundles of required and optional properties (and their types) within an object, allow common mistakes to be caught while you’re writing the code, and make it easier for your IDE to provide robust autocomplete and other real-time coding advice.</p> -</div> -<div class="paragraph"> -<p>Coding in TypeScript does involve an additional step: compiling your app with the TypeScript compiler, <code>tsc</code>. For typical AWS CDK apps, compilation requires a few seconds at most.</p> -</div> -<div class="paragraph"> -<p>The easiest way to migrate an existing JavaScript AWS CDK app to TypeScript is to create a new TypeScript project using <code>cdk init app --language typescript</code>, then copy your source files (and any other necessary files, such as assets like AWS Lambda function source code) to the new project. Rename your JavaScript files to end in <code>.ts</code> and begin developing in TypeScript.</p> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="work-with-cdk-python">5.7. Working with the AWS CDK in Python</h3> -<div class="paragraph"> -<p>Python is a fully-supported client language for the AWS Cloud Development Kit (AWS CDK) and is considered stable. Working with the AWS CDK in Python uses familiar tools, including the standard Python implementation (CPython), virtual environments with <code>virtualenv</code>, and the Python package installer <code>pip</code>. The modules comprising the AWS Construct Library are distributed via <a href="https://pypi.org/search/?q=aws-cdk">pypi.org</a>. The Python version of the AWS CDK even uses Python-style identifiers (for example, <code>snake_case</code> method names).</p> -</div> -<div class="paragraph"> -<p>You can use any editor or IDE. Many AWS CDK developers use <a href="https://code.visualstudio.com/">Visual Studio Code</a> (or its open-source equivalent <a href="https://vscodium.com/">VSCodium</a>), which has good support for Python via an <a href="https://marketplace.visualstudio.com/items?itemName=ms-python.python">official extension</a>. The IDLE editor included with Python will suffice to get started. The Python modules for the AWS CDK do have type hints, which are useful for a linting tool or an IDE that supports type validation.</p> -</div> -<div class="paragraph topiclist"> -<p>[[Topic List]]</p> -</div> -<div class="sect3"> -<h4 id="python-prerequisites">5.7.1. Get started with <code class="noloc">Python</code></h4> -<div class="paragraph"> -<p>To work with the AWS CDK, you must have an AWS account and credentials and have installed Node.js and the AWS CDK Toolkit. See <a href="#getting-started">Getting started with the AWS CDK</a>.</p> -</div> -<div class="paragraph"> -<p>Python AWS CDK applications require Python 3.6 or later. If you don’t already have it installed, <a href="https://www.python.org/downloads/">download a compatible version</a> for your operating system at <a href="https://www.python.org/">python.org</a>. If you run Linux, your system may have come with a compatible version, or you may install it using your distro’s package manager (<code>yum</code>, <code>apt</code>, etc.). Mac users may be interested in <a href="https://brew.sh/">Homebrew</a>, a Linux-style package manager for macOS.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>Third-party language deprecation: language version is only supported until its EOL (End Of Life) shared by the vendor or community and is subject to change with prior notice.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>The Python package installer, <code>pip</code>, and virtual environment manager, <code>virtualenv</code>, are also required. Windows installations of compatible Python versions include these tools. On Linux, <code>pip</code> and <code>virtualenv</code> may be provided as separate packages in your package manager. Alternatively, you may install them with the following commands:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">python -m ensurepip --upgrade -python -m pip install --upgrade pip -python -m pip install --upgrade virtualenv</code></pre> -</div> -</div> -<div class="paragraph"> -<p>If you encounter a permission error, run the above commands with the <code>--user</code> flag so that the modules are installed in your user directory, or use <code>sudo</code> to obtain the permissions to install the modules system-wide.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>It is common for Linux distros to use the executable name <code>python3</code> for Python 3.x, and have <code>python</code> refer to a Python 2.x installation. Some distros have an optional package you can install that makes the <code>python</code> command refer to Python 3. Failing that, you can adjust the command used to run your application by editing <code>cdk.json</code> in the project’s main directory.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>On Windows, you may want to invoke Python (and <strong class="command">pip</strong>) using the <strong class="command">py</strong> executable, the <a href="https://docs.python.org/3/using/windows.html#launcher">>Python launcher for Windows</a>. Among other things, the launcher allows you to easily specify which installed version of Python you want to use.</p> -</div> -<div class="paragraph"> -<p>If typing <strong class="command">python</strong> at the command line results in a message about installing Python from the Windows Store, even after installing a Windows version of Python, open Windows' Manage App Execution Aliases settings panel and turn off the two App Installer entries for Python.</p> -</div> -</td> -</tr> -</table> -</div> -</div> -<div class="sect3"> -<h4 id="python-newproject">5.7.2. Creating a project</h4> -<div class="paragraph"> -<p>You create a new AWS CDK project by invoking <code>cdk init</code> in an empty directory. Use the <code>--language</code> option and specify <code>python</code>:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">mkdir my-project -cd my-project -cdk init app --language python</code></pre> -</div> -</div> -<div class="paragraph"> -<p><code>cdk init</code> uses the name of the project folder to name various elements of the project, including classes, subfolders, and files. Hyphens in the folder name are converted to underscores. However, the name should otherwise follow the form of a Python identifier; for example, it should not start with a number or contain spaces.</p> -</div> -<div class="paragraph"> -<p>To work with the new project, activate its virtual environment. This allows the project’s dependencies to be installed locally in the project folder, instead of globally.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">source .venv/bin/activate</code></pre> -</div> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>You may recognize this as the Mac/Linux command to activate a virtual environment. The Python templates include a batch file, <code>source.bat</code>, that allows the same command to be used on Windows. The traditional Windows command, <code>.\venv\Scripts\activate</code>, works, too.</p> -</div> -<div class="paragraph"> -<p>If you initialized your AWS CDK project using CDK Toolkit v1.70.0 or earlier, your virtual environment is in the <code class="path">.env</code> directory instead of <code class="path">.venv</code>.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="admonitionblock important"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-important" title="Important"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>Activate the project’s virtual environment whenever you start working on it. Otherwise, you won’t have access to the modules installed there, and modules you install will go in the Python global module directory (or will result in a permission error).</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>After activating your virtual environment for the first time, install the app’s standard dependencies:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">python -m pip install -r requirements.txt</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="python-managemodules">5.7.3. Managing AWS Construct Library modules</h4> -<div class="paragraph"> -<p>Use the Python package installer, <strong class="command">pip</strong>, to install and update AWS Construct Library modules for use by your apps, as well as other packages you need. <strong class="command">pip</strong> also installs the dependencies for those modules automatically. If your system does not recognize <strong class="command">pip</strong> as a standalone command, invoke <strong class="command">pip</strong> as a Python module, like this:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">python -m pip PIP-COMMAND</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Most AWS CDK constructs are in <code>aws-cdk-lib</code>. Experimental modules are in separate modules named like <code>aws-cdk.[replaceable]</code>SERVICE-NAME<code>.alpha</code>. The service name includes an <em>aws</em> prefix. If you’re unsure of a module’s name, <a href="https://pypi.org/search/?q=aws-cdk">search for it at PyPI</a>. For example, the command below installs the AWS CodeStar library.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">python -m pip install aws-cdk.aws-codestar-alpha</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Some services' constructs are in more than one namespace. For example, besides <code>aws-cdk.aws-route53</code>, there are three additional Amazon Route 53 namespaces, named <code>aws-route53-targets</code>, <code>aws-route53-patterns</code>, and <code>aws-route53resolver</code>.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>The <a href="https://docs.aws.amazon.com/cdk/api/v2/python/index.html">Python edition of the CDK API Reference</a> also shows the package names.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>The names used for importing AWS Construct Library modules into your Python code look like the following.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">import aws_cdk.aws_s3 as s3 -import aws_cdk.aws_lambda as lambda_</code></pre> -</div> -</div> -<div class="paragraph"> -<p>We recommend the following practices when importing AWS CDK classes and AWS Construct Library modules in your applications. Following these guidelines will help make your code consistent with other AWS CDK applications as well as easier to understand.</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Generally, import individual classes from top-level <code>aws_cdk</code>.</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">from aws_cdk import App, Construct</code></pre> -</div> -</div> -</li> -<li> -<p>If you need many classes from the <code>aws_cdk</code>, you may use a namespace alias of <code>cdk</code> instead of importing individual classes. Avoid doing both.</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">import aws_cdk as cdk</code></pre> -</div> -</div> -</li> -<li> -<p>Generally, import AWS Construct Libraries using short namespace aliases.</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">import aws_cdk.aws_s3 as s3</code></pre> -</div> -</div> -</li> -</ul> -</div> -<div class="paragraph"> -<p>After installing a module, update your project’s <code class="path">requirements.txt</code> file, which lists your project’s dependencies. It is best to do this manually rather than using <code>pip freeze</code>. <code>pip freeze</code> captures the current versions of all modules installed in your Python virtual environment, which can be useful when bundling up a project to be run elsewhere.</p> -</div> -<div class="paragraph"> -<p>Usually, though, your <code class="path">requirements.txt</code> should list only top-level dependencies (modules that your app depends on directly) and not the dependencies of those libraries. This strategy makes updating your dependencies simpler.</p> -</div> -<div class="paragraph"> -<p>You can edit <code class="path">requirements.txt</code> to allow upgrades; simply replace the <code>==</code> preceding a version number with <code>~=</code> to allow upgrades to a higher compatible version, or remove the version requirement entirely to specify the latest available version of the module.</p> -</div> -<div class="paragraph"> -<p>With <code class="path">requirements.txt</code> edited appropriately to allow upgrades, issue this command to upgrade your project’s installed modules at any time:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">pip install --upgrade -r requirements.txt</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="work-with-cdk-python-dependencies">5.7.4. Managing dependencies in <code class="noloc">Python</code></h4> -<div class="paragraph"> -<p>In Python, you specify dependencies by putting them in <code class="path">requirements.txt</code> for applications or <code class="path">setup.py</code> for construct libraries. Dependencies are then managed with the PIP tool. PIP is invoked in one of the following ways:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">pip command options -python -m pip command options</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The <strong class="command">python -m pip</strong> invocation works on most systems; <strong class="command">pip</strong> requires that PIP’s executable be on the system path. If <strong class="command">pip</strong> doesn’t work, try replacing it with <strong class="command">python -m pip</strong>.</p> -</div> -<div class="paragraph"> -<p>The <strong class="command">cdk init --language python</strong> command creates a virtual environment for your new project. This lets each project have its own versions of dependencies, and also a basic <code class="path">requirements.txt</code> file. You must activate this virtual environment by running <strong class="command">source .venv/bin/activate</strong> each time you begin working with the project. On Windows, run <strong class="command">.\venv\Scripts\activate</strong> instead</p> -</div> -<div class="sect4"> -<h5 id="work-with-cdk-python-dependencies-apps">CDK applications</h5> -<div class="paragraph"> -<p>The following is an example <code class="path">requirements.txt</code> file. Because PIP does not have a dependency-locking feature, we recommend that you use the == operator to specify exact versions for all dependencies, as shown here.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">aws-cdk-lib==2.14.0 -aws-cdk.aws-appsync-alpha==2.10.0a0</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Installing a module with <strong class="command">pip install</strong> does not automatically add it to <code class="path">requirements.txt</code>. You must do that yourself. If you want to upgrade to a later version of a dependency, edit its version number in <code class="path">requirements.txt</code>.</p> -</div> -<div class="paragraph"> -<p>To install or update your project’s dependencies after creating or editing <code class="path">requirements.txt</code>, run the following:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">python -m pip install -r requirements.txt</code></pre> -</div> -</div> -<div class="admonitionblock tip"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-tip" title="Tip"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>The <strong class="command">pip freeze</strong> command outputs the versions of all installed dependencies in a format that can be written to a text file. This can be used as a requirements file with <code class="path">pip install -r</code>. This file is convenient for pinning all dependencies (including transitive ones) to the exact versions that you tested with. To avoid problems when upgrading packages later, use a separate file for this, such as <code class="path">freeze.txt</code> (not <code class="path">requirements.txt</code>). Then, regenerate it when you upgrade your project’s dependencies.</p> -</div> -</td> -</tr> -</table> -</div> -</div> -<div class="sect4"> -<h5 id="work-with-cdk-python-dependencies-libraries">Third-party construct libraries</h5> -<div class="paragraph"> -<p>In libraries, dependencies are specified in <code class="path">setup.py</code>, so that transitive dependencies are automatically downloaded when the package is consumed by an application. Otherwise, every application that wants to use your package needs to copy your dependencies into their <code class="path">requirements.txt</code>. An example <code class="path">setup.py</code> is shown here.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">from setuptools import setup - -setup( - name='my-package', - version='0.0.1', - install_requires=[ - 'aws-cdk-lib==2.14.0', - ], - ... -)</code></pre> -</div> -</div> -<div class="paragraph"> -<p>To work on the package for development, create or activate a virtual environment, then run the following command.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">python -m pip install -e .</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Although PIP automatically installs transitive dependencies, there can only be one installed copy of any one package. The version that is specified highest in the dependency tree is selected; applications always have the last word in what version of packages get installed.</p> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="python-cdk-idioms">5.7.5. AWS CDK idioms in Python</h4> -<div class="sect4"> -<h5 id="python-keywords">Language conflicts</h5> -<div class="paragraph"> -<p>In Python, <code>lambda</code> is a language keyword, so you cannot use it as a name for the AWS Lambda construct library module or Lambda functions. The Python convention for such conflicts is to use a trailing underscore, as in <code>lambda_</code>, in the variable name.</p> -</div> -<div class="paragraph"> -<p>By convention, the second argument to AWS CDK constructs is named <code>id</code>. When writing your own stacks and constructs, calling a parameter <code>id</code> "shadows" the Python built-in function <code>id()</code>, which returns an object’s unique identifier. This function isn’t used very often, but if you should happen to need it in your construct, rename the argument, for example <code>construct_id</code>.</p> -</div> -</div> -<div class="sect4"> -<h5 id="python-props">Arguments and properties</h5> -<div class="paragraph"> -<p>All AWS Construct Library classes are instantiated using three arguments: the <em>scope</em> in which the construct is being defined (its parent in the construct tree), an <em>id</em>, and <em>props</em>, a bundle of key/value pairs that the construct uses to configure the resources it creates. Other classes and methods also use the "bundle of attributes" pattern for arguments.</p> -</div> -<div class="paragraph"> -<p><em>scope</em> and <em>id</em> should always be passed as positional arguments, not keyword arguments, because their names change if the construct accepts a property named <em>scope</em> or <em>id</em>.</p> -</div> -<div class="paragraph"> -<p>In Python, props are expressed as keyword arguments. If an argument contains nested data structures, these are expressed using a class which takes its own keyword arguments at instantiation. The same pattern is applied to other method calls that take a structured argument.</p> -</div> -<div class="paragraph"> -<p>For example, in a Amazon S3 bucket’s <code>add_lifecycle_rule</code> method, the <code>transitions</code> property is a list of <code>Transition</code> instances.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">bucket.add_lifecycle_rule( - transitions=[ - Transition( - storage_class=StorageClass.GLACIER, - transition_after=Duration.days(10) - ) - ] -)</code></pre> -</div> -</div> -<div class="paragraph"> -<p>When extending a class or overriding a method, you may want to accept additional arguments for your own purposes that are not understood by the parent class. In this case you should accept the arguments you don’t care about using the <code><strong>*kwargs</code> idiom, and use keyword-only arguments to accept the arguments you’re interested in. When calling the parent’s constructor or the overridden method, pass only the arguments it is expecting (often just <code>\</strong>*kwargs</code>). Passing arguments that the parent class or method doesn’t expect results in an error.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>class MyConstruct(Construct): - def __init__(self, id, *, MyProperty=42, **kwargs): - super().__init__(self, id, **kwargs) - # ...</code></pre> -</div> -</div> -<div class="paragraph"> -<p>A future release of the AWS CDK could coincidentally add a new property with a name you used for your own property. This won’t cause any technical issues for users of your construct or method (since your property isn’t passed "up the chain," the parent class or overridden method will simply use a default value) but it may cause confusion. You can avoid this potential problem by naming your properties so they clearly belong to your construct. If there are many new properties, bundle them into an appropriately-named class and pass it as a single keyword argument.</p> -</div> -</div> -<div class="sect4"> -<h5 id="python-missing-values">Missing values</h5> -<div class="paragraph"> -<p>The AWS CDK uses <code>None</code> to represent missing or undefined values. When working with <code>\**kwargs</code>, use the dictionary’s <code>get()</code> method to provide a default value if a property is not provided. Avoid using <code>kwargs[…​]</code>, as this raises <code>KeyError</code> for missing values.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">encrypted = kwargs.get("encrypted") # None if no property "encrypted" exists -encrypted = kwargs.get("encrypted", False) # specify default of False if property is missing</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Some AWS CDK methods (such as <code>tryGetContext()</code> to get a runtime context value) may return <code>None</code>, which you will need to check explicitly.</p> -</div> -</div> -<div class="sect4"> -<h5 id="python-interfaces">Using interfaces</h5> -<div class="paragraph"> -<p>Python doesn’t have an interface feature as some other languages do, though it does have <a href="https://docs.python.org/3/library/abc.html">abstract base classes</a>, which are similar. (If you’re not familiar with interfaces, Wikipedia has <a href="https://en.wikipedia.org/wiki/Interface_(computing)#In_object-oriented_languages">a good introduction</a>.) TypeScript, the language in which the AWS CDK is implemented, does provide interfaces, and constructs and other AWS CDK objects often require an object that adheres to a particular interface, rather than inheriting from a particular class. So the AWS CDK provides its own interface feature as part of the <a href="https://github.com/aws/jsii">JSII</a> layer.</p> -</div> -<div class="paragraph"> -<p>To indicate that a class implements a particular interface, you can use the <code>@jsii.implements</code> decorator:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">from aws_cdk import IAspect, IConstruct -import jsii - -@jsii.implements(IAspect) -class MyAspect(): - def visit(self, node: IConstruct) -> None: - print("Visited", node.node.path)</code></pre> -</div> -</div> -</div> -<div class="sect4"> -<h5 id="python-type-pitfalls">Type pitfalls</h5> -<div class="paragraph"> -<p>Python uses dynamic typing, where all variables may refer to a value of any type. Parameters and return values may be annotated with types, but these are "hints" and are not enforced. This means that in Python, it is easy to pass the incorrect type of value to a AWS CDK construct. Instead of getting a type error during build, as you would from a statically-typed language, you may instead get a runtime error when the JSII layer (which translates between Python and the AWS CDK’s TypeScript core) is unable to deal with the unexpected type.</p> -</div> -<div class="paragraph"> -<p>In our experience, the type errors Python programmers make tend to fall into these categories.</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Passing a single value where a construct expects a container (Python list or dictionary) or vice versa.</p> -</li> -<li> -<p>Passing a value of a type associated with a layer 1 (<code>CfnXxxxxx</code>) construct to a L2 or L3 construct, or vice versa.</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>The AWS CDK Python modules do include type annotations, so you can use tools that support them to help with types. If you are not using an IDE that supports these, such as <a href="https://www.jetbrains.com/pycharm/">PyCharm</a>, you might want to call the <a href="http://mypy-lang.org/">MyPy</a> type validator as a step in your build process. There are also runtime type checkers that can improve error messages for type-related errors.</p> -</div> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="work-with-cdk-java">5.8. Working with the AWS CDK in Java</h3> -<div class="paragraph"> -<p>Java is a fully-supported client language for the AWS CDK and is considered stable. You can develop AWS CDK applications in Java using familiar tools, including the JDK (Oracle’s, or an OpenJDK distribution such as Amazon Corretto) and Apache Maven.</p> -</div> -<div class="paragraph"> -<p>The AWS CDK supports Java 8 and later. We recommend using the latest version you can, however, because later versions of the language include improvements that are particularly convenient for developing AWS CDK applications. For example, Java 9 introduces the <code>Map.of()</code> method (a convenient way to declare hashmaps that would be written as object literals in TypeScript). Java 10 introduces local type inference using the <code>var</code> keyword.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>Most code examples in this Developer Guide work with Java 8. A few examples use <code>Map.of()</code>; these examples include comments noting that they require Java 9.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>You can use any text editor, or a Java IDE that can read Maven projects, to work on your AWS CDK apps. We provide <a href="https://www.eclipse.org/downloads/">Eclipse</a> hints in this Guide, but IntelliJ IDEA, NetBeans, and other IDEs can import Maven projects and can be used for developing AWS CDK applications in Java.</p> -</div> -<div class="paragraph"> -<p>It is possible to write AWS CDK applications in JVM-hosted languages other than Java (for example, Kotlin, Groovy, Clojure, or Scala), but the experience may not be particularly idiomatic, and we are unable to provide any support for these languages.</p> -</div> -<div class="paragraph topiclist"> -<p>[[Topic List]]</p> -</div> -<div class="sect3"> -<h4 id="java-prerequisites">5.8.1. Get started with <code class="noloc">Java</code></h4> -<div class="paragraph"> -<p>To work with the AWS CDK, you must have an AWS account and credentials and have installed Node.js and the AWS CDK Toolkit. See <a href="#getting-started">Getting started with the AWS CDK</a>.</p> -</div> -<div class="paragraph"> -<p>Java AWS CDK applications require Java 8 (v1.8) or later. We recommend <a href="https://aws.amazon.com/corretto/">Amazon Corretto</a>, but you can use any OpenJDK distribution or <a href="https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html">Oracle’s JDK</a>. You will also need <a href="https://maven.apache.org/download.cgi">Apache Maven</a> 3.5 or later. You can also use tools such as Gradle, but the application skeletons generated by the AWS CDK Toolkit are Maven projects.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>Third-party language deprecation: language version is only supported until its EOL (End Of Life) shared by the vendor or community and is subject to change with prior notice.</p> -</div> -</td> -</tr> -</table> -</div> -</div> -<div class="sect3"> -<h4 id="java-newproject">5.8.2. Creating a project</h4> -<div class="paragraph"> -<p>You create a new AWS CDK project by invoking <code>cdk init</code> in an empty directory. Use the <code>--language</code> option and specify <code>java</code>:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">mkdir my-project -cd my-project -cdk init app --language java</code></pre> -</div> -</div> -<div class="paragraph"> -<p><code>cdk init</code> uses the name of the project folder to name various elements of the project, including classes, subfolders, and files. Hyphens in the folder name are converted to underscores. However, the name should otherwise follow the form of a Java identifier; for example, it should not start with a number or contain spaces.</p> -</div> -<div class="paragraph"> -<p>The resulting project includes a reference to the <code>software.amazon.awscdk</code> Maven package. It and its dependencies are automatically installed by Maven.</p> -</div> -<div class="paragraph"> -<p>If you are using an IDE, you can now open or import the project. In Eclipse, for example, choose <strong>File</strong> > <strong>Import</strong> > <strong>Maven</strong> > <strong>Existing Maven Projects</strong>. Make sure that the project settings are set to use Java 8 (1.8).</p> -</div> -</div> -<div class="sect3"> -<h4 id="java-managemodules">5.8.3. Managing AWS Construct Library modules</h4> -<div class="paragraph"> -<p>Use Maven to install AWS Construct Library packages, which are in the group <code>software.amazon.awscdk</code>. Most constructs are in the artifact <code>aws-cdk-lib</code>, which is added to new Java projects by default. Modules for services whose higher-level CDK support is still being developed are in separate "experimental" packages, named with a short version (no AWS or Amazon prefix) of their service’s name. <a href="https://search.maven.org/search?q=software.amazon.awscdk">Search the Maven Central Repository</a> to find the names of all AWS CDK and AWS Construct Module libraries.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>The <a href="https://docs.aws.amazon.com/cdk/api/v2/java/index.html">Java edition of the CDK API Reference</a> also shows the package names.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>Some services' AWS Construct Library support is in more than one namespace. For example, Amazon Route 53 has its functionality divided into <code>software.amazon.awscdk.route53</code>, <code>route53-patterns</code>, <code>route53resolver</code>, and <code>route53-targets</code>.</p> -</div> -<div class="paragraph"> -<p>The main AWS CDK package is imported in Java code as <code>software.amazon.awscdk</code>. Modules for the various services in the AWS Construct Library live under <code>software.amazon.awscdk.services</code> and are named similarly to their Maven package name. For example, the Amazon S3 module’s namespace is <code>software.amazon.awscdk.services.s3</code>.</p> -</div> -<div class="paragraph"> -<p>We recommend writing a separate Java <code>import</code> statement for each AWS Construct Library class you use in each of your Java source files, and avoiding wildcard imports. You can always use a type’s fully-qualified name (including its namespace) without an <code>import</code> statement.</p> -</div> -<div class="paragraph"> -<p>If your application depends on an experimental package, edit your project’s <code class="path">pom.xml</code> and add a new <code><dependency></code> element in the <code><dependencies></code> container. For example, the following <code><dependency></code> element specifies the CodeStar experimental construct library module:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none"><dependency> - <groupId>software.amazon.awscdk</groupId> - <artifactId>codestar-alpha</artifactId> - <version>2.0.0-alpha.10</version> -</dependency></code></pre> -</div> -</div> -<div class="admonitionblock tip"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-tip" title="Tip"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>If you use a Java IDE, it probably has features for managing Maven dependencies. We recommend editing <code class="path">pom.xml</code> directly, however, unless you are absolutely sure the IDE’s functionality matches what you’d do by hand.</p> -</div> -</td> -</tr> -</table> -</div> -</div> -<div class="sect3"> -<h4 id="work-with-cdk-java-dependencies">5.8.4. Managing dependencies in <code class="noloc">Java</code></h4> -<div class="paragraph"> -<p>In Java, dependencies are specified in <code class="path">pom.xml</code> and installed using Maven. The <code><dependencies></code> container includes a <code><dependency></code> element for each package. Following is a section of <code>pom.xml</code> for a typical CDK Java app.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-xml" data-lang="xml"><dependencies> - <dependency> - <groupId>software.amazon.awscdk</groupId> - <artifactId>aws-cdk-lib</artifactId> - <version>2.14.0</version> - </dependency> - <dependency> - <groupId>software.amazon.awscdk</groupId> - <artifactId>appsync-alpha</artifactId> - <version>2.10.0-alpha.0</version> - </dependency> -</dependencies></code></pre> -</div> -</div> -<div class="admonitionblock tip"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-tip" title="Tip"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>Many Java IDEs have integrated Maven support and visual <code class="path">pom.xml</code> editors, which you may find convenient for managing dependencies.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>Maven does not support dependency locking. Although it’s possible to specify version ranges in <code class="path">pom.xml</code>, we recommend you always use exact versions to keep your builds repeatable.</p> -</div> -<div class="paragraph"> -<p>Maven automatically installs transitive dependencies, but there can only be one installed copy of each package. The version that is specified highest in the POM tree is selected; applications always have the last word in what version of packages get installed.</p> -</div> -<div class="paragraph"> -<p>Maven automatically installs or updates your dependencies whenever you build (<strong class="command">mvn compile</strong>) or package (<strong class="command">mvn package</strong>) your project. The CDK Toolkit does this automatically every time you run it, so generally there is no need to manually invoke Maven.</p> -</div> -</div> -<div class="sect3"> -<h4 id="java-cdk-idioms">5.8.5. AWS CDK idioms in Java</h4> -<div class="sect4"> -<h5 id="java-props">Props</h5> -<div class="paragraph"> -<p>All AWS Construct Library classes are instantiated using three arguments: the <em>scope</em> in which the construct is being defined (its parent in the construct tree), an <em>id</em>, and <em>props</em>, a bundle of key/value pairs that the construct uses to configure the resources it creates. Other classes and methods also use the "bundle of attributes" pattern for arguments.</p> -</div> -<div class="paragraph"> -<p>In Java, props are expressed using the <a href="https://en.wikipedia.org/wiki/Builder_pattern">Builder pattern</a>. Each construct type has a corresponding props type; for example, the <code>Bucket</code> construct (which represents an Amazon S3 bucket) takes as its props an instance of <code>BucketProps</code>.</p> -</div> -<div class="paragraph"> -<p>The <code>BucketProps</code> class (like every AWS Construct Library props class) has an inner class called <code>Builder</code>. The <code>BucketProps.Builder</code> type offers methods to set the various properties of a <code>BucketProps</code> instance. Each method returns the <code>Builder</code> instance, so the method calls can be chained to set multiple properties. At the end of the chain, you call <code>build()</code> to actually produce the <code>BucketProps</code> object.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">Bucket bucket = new Bucket(this, "amzn-s3-demo-bucket", new BucketProps.Builder() - .versioned(true) - .encryption(BucketEncryption.KMS_MANAGED) - .build());</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Constructs, and other classes that take a props-like object as their final argument, offer a shortcut. The class has a <code>Builder</code> of its own that instantiates it and its props object in one step. This way, you don’t need to explicitly instantiate (for example) both <code>BucketProps</code> and a <code>Bucket</code>--and you don’t need an import for the props type.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">Bucket bucket = Bucket.Builder.create(this, "amzn-s3-demo-bucket") - .versioned(true) - .encryption(BucketEncryption.KMS_MANAGED) - .build();</code></pre> -</div> -</div> -<div class="paragraph"> -<p>When deriving your own construct from an existing construct, you may want to accept additional properties. We recommend that you follow these builder patterns. However, this isn’t as simple as subclassing a construct class. You must provide the moving parts of the two new <code>Builder</code> classes yourself. You may prefer to simply have your construct accept one or more additional arguments. You should provide additional constructors when an argument is optional.</p> -</div> -</div> -<div class="sect4"> -<h5 id="java-generic-structures">Generic structures</h5> -<div class="paragraph"> -<p>In some APIs, the AWS CDK uses JavaScript arrays or untyped objects as input to a method. (See, for example, AWS CodeBuild’s <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_codebuild.BuildSpec.html#static-fromwbrobjectvalue">BuildSpec.fromObject()</a> method.) In Java, these objects are represented as <code>java.util.Map<String, Object></code>. In cases where the values are all strings, you can use <code>Map<String, String></code>.</p> -</div> -<div class="paragraph"> -<p>Java does not provide a way to write literals for such containers like some other languages do. In Java 9 and later, you can use <a href="https://docs.oracle.com/javase/9/docs/api/java/util/Map.html#ofEntries-java.util.Map.Entry…​-">java.util.Map.of()</a> to conveniently define maps of up to ten entries inline with one of these calls.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">java.util.Map.of( - "base-directory", "dist", - "files", "LambdaStack.template.json" - )</code></pre> -</div> -</div> -<div class="paragraph"> -<p>To create maps with more than ten entries, use <a href="https://docs.oracle.com/javase/9/docs/api/java/util/Map.html#ofEntries-java.util.Map.Entry…​-">java.util.Map.ofEntries()</a>.</p> -</div> -<div class="paragraph"> -<p>If you are using Java 8, you could provide your own methods similar to to these.</p> -</div> -<div class="paragraph"> -<p>JavaScript arrays are represented as <code>List<Object></code> or <code>List<String></code> in Java. The method <code>java.util.Arrays.asList</code> is convenient for defining short <code>List</code>s.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">List<String> cmds = Arrays.asList("cd lambda", "npm install", "npm install typescript")</code></pre> -</div> -</div> -</div> -<div class="sect4"> -<h5 id="java-missing-values">Missing values</h5> -<div class="paragraph"> -<p>In Java, missing values in AWS CDK objects such as props are represented by <code>null</code>. You must explicitly test any value that could be <code>null</code> to make sure it contains a value before doing anything with it. Java does not have "syntactic sugar" to help handle null values as some other languages do. You may find Apache ObjectUtil’s <a href="https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/ObjectUtils.html#defaultIfNull-T-T-">defaultIfNull</a> and <a href="https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/ObjectUtils.html#firstNonNull-T…​-">firstNonNull</a> useful in some situations. Alternatively, write your own static helper methods to make it easier to handle potentially null values and make your code more readable.</p> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="java-running">5.8.6. Build and run CDK applications</h4> -<div class="paragraph"> -<p>The AWS CDK automatically compiles your app before running it. However, it can be useful to build your app manually to check for errors and to run tests. You can do this in your IDE (for example, press Control-B in Eclipse) or by issuing <code>mvn compile</code> at a command prompt while in your project’s root directory.</p> -</div> -<div class="paragraph"> -<p>Run any tests you’ve written by running <code>mvn test</code> at a command prompt.</p> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="work-with-cdk-csharp">5.9. Working with the AWS CDK in C#</h3> -<div class="paragraph"> -<p>.NET is a fully-supported client language for the AWS CDK and is considered stable. C# is the main .NET language for which we provide examples and support. You can choose to write AWS CDK applications in other .NET languages, such as Visual Basic or F#, but AWS offers limited support for using these languages with the CDK.</p> -</div> -<div class="paragraph"> -<p>You can develop AWS CDK applications in C# using familiar tools including Visual Studio, Visual Studio Code, the <code>dotnet</code> command, and the NuGet package manager. The modules comprising the AWS Construct Library are distributed via <a href="https://www.nuget.org/packages?q=amazon.cdk.aws">nuget.org</a>.</p> -</div> -<div class="paragraph"> -<p>We suggest using <a href="https://visualstudio.microsoft.com/downloads/">Visual Studio 2019</a> (any edition) on Windows to develop AWS CDK apps in C#.</p> -</div> -<div class="paragraph topiclist"> -<p>[[Topic List]]</p> -</div> -<div class="sect3"> -<h4 id="csharp-prerequisites">5.9.1. Get started with <code class="noloc">C#</code></h4> -<div class="paragraph"> -<p>To work with the AWS CDK, you must have an AWS account and credentials and have installed Node.js and the AWS CDK Toolkit. See <a href="#getting-started">Getting started with the AWS CDK</a>.</p> -</div> -<div class="paragraph"> -<p>C# AWS CDK applications require .NET Core v3.1 or later, available <a href="https://dotnet.microsoft.com/download/dotnet-core/3.1">here</a>.</p> -</div> -<div class="paragraph"> -<p>The .NET toolchain includes <code>dotnet</code>, a command-line tool for building and running .NET applications and managing NuGet packages. Even if you work mainly in Visual Studio, this command can be useful for batch operations and for installing AWS Construct Library packages.</p> -</div> -</div> -<div class="sect3"> -<h4 id="csharp-newproject">5.9.2. Creating a project</h4> -<div class="paragraph"> -<p>You create a new AWS CDK project by invoking <code>cdk init</code> in an empty directory. Use the <code>--language</code> option and specify <code>csharp</code>:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">mkdir my-project -cd my-project -cdk init app --language csharp</code></pre> -</div> -</div> -<div class="paragraph"> -<p><code>cdk init</code> uses the name of the project folder to name various elements of the project, including classes, subfolders, and files. Hyphens in the folder name are converted to underscores. However, the name should otherwise follow the form of a C# identifier; for example, it should not start with a number or contain spaces.</p> -</div> -<div class="paragraph"> -<p>The resulting project includes a reference to the <code>Amazon.CDK.Lib</code> NuGet package. It and its dependencies are installed automatically by NuGet.</p> -</div> -</div> -<div class="sect3"> -<h4 id="csharp-managemodules">5.9.3. Managing AWS Construct Library modules</h4> -<div class="paragraph"> -<p>The .NET ecosystem uses the NuGet package manager. The main CDK package, which contains the core classes and all stable service constructs, is <code class="path">Amazon.CDK.Lib</code>. Experimental modules, where new functionality is under active development, are named like <code class="path">Amazon.CDK.AWS.SERVICE-NAME.Alpha</code>, where the service name is a short name without an AWS or Amazon prefix. For example, the NuGet package name for the AWS IoT module is <code class="path">Amazon.CDK.AWS.IoT.Alpha</code>. If you can’t find a package you want, <a href="https://www.nuget.org/packages?q=amazon.cdk.aws">search Nuget.org</a>.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>The <a href="https://docs.aws.amazon.com/cdk/api/latest/dotnet/api/index.html">.NET edition of the CDK API Reference</a> also shows the package names.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>Some services' AWS Construct Library support is in more than one module. For example, AWS IoT has a second module named <code class="path">Amazon.CDK.AWS.IoT.Actions.Alpha</code>.</p> -</div> -<div class="paragraph"> -<p>The AWS CDK’s main module, which you’ll need in most AWS CDK apps, is imported in C# code as <code>Amazon.CDK</code>. Modules for the various services in the AWS Construct Library live under <code>Amazon.CDK.AWS</code>. For example, the Amazon S3 module’s namespace is <code>Amazon.CDK.AWS.S3</code>.</p> -</div> -<div class="paragraph"> -<p>We recommend writing C# <code>using</code> directives for the CDK core constructs and for each AWS service you use in each of your C# source files. You may find it convenient to use an alias for a namespace or type to help resolve name conflicts. You can always use a type’s fully-qualfiied name (including its namespace) without a <code>using</code> statement.</p> -</div> -</div> -<div class="sect3"> -<h4 id="work-with-cdk-csharp-dependencies">5.9.4. Managing dependencies in <code class="noloc">C#</code></h4> -<div class="paragraph"> -<p>In C# AWS CDK apps, you manage dependencies using NuGet. NuGet has four standard, mostly equivalent interfaces. Use the one that suits your needs and working style. You can also use compatible tools, such as <a href="https://fsprojects.github.io/Paket/">Paket</a> or <a href="https://www.myget.org/">MyGet</a> or even edit the <code class="path">.csproj</code> file directly.</p> -</div> -<div class="paragraph"> -<p>NuGet does not let you specify version ranges for dependencies. Every dependency is pinned to a specific version.</p> -</div> -<div class="paragraph"> -<p>After updating your dependencies, Visual Studio will use NuGet to retrieve the specified versions of each package the next time you build. If you are not using Visual Studio, use the <strong class="command">dotnet restore</strong> command to update your dependencies.</p> -</div> -<div class="sect4"> -<h5 id="manage-dependencies-csharp-direct-edit">Editing the project file directly</h5> -<div class="paragraph"> -<p>Your project’s <code class="path">.csproj</code> file contains an <code><ItemGroup></code> container that lists your dependencies as <code><PackageReference</code> elements.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code><ItemGroup> - <PackageReference Include="Amazon.CDK.Lib" Version="2.14.0" /> - <PackageReference Include="Constructs" Version="%constructs-version%" /> -</ItemGroup></code></pre> -</div> -</div> -</div> -<div class="sect4"> -<h5 id="manage-dependencies-csharp-vs-nuget-gui">The Visual Studio NuGet GUI</h5> -<div class="paragraph"> -<p>Visual Studio’s NuGet tools are accessible from <strong>Tools</strong> > <strong>NuGet Package Manager</strong> > <strong>Manage NuGet Packages for Solution</strong>. Use the <strong>Browse</strong> tab to find the AWS Construct Library packages you want to install. You can choose the desired version, including prerelease versions of your modules, and add them to any of the open projects.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>All AWS Construct Library modules deemed "experimental" (see <a href="#versioning">AWS CDK versioning</a>) are flagged as prerelease in NuGet and have an <code>alpha</code> name suffix.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="imageblock"> -<div class="content"> -<img src="images/visual-studio-nuget.png" alt="NuGet package manager showing Amazon CDKAWS alpha packages for various services."> -</div> -</div> -<div class="paragraph"> -<p>Look on the <strong>Updates</strong> page to install new versions of your packages.</p> -</div> -</div> -<div class="sect4"> -<h5 id="manage-dependencies-csharp-vs-nuget-console">The NuGet console</h5> -<div class="paragraph"> -<p>The NuGet console is a PowerShell-based interface to NuGet that works in the context of a Visual Studio project. You can open it in Visual Studio by choosing <strong>Tools</strong> > <strong>NuGet Package Manager</strong> > <strong>Package Manager Console</strong>. For more information about using this tool, see <a href="https://docs.microsoft.com/en-us/nuget/consume-packages/install-use-packages-powershell">Install and Manage Packages with the Package Manager Console in Visual Studio</a>.</p> -</div> -</div> -<div class="sect4"> -<h5 id="manage-dependencies-csharp-vs-dotnet-command">The <code>dotnet</code> command</h5> -<div class="paragraph"> -<p>The <code>dotnet</code> command is the primary command line tool for working with Visual Studio C# projects. You can invoke it from any Windows command prompt. Among its many capabilities, <code>dotnet</code> can add NuGet dependencies to a Visual Studio project.</p> -</div> -<div class="paragraph"> -<p>Assuming you’re in the same directory as the Visual Studio project (<code class="path">.csproj</code>) file, issue a command like the following to install a package. Because the main CDK library is included when you create a project, you only need to explicitly install experimental modules. Experimental modules require you to specify an explicit version number.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">dotnet add package Amazon.CDK.AWS.IoT.Alpha -v VERSION-NUMBER</code></pre> -</div> -</div> -<div class="paragraph"> -<p>You can issue the command from another directory. To do so, include the path to the project file, or to the directory that contains it, after the <code>add</code> keyword. The following example assumes that you are in your AWS CDK project’s main directory.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">dotnet add src/PROJECT-DIR package Amazon.CDK.AWS.IoT.Alpha -v VERSION-NUMBER</code></pre> -</div> -</div> -<div class="paragraph"> -<p>To install a specific version of a package, include the <code>-v</code> flag and the desired version.</p> -</div> -<div class="paragraph"> -<p>To update a package, issue the same <code>dotnet add</code> command you used to install it. For experimental modules, again, you must specify an explicit version number.</p> -</div> -<div class="paragraph"> -<p>For more information about managing packages using the <code>dotnet</code> command, see <a href="https://docs.microsoft.com/en-us/nuget/consume-packages/install-use-packages-dotnet-cli">Install and Manage Packages Using the dotnet CLI</a>.</p> -</div> -</div> -<div class="sect4"> -<h5 id="manage-dependencies-csharp-vs-nuget-command">The <code>nuget</code> command</h5> -<div class="paragraph"> -<p>The <code>nuget</code> command line tool can install and update NuGet packages. However, it requires your Visual Studio project to be set up differently from the way <code>cdk init</code> sets up projects. (Technical details: <code>nuget</code> works with <code>Packages.config</code> projects, while <code>cdk init</code> creates a newer-style <code>PackageReference</code> project.)</p> -</div> -<div class="paragraph"> -<p>We do not recommend the use of the <code>nuget</code> tool with AWS CDK projects created by <code>cdk init</code>. If you are using another type of project, and want to use <code>nuget</code>, see the <a href="https://docs.microsoft.com/en-us/nuget/reference/nuget-exe-cli-reference">NuGet CLI Reference</a>.</p> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="csharp-cdk-idioms">5.9.5. AWS CDK idioms in C#</h4> -<div class="sect4"> -<h5 id="csharp-props">Props</h5> -<div class="paragraph"> -<p>All AWS Construct Library classes are instantiated using three arguments: the <em>scope</em> in which the construct is being defined (its parent in the construct tree), an <em>id</em>, and <em>props</em>, a bundle of key/value pairs that the construct uses to configure the resources it creates. Other classes and methods also use the "bundle of attributes" pattern for arguments.</p> -</div> -<div class="paragraph"> -<p>In C#, props are expressed using a props type. In idiomatic C# fashion, we can use an object initializer to set the various properties. Here we’re creating an Amazon S3 bucket using the <code>Bucket</code> construct; its corresponding props type is <code>BucketProps</code>.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">var bucket = new Bucket(this, "amzn-s3-demo-bucket", new BucketProps { - Versioned = true -});</code></pre> -</div> -</div> -<div class="admonitionblock tip"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-tip" title="Tip"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>Add the package <code>Amazon.JSII.Analyzers</code> to your project to get required-values checking in your props definitions inside Visual Studio.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>When extending a class or overriding a method, you may want to accept additional props for your own purposes that are not understood by the parent class. To do this, subclass the appropriate props type and add the new attributes.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">// extend BucketProps for use with MimeBucket -class MimeBucketProps : BucketProps { - public string MimeType { get; set; } -} - -// hypothetical bucket that enforces MIME type of objects inside it -class MimeBucket : Bucket { - public MimeBucket( readonly Construct scope, readonly string id, readonly MimeBucketProps props=null) : base(scope, id, props) { - // ... - } -} - -// instantiate our MimeBucket class -var bucket = new MimeBucket(this, "amzn-s3-demo-bucket", new MimeBucketProps { - Versioned = true, - MimeType = "image/jpeg" -});</code></pre> -</div> -</div> -<div class="paragraph"> -<p>When calling the parent class’s initializer or overridden method, you can generally pass the props you received. The new type is compatible with its parent, and extra props you added are ignored.</p> -</div> -<div class="paragraph"> -<p>A future release of the AWS CDK could coincidentally add a new property with a name you used for your own property. This won’t cause any technical issues using your construct or method (since your property isn’t passed "up the chain," the parent class or overridden method will simply use a default value) but it may cause confusion for your construct’s users. You can avoid this potential problem by naming your properties so they clearly belong to your construct. If there are many new properties, bundle them into an appropriately-named class and pass them as a single property.</p> -</div> -</div> -<div class="sect4"> -<h5 id="csharp-generic-structures">Generic structures</h5> -<div class="paragraph"> -<p>In some APIs, the AWS CDK uses JavaScript arrays or untyped objects as input to a method. (See, for example, AWS CodeBuild’s <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_codebuild.BuildSpec.html">BuildSpec.fromObject()</a> method.) In C#, these objects are represented as <code>System.Collections.Generic.Dictionary<String, Object></code>. In cases where the values are all strings, you can use <code>Dictionary<String, String></code>. JavaScript arrays are represented as <code>object[]</code> or <code>string[]</code> array types in C#.</p> -</div> -<div class="admonitionblock tip"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-tip" title="Tip"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>You might define short aliases to make it easier to work with these specific dictionary types.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using StringDict = System.Collections.Generic.Dictionary<string, string>; -using ObjectDict = System.Collections.Generic.Dictionary<string, object>;</code></pre> -</div> -</div> -</td> -</tr> -</table> -</div> -</div> -<div class="sect4"> -<h5 id="csharp-missing-values">Missing values</h5> -<div class="paragraph"> -<p>In C#, missing values in AWS CDK objects such as props are represented by <code>null</code>. The null-conditional member access operator <code>?.</code> and the null coalescing operator <code>??</code> are convenient for working with these values.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">// mimeType is null if props is null or if props.MimeType is null -string mimeType = props?.MimeType; - -// mimeType defaults to text/plain. either props or props.MimeType can be null -string MimeType = props?.MimeType ?? "text/plain";</code></pre> -</div> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="csharp-running">5.9.6. Build and run CDK appliations</h4> -<div class="paragraph"> -<p>The AWS CDK automatically compiles your app before running it. However, it can be useful to build your app manually to check for errors and run tests. You can do this by pressing F6 in Visual Studio or by issuing <code>dotnet build src</code> from the command line, where <code>src</code> is the directory in your project directory that contains the Visual Studio Solution (<code class="path">.sln</code>) file.</p> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="work-with-cdk-go">5.10. Working with the AWS CDK in Go</h3> -<div class="paragraph"> -<p>Go is a fully-supported client language for the AWS Cloud Development Kit (AWS CDK) and is considered stable. Working with the AWS CDK in Go uses familiar tools. The Go version of the AWS CDK even uses Go-style identifiers.</p> -</div> -<div class="paragraph"> -<p>Unlike the other languages the CDK supports, Go is not a traditional object-oriented programming language. Go uses composition where other languages often leverage inheritance. We have tried to employ idiomatic Go approaches as much as possible, but there are places where the CDK may differ.</p> -</div> -<div class="paragraph"> -<p>This topic provides guidance when working with the AWS CDK in Go. See the <a href="https://aws.amazon.com/blogs/developer/getting-started-with-the-aws-cloud-development-kit-and-go/">announcement blog post</a> for a walkthrough of a simple Go project for the AWS CDK.</p> -</div> -<div class="paragraph topiclist"> -<p>[[Topic List]]</p> -</div> -<div class="sect3"> -<h4 id="go-prerequisites">5.10.1. Get started with <code class="noloc">Go</code></h4> -<div class="paragraph"> -<p>To work with the AWS CDK, you must have an AWS account and credentials and have installed Node.js and the AWS CDK Toolkit. See <a href="#getting-started">Getting started with the AWS CDK</a>.</p> -</div> -<div class="paragraph"> -<p>The Go bindings for the AWS CDK use the standard <a href="https://golang.org/dl/">Go toolchain</a>, v1.18 or later. You can use the editor of your choice.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>Third-party language deprecation: language version is only supported until its EOL (End Of Life) shared by the vendor or community and is subject to change with prior notice.</p> -</div> -</td> -</tr> -</table> -</div> -</div> -<div class="sect3"> -<h4 id="go-newproject">5.10.2. Creating a project</h4> -<div class="paragraph"> -<p>You create a new AWS CDK project by invoking <code>cdk init</code> in an empty directory. Use the <code>--language</code> option and specify <code>go</code>:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">mkdir my-project -cd my-project -cdk init app --language go</code></pre> -</div> -</div> -<div class="paragraph"> -<p><code>cdk init</code> uses the name of the project folder to name various elements of the project, including classes, subfolders, and files. Hyphens in the folder name are converted to underscores. However, the name should otherwise follow the form of a Go identifier; for example, it should not start with a number or contain spaces.</p> -</div> -<div class="paragraph"> -<p>The resulting project includes a reference to the core AWS CDK Go module, <code class="path">github.com/aws/aws-cdk-go/awscdk/v2</code>, in <code class="path">go.mod</code>. Issue <strong class="command">go get</strong> to install this and other required modules.</p> -</div> -</div> -<div class="sect3"> -<h4 id="go-managemodules">5.10.3. Managing AWS Construct Library modules</h4> -<div class="paragraph"> -<p>In most AWS CDK documentation and examples, the word "module" is often used to refer to AWS Construct Library modules, one or more per AWS service, which differs from idiomatic Go usage of the term. The CDK Construct Library is provided in one Go module with the individual Construct Library modules, which support the various AWS services, provided as Go packages within that module.</p> -</div> -<div class="paragraph"> -<p>Some services' AWS Construct Library support is in more than one Construct Library module (Go package). For example, Amazon Route 53 has three Construct Library modules in addition to the main <code>awsroute53</code> package, named <code>awsroute53patterns</code>, <code>awsroute53resolver</code>, and <code>awsroute53targets</code>.</p> -</div> -<div class="paragraph"> -<p>The AWS CDK’s core package, which you’ll need in most AWS CDK apps, is imported in Go code as <code>github.com/aws/aws-cdk-go/awscdk/v2</code>. Packages for the various services in the AWS Construct Library live under <code>github.com/aws/aws-cdk-go/awscdk/v2</code>. For example, the Amazon S3 module’s namespace is <code>github.com/aws/aws-cdk-go/awscdk/v2/awss3</code>.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">import ( - "github.com/aws/aws-cdk-go/awscdk/v2/awss3" - // ... -)</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Once you have imported the Construct Library modules (Go packages) for the services you want to use in your app, you access constructs in that module using, for example, <code>awss3.Bucket</code>.</p> -</div> -</div> -<div class="sect3"> -<h4 id="work-with-cdk-go-dependencies">5.10.4. Managing dependencies in <code class="noloc">Go</code></h4> -<div class="paragraph"> -<p>In Go, dependencies versions are defined in <code class="path">go.mod</code>. The default <code class="path">go.mod</code> is similar to the one shown here.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">module my-package - -go 1.16 - -require ( - github.com/aws/aws-cdk-go/awscdk/v2 v2.16.0 - github.com/aws/constructs-go/constructs/v10 v10.0.5 - github.com/aws/jsii-runtime-go v1.29.0 -)</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Package names (modules, in Go parlance) are specified by URL with the required version number appended. Go’s module system does not support version ranges.</p> -</div> -<div class="paragraph"> -<p>Issue the <strong class="command">go get</strong> command to install all required modules and update <code class="path">go.mod</code>. To see a list of available updates for your dependencies, issue <strong class="command">go list -m -u all</strong>.</p> -</div> -</div> -<div class="sect3"> -<h4 id="go-cdk-idioms">5.10.5. AWS CDK idioms in Go</h4> -<div class="sect4"> -<h5 id="go-naming">Field and method names</h5> -<div class="paragraph"> -<p>Field and method names use camel casing (<code>likeThis</code>) in TypeScript, the CDK’s language of origin. In Go, these follow Go conventions, so are Pascal-cased (<code>LikeThis</code>).</p> -</div> -</div> -<div class="sect4"> -<h5 id="go-cdk-jsii-close">Cleaning up</h5> -<div class="paragraph"> -<p>In your <code>main</code> method, use <code>defer jsii.Close()</code> to make sure your CDK app cleans up after itself.</p> -</div> -</div> -<div class="sect4"> -<h5 id="go-missing-values">Missing values and pointer conversion</h5> -<div class="paragraph"> -<p>In Go, missing values in AWS CDK objects such as property bundles are represented by <code>nil</code>. Go doesn’t have nullable types; the only type that can contain <code>nil</code> is a pointer. To allow values to be optional, then, all CDK properties, arguments, and return values are pointers, even for primitive types. This applies to required values as well as optional ones, so if a required value later becomes optional, no breaking change in type is needed.</p> -</div> -<div class="paragraph"> -<p>When passing literal values or expressions, use the following helper functions to create pointers to the values.</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><code>jsii.String</code></p> -</li> -<li> -<p><code>jsii.Number</code></p> -</li> -<li> -<p><code>jsii.Bool</code></p> -</li> -<li> -<p><code>jsii.Time</code></p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>For consistency, we recommend that you use pointers similarly when defining your own constructs, even though it may seem more convenient to, for example, receive your construct’s <code>id</code> as a string rather than a pointer to a string.</p> -</div> -<div class="paragraph"> -<p>When dealing with optional AWS CDK values, including primitive values as well as complex types, you should explicitly test pointers to make sure they are not <code>nil</code> before doing anything with them. Go does not have "syntactic sugar" to help handle empty or missing values as some other languages do. However, required values in property bundles and similar structures are guaranteed to exist (construction fails otherwise), so these values need not be <code>nil</code>-checked.</p> -</div> -</div> -<div class="sect4"> -<h5 id="go-props">Constructs and Props</h5> -<div class="paragraph"> -<p>Constructs, which represent one or more AWS resources and their associated attributes, are represented in Go as interfaces. For example, <code>awss3.Bucket</code> is an interface. Every construct has a factory function, such as <code>awss3.NewBucket</code>, to return a struct that implements the corresponding interface.</p> -</div> -<div class="paragraph"> -<p>All factory functions take three arguments: the <code>scope</code> in which the construct is being defined (its parent in the construct tree), an <code>id</code>, and <code>props</code>, a bundle of key/value pairs that the construct uses to configure the resources it creates. The "bundle of attributes" pattern is also used elsewhere in the AWS CDK.</p> -</div> -<div class="paragraph"> -<p>In Go, props are represented by a specific struct type for each construct. For example, an <code>awss3.Bucket</code> takes a props argument of type <code>awss3.BucketProps</code>. Use a struct literal to write props arguments.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">var bucket = awss3.NewBucket(stack, jsii.String("amzn-s3-demo-bucket"), &awss3.BucketProps{ - Versioned: jsii.Bool(true), -})</code></pre> -</div> -</div> -</div> -<div class="sect4"> -<h5 id="go-generic-structures">Generic structures</h5> -<div class="paragraph"> -<p>In some places, the AWS CDK uses JavaScript arrays or untyped objects as input to a method. (See, for example, AWS CodeBuild’s <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_codebuild.BuildSpec.html#static-fromwbrobjectvalue">BuildSpec.fromObject()</a> method.) In Go, these objects are represented as slices and an empty interface, respectively.</p> -</div> -<div class="paragraph"> -<p>The CDK provides variadic helper functions such as <code>jsii.Strings</code> for building slices containing primitive types.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">jsii.Strings("One", "Two", "Three")</code></pre> -</div> -</div> -</div> -<div class="sect4"> -<h5 id="go-writing-constructs">Developing custom constructs</h5> -<div class="paragraph"> -<p>In Go, it is usually more straightforward to write a new construct than to extend an existing one. First, define a new struct type, anonymously embedding one or more existing types if extension-like semantics are desired. Write methods for any new functionality you’re adding and the fields necessary to hold the data they need. Define a props interface if your construct needs one. Finally, write a factory function <code>NewMyConstruct()</code> to return an instance of your construct.</p> -</div> -<div class="paragraph"> -<p>If you are simply changing some default values on an existing construct or adding a simple behavior at instantiation, you don’t need all that plumbing. Instead, write a factory function that calls the factory function of the construct you’re "extending." In other CDK languages, for example, you might create a <code>TypedBucket</code> construct that enforces the type of objects in an Amazon S3 bucket by overriding the <code>s3.Bucket</code> type and, in your new type’s initializer, adding a bucket policy that allows only specified filename extensions to be added to the bucket. In Go, it is easier to simply write a <code>NewTypedBucket</code> that returns an <code>s3.Bucket</code> (instantiated using <code>s3.NewBucket</code>) to which you have added an appropriate bucket policy. No new construct type is necessary because the functionality is already available in the standard bucket construct; the new "construct" just provides a simpler way to configure it.</p> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="go-running">5.10.6. Building, synthesizing, and deploying</h4> -<div class="paragraph"> -<p>The AWS CDK automatically compiles your app before running it. However, it can be useful to build your app manually to check for errors and to run tests. You can do this by issuing <code>go build</code> at a command prompt while in your project’s root directory.</p> -</div> -<div class="paragraph"> -<p>Run any tests you’ve written by running <code>go test</code> at a command prompt.</p> -</div> -</div> -</div> -</div> -</div> -<div class="sect1 topic"> -<h2 id="best-practices">6. Best practices for developing and deploying cloud infrastructure with the AWS CDK</h2> -<div class="sectionbody"> -<div class="paragraph"> -<p>With the AWS CDK, developers or administrators can define their cloud infrastructure by using a supported programming language. CDK applications should be organized into logical units, such as API, database, and monitoring resources, and optionally have a pipeline for automated deployments. The logical units should be implemented as constructs including the following:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Infrastructure (such as Amazon S3 buckets, Amazon RDS databases, or an Amazon VPC network)</p> -</li> -<li> -<p>Runtime code (such as AWS Lambda functions)</p> -</li> -<li> -<p>Configuration code</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>Stacks define the deployment model of these logical units. For a more detailed introduction to the concepts behind the CDK, see <a href="#getting-started">Getting started with the AWS CDK</a>.</p> -</div> -<div class="paragraph"> -<p>The AWS CDK reflects careful consideration of the needs of our customers and internal teams and of the failure patterns that often arise during the deployment and ongoing maintenance of complex cloud applications. We discovered that failures are often related to "out-of-band" changes to an application that aren’t fully tested, such as configuration changes. Therefore, we developed the AWS CDK around a model in which your entire application is defined in code, not only business logic but also infrastructure and configuration. That way, proposed changes can be carefully reviewed, comprehensively tested in environments resembling production to varying degrees, and fully rolled back if something goes wrong.</p> -</div> -<div class="imageblock"> -<div class="content"> -<img src="images/all-in-one.jpg" alt="Software development lifecycle icons representing infrastructure, application, source code, configuration, and deployment."> -</div> -</div> -<div class="paragraph"> -<p>At deployment time, the AWS CDK synthesizes a cloud assembly that contains the following:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>AWS CloudFormation templates that describe your infrastructure in all target environments</p> -</li> -<li> -<p>File assets that contain your runtime code and their supporting files</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>With the CDK, every commit in your application’s main version control branch can represent a complete, consistent, deployable version of your application. Your application can then be deployed automatically whenever a change is made.</p> -</div> -<div class="paragraph"> -<p>The philosophy behind the AWS CDK leads to our recommended best practices, which we have divided into four broad categories.</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><a href="#best-practices-organization">Organization best practices</a></p> -</li> -<li> -<p><a href="#best-practices-code">Coding best practices</a></p> -</li> -<li> -<p><a href="#best-practices-constructs">Construct best practices</a></p> -</li> -<li> -<p><a href="#best-practices-apps">Application best practices</a></p> -</li> -</ul> -</div> -<div class="admonitionblock tip"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-tip" title="Tip"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>Also consider <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/best-practices.html">best practices for AWS CloudFormation</a> and the individual AWS services that you use, where applicable to CDK-defined infrastructure.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="sect2"> -<h3 id="best-practices-organization">6.1. Organization best practices</h3> -<div class="paragraph"> -<p>In the beginning stages of AWS CDK adoption, it’s important to consider how to set up your organization for success. It’s a best practice to have a team of experts responsible for training and guiding the rest of the company as they adopt the CDK. The size of this team might vary, from one or two people at a small company to a full-fledged Cloud Center of Excellence (CCoE) at a larger company. This team is responsible for setting standards and policies for cloud infrastructure at your company, and also for training and mentoring developers.</p> -</div> -<div class="paragraph"> -<p>The CCoE might provide guidance on what programming languages should be used for cloud infrastructure. Details will vary from one organization to the next, but a good policy helps make sure that developers can understand and maintain the company’s cloud infrastructure.</p> -</div> -<div class="paragraph"> -<p>The CCoE also creates a "landing zone" that defines your organizational units within AWS. A landing zone is a pre-configured, secure, scalable, multi-account AWS environment based on best practice blueprints. To tie together the services that make up your landing zone, you can use <a href="https://aws.amazon.com/controltower/">AWS Control Tower</a>, which configures and manages your entire multi-account system from a single user interface.</p> -</div> -<div class="paragraph"> -<p>Development teams should be able to use their own accounts for testing and deploy new resources in these accounts as needed. Individual developers can treat these resources as extensions of their own development workstation. Using <a href="#cdk-pipeline">CDK Pipelines</a>, the AWS CDK applications can then be deployed via a CI/CD account to testing, integration, and production environments (each isolated in its own AWS Region or account). This is done by merging the developers' code into your organization’s canonical repository.</p> -</div> -<div class="imageblock"> -<div class="content"> -<img src="images/best-practice-deploy-to-multiple-accounts.png" alt="Diagram showing deployment process from developer accounts to multiple target accounts via CI/CD pipeline."> -</div> -</div> -</div> -<div class="sect2"> -<h3 id="best-practices-code">6.2. Coding best practices</h3> -<div class="paragraph"> -<p>This section presents best practices for organizing your AWS CDK code. The following diagram shows the relationship between a team and that team’s code repositories, packages, applications, and construct libraries.</p> -</div> -<div class="imageblock"> -<div class="content"> -<img src="images/code-organization.jpg" alt="Diagram showing team’s code organization: repository, package, CDK app or construct library."> -</div> -</div> -<div class="sect3"> -<h4 id="best-practices-code-kiss">6.2.1. Start simple and add complexity only when you need it</h4> -<div class="paragraph"> -<p>The guiding principle for most of our best practices is to keep things simple as possible—​but no simpler. Add complexity only when your requirements dictate a more complicated solution. With the AWS CDK, you can refactor your code as necessary to support new requirements. You don’t have to architect for all possible scenarios upfront.</p> -</div> -</div> -<div class="sect3"> -<h4 id="best-practices-code-well-architected">6.2.2. Align with the AWS Well-Architected Framework</h4> -<div class="paragraph"> -<p>The <a href="https://aws.amazon.com/architecture/well-architected/">AWS Well-Architected</a> Framework defines a <em>component</em> as the code, configuration, and AWS resources that together deliver against a requirement. A component is often the unit of technical ownership, and is decoupled from other components. The term <em>workload</em> is used to identify a set of components that together deliver business value. A workload is usually the level of detail that business and technology leaders communicate about.</p> -</div> -<div class="paragraph"> -<p>An AWS CDK application maps to a component as defined by the AWS Well-Architected Framework. AWS CDK apps are a mechanism to codify and deliver Well-Architected cloud application best practices. You can also create and share components as reusable code libraries through artifact repositories, such as AWS CodeArtifact.</p> -</div> -</div> -<div class="sect3"> -<h4 id="best-practices-code-package">6.2.3. Every application starts with a single package in a single repository</h4> -<div class="paragraph"> -<p>A single package is the entry point of your AWS CDK app. Here, you define how and where to deploy the different logical units of your application. You also define the CI/CD pipeline to deploy the application. The app’s constructs define the logical units of your solution.</p> -</div> -<div class="paragraph"> -<p>Use additional packages for constructs that you use in more than one application. (Shared constructs should also have their own lifecycle and testing strategy.) Dependencies between packages in the same repository are managed by your repo’s build tooling.</p> -</div> -<div class="paragraph"> -<p>Although it’s possible, we don’t recommend putting multiple applications in the same repository, especially when using automated deployment pipelines. Doing this increases the "blast radius" of changes during deployment. When there are multiple applications in a repository, changes to one application trigger deployment of the others (even if the others haven’t changed). Furthermore, a break in one application prevents the other applications from being deployed.</p> -</div> -</div> -<div class="sect3"> -<h4 id="best-practices-code-repo">6.2.4. Move code into repositories based on code lifecycle or team ownership</h4> -<div class="paragraph"> -<p>When packages begin to be used in multiple applications, move them to their own repository. This way, the packages can be referenced by application build systems that use them, and they can also be updated on cadences independent of the application lifecycles. However, at first it might make sense to put all shared constructs in one repository.</p> -</div> -<div class="paragraph"> -<p>Also, move packages to their own repository when different teams are working on them. This helps enforce access control.</p> -</div> -<div class="paragraph"> -<p>To consume packages across repository boundaries, you need a private package repository—​similar to NPM, PyPi, or Maven Central, but internal to your organization. You also need a release process that builds, tests, and publishes the package to the private package repository. <a href="https://docs.aws.amazon.com/codeartifact/latest/ug/">CodeArtifact</a> can host packages for most popular programming languages.</p> -</div> -<div class="paragraph"> -<p>Dependencies on packages in the package repository are managed by your language’s package manager, such as NPM for TypeScript or JavaScript applications. Your package manager helps to make sure that builds are repeatable. It does this by recording the specific versions of every package that your application depends on. It also lets you upgrade those dependencies in a controlled manner.</p> -</div> -<div class="paragraph"> -<p>Shared packages need a different testing strategy. For a single application, it might be good enough to deploy the application to a testing environment and confirm that it still works. But shared packages must be tested independently of the consuming application, as if they were being released to the public. (Your organization might choose to actually release some shared packages to the public.)</p> -</div> -<div class="paragraph"> -<p>Keep in mind that a construct can be arbitrarily simple or complex. A <code>Bucket</code> is a construct, but <code>CameraShopWebsite</code> could be a construct, too.</p> -</div> -</div> -<div class="sect3"> -<h4 id="best-practices-code-all">6.2.5. Infrastructure and runtime code live in the same package</h4> -<div class="paragraph"> -<p>In addition to generating AWS CloudFormation templates for deploying infrastructure, the AWS CDK also bundles runtime assets like Lambda functions and Docker images and deploys them alongside your infrastructure. This makes it possible to combine the code that defines your infrastructure and the code that implements your runtime logic into a single construct. It’s a best practice to do this. These two kinds of code don’t need to live in separate repositories or even in separate packages.</p> -</div> -<div class="paragraph"> -<p>To evolve the two kinds of code together, you can use a self-contained construct that completely describes a piece of functionality, including its infrastructure and logic. With a self-contained construct, you can test the two kinds of code in isolation, share and reuse the code across projects, and version all the code in sync.</p> -</div> -</div> -</div> -<div class="sect2"> -<h3 id="best-practices-constructs">6.3. Construct best practices</h3> -<div class="paragraph"> -<p>This section contains best practices for developing constructs. Constructs are reusable, composable modules that encapsulate resources. They’re the building blocks of AWS CDK apps.</p> -</div> -<div class="sect3"> -<h4 id="best-practices-constructs-model">6.3.1. Model with constructs, deploy with stacks</h4> -<div class="paragraph"> -<p>Stacks are the unit of deployment: everything in a stack is deployed together. So when building your application’s higher-level logical units from multiple AWS resources, represent each logical unit as a <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html">Construct</a>, not as a <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html">Stack</a>. Use stacks only to describe how your constructs should be composed and connected for your various deployment scenarios.</p> -</div> -<div class="paragraph"> -<p>For example, if one of your logical units is a website, the constructs that make it up (such as an Amazon S3 bucket, API Gateway, Lambda functions, or Amazon RDS tables) should be composed into a single high-level construct. Then that construct should be instantiated in one or more stacks for deployment.</p> -</div> -<div class="paragraph"> -<p>By using constructs for building and stacks for deploying, you improve reuse potential of your infrastructure and give yourself more flexibility in how it’s deployed.</p> -</div> -</div> -<div class="sect3"> -<h4 id="best-practices-constructs-config">6.3.2. Configure with properties and methods, not environment variables</h4> -<div class="paragraph"> -<p>Environment variable lookups inside constructs and stacks are a common anti-pattern. Both constructs and stacks should accept a properties object to allow for full configurability completely in code. Doing otherwise introduces a dependency on the machine that the code will run on, which creates yet more configuration information that you have to track and manage.</p> -</div> -<div class="paragraph"> -<p>In general, environment variable lookups should be limited to the top level of an AWS CDK app. They should also be used to pass in information that’s needed for running in a development environment. For more information, see <a href="#environments">Environments for the AWS CDK</a>.</p> -</div> -</div> -<div class="sect3"> -<h4 id="best-practices-constructs-test">6.3.3. Unit test your infrastructure</h4> -<div class="paragraph"> -<p>To consistently run a full suite of unit tests at build time in all environments, avoid network lookups during synthesis and model all your production stages in code. (These best practices are covered later.) If any single commit always results in the same generated template, you can trust the unit tests that you write to confirm that the generated templates look the way you expect. For more information, see <a href="#testing">Test AWS CDK applications</a>.</p> -</div> -</div> -<div class="sect3"> -<h4 id="best-practices-constructs-logicalid">6.3.4. Don’t change the logical ID of stateful resources</h4> -<div class="paragraph"> -<p>Changing the logical ID of a resource results in the resource being replaced with a new one at the next deployment. For stateful resources like databases and S3 buckets, or persistent infrastructure like an Amazon VPC, this is seldom what you want. Be careful about any refactoring of your AWS CDK code that could cause the ID to change. Write unit tests that assert that the logical IDs of your stateful resources remain static. The logical ID is derived from the <code>id</code> you specify when you instantiate the construct, and the construct’s position in the construct tree. For more information, see <a href="#identifiers-logical-ids">Logical IDs</a>.</p> -</div> -</div> -<div class="sect3"> -<h4 id="best-practices-constructs-compliance">6.3.5. Constructs aren’t enough for compliance</h4> -<div class="paragraph"> -<p>Many enterprise customers write their own wrappers for L2 constructs (the "curated" constructs that represent individual AWS resources with built-in sane defaults and best practices). These wrappers enforce security best practices such as static encryption and specific IAM policies. For example, you might create a <code>MyCompanyBucket</code> that you then use in your applications in place of the usual Amazon S3 <code>Bucket</code> construct. This pattern is useful for surfacing security guidance early in the software development lifecycle, but don’t rely on it as the sole means of enforcement.</p> -</div> -<div class="paragraph"> -<p>Instead, use AWS features such as <a href="https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps.html">service control policies</a> and <a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html">permission boundaries</a> to enforce your security guardrails at the organization level. Use <a href="#aspects">Aspects and the AWS CDK</a> or tools like <a href="https://github.com/aws-cloudformation/cloudformation-guard">CloudFormation Guard</a> to make assertions about the security properties of infrastructure elements before deployment. Use AWS CDK for what it does best.</p> -</div> -<div class="paragraph"> -<p>Finally, keep in mind that writing your own "L2+" constructs might prevent your developers from taking advantage of AWS CDK packages such as <a href="https://docs.aws.amazon.com/solutions/latest/constructs/welcome.html">AWS Solutions Constructs</a> or third-party constructs from Construct Hub. These packages are typically built on standard AWS CDK constructs and won’t be able to use your wrapper constructs.</p> -</div> -</div> -</div> -<div class="sect2"> -<h3 id="best-practices-apps">6.4. Application best practices</h3> -<div class="paragraph"> -<p>In this section we discuss how to write your AWS CDK applications, combining constructs to define how your AWS resources are connected.</p> -</div> -<div class="sect3"> -<h4 id="best-practices-apps-synth">6.4.1. Make decisions at synthesis time</h4> -<div class="paragraph"> -<p>Although AWS CloudFormation lets you make decisions at deployment time (using <code>Conditions</code>, <code>{ Fn::If }</code>, and <code>Parameters</code>), and the AWS CDK gives you some access to these mechanisms, we recommend against using them. The types of values that you can use and the types of operations you can perform on them are limited compared to what’s available in a general-purpose programming language.</p> -</div> -<div class="paragraph"> -<p>Instead, try to make all decisions, such as which construct to instantiate, in your AWS CDK application by using your programming language’s <code>if</code> statements and other features. For example, a common CDK idiom, iterating over a list and instantiating a construct with values from each item in the list, simply isn’t possible using AWS CloudFormation expressions.</p> -</div> -<div class="paragraph"> -<p>Treat AWS CloudFormation as an implementation detail that the AWS CDK uses for robust cloud deployments, not as a language target. You’re not writing AWS CloudFormation templates in TypeScript or Python, you’re writing CDK code that happens to use CloudFormation for deployment.</p> -</div> -</div> -<div class="sect3"> -<h4 id="best-practices-apps-names">6.4.2. Use generated resource names, not physical names</h4> -<div class="paragraph"> -<p>Names are a precious resource. Each name can only be used once. Therefore, if you hardcode a table name or bucket name into your infrastructure and application, you can’t deploy that piece of infrastructure twice in the same account. (The name we’re talking about here is the name specified by, for example, the <code>bucketName</code> property on an Amazon S3 bucket construct.)</p> -</div> -<div class="paragraph"> -<p>What’s worse, you can’t make changes to the resource that require it to be replaced. If a property can only be set at resource creation, such as the <code>KeySchema</code> of an Amazon DynamoDB table, then that property is immutable. Changing this property requires a new resource. However, the new resource must have the same name in order to be a true replacement. But it can’t have the same name while the existing resource is still using that name.</p> -</div> -<div class="paragraph"> -<p>A better approach is to specify as few names as possible. If you omit resource names, the AWS CDK will generate them for you in a way that won’t cause problems. Suppose you have a table as a resource. You can then pass the generated table name as an environment variable into your AWS Lambda function. In your AWS CDK application, you can reference the table name as <code>table.tableName</code>. Alternatively, you can generate a configuration file on your Amazon EC2 instance on startup, or write the actual table name to the AWS Systems Manager Parameter Store so your application can read it from there.</p> -</div> -<div class="paragraph"> -<p>If the place you need it is another AWS CDK stack, that’s even more straightforward. Supposing that one stack defines the resource and another stack needs to use it, the following applies:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>If the two stacks are in the same AWS CDK app, pass a reference between the two stacks. For example, save a reference to the resource’s construct as an attribute of the defining stack (<code>this.stack.uploadBucket = amzn-s3-demo-bucket</code>). Then, pass that attribute to the constructor of the stack that needs the resource.</p> -</li> -<li> -<p>When the two stacks are in different AWS CDK apps, use a static <code>from</code> method to use an externally defined resource based on its ARN, name, or other attributes. (For example, use <code>Table.fromArn()</code> for a DynamoDB table). Use the <code>CfnOutput</code> construct to print the ARN or other required value in the output of <code>cdk deploy</code>, or look in the AWS Management Console. Alternatively, the second app can read the CloudFormation template generated by the first app and retrieve that value from the <code>Outputs</code> section.</p> -</li> -</ul> -</div> -</div> -<div class="sect3"> -<h4 id="best-practices-apps-removal-logs">6.4.3. Define removal policies and log retention</h4> -<div class="paragraph"> -<p>The AWS CDK attempts to keep you from losing data by defaulting to policies that retain everything you create. For example, the default removal policy on resources that contain data (such as Amazon S3 buckets and database tables) is not to delete the resource when it is removed from the stack. Instead, the resource is orphaned from the stack. Similarly, the CDK’s default is to retain all logs forever. In production environments, these defaults can quickly result in the storage of large amounts of data that you don’t actually need, and a corresponding AWS bill.</p> -</div> -<div class="paragraph"> -<p>Consider carefully what you want these policies to be for each production resource and specify them accordingly. Use <a href="#aspects">Aspects and the AWS CDK</a> to validate the removal and logging policies in your stack.</p> -</div> -</div> -<div class="sect3"> -<h4 id="best-practices-apps-separate">6.4.4. Separate your application into multiple stacks as dictated by deployment requirements</h4> -<div class="paragraph"> -<p>There is no hard and fast rule to how many stacks your application needs. You’ll usually end up basing the decision on your deployment patterns. Keep in mind the following guidelines:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>It’s typically more straightforward to keep as many resources in the same stack as possible, so keep them together unless you know you want them separated.</p> -</li> -<li> -<p>Consider keeping stateful resources (like databases) in a separate stack from stateless resources. You can then turn on termination protection on the stateful stack. This way, you can freely destroy or create multiple copies of the stateless stack without risk of data loss.</p> -</li> -<li> -<p>Stateful resources are more sensitive to construct renaming—​renaming leads to resource replacement. Therefore, don’t nest stateful resources inside constructs that are likely to be moved around or renamed (unless the state can be rebuilt if lost, like a cache). This is another good reason to put stateful resources in their own stack.</p> -</li> -</ul> -</div> -</div> -<div class="sect3"> -<h4 id="best-practices-apps-context">6.4.5. Commit <code class="path">cdk.context.json</code> to avoid non-deterministic behavior</h4> -<div class="paragraph"> -<p>Determinism is key to successful AWS CDK deployments. An AWS CDK app should have essentially the same result whenever it is deployed to a given environment.</p> -</div> -<div class="paragraph"> -<p>Since your AWS CDK app is written in a general-purpose programming language, it can execute arbitrary code, use arbitrary libraries, and make arbitrary network calls. For example, you could use an AWS SDK to retrieve some information from your AWS account while synthesizing your app. Recognize that doing so will result in additional credential setup requirements, increased latency, and a chance, however small, of failure every time you run <code>cdk synth</code>.</p> -</div> -<div class="paragraph"> -<p>Never modify your AWS account or resources during synthesis. Synthesizing an app should not have side effects. Changes to your infrastructure should happen only in the deployment phase, after the AWS CloudFormation template has been generated. This way, if there’s a problem, AWS CloudFormation can automatically roll back the change. To make changes that can’t be easily made within the AWS CDK framework, use <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.custom_resources-readme.html">custom resources</a> to execute arbitrary code at deployment time.</p> -</div> -<div class="paragraph"> -<p>Even strictly read-only calls are not necessarily safe. Consider what happens if the value returned by a network call changes. What part of your infrastructure will that impact? What will happen to already-deployed resources? Following are two example situations in which a sudden change in values might cause a problem.</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>If you provision an Amazon VPC to all available Availability Zones in a specified Region, and the number of AZs is two on deployment day, then your IP space gets split in half. If AWS launches a new Availability Zone the next day, the next deployment after that tries to split your IP space into thirds, requiring all subnets to be recreated. This probably won’t be possible because your Amazon EC2 instances are still running, and you’ll have to clean this up manually.</p> -</li> -<li> -<p>If you query for the latest Amazon Linux machine image and deploy an Amazon EC2 instance, and the next day a new image is released, a subsequent deployment picks up the new AMI and replaces all your instances. This might not be what you expected to happen.</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>These situations can be pernicious because the AWS-side change might occur after months or years of successful deployments. Suddenly your deployments are failing "for no reason" and you long ago forgot what you did and why.</p> -</div> -<div class="paragraph"> -<p>Fortunately, the AWS CDK includes a mechanism called <em>context providers</em> to record a snapshot of non-deterministic values. This allows future synthesis operations to produce exactly the same template as they did when first deployed. The only changes in the new template are the changes that <em>you</em> made in your code. When you use a construct’s <code>.fromLookup()</code> method, the result of the call is cached in <code class="path">cdk.context.json</code>. You should commit this to version control along with the rest of your code to make sure that future executions of your CDK app use the same value. The CDK Toolkit includes commands to manage the context cache, so you can refresh specific entries when you need to. For more information, see <a href="#context">Context values and the AWS CDK</a>.</p> -</div> -<div class="paragraph"> -<p>If you need some value (from AWS or elsewhere) for which there is no native CDK context provider, we recommend writing a separate script. The script should retrieve the value and write it to a file, then read that file in your CDK app. Run the script only when you want to refresh the stored value, not as part of your regular build process.</p> -</div> -</div> -<div class="sect3"> -<h4 id="best-practices-apps-roles">6.4.6. Let the AWS CDK manage roles and security groups</h4> -<div class="paragraph"> -<p>With the AWS CDK construct library’s <code>grant()</code> convenience methods, you can create AWS Identity and Access Management roles that grant access to one resource by another using minimally scoped permissions. For example, consider a line like the following:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">amzn-s3-demo-bucket.grantRead(myLambda)</code></pre> -</div> -</div> -<div class="paragraph"> -<p>This single line adds a policy to the Lambda function’s role (which is also created for you). That role and its policies are more than a dozen lines of CloudFormation that you don’t have to write. The AWS CDK grants only the minimal permissions required for the function to read from the bucket.</p> -</div> -<div class="paragraph"> -<p>If you require developers to always use predefined roles that were created by a security team, AWS CDK coding becomes much more complicated. Your teams could lose a lot of flexibility in how they design their applications. A better alternative is to use <a href="https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps.html">service control policies</a> and <a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html">permission boundaries</a> to make sure that developers stay within the guardrails.</p> -</div> -</div> -<div class="sect3"> -<h4 id="best-practices-apps-stages">6.4.7. Model all production stages in code</h4> -<div class="paragraph"> -<p>In traditional AWS CloudFormation scenarios, your goal is to produce a single artifact that is parameterized so that it can be deployed to various target environments after applying configuration values specific to those environments. In the CDK, you can, and should, build that configuration into your source code. Create a stack for your production environment, and create a separate stack for each of your other stages. Then, put the configuration values for each stack in the code. Use services like <a href="https://aws.amazon.com/secrets-manager/">Secrets Manager</a> and <a href="https://aws.amazon.com/systems-manager/">Systems Manager</a> Parameter Store for sensitive values that you don’t want to check in to source control, using the names or ARNs of those resources.</p> -</div> -<div class="paragraph"> -<p>When you synthesize your application, the cloud assembly created in the <code class="path">cdk.out</code> folder contains a separate template for each environment. Your entire build is deterministic. There are no out-of-band changes to your application, and any given commit always yields the exact same AWS CloudFormation template and accompanying assets. This makes unit testing much more reliable.</p> -</div> -</div> -<div class="sect3"> -<h4 id="best-practices-apps-measure">6.4.8. Measure everything</h4> -<div class="paragraph"> -<p>Achieving the goal of full continuous deployment, with no human intervention, requires a high level of automation. That automation is only possible with extensive amounts of monitoring. To measure all aspects of your deployed resources, create metrics, alarms, and dashboards. Don’t stop at measuring things like CPU usage and disk space. Also record your business metrics, and use those measurements to automate deployment decisions like rollbacks. Most of the L2 constructs in AWS CDK have convenience methods to help you create metrics, such as the <code>metricUserErrors()</code> method on the <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_dynamodb.Table.html">dynamodb.Table</a> class.</p> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="best-practices-security">6.5. AWS CDK security best practices</h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>The AWS Cloud Development Kit (AWS CDK) is a powerful tool that developers can use to configure AWS services and provision infrastructure on AWS. With any tool that provides such control and capabilities, organizations will need to establish policies and practices to ensure that the tool is being used in safe and secure ways. For example, organizations may want to restrict developer access to specific services to ensure that they can’t tamper with compliance or cost control measures that are configured in the account.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>The AWS Cloud Development Kit (AWS CDK) is a powerful tool that developers can use to configure AWS services and provision infrastructure on AWS. With any tool that provides such control and capabilities, organizations will need to establish policies and practices to ensure that the tool is being used in safe and secure ways. For example, organizations may want to restrict developer access to specific services to ensure that they can’t tamper with compliance or cost control measures that are configured in the account.</p> -</div> -<div class="paragraph"> -<p>Often, there can be a tension between security and productivity, and each organization needs to establish the proper balance for themselves. This topic provides security best practices for the AWS CDK that you can consider as you create and implement your own security policies. The following best practices are general guidelines and don’t represent a complete security solution. Because these best practices might not be appropriate or sufficient for your environment, treat them as helpful considerations rather than prescriptions.</p> -</div> -<div class="sect3"> -<h4 id="best-practices-security-iam">6.5.1. Follow IAM security best practices</h4> -<div class="paragraph"> -<p>AWS Identity and Access Management (IAM) is a web service that helps you securely control access to AWS resources. Organizations, individuals, and the AWS CDK use IAM to manage permissions that determine the actions that can be performed on AWS resources. When using IAM, follow the IAM security best practices. For more information, see <a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/IAMBestPracticesAndUseCases.html">Security best practices and use cases in AWS Identity and Access Management</a> in the <em>IAM User Guide</em>.</p> -</div> -</div> -<div class="sect3"> -<h4 id="best-practices-security-permissions">6.5.2. Manage permissions for the AWS CDK</h4> -<div class="paragraph"> -<p>When you use the AWS CDK across your organization to develop and manage your infrastructure, you’ll want to consider the following scenarios where managing permissions will be important:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><strong>Permissions for AWS CDK deployments</strong> – These permissions determine who can make changes to your AWS resources and what changes they can make.</p> -</li> -<li> -<p><strong>Permissions between resources</strong> – These are the permissions that allow interactions between the AWS resources that you create and manage with the AWS CDK.</p> -</li> -</ul> -</div> -<div class="sect4"> -<h5 id="best-practices-security-permissions-deployments">Manage permissions for AWS CDK deployments</h5> -<div class="paragraph"> -<p>Developers use the AWS CDK to define infrastructure locally on their development machines. This infrastructure is implemented in AWS environments through deployments that typically involve using the AWS CDK Command Line Interface (AWS CDK <code class="noloc">CLI</code>). With deployments, you may want to control what changes developers can make in your environments. For example, you might have an Amazon Virtual Private Cloud (Amazon VPC) resource that you don’t want developers to modify.</p> -</div> -<div class="paragraph"> -<p>By default, the CDK <code class="noloc">CLI</code> uses a combination of the actor’s security credentials and IAM roles that are created during bootstrapping to receive permissions for deployments. The actor’s security credentials are first used for authentication and IAM roles are then assumed to perform various actions during deployment, such as using the AWS CloudFormation service to create resources. For more information on how CDK deployments work, including the IAM roles that are used, see <a href="#deploy">Deploy AWS CDK applications</a>.</p> -</div> -<div class="paragraph"> -<p>To restrict who can perform deployments and the actions that can be performed during deployment, consider the following:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>The actor’s security credentials are the first set of credentials used to authenticate to AWS. From here, the permissions used to perform actions during deployment are granted to the IAM roles that are assumed during the deployment workflow. You can restrict who can perform deployments by limiting who can assume these roles. You can also restrict the actions that can be performed during deployment by replacing these IAM roles with your own.</p> -</li> -<li> -<p>Permissions for performing deployments are given to the <code>DeploymentActionRole</code>. You can control permissions for who can perform deployments by limiting who can assume this role. By using a role for deployments, you can perform cross-account deployments since the role can be assumed by AWS identities in a different account. By default, all identities in the same AWS account with the appropriate <code>AssumeRole</code> policy statement can assume this role.</p> -</li> -<li> -<p>Permissions for creating and modifying resources through AWS CloudFormation are given to the <code>CloudFormationExecutionRole</code>. This role also requires permission to read from the bootstrap resources. You control the permissions that CDK deployments have by using a managed policy for the <code>CloudFormationExecutionRole</code> and optionally by configuring a permissions boundary. By default, this role has <code>AdministratorAccess</code> permissions with no permission boundary.</p> -</li> -<li> -<p>Permissions for interacting with bootstrap resources are given to the <code>FilePublishingRole</code> and <code>ImagePublishingRole</code>. The actor performing deployments must have permission to assume these roles. By default, all identities in the same AWS account with the appropriate <code>AssumeRole</code> policy statement can assume this role.</p> -</li> -<li> -<p>Permissions for accessing bootstrap resources to perform lookups are given to the <code>LookupRole</code>. The actor performing deployments must have permission to assume this role. By default, this role has <code>readOnly</code> access to the bootstrap resources. By default, all identities in the same AWS account with the appropriate <code>AssumeRole</code> policy statement can assume this role.</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>To configure the IAM identities in your AWS account with permission to assume these roles, add a policy with the following policy statement to the identities:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-json" data-lang="json">{ - "Version": "2012-10-17", - "Statement": [{ - "Sid": "AssumeCDKRoles", - "Effect": "Allow", - "Action": "sts:AssumeRole", - "Resource": "*", - "Condition": { - "StringEquals": { - "iam:ResourceTag/aws-cdk:bootstrap-role": [ - "image-publishing", - "file-publishing", - "deploy", - "lookup" - ] - } - } - }] -}</code></pre> -</div> -</div> -<div class="sect5"> -<h6 id="best-practices-security-permissions-deployments-roles">Modify the permissions for the roles assumed during deployment</h6> -<div class="paragraph"> -<p>By modifying permissions for the roles assumed during deployment, you can manage the actions that can be performed during deployment. To modify permissions, you create your own IAM roles and specify them when bootstrapping your environment. When you customize bootstrapping, you will have to customize synthesis. For general instructions, see <a href="#bootstrapping-customizing">Customize AWS CDK bootstrapping</a>.</p> -</div> -</div> -<div class="sect5"> -<h6 id="best-practices-security-permissions-deployments-creds">Modify the security credentials and roles used during deployment</h6> -<div class="paragraph"> -<p>The roles and bootstrap resources that are used during deployments are determined by the CDK stack synthesizer that you use. To modify this behavior, you can customize synthesis. For more information, see <a href="#configure-synth">Configure and perform CDK stack synthesis</a>.</p> -</div> -</div> -<div class="sect5"> -<h6 id="best-practices-security-permissions-deployments-least">Considerations for granting least privilege access</h6> -<div class="paragraph"> -<p>Granting least privilege access is a security best practice that we recommend that you consider as you develop your security strategy. For more information, see <a href="https://docs.aws.amazon.com/wellarchitected/latest/security-pillar/sec_permissions_least_privileges.html">SEC03-BP02 Grant least privilege access</a> in the <em>AWS Well-Architected Framework Guide</em>.</p> -</div> -<div class="paragraph"> -<p>Often, granting least privilege access involves restricting IAM policies to the minimum access necessary to perform a given task. Attempting to grant least privilege access through fine-grained permissions with the CDK using this approach can impact CDK deployments and cause you to have to create wider-scoped permissions than you’d like. The following are a few things to consider when using this approach:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Determining an exhaustive list of permissions that allow developers to use the AWS CDK to provision infrastructure through CloudFormation is difficult and complex.</p> -</li> -<li> -<p>If you want to be fine-grained, permissions may become too long to fit within the maximum length of IAM policy documents.</p> -</li> -<li> -<p>Providing an incomplete set of permissions can severely impact developer productivity and deployments.</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>With the CDK, deployments are performed using CloudFormation. CloudFormation initiates a set of AWS API calls in order using the permissions that are provided. The permissions necessary at any point in time depends on many factors:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>The AWS services that are being modified. Specifically, the resources and properties that are being used and changed.</p> -</li> -<li> -<p>The current state of the CloudFormation stack.</p> -</li> -<li> -<p>Issues that may occur during deployments and if rollbacks are needed, which will require <code>Delete</code> permissions in addition to <code>Create</code>.</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>When the provided permissions are incomplete, manual intervention will be required. The following are a few examples:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>If you discover incomplete permissions during roll forward, you’ll need to pause deployment, and take time to discuss and provision new permissions before continuing.</p> -</li> -<li> -<p>If deployment rolls back and the permissions to apply the roll back are missing, it may leave your CloudFormation stack in a state that will require a lot of manual work to recover from.</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>Since this approach can result in complications and severely limit developer productivity, we don’t recommend it. Instead, we recommend implementing guardrails and preventing bypass.</p> -</div> -</div> -<div class="sect5"> -<h6 id="best-practices-security-permissions-deployments-guardrails">Implementing guardrails and preventing bypass</h6> -<div class="paragraph"> -<p>You can implement guardrails, compliance rules, auditing, and monitoring by using services such as AWS Control Tower, AWS Config, AWS CloudTrail, AWS Security Hub, and others. With this approach, you grant developers permission to do everything, except tampering with the existing validation mechanisms. Developers have the freedom to implement changes quickly, as long as they stay within policy. This is the approach we recommend when using the AWS CDK. For more information on guardrails, see <a href="https://docs.aws.amazon.com/wellarchitected/latest/management-and-governance-guide/controls.html">Controls</a> in the <em>Management and Governance Cloud Environment Guide</em>.</p> -</div> -<div class="paragraph"> -<p>We also recommend using <em>permissions boundaries</em> or <em>service control policies (SCPs)</em> as a way of implementing guardrails. For more information on implementing permissions boundaries with the AWS CDK, see <a href="#customize-permissions-boundaries">Create and apply permissions boundaries for the AWS CDK</a>.</p> -</div> -<div class="paragraph"> -<p>If you are using any compliance control mechanisms, set them up during the bootstrapping phase. Make sure that the <code>CloudFormationExecutionRole</code> or developer-accessible identities have policies or permissions boundaries attached that prevent bypass of the mechanisms that you put in place. The appropriate policies depends on the specific mechanisms that you use.</p> -</div> -</div> -</div> -<div class="sect4"> -<h5 id="best-practices-security-permissions-resources">Manage permissions between resources provisioned by the AWS CDK</h5> -<div class="paragraph"> -<p>How you manage permissions between resources that are provisioned by the AWS CDK depends on whether you allow the CDK to create roles and policies.</p> -</div> -<div class="paragraph"> -<p>When you use L2 constructs from the AWS Construct Library to define your infrastructure, you can use the provided <code>grant</code> methods to provision permissions between resources. With <code>grant</code> methods, you specify the type of access you want between resources and the AWS CDK provisions least privilege IAM roles to accomplish your intent. This approach meets security requirements for most organizations while being efficient for developers. For more information, see <a href="#define-iam-l2">Define permissions for L2 constructs with the AWS CDK</a>.</p> -</div> -<div class="paragraph"> -<p>If you want to work around this feature by replacing the automatically generated roles with manually created ones, consider the following:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Your IAM roles will need to be manually created, slowing down application development.</p> -</li> -<li> -<p>When IAM roles need to be manually created and managed, people will often combine multiple logical roles into a single role to make them easier to manage. This runs counter to the least privilege principle.</p> -</li> -<li> -<p>Since these roles will need to be created before deployment, the resources that need to be referenced will not yet exist. Therefore, you’ll need to use wildcards, which runs counter to the least privilege principle.</p> -</li> -<li> -<p>A common workaround to using wildcards is to mandate that all resources be given a predictable name. However, this interferes with CloudFormation’s ability to replace resources when necessary and may slow down or block development. Because of this, we recommend that you allow CloudFormation to create unique resource names for you.</p> -</li> -<li> -<p>It will be impossible to perform continuous delivery since manual actions must be performed prior to every deployment.</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>When organizations want to prevent the CDK from creating roles, it is usually to prevent developers from being able to create IAM roles. The concern is that by giving developers permission to create IAM roles using the AWS CDK, they could possibly elevate their own privileges. To mitigate against this, we recommend using <em>permission boundaries</em> or <em>service control policies (SCPs)</em>. With permission boundaries, you can set limits for what developers and the CDK are allowed to do. For more information on using permission boundaries with the CDK, see <a href="#customize-permissions-boundaries">Create and apply permissions boundaries for the AWS CDK</a>.</p> -</div> -</div> -</div> -</div> -</div> -</div> -<div class="sect1 topic"> -<h2 id="migrating-v2">7. Migrating from AWS CDK v1 to AWS CDK v2</h2> -<div class="sectionbody"> -<div class="paragraph"> -<p>Version 2 of the AWS Cloud Development Kit (AWS CDK) is designed to make writing infrastructure as code in your preferred programming language easier. This topic describes the changes between v1 and v2 of the AWS CDK.</p> -</div> -<div class="admonitionblock tip"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-tip" title="Tip"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>To identify stacks deployed with AWS CDK v1, use the <a href="https://www.npmjs.com/package/awscdk-v1-stack-finder">awscdk-v1-stack-finder</a> utility.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>The main changes from AWS CDK v1 to CDK v2 are as follows.</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>AWS CDK v2 consolidates the stable parts of the AWS Construct Library, including the core library, into a single package, <code class="path">aws-cdk-lib</code>. Developers no longer need to install additional packages for the individual AWS services they use. This single-package approach also means that you don’t have to synchronize the versions of the various CDK library packages.</p> -<div class="paragraph"> -<p>L1 (CfnXXXX) constructs, which represent the exact resources available in AWS CloudFormation, are always considered stable and so are included in <code class="path">aws-cdk-lib</code>.</p> -</div> -</li> -<li> -<p>Experimental modules, where we’re still working with the community to develop new <a href="#constructs-lib-levels">L2 or L3 constructs</a>, are not included in <code class="path">aws-cdk-lib</code>. Instead, they’re distributed as individual packages. Experimental packages are named with an <code class="path">alpha</code> suffix and a semantic version number. The semantic version number matches the first version of the AWS Construct Library that they’re compatible with, also with an <code class="path">alpha</code> suffix. Constructs move into <code class="path">aws-cdk-lib</code> after being designated stable, permitting the main Construct Library to adhere to strict semantic versioning.</p> -<div class="paragraph"> -<p>Stability is specified at the service level. For example, if we begin creating one or more <a href="#constructs-lib-levels">L2 constructs</a> for Amazon AppFlow, which at this writing has only L1 constructs, they first appear in a module named <code class="path">@aws-cdk/aws-appflow-alpha</code>. Then, they move to <code class="path">aws-cdk-lib</code> when we feel that the new constructs meet the fundamental needs of customers.</p> -</div> -<div class="paragraph"> -<p>Once a module has been designated stable and incorporated into <code class="path">aws-cdk-lib</code>, new APIs are added using the "BetaN" convention described in the next bullet.</p> -</div> -<div class="paragraph"> -<p>A new version of each experimental module is released with every release of the AWS CDK. For the most part, however, they needn’t be kept in sync. You can upgrade <code class="path">aws-cdk-lib</code> or the experimental module whenever you want. The exception is that when two or more related experimental modules depend on each other, they must be the same version.</p> -</div> -</li> -<li> -<p>For stable modules to which new functionality is being added, new APIs (whether entirely new constructs or new methods or properties on an existing construct) receive a <code class="path">Beta1</code> suffix while work is in progress. (Followed by <code class="path">Beta2</code>, <code class="path">Beta3</code>, and so on when breaking changes are needed.) A version of the API without the suffix is added when the API is designated stable. All methods except the latest (whether beta or final) are then deprecated.</p> -<div class="paragraph"> -<p>For example, if we add a new method <code>grantPower()</code> to a construct, it initially appears as <code>grantPowerBeta1()</code>. If breaking changes are needed (for example, a new required parameter or property), the next version of the method would be named <code>grantPowerBeta2()</code>, and so on. When work is complete and the API is finalized, the method <code>grantPower()</code> (with no suffix) is added, and the BetaN methods are deprecated.</p> -</div> -<div class="paragraph"> -<p>All the beta APIs remain in the Construct Library until the next major version (3.0) release, and their signatures will not change. You’ll see deprecation warnings if you use them, so you should move to the final version of the API at your earliest convenience. However, no future AWS CDK 2.x releases will break your application.</p> -</div> -</li> -<li> -<p>The <code>Construct</code> class has been extracted from the AWS CDK into a separate library, along with related types. This is done to support efforts to apply the Construct Programming Model to other domains. If you are writing your own constructs or using related APIs, you must declare the <code class="path">constructs</code> module as a dependency and make minor changes to your imports. If you are using advanced features, such as hooking into the CDK app lifecycle, more changes may be needed. For full details, <a href="https://github.com/aws/aws-cdk-rfcs/blob/master/text/0192-remove-constructs-compat.md#release-notes">see the RFC</a>.</p> -</li> -<li> -<p>Deprecated properties, methods, and types in AWS CDK v1.x and its Construct Library have been removed completely from the CDK v2 API. In most supported languages, these APIs produce warnings under v1.x, so you may have already migrated to the replacement APIs. A complete <a href="https://github.com/aws/aws-cdk/blob/master/DEPRECATED_APIs.md">list of deprecated APIs</a> in CDK v1.x is available on GitHub.</p> -</li> -<li> -<p>Behavior that was gated by feature flags in AWS CDK v1.x is enabled by default in CDK v2. The earlier feature flags are no longer needed, and in most cases they’re not supported. A few are still available to let you revert to CDK v1 behavior in very specific circumstances. For more information, see <a href="#migrating-v2-v1-upgrade-cdk-json">Updating feature flags</a>.</p> -</li> -<li> -<p>With CDK v2, the environments you deploy into must be bootstrapped using the modern bootstrap stack. The legacy bootstrap stack (the default under v1) is no longer supported. CDK v2 furthermore requires a new version of the modern stack. To upgrade your existing environments, re-bootstrap them. It is no longer necessary to set any feature flags or environment variables to use the modern bootstrap stack.</p> -</li> -</ul> -</div> -<div class="admonitionblock important"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-important" title="Important"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>The modern bootstrap template effectively grants the permissions implied by the <code>--cloudformation-execution-policies</code> to any AWS account in the <code>--trust</code> list. By default, this extends permissions to read and write to any resource in the bootstrapped account. Make sure to <a href="#bootstrapping-customizing">configure the bootstrapping stack</a> with policies and trusted accounts that you are comfortable with.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="sect2"> -<h3 id="migrating-v2-prerequisites">7.1. New prerequisites</h3> -<div class="paragraph"> -<p>Most requirements for AWS CDK v2 are the same as for AWS CDK v1.x. Additional requirements are listed here.</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>For TypeScript developers, TypeScript 3.8 or later is required.</p> -</li> -<li> -<p>A new version of the CDK Toolkit is required for use with CDK v2. Now that CDK v2 is generally available, v2 is the default version when installing the CDK Toolkit. It is backward-compatible with CDK v1 projects, so you don’t need to keep the earlier version installed unless you want to create CDK v1 projects. To upgrade, issue <code>npm install -g aws-cdk</code>.</p> -</li> -</ul> -</div> -</div> -<div class="sect2"> -<h3 id="migrating-v2-dp-upgrade">7.2. Upgrading from AWS CDK v2 Developer Preview</h3> -<div class="paragraph"> -<p>If you’re using the CDK v2 Developer Preview, you have dependencies in your project on a Release Candidate version of the AWS CDK, such as <code>2.0.0-rc1</code>. Update these to <code>2.0.0</code>, then update the modules installed in your project.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p><code>npm install</code> or <code>yarn install</code></p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">JavaScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p><code>npm install</code> or <code>yarn install</code></p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">python -m pip install -r requirements.txt</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">mvn package</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">dotnet restore</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">go get</code></pre> -</div> -</div> -<div class="paragraph"> -<p>After updating your dependencies, issue <code>npm update -g aws-cdk</code> to update the CDK Toolkit to the release version.</p> -</div> -</div> -<div class="sect2"> -<h3 id="migrating-v2-v1-uppgrade">7.3. Migrating from AWS CDK v1 to CDK v2</h3> -<div class="paragraph"> -<p>To migrate your app to AWS CDK v2, first update the feature flags in <code class="path">cdk.json</code>. Then update your app’s dependencies and imports as necessary for the programming language that it’s written in.</p> -</div> -<div class="sect3"> -<h4 id="migrating-v2-v1-recent-v1">7.3.1. Updating to a recent v1</h4> -<div class="paragraph"> -<p>We are seeing a number of customers upgrading from an old version of AWS CDK v1 to the most recent version of v2 in one step. While it is certainly possible to do that, you would be both upgrading across multiple years of changes (that unfortunately may not all have had the same amount of evolution testing we have today), as well as upgrading across versions with new defaults and a different code organization.</p> -</div> -<div class="paragraph"> -<p>For the safest upgrade experience and to more easily diagnose the sources of any unexpected changes, we recommend you separate those two steps: first upgrade to the latest v1 version, then make the switch to v2 afterwards.</p> -</div> -</div> -<div class="sect3"> -<h4 id="migrating-v2-v1-upgrade-cdk-json">7.3.2. Updating feature flags</h4> -<div class="paragraph"> -<p>Remove the following v1 feature flags from <code class="path">cdk.json</code> if they exist, as these are all active by default in AWS CDK v2. If their old effect is important for your infrastructure, you will need to make source code changes. See <a href="https://github.com/aws/aws-cdk/blob/main/packages/%40aws-cdk/cx-api/FEATURE_FLAGS.md">the list of flags on GitHub</a> for more information.</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><code>@aws-cdk/core:enableStackNameDuplicates</code></p> -</li> -<li> -<p><code>aws-cdk:enableDiffNoFail</code></p> -</li> -<li> -<p><code>@aws-cdk/aws-ecr-assets:dockerIgnoreSupport</code></p> -</li> -<li> -<p><code>@aws-cdk/aws-secretsmanager:parseOwnedSecretName</code></p> -</li> -<li> -<p><code>@aws-cdk/aws-kms:defaultKeyPolicies</code></p> -</li> -<li> -<p><code>@aws-cdk/aws-s3:grantWriteWithoutAcl</code></p> -</li> -<li> -<p><code>@aws-cdk/aws-efs:defaultEncryptionAtRest</code></p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>A handful of v1 feature flags can be set to <code>false</code> in order to revert to specific AWS CDK v1 behaviors; see <a href="#featureflags-disabling">Reverting to v1 behavior</a> or the list on GitHub for a complete reference.</p> -</div> -<div class="paragraph"> -<p>For both types of flags, use the <code>cdk diff</code> command to inspect the changes to your synthesized template to see if the changes to any of these flags affect your infrastructure.</p> -</div> -</div> -<div class="sect3"> -<h4 id="work-with-cdk-v2-cli">7.3.3. CDK Toolkit compatibility</h4> -<div class="paragraph"> -<p>CDK v2 requires v2 or later of the CDK Toolkit. This version is backward-compatible with CDK v1 apps. Therefore, you can use a single globally installed version of CDK Toolkit with all your AWS CDK projects, whether they use v1 or v2. An exception is that CDK Toolkit v2 only creates CDK v2 projects.</p> -</div> -<div class="paragraph"> -<p>If you need to create both v1 and v2 CDK projects, <strong>do not install CDK Toolkit v2 globally.</strong> (Remove it if you already have it installed: <code>npm remove -g aws-cdk</code>.) To invoke the CDK Toolkit, use <strong class="command">npx</strong> to run v1 or v2 of the CDK Toolkit as desired.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">npx aws-cdk@1.x init app --language typescript -npx aws-cdk@2.x init app --language typescript</code></pre> -</div> -</div> -<div class="admonitionblock tip"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-tip" title="Tip"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>Set up command line aliases so you can use the <strong class="command">cdk</strong> and <strong class="command">cdk1</strong> commands to invoke the desired version of the CDK Toolkit.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">macOS/Linux</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">alias cdk1="npx aws-cdk@1.x" -alias cdk="npx aws-cdk@2.x"</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Windows</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">doskey cdk1=npx aws-cdk@1.x $* -doskey cdk=npx aws-cdk@2.x $*</code></pre> -</div> -</div> -</td> -</tr> -</table> -</div> -</div> -<div class="sect3"> -<h4 id="migrating-v2-v1-upgrade-dependencies">7.3.4. Updating dependencies and imports</h4> -<div class="paragraph"> -<p>Update your app’s dependencies, then install the new packages. Finally, update the imports in your code.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>* -.Applications -For CDK apps, update <code class="path">package.json</code> as follows. Remove dependencies on v1-style individual stable modules and establish the lowest version of <code class="path">aws-cdk-lib</code> you require for your application (2.0.0 here).</p> -<div class="paragraph"> -<p>Experimental constructs are provided in separate, independently versioned packages with names that end in <code class="path">alpha</code> and an alpha version number. The alpha version number corresponds to the first release of <code class="path">aws-cdk-lib</code> with which they’re compatible. Here, we have pinned <code class="path">aws-codestar</code> to v2.0.0-alpha.1.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-json" data-lang="json">{ - "dependencies": { - "aws-cdk-lib": "^2.0.0", - "@aws-cdk/aws-codestar-alpha": "2.0.0-alpha.1", - "constructs": "^10.0.0" - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<div class="title">Construct libraries</div> -<p>For construct libraries, establish the lowest version of <code class="path">aws-cdk-lib</code> you require for your application (2.0.0 here) and update <code class="path">package.json</code> as follows.</p> -</div> -<div class="paragraph"> -<p>Note that <code class="path">aws-cdk-lib</code> appears both as a peer dependency and a dev dependency.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-json" data-lang="json">{ - "peerDependencies": { - "aws-cdk-lib": "^2.0.0", - "constructs": "^10.0.0" - }, - "devDependencies": { - "aws-cdk-lib": "^2.0.0", - "constructs": "^10.0.0", - "typescript": "~3.9.0" - } -}</code></pre> -</div> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -You should perform a major version bump on your library’s version number when releasing a v2-compatible library, because this is a breaking change for library consumers. It is not possible to support both CDK v1 and v2 with a single library. To continue to support customers who are still using v1, you could maintain the earlier release in parallel, or create a new package for v2. -</td> -</tr> -</table> -</div> -</dd> -</dl> -</div> -<div class="paragraph"> -<p>It’s up to you how long you want to continue supporting AWS CDK v1 customers. You might take your cue from the lifecycle of CDK v1 itself, which entered maintenance on June 1, 2022 and will reach end-of-life on June 1, 2023. For full details, see <a href="https://github.com/aws/aws-cdk-rfcs/blob/master/text/0079-cdk-2.0.md#aws-cdk-maintenance-policy">AWS CDK Maintenance Policy</a>.</p> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<div class="title">Both libraries and apps</div> -<p>Install the new dependencies by running <code>npm install</code> or <code>yarn install</code>.</p> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p>Change your imports to import <code>Construct</code> from the new <code class="path">constructs</code> module, core types such as <code>App</code> and <code>Stack</code> from the top level of <code class="path">aws-cdk-lib</code>, and stable Construct Library modules for the services you use from namespaces under <code class="path">aws-cdk-lib</code>.</p> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import { Construct } from 'constructs'; -import { App, Stack } from 'aws-cdk-lib'; // core constructs -import { aws_s3 as s3 } from 'aws-cdk-lib'; // stable module -import * as codestar from '@aws-cdk/aws-codestar-alpha'; // experimental module</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Update <code class="path">package.json</code> as follows. Remove dependencies on v1-style individual stable modules and establish the lowest version of <code class="path">aws-cdk-lib</code> you require for your application (2.0.0 here).</p> -<div class="paragraph"> -<p>Experimental constructs are provided in separate, independently versioned packages with names that end in <code class="path">alpha</code> and an alpha version number. The alpha version number corresponds to the first release of <code class="path">aws-cdk-lib</code> with which they’re compatible. Here, we have pinned <code class="path">aws-codestar</code> to v2.0.0-alpha.1.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-json" data-lang="json">{ - "dependencies": { - "aws-cdk-lib": "^2.0.0", - "@aws-cdk/aws-codestar-alpha": "2.0.0-alpha.1", - "constructs": "^10.0.0" - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Install the new dependencies by running <code>npm install</code> or <code>yarn install</code>.</p> -</div> -<div class="paragraph"> -<p>Change your app’s imports to do the following:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Import <code>Construct</code> from the new <code class="path">constructs</code> module</p> -</li> -<li> -<p>Import core types, such as <code>App</code> and <code>Stack</code>, from the top level of <code class="path">aws-cdk-lib</code></p> -</li> -<li> -<p>Import AWS Construct Library modules from namespaces under <code class="path">aws-cdk-lib</code></p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const { Construct } = require('constructs'); -const { App, Stack } = require('aws-cdk-lib'); // core constructs -const s3 = require('aws-cdk-lib').aws_s3; // stable module -const codestar = require('@aws-cdk/aws-codestar-alpha'); // experimental module</code></pre> -</div> -</div> -</li> -</ul> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Python</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Update <code class="path">requirements.txt</code> or the <code>install_requires</code> definition in <code>setup.py</code> as follows. Remove dependencies on v1-style individual stable modules.</p> -<div class="paragraph"> -<p>Experimental constructs are provided in separate, independently versioned packages with names that end in <code class="path">alpha</code> and an alpha version number. The alpha version number corresponds to the first release of <code class="path">aws-cdk-lib</code> with which they’re compatible. Here, we have pinned <code class="path">aws-codestar</code> to v2.0.0alpha1.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">install_requires=[ - "aws-cdk-lib>=2.0.0", - "constructs>=10.0.0", - "aws-cdk.aws-codestar-alpha>=2.0.0alpha1", - # ... -],</code></pre> -</div> -</div> -<div class="admonitionblock tip"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-tip" title="Tip"></i> -</td> -<td class="content"> -Uninstall any other versions of AWS CDK modules already installed in your app’s virtual environment using <code>pip uninstall</code>. Then Install the new dependencies with <code>python -m pip install -r requirements.txt</code>. -</td> -</tr> -</table> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div class="paragraph"> -<p>Change your app’s imports to do the following:</p> -</div> -<div class="paragraph"> -<p>+ -<strong> Import <code>Construct</code> from the new <code class="path">constructs</code> module -</strong> Import core types, such as <code>App</code> and <code>Stack</code>, from the top level of <code class="path">aws_cdk</code> -** Import AWS Construct Library modules from namespaces under <code class="path">aws_cdk</code></p> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">from constructs import Construct -from aws_cdk import App, Stack # core constructs -from aws_cdk import aws_s3 as s3 # stable module -import aws_cdk.aws_codestar_alpha as codestar # experimental module - -# ... - -class MyConstruct(Construct): - # ... - -class MyStack(Stack): - # ... - -s3.Bucket(...)</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>In <code class="path">pom.xml</code>, remove all <code>software.amazon.awscdk</code> dependencies for stable modules and replace them with dependencies on <code>software.constructs</code> (for <code>Construct</code>) and <code>software.amazon.awscdk</code>.</p> -<div class="paragraph"> -<p>Experimental constructs are provided in separate, independently versioned packages with names that end in <code class="path">alpha</code> and an alpha version number. The alpha version number corresponds to the first release of <code class="path">aws-cdk-lib</code> with which they’re compatible. Here, we have pinned <code class="path">aws-codestar</code> to v2.0.0-alpha.1.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-xml" data-lang="xml"><dependency> - <groupId>software.amazon.awscdk</groupId> - <artifactId>aws-cdk-lib</artifactId> - <version>2.0.0</version> -</dependency><dependency> - <groupId>software.amazon.awscdk</groupId> - <artifactId>code-star-alpha</artifactId> - <version>2.0.0-alpha.1</version> -</dependency> -<dependency> - <groupId>software.constructs</groupId> - <artifactId>constructs</artifactId> - <version>10.0.0</version> -</dependency></code></pre> -</div> -</div> -<div class="paragraph"> -<p>Install the new dependencies by running <code>mvn package</code>.</p> -</div> -<div class="paragraph"> -<p>Change your code to do the following:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Import <code>Construct</code> from the new <code class="path">software.constructs</code> library</p> -</li> -<li> -<p>Import core classes, like <code>Stack</code> and <code>App</code>, from <code class="path">software.amazon.awscdk</code></p> -</li> -<li> -<p>Import service constructs from <code class="path">software.amazon.awscdk.services</code></p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">import software.constructs.Construct; -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.StackProps; -import software.amazon.awscdk.App; -import software.amazon.awscdk.services.s3.Bucket; -import software.amazon.awscdk.services.codestar.alpha.GitHubRepository;</code></pre> -</div> -</div> -</li> -</ul> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">C#</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The most straightforward way to upgrade the dependencies of a C# CDK application is to edit the <code class="path">.csproj</code> file manually. Remove all stable <code>Amazon.CDK.*</code> package references and replace them with references to the <code class="path">Amazon.CDK.Lib</code> and <code class="path">Constructs</code> packages.</p> -<div class="paragraph"> -<p>Experimental constructs are provided in separate, independently versioned packages with names that end in <code class="path">alpha</code> and an alpha version number. The alpha version number corresponds to the first release of <code class="path">aws-cdk-lib</code> with which they’re compatible. Here, we have pinned <code class="path">aws-codestar</code> to v2.0.0-alpha.1.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-xml" data-lang="xml"><PackageReference Include="Amazon.CDK.Lib" Version="2.0.0" /> -<PackageReference Include="Amazon.CDK.AWS.Codestar.Alpha" Version="2.0.0-alpha.1" /> -<PackageReference Include="Constructs" Version="10.0.0" /></code></pre> -</div> -</div> -<div class="paragraph"> -<p>Install the new dependencies by running <code>dotnet restore</code>.</p> -</div> -<div class="paragraph"> -<p>Change the imports in your source files as follows.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Constructs; // for Construct class -using Amazon.CDK; // for core classes like App and Stack -using Amazon.CDK.AWS.S3; // for stable constructs like Bucket -using Amazon.CDK.Codestar.Alpha; // for experimental constructs</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Go</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Issue <strong class="command">go get</strong> to update your dependencies to the latest version and update your project’s <code class="path">.mod</code> file.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -</div> -<div class="sect2"> -<h3 id="migrating-v2-diff.title">7.4. Testing your migrated app before deploying</h3> -<div class="paragraph"> -<p>Before deploying your stacks, use <code>cdk diff</code> to check for unexpected changes to the resources. Changes to logical IDs (causing replacement of resources) are <strong>not</strong> expected.</p> -</div> -<div class="paragraph"> -<p>Expected changes include but are not limited to:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Changes to the <code>CDKMetadata</code> resource.</p> -</li> -<li> -<p>Updated asset hashes.</p> -</li> -<li> -<p>Changes related to the new-style stack synthesis. Applies if your app used the legacy stack synthesizer in v1.</p> -</li> -<li> -<p>The addition of a <code>CheckBootstrapVersion</code> rule.</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>Unexpected changes are typically not caused by upgrading to AWS CDK v2 in itself. Usually, they’re the result of deprecated behavior that was previously changed by feature flags. This is a symptom of upgrading from a version of CDK earlier than about 1.85.x. You would see the same changes upgrading to the latest v1.x release. You can usually resolve this by doing the following:</p> -</div> -<div class="olist arabic"> -<ol class="arabic"> -<li> -<p>Upgrade your app to the latest v1.x release</p> -</li> -<li> -<p>Remove feature flags</p> -</li> -<li> -<p>Revise your code as necessary</p> -</li> -<li> -<p>Deploy</p> -</li> -<li> -<p>Upgrade to v2</p> -</li> -</ol> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>If your upgraded app is undeployable after the two-stage upgrade, <a href="https://github.com/aws/aws-cdk/issues/new/choose">report the issue</a>.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>When you are ready to deploy the stacks in your app, consider deploying a copy first so you can test it. The easiest way to do this is to deploy it into a different Region. However, you can also change the IDs of your stacks. After testing, be sure to destroy the testing copy with <strong class="command">cdk destroy</strong>.</p> -</div> -</div> -<div class="sect2"> -<h3 id="migrating-v2-trouble.title">7.5. Troubleshooting</h3> -<div class="paragraph"> -<div class="title">TypeScript <code>'from' expected</code> or <code>';' expected</code> error in imports</div> -<p>Upgrade to TypeScript 3.8 or later.</p> -</div> -<div class="paragraph"> -<div class="title">Run 'cdk bootstrap'</div> -<p>If you see an error like the following:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre>❌ MyStack failed: Error: MyStack: SSM parameter /cdk-bootstrap/hnb659fds/version not found. Has the environment been bootstrapped? Please run 'cdk bootstrap' (see https://docs.aws.amazon.com/cdk/latest/guide/bootstrapping.html) - at CloudFormationDeployments.validateBootstrapStackVersion (.../aws-cdk/lib/api/cloudformation-deployments.ts:323:13) - at processTicksAndRejections (internal/process/task_queues.js:97:5) -MyStack: SSM parameter /cdk-bootstrap/hnb659fds/version not found. Has the environment been bootstrapped? Please run 'cdk bootstrap' (see https://docs.aws.amazon.com/cdk/latest/guide/bootstrapping.html)</pre> -</div> -</div> -<div class="paragraph"> -<p>AWS CDK v2 requires an updated bootstrap stack, and furthermore, all v2 deployments require bootstrap resources. (With v1, you could deploy simple stacks without bootstrapping.) For complete details, see <a href="#bootstrapping">AWS CDK bootstrapping</a>.</p> -</div> -</div> -<div class="sect2"> -<h3 id="finding-v1-stacks.title">7.6. Finding v1 stacks</h3> -<div class="paragraph"> -<p>When migrating your CDK application from v1 to v2, you might want to identify the deployed AWS CloudFormation stacks that were created using v1. To do this, run the following command:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">npx awscdk-v1-stack-finder</code></pre> -</div> -</div> -<div class="paragraph"> -<p>For usage details, see the awscdk-v1-stack-finder <a href="https://github.com/cdklabs/awscdk-v1-stack-finder/blob/main/README.md">README</a>.</p> -</div> -</div> -</div> -</div> -<div class="sect1 topic"> -<h2 id="migrate">8. Migrate existing resources and AWS CloudFormation templates to the AWS CDK</h2> -<div class="sectionbody"> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Use the AWS Cloud Development Kit (AWS CDK) Command Line Interface (AWS CDK <code class="noloc">CLI</code>) to migrate deployed AWS resources, deployed AWS CloudFormation stacks, and local AWS CloudFormation templates to AWS CDK.</p> -</div> -</blockquote> -</div> -<table class="tableblock frame-all grid-all stretch"> -<colgroup> -<col style="width: 100%;"> -</colgroup> -<tbody> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">The CDK Migrate feature is in preview release for AWS CDK and is subject to change.</p></td> -</tr> -</tbody> -</table> -<div class="paragraph"> -<p>Use the AWS Cloud Development Kit (AWS CDK) Command Line Interface (AWS CDK <code class="noloc">CLI</code>) to migrate deployed AWS resources, deployed AWS CloudFormation stacks, and local AWS CloudFormation templates to AWS CDK.</p> -</div> -<div class="paragraph topiclist"> -<p>[[Topic List]]</p> -</div> -<div class="sect2"> -<h3 id="migrate-intro">8.1. How migration works</h3> -<div class="paragraph"> -<p>Use the AWS CDK <code class="noloc">CLI</code><code>cdk migrate</code> command to migrate from the following sources:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Deployed AWS resources.</p> -</li> -<li> -<p>Deployed AWS CloudFormation stacks.</p> -</li> -<li> -<p>Local AWS CloudFormation templates.</p> -<div class="dlist"> -<dl> -<dt class="hdlist1">Deployed AWS resources</dt> -</dl> -</div> -</li> -<li> -<p>You can migrate deployed AWS resources from a specific environment (AWS account and AWS Region) that are not associated with an AWS CloudFormation stack.</p> -<div class="paragraph"> -<p>The AWS CDK <code class="noloc">CLI</code> utilizes the <em>IaC generator</em> service to scan for resources in your AWS environment to gather resource details. To learn more about IaC generator, see <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/generate-IaC.html">Generating templates for existing resources</a> in the <em>AWS CloudFormation User Guide</em>.</p> -</div> -<div class="paragraph"> -<p>After gathering resource details, the AWS CDK <code class="noloc">CLI</code> creates a new CDK app that includes a single stack containing your migrated resources.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Deployed AWS CloudFormation stacks</dt> -</dl> -</div> -</li> -<li> -<p>You can migrate a single AWS CloudFormation stack into a new AWS CDK app. The AWS CDK <code class="noloc">CLI</code> will retrieve the AWS CloudFormation template of your stack and create a new CDK app. The CDK app will consist of a single stack that contains your migrated AWS CloudFormation stack.</p> -<div class="dlist"> -<dl> -<dt class="hdlist1">Local AWS CloudFormation templates</dt> -</dl> -</div> -</li> -<li> -<p>You can migrate from a local AWS CloudFormation template. Local templates may or may not contain deployed resources. The AWS CDK <code class="noloc">CLI</code> will create a new CDK app that contains a single stack with your resources.</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>After migrating, you can manage, modify, and deploy your CDK app to AWS CloudFormation to provision or update your resources.</p> -</div> -</div> -<div class="sect2"> -<h3 id="migrate-benefits">8.2. Benefits of CDK Migrate</h3> -<div class="paragraph"> -<p>Migrating resources into AWS CDK has historically been a manual process that requires time and expertise with AWS CloudFormation and AWS CDK to even begin. With CDK Migrate, the AWS CDK <code class="noloc">CLI</code> facilitates a majority of the migration effort for you in a fraction of the time. CDK Migrate will quickly get you started with using the AWS CDK to develop and manage new and existing applications on AWS.</p> -</div> -</div> -<div class="sect2"> -<h3 id="migrate-considerations">8.3. Considerations</h3> -<div class="sect3"> -<h4 id="migrate-considerations-general">8.3.1. General considerations</h4> -<div class="dlist"> -<dl> -<dt class="hdlist1">CDK Migrate vs. CDK Import</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The <code>cdk import</code> command can import deployed resources into a new or existing CDK app. When importing, each resource will have to manually be defined as an L1 construct in your app. We recommend using <code>cdk import</code> to import one or more resources at a time into a new or existing CDK app. To learn more, see <a href="#cli-import">Import existing resources into a stack</a>.</p> -<div class="paragraph"> -<p>The <code>cdk migrate</code> command migrates from deployed resources, deployed AWS CloudFormation stacks, or local AWS CloudFormation templates into a new CDK app. During migration, the AWS CDK <code class="noloc">CLI</code> uses <code>cdk import</code> to import your resources into the new CDK app. The AWS CDK <code class="noloc">CLI</code> also generates L1 constructs for each resource for you. We recommend using <code>cdk migrate</code> when importing from a supported migration source into a new AWS CDK app.</p> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">CDK Migrate creates L1 constructs only</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The newly created CDK app will include L1 constructs only. You can add higher-level constructs to your app after migration.</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">CDK Migrate creates CDK apps that contain a single stack</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The newly created CDK app will contain a single stack.</p> -<div class="paragraph"> -<p>When migrating deployed resources, all migrated resources will be contained within a single stack in the new CDK app.</p> -</div> -<div class="paragraph"> -<p>When migrating AWS CloudFormation stacks, you can only migrate a single AWS CloudFormation stack into a single stack in the new CDK app.</p> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Migrating assets</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Project assets, such as AWS Lambda code, will not directly migrate into the new CDK app. After migration, you can specify asset values to include them in the CDK app.</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Migrating stateful resources</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>When migrating stateful resources, such as databases and Amazon Simple Storage Service (Amazon S3) buckets, you’d most often want to migrate the existing resource instead of creating a new resource.</p> -<div class="paragraph"> -<p>To migrate and preserve stateful resources, do the following:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Verify that your stateful resource supports import. For more information, see <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resource-import-supported-resources.html">Resource type support</a> in the <em>AWS CloudFormation User Guide</em>.</p> -</li> -<li> -<p>After migration, verify that the migrated resource’s logical ID in the new CDK app matches the logical ID of the deployed resource.</p> -</li> -<li> -<p>If migrating from an AWS CloudFormation stack, verify that the stack name in the new CDK app matches the AWS CloudFormation stack.</p> -</li> -<li> -<p>Deploy the CDK app using the same AWS account and AWS Region of the migrated resource.</p> -</li> -</ul> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect3"> -<h4 id="migrate-considerations-template">8.3.2. Considerations when migrating from an AWS CloudFormation template</h4> -<div class="dlist"> -<dl> -<dt class="hdlist1">CDK Migrate supports single template migration</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>When migrating AWS CloudFormation templates, you can select a single template to migrate. Nested templates are not supported.</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Migrating templates with intrinsic functions</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>When migrating from an AWS CloudFormation template that uses intrinsic functions, the AWS CDK <code class="noloc">CLI</code> will attempt to migrate your logic into the CDK app with the <code>Fn</code> class. To learn more, see <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Fn.html">class Fn</a> in the <em>AWS Cloud Development Kit (AWS CDK) API Reference</em>.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect3"> -<h4 id="migrate-considerations-resources">8.3.3. Considerations when migrating from deployed resources</h4> -<div class="dlist"> -<dl> -<dt class="hdlist1">Scan limitations</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>When scanning your environment for resources, IaC generator has specific limitations on the data it can retrieve and quota limitations when scanning. To learn more, see <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/generate-IaC.html#generate-template-considerations">Considerations</a> in the <em>AWS CloudFormation User Guide</em>.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -</div> -<div class="sect2"> -<h3 id="migrate-prerequisites">8.4. Prerequisites</h3> -<div class="paragraph"> -<p>Before using the <code>cdk migrate</code> command, complete all set up steps in <a href="#getting-started">Getting started with the AWS CDK</a>.</p> -</div> -</div> -<div class="sect2"> -<h3 id="migrate-gs">8.5. Get started with CDK Migrate</h3> -<div class="paragraph"> -<p>To begin, run the AWS CDK <code class="noloc">CLI</code><code>cdk migrate</code> command from a directory of your choice. Provide required and optional options, depending on the type of migration you are performing.</p> -</div> -<div class="paragraph"> -<p>For a full list and description of options that you can use with <code>cdk migrate</code>, see <a href="#ref-cli-cdk-migrate">cdk migrate</a>.</p> -</div> -<div class="paragraph"> -<p>The following are some important options that you may want to provide.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Stack name</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The only required option is <code>--stack-name</code>. Use this option to specify a name for the stack that will be created within the AWS CDK app after migration. The stack name will also be used as the name of your AWS CloudFormation stack at deployment.</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Language</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Use <code>--language</code> to specify the programming language of the new CDK app.</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">AWS account and AWS Region</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The AWS CDK <code class="noloc">CLI</code> retrieves AWS account and AWS Region information from default sources. For more information, see <a href="#environments">Environments for the AWS CDK</a>. You can use <code>--account</code> and <code>--region</code> options with <code>cdk migrate</code> to provide other values.</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Output directory of your new CDK project</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>By default, the AWS CDK <code class="noloc">CLI</code> will create a new CDK project in your working directory and use the value you provide with <code>--stack-name</code> to name the project folder. If a folder with the same name currently exists, the AWS CDK <code class="noloc">CLI</code> will overwrite that folder.</p> -<div class="paragraph"> -<p>You can specify a different output path for the new CDK project folder with the <code>--output-path</code> option.</p> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Migration source</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Provide an option to specify the source you are migrating from.</p> -<div class="ulist"> -<ul> -<li> -<p><code>--from-path</code> – Migrate from a local AWS CloudFormation template.</p> -</li> -<li> -<p><code>--from-scan</code> – Migrate from deployed resources in an AWS account and AWS Region.</p> -</li> -<li> -<p><code>--from-stack</code> – Migrate from an AWS CloudFormation stack.</p> -</li> -</ul> -</div> -</li> -</ul> -</div> -<div class="paragraph"> -<p>Depending on your migration source, you can provide additional options to customize the <code>cdk migrate</code> command.</p> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect2"> -<h3 id="migrate-stack">8.6. Migrate from an AWS CloudFormation stack</h3> -<div class="paragraph"> -<p>To migrate from a deployed AWS CloudFormation stack, provide the <code>--from-stack</code> option. Provide the name of your deployed AWS CloudFormation stack with <code>--stack-name</code>. The following is an example:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk migrate --from-stack --stack-name "myCloudFormationStack"</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The AWS CDK <code class="noloc">CLI</code> will do the following:</p> -</div> -<div class="olist arabic"> -<ol class="arabic"> -<li> -<p>Retrieve the AWS CloudFormation template of your deployed stack.</p> -</li> -<li> -<p>Run <code>cdk init</code> to initialize a new CDK app.</p> -</li> -<li> -<p>Create a stack within the CDK app that contains your migrated AWS CloudFormation stack.</p> -</li> -</ol> -</div> -<div class="paragraph"> -<p>When you migrate from a deployed AWS CloudFormation stack, the AWS CDK <code class="noloc">CLI</code> attempts to match deployed resource logical IDs and the deployed AWS CloudFormation stack name to the migrated resources and stack in the new CDK app.</p> -</div> -<div class="paragraph"> -<p>After migration, you can manage and modify your CDK app normally. When you deploy, AWS CloudFormation will identify the deployment as an AWS CloudFormation stack update due to the matching AWS CloudFormation stack name. Resources with matching logical IDs will be updated. For more information on deploying, see <a href="#migrate-manage">Manage and deploy your CDK app</a>.</p> -</div> -</div> -<div class="sect2"> -<h3 id="migrate-template">8.7. Migrate from an AWS CloudFormation template</h3> -<div class="paragraph"> -<p>CDK Migrate supports migrating from AWS CloudFormation templates formatted in <code class="path">JSON</code> or <code class="path">YAML</code>.</p> -</div> -<div class="paragraph"> -<p>To migrate from a local AWS CloudFormation template, use the <code>--from-path</code> option and provide a path to the local template. You must also provide the required <code>--stack-name</code> option. The following is an example:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk migrate --from-path "./template.json" --stack-name "myCloudFormationStack"</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The AWS CDK <code class="noloc">CLI</code> will do the following:</p> -</div> -<div class="olist arabic"> -<ol class="arabic"> -<li> -<p>Retrieve your local AWS CloudFormation template.</p> -</li> -<li> -<p>Run <code>cdk init</code> to initialize a new CDK app.</p> -</li> -<li> -<p>Create a stack within the CDK app that contains your migrated AWS CloudFormation template.</p> -</li> -</ol> -</div> -<div class="paragraph"> -<p>After migration, you can manage and modify your CDK app normally. At deployment, you have the following options:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><strong>Update an AWS CloudFormation stack</strong> – If the local AWS CloudFormation template was previously deployed, you can update the deployed AWS CloudFormation stack.</p> -</li> -<li> -<p><strong>Deploy a new AWS CloudFormation stack</strong> – If the local AWS CloudFormation template was never deployed, or if you want to create a new stack from a previously deployed template, you can deploy a new AWS CloudFormation stack.</p> -</li> -</ul> -</div> -<div class="sect3"> -<h4 id="migrate-template-sam">8.7.1. Migrate from an AWS SAM template</h4> -<div class="paragraph"> -<p>To migrate from an AWS Serverless Application Model (AWS SAM) template, you must first convert it to an AWS CloudFormation template or deploy to create an AWS CloudFormation stack.</p> -</div> -<div class="paragraph"> -<p>To convert an AWS SAM template to AWS CloudFormation, you can use the AWS SAM <code class="noloc">CLI</code><code>sam validate --debug</code> command. You may have to set <code>lint</code> to <code>false</code> in your <code class="path">samconfig.toml</code> file before running this command.</p> -</div> -<div class="paragraph"> -<p>To convert to an AWS CloudFormation stack, deploy the AWS SAM template using the AWS SAM <code class="noloc">CLI</code>. Then migrate from the deployed stack.</p> -</div> -</div> -</div> -<div class="sect2"> -<h3 id="migrate-resources">8.8. Migrate from deployed resources</h3> -<div class="paragraph"> -<p>To migrate from deployed AWS resources, provide the <code>--from-scan</code> option. You must also provide the required <code>--stack-name</code> option. The following is an example:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk migrate --from-scan --stack-name "myCloudFormationStack"</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The AWS CDK <code class="noloc">CLI</code> will do the following:</p> -</div> -<div class="olist arabic"> -<ol class="arabic"> -<li> -<p><strong>Scan your account for resource and property details</strong> – The AWS CDK <code class="noloc">CLI</code> utilizes IaC generator to scan your account and gather details.</p> -</li> -<li> -<p><strong>Generate an AWS CloudFormation template</strong> – After scanning, the AWS CDK <code class="noloc">CLI</code> utilizes IaC generator to create an AWS CloudFormation template.</p> -</li> -<li> -<p><strong>Initialize a new CDK app and migrate your template</strong> – The AWS CDK <code class="noloc">CLI</code> runs <code>cdk init</code> to initialize a new AWS CDK app and migrates your AWS CloudFormation template into the CDK app as a single stack.</p> -</li> -</ol> -</div> -<div class="sect3"> -<h4 id="migrate-resources-filters">8.8.1. Use filters</h4> -<div class="paragraph"> -<p>By default, the AWS CDK <code class="noloc">CLI</code> will scan the entire AWS environment and migrate resources up to the maximum quota limit of IaC generator. You can provide filters with the AWS CDK <code class="noloc">CLI</code> to specify a criteria for which resources get migrated from your account to the new CDK app. To learn more, see <code><a href="#ref-cli-cdk-migrate-options-filter">--filter</a></code>.</p> -</div> -</div> -<div class="sect3"> -<h4 id="migrate-resources-scan">8.8.2. Scanning for resources with IaC generator</h4> -<div class="paragraph"> -<p>Depending on the number of resources in your account, scanning may take a few minutes. A progress bar will display during the scanning process.</p> -</div> -<div id="migrate-resources-supported" class="dlist"> -<dl> -<dt class="hdlist1">Supported resource types</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The AWS CDK <code class="noloc">CLI</code> will migrate resources supported by the IaC generator. For a full list, see <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resource-import-supported-resources.html">Resource type support</a> in the <em>AWS CloudFormation User Guide</em>.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect3"> -<h4 id="migrate-resources-writeonly">8.8.3. Resolve write-only properties</h4> -<div class="paragraph"> -<p>Some supported resources contain write-only properties. These properties can be written to, to configure the property, but can’t be read by IaC generator or AWS CloudFormation to obtain the value. For example, a property used to specify a database password may be write-only for security reasons.</p> -</div> -<div class="paragraph"> -<p>When scanning resources during migration, IaC generator will detect resources that may contain write-only properties and will categorize them into any of the following types:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><code>MUTUALLY_EXCLUSIVE_PROPERTIES</code> – These are write-only properties for a specific resource that are interchangeable and serve a similar purpose. One of the mutually exclusive properties are required to configure your resource. For example, the <code>S3Bucket</code>, <code>ImageUri</code>, and <code>ZipFile</code> properties for an <code>AWS::Lambda::Function</code> resource are mutually exclusive write-only properties. Any one of them can be used to specify your function assets, but you must use one.</p> -</li> -<li> -<p><code>MUTUALLY_EXCLUSIVE_TYPES</code> – These are required write-only properties that accept multiple configuration types. For example, the <code>Body</code> property of an <code>AWS::ApiGateway::RestApi</code> resource accepts an object or string type.</p> -</li> -<li> -<p><code>UNSUPPORTED_PROPERTIES</code> – These are write-only properties that don’t fall under the other two categories. They are either optional properties or required properties that accept an array of objects.</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>For more information on write-only properties and how IaC generator manages them when scanning for deployed resources and creating AWS CloudFormation templates, see <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/generate-IaC-write-only-properties.html">IaC generator and write-only properties</a> in the <em>AWS CloudFormation User Guide</em>.</p> -</div> -<div class="paragraph"> -<p>After migration, you must specify write-only property values in the new CDK app. The AWS CDK <code class="noloc">CLI</code> will append a <strong>Warnings</strong> section to the CDK project’s <code class="path">ReadMe</code> file to document any write-only properties that were identified by IaC generator. The following is an example:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-markdown" data-lang="markdown"># Welcome to your CDK TypeScript project -... -## Warnings -### Write-only properties -Write-only properties are resource property values that can be written to but can't be read by AWS CloudFormation or CDK Migrate. For more information, see [IaC generator and write-only properties](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/generate-IaC-write-only-properties.html). - -Write-only properties discovered during migration are organized here by resource ID and categorized by write-only property type. Resolve write-only properties by providing property values in your CDK app. For guidance, see [Resolve write-only properties](https://docs.aws.amazon.com/cdk/v2/guide/migrate.html#migrate-resources-writeonly). -### MyLambdaFunction -- **UNSUPPORTED_PROPERTIES**: - - SnapStart/ApplyOn: Applying SnapStart setting on function resource type.Possible values: [PublishedVersions, None] -This property can be replaced with other types - - Code/S3ObjectVersion: For versioned objects, the version of the deployment package object to use. -This property can be replaced with other exclusive properties -- **MUTUALLY_EXCLUSIVE_PROPERTIES**: - - Code/S3Bucket: An Amazon S3 bucket in the same AWS Region as your function. The bucket can be in a different AWS account. -This property can be replaced with other exclusive properties - - Code/S3Key: The Amazon S3 key of the deployment package. -This property can be replaced with other exclusive properties</code></pre> -</div> -</div> -<div class="ulist"> -<ul> -<li> -<p>Warnings are organized under headings that identify the resource’s logical ID that they are associated with.</p> -</li> -<li> -<p>Warnings are categorized by type. These types come directly from IaC generator.</p> -<div class="olist arabic"> -<ol class="arabic"> -<li> -<p>Identify write-only properties to resolve from the <strong>Warnings</strong> section of your CDK project’s <code class="path">ReadMe</code> file. Here, you can take note of the resources in your CDK app that may contain write-only properties and identify the write-only property types that were discovered.</p> -<div class="olist loweralpha"> -<ol class="loweralpha" type="a"> -<li> -<p>For <code>MUTUALLY_EXCLUSIVE_PROPERTIES</code>, determine which mutually exclusive property to configure in your AWS CDK app.</p> -</li> -<li> -<p>For <code>MUTUALLY_EXCLUSIVE_TYPES</code>, determine which accepted type that you will use to configure the property.</p> -</li> -<li> -<p>For <code>UNSUPPORTED_PROPERTIES</code>, determine if the property is optional or required. Then, configure as necessary.</p> -</li> -</ol> -</div> -</li> -<li> -<p>Use guidance from <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/generate-IaC-write-only-properties.html">IaC generator and write-only properties</a> to reference what the warning types mean.</p> -</li> -<li> -<p>In your CDK app, write-only property values to resolve will also be specified in the <code>Props</code> section of your app. Provide the correct values here. For property descriptions and guidance, you can reference the <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-construct-library.html">AWS CDK API Reference</a>.</p> -<div class="paragraph"> -<p>The following is an example of the <code>Props</code> section within a migrated CDK app with two write-only properties to resolve:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">export interface MyTestAppStackProps extends cdk.StackProps { - /** - * The Amazon S3 key of the deployment package. - */ - readonly lambdaFunction00asdfasdfsadf008grk1CodeS3Keym8P82: string; - /** - * An Amazon S3 bucket in the same AWS Region as your function. The bucket can be in a different AWS account. - */ - readonly lambdaFunction00asdfasdfsadf008grk1CodeS3Bucketzidw8: string; -}</code></pre> -</div> -</div> -</li> -</ol> -</div> -</li> -</ul> -</div> -<div class="paragraph"> -<p>Once you resolve all write-only property values, you’re ready to prepare for deployment.</p> -</div> -</div> -<div class="sect3"> -<h4 id="migrate-resources-file">8.8.4. The migrate.json file</h4> -<div class="paragraph"> -<p>The AWS CDK <code class="noloc">CLI</code> creates a <code class="path">migrate.json</code> file in your AWS CDK project during migration. This file contains reference information on your deployed resources. When you deploy your CDK app for the first time, the AWS CDK <code class="noloc">CLI</code> uses this file to reference your deployed resources, associates your resources with the new AWS CloudFormation stack, and deletes the file.</p> -</div> -</div> -</div> -<div class="sect2"> -<h3 id="migrate-manage">8.9. Manage and deploy your CDK app</h3> -<div class="paragraph"> -<p>When migrating to AWS CDK, the new CDK app may not be deployment-ready immediately. This topic describes action items to consider while managing and deploying your new CDK app.</p> -</div> -<div class="sect3"> -<h4 id="migrate-manage-prepare">8.9.1. Prepare for deployment</h4> -<div class="paragraph"> -<p>Before deploying, you must prepare your CDK app.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Synthesize your app</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Use the <code>cdk synth</code> command to synthesize the stack in your CDK app into an AWS CloudFormation template.</p> -<div class="paragraph"> -<p>If you migrated from a deployed AWS CloudFormation stack or template, you can compare the synthesized template to the migrated template to verify resource and property values.</p> -</div> -<div class="paragraph"> -<p>To learn more about <code>cdk synth</code>, see <a href="#cli-synth">Synthesize stacks</a>.</p> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Perform a diff</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>If you migrated from a deployed AWS CloudFormation stack, you can use the cdk diff command to compare with the stack in your new CDK app.</p> -<div class="paragraph"> -<p>To learn more about cdk diff, see <a href="#cli-diff">Compare stacks</a>.</p> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Bootstrap your environment</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>If you are deploying from an AWS environment for the first time, use <code>cdk bootstrap</code> to prepare your environment. To learn more, see <a href="#bootstrapping">AWS CDK bootstrapping</a>.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect3"> -<h4 id="migrate-manage-deploy">8.9.2. Deploy your CDK app</h4> -<div class="paragraph"> -<p>When you deploy a CDK app, the AWS CDK <code class="noloc">CLI</code> utilizes the AWS CloudFormation service to provision your resources. Resources are bundled into a single stack in the CDK app and are deployed as a single AWS CloudFormation stack.</p> -</div> -<div class="paragraph"> -<p>Depending on where you migrated from, you can deploy to create a new AWS CloudFormation stack or update an existing AWS CloudFormation stack.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Deploy to create a new AWS CloudFormation stack</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>If you migrated from deployed resources, the AWS CDK <code class="noloc">CLI</code> will automatically create a new AWS CloudFormation stack at deployment. Your deployed resources will be included in the new AWS CloudFormation stack.</p> -<div class="paragraph"> -<p>If you migrated from a local AWS CloudFormation template that was never deployed, the AWS CDK <code class="noloc">CLI</code> will automatically create a new AWS CloudFormation stack at deployment.</p> -</div> -<div class="paragraph"> -<p>If you migrated from a deployed AWS CloudFormation stack or local AWS CloudFormation template that was previously deployed, you can deploy to create a new AWS CloudFormation stack. To create a new stack, do the following:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Deploy to a new AWS environment. This consists of using a different AWS account or deploying to a different AWS Region.</p> -</li> -<li> -<p>If you want to deploy a new stack to the same AWS environment of the migrated stack or template, you must modify the stack name in your CDK app to a new value. You must also modify all logical IDs of resources in your CDK app. Then, you can deploy to the same environment to create a new stack and new resources.</p> -</li> -</ul> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Deploy to update an existing AWS CloudFormation stack</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>If you migrated from a deployed AWS CloudFormation stack or local AWS CloudFormation template that was previously deployed, you can deploy to update the existing AWS CloudFormation stack.</p> -<div class="paragraph"> -<p>Verify that the stack name in your CDK app matches the stack name of the deployed AWS CloudFormation stack and deploy to the same AWS environment.</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -</div> -</div> -</div> -<div class="sect1 topic"> -<h2 id="configure-access">9. Configure security credentials for the AWS CDK <code class="noloc">CLI</code></h2> -<div class="sectionbody"> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>When you use the AWS Cloud Development Kit (AWS CDK) to develop applications in your local environment, you will primarily use the AWS CDK <code class="noloc">CLI</code> to interact with AWS to deploy and manage your CDK stacks. To use the CDK <code class="noloc">CLI</code>, you must configure security credentials.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>When you use the AWS Cloud Development Kit (AWS CDK) to develop applications in your local environment, you will primarily use the AWS CDK Command Line Interface (AWS CDK <code class="noloc">CLI</code>) to interact with AWS. For example, you can use the CDK <code class="noloc">CLI</code> to deploy your application or to delete your resources from your AWS environment.</p> -</div> -<div class="paragraph"> -<p>To use the CDK <code class="noloc">CLI</code> to interact with AWS, you must configure security credentials on your local machine. This lets AWS know who you are and what permissions you have.</p> -</div> -<div class="paragraph"> -<p>To learn more about security credentials, see <a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/security-creds.html">AWS security credentials</a> in the <em>IAM User Guide</em>.</p> -</div> -<div class="sect2"> -<h3 id="configure-access-prerequisites">9.1. Prerequisites</h3> -<div class="paragraph"> -<p>Configuring security credentials is part of the <em>getting started</em> process. Complete all prerequisites and previous steps at <a href="#getting-started">Getting started with the AWS CDK</a>.</p> -</div> -</div> -<div class="sect2"> -<h3 id="configure-access-how">9.2. How to configure security credentials</h3> -<div class="paragraph"> -<p>How you configure security credentials depends on how you or your organization manages users. Whether you use AWS Identity and Access Management (IAM) or AWS IAM Identity Center, we recommend that you use the AWS Command Line Interface (AWS CLI) to configure and manage security credentials for the CDK <code class="noloc">CLI</code>. This includes using AWS CLI commands like <code>aws configure</code> to configure security credentials on your local machine. However, you can use alternative methods such as manually updating your <code class="path">config</code> and <code class="path">credentials</code> files, or setting environment variables.</p> -</div> -<div class="paragraph"> -<p>For guidance on configuring security credentials using the AWS CLI, along with information on configuration and credential precedence when using different methods, see <a href="https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-authentication.html">Authentication and access credentials</a> in the <em>AWS Command Line Interface User Guide</em>. The CDK <code class="noloc">CLI</code> adheres to the same configuration and credential precedence of the AWS CLI. The <code>--profile</code> command line option takes precedence over environment variables. If you have both the <code>AWS_PROFILE</code> and <code>CDK_DEFAULT_PROFILE</code> environment variables configured, the <code>AWS_PROFILE</code> environment variable takes precedence.</p> -</div> -<div class="paragraph"> -<p>If you configure multiple profiles, you can use the CDK <code class="noloc">CLI</code><code><a href="#ref-cli-cmd-options-profile">--profile</a></code> option with any command to specify the profile from your <code class="path">credentials</code> and <code class="path">config</code> files to use for authentication. If you don’t provide <code>--profile</code>, the <code>default</code> profile will be used.</p> -</div> -<div class="paragraph"> -<p>If you prefer to quickly configure basic settings, including security credentials, see <a href="https://docs.aws.amazon.com/cli/latest/userguide/getting-started-quickstart.html">Set up the AWS CLI</a> in the <em>AWS Command Line Interface User Guide</em>.</p> -</div> -<div class="paragraph"> -<p>Once you’ve configured security credentials on your local machine, you can use the CDK <code class="noloc">CLI</code> to interact with AWS.</p> -</div> -</div> -<div class="sect2"> -<h3 id="configure-access-sso">9.3. Configure and manage security credentials for IAM Identity Center users</h3> -<div class="paragraph"> -<p>IAM Identity Center users can authenticate with IAM Identity Center or manually by using short-term credentials.</p> -</div> -<div class="sect3"> -<h4 id="configure-access-sso-auto">9.3.1. Authenticate with IAM Identity Center to generate short-term credentials</h4> -<div class="paragraph"> -<p>You can configure the AWS CLI to authenticate with IAM Identity Center. This is the recommended approach of configuring security credentials for IAM Identity Center users. IAM Identity Center users can use the AWS CLI <code>aws configure sso</code> wizard to configure an IAM Identity Center profile and <code>sso-session</code>, which gets stored in the <code class="path">config</code> file on your local machine. For instructions, see <a href="https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sso.html">Configure the AWS CLI to use AWS IAM Identity Center</a> in the <em>AWS Command Line Interface User Guide</em>.</p> -</div> -<div class="paragraph"> -<p>Next, you can use the AWS CLI <code>aws sso login</code> command to request refreshed credentials. You can also use this command to switch profiles. For instructions, see <a href="https://docs.aws.amazon.com/cli/latest/userguide/sso-using-profile.html">Use an IAM Identity Center named profile</a> in the <em>AWS Command Line Interface User Guide</em>.</p> -</div> -<div class="paragraph"> -<p>Once authenticated, you can use the CDK <code class="noloc">CLI</code> to interact with AWS for the duration of your session. For an example, see <a href="#configure-access-sso-example-cli">Example: Authenticate with IAM Identity Center automatic token refresh for use with the AWS CDK CLI</a>.</p> -</div> -</div> -<div class="sect3"> -<h4 id="configure-access-sso-manual">9.3.2. Manually configure short-term credentials</h4> -<div class="paragraph"> -<p>As an alternative to using the AWS CLI and authenticating with IAM Identity Center, IAM Identity Center users can obtain short-term credentials from the AWS Management Console and manually configure the <code class="path">credentials</code> and <code class="path">config</code> files on their local machine. Once configured, you can use the CDK <code class="noloc">CLI</code> to interact with AWS until your credentials expire. For instructions, see <a href="https://docs.aws.amazon.com/cli/latest/userguide/cli-authentication-short-term.html">Authenticate with short-term credentials</a> in the <em>AWS Command Line Interface User Guide</em>.</p> -</div> -</div> -</div> -<div class="sect2"> -<h3 id="configure-access-iam">9.4. Configure and manage security credentials for IAM users</h3> -<div class="paragraph"> -<p>IAM users can use an IAM role or IAM user credentials with the CDK <code class="noloc">CLI</code>.</p> -</div> -<div class="sect3"> -<h4 id="configure-access-iam-role">9.4.1. Use an IAM role to configure short-term credentials</h4> -<div class="paragraph"> -<p>IAM users can assume IAM roles to gain additional (or different) permissions. For IAM users, this is the recommended approach since it provides short-term credentials.</p> -</div> -<div class="paragraph"> -<p>First, the IAM role and user’s permission to assume the role must be configured. This is typically performed by an administrator using the AWS Management Console or AWS CLI. Then, the IAM user can use the AWS CLI to assume the role and configure short-term credentials on their local machine. For instructions, see <a href="https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-role.html">Use an IAM role in the AWS CLI</a> in the <em>AWS Command Line Interface User Guide</em>.</p> -</div> -</div> -<div class="sect3"> -<h4 id="configure-access-iam-user">9.4.2. Use IAM user credentials</h4> -<div class="admonitionblock warning"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-warning" title="Warning"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>To avoid security risks, we don’t recommend using IAM user credentials since they provide long-term access. If you must use long-term credentials, we recommend that you <a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#rotate-credentials">update access keys</a> as an IAM security best practice.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>IAM users can obtain access keys from the AWS Management Console. You can then use the AWS CLI to configure long-term credentials on your local machine. For instructions, see <a href="https://docs.aws.amazon.com/cli/latest/userguide/cli-authentication-user.html">Authenticate with IAM user credentials</a> in the <em>AWS Command Line Interface User Guide</em>.</p> -</div> -</div> -</div> -<div class="sect2"> -<h3 id="configure-access-info">9.5. Additional information</h3> -<div class="paragraph"> -<p>To learn about the different ways that you can sign in to AWS, depending on the type of user you are, see <a href="https://docs.aws.amazon.com/signin/latest/userguide/what-is-sign-in.html">What is AWS Sign-In?</a> in the <em>AWS Sign-In User Guide</em>.</p> -</div> -<div class="paragraph"> -<p>For reference information when using AWS <code class="noloc">SDKs</code> and tools, including the AWS CLI, see the <a href="https://docs.aws.amazon.com/sdkref/latest/guide/overview.html">AWS SDKs and Tools Reference Guide</a>.</p> -</div> -</div> -<div class="sect2 topic"> -<h3 id="configure-access-sso-example-cli">9.6. Example: Authenticate with IAM Identity Center automatic token refresh for use with the AWS CDK <code class="noloc">CLI</code></h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>In this example, we configure the AWS Command Line Interface to authenticate our user with the AWS IAM Identity Center token provider configuration. The SSO token provider configuration lets the AWS CLI automatically retrieve refreshed authentication tokens to generate short-term credentials that we can use with the AWS Cloud Development Kit (AWS CDK) Command Line Interface (AWS CDK <code class="noloc">CLI</code>).</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>In this example, we configure the AWS Command Line Interface (AWS CLI) to authenticate our user with the AWS IAM Identity Center token provider configuration. The SSO token provider configuration lets the AWS CLI automatically retrieve refreshed authentication tokens to generate short-term credentials that we can use with the AWS Cloud Development Kit (AWS CDK) Command Line Interface (AWS CDK <code class="noloc">CLI</code>).</p> -</div> -<div class="paragraph topiclist"> -<p>[[Topic List]]</p> -</div> -<div class="sect3"> -<h4 id="configure-access-sso-example-cli-prerequisites">9.6.1. Prerequisites</h4> -<div class="paragraph"> -<p>This example assumes that the following prerequisites have been completed:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Prerequisites required to get set up with AWS and install our starting <code class="noloc">CLI</code> tools. For more information, see <a href="#configure-access-prerequisites">Prerequisites</a>.</p> -</li> -<li> -<p>IAM Identity Center has been set up by our organization as the method of managing users.</p> -</li> -<li> -<p>At least one user has been created in IAM Identity Center.</p> -</li> -</ul> -</div> -</div> -<div class="sect3"> -<h4 id="configure-access-sso-example-cli-configure">9.6.2. Step 1: Configure the AWS CLI</h4> -<div class="paragraph"> -<p>For detailed instructions on this step, see <a href="https://docs.aws.amazon.com/cli/latest/userguide/sso-configure-profile-token.html">Configure the AWS CLI to use IAM Identity Center token provider credentials with automatic authentication refresh</a> in the <em>AWS Command Line Interface User Guide</em>.</p> -</div> -<div class="paragraph"> -<p>We sign in to the AWS access portal provided by our organization to gather our IAM Identity Center information. This includes the <strong>SSO start URL</strong> and <strong>SSO Region</strong>.</p> -</div> -<div class="paragraph"> -<p>Next, we use the AWS CLI <code>aws configure sso</code> command to configure an IAM Identity Center profile and <code>sso-session</code> on our local machine:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ aws configure sso -SSO session name (Recommended): my-sso -SSO start URL [None]: https://my-sso-portal.awsapps.com/start -SSO region [None]: us-east-1 -SSO registration scopes [sso:account:access]: <ENTER></code></pre> -</div> -</div> -<div class="paragraph"> -<p>The AWS CLI attempts to open our default browser to begin the login process for our IAM Identity Center account. If the AWS CLI is unable to open our browser, instructions are provided to manually start the login process. This process associates the IAM Identity Center session with our current AWS CLI session.</p> -</div> -<div class="paragraph"> -<p>After establishing our session, the AWS CLI displays the AWS accounts available to us:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>There are 2 AWS accounts available to you. -> DeveloperAccount, developer-account-admin@example.com (123456789011) - ProductionAccount, production-account-admin@example.com (123456789022)</code></pre> -</div> -</div> -<div class="paragraph"> -<p>We use the arrow keys to select our <strong>DeveloperAccount</strong>.</p> -</div> -<div class="paragraph"> -<p>Next, the AWS CLI displays the IAM roles available to us from our selected account:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">Using the account ID 123456789011 -There are 2 roles available to you. -> ReadOnly - FullAccess</code></pre> -</div> -</div> -<div class="paragraph"> -<p>We use the arrow keys to select <strong>FullAccess</strong>.</p> -</div> -<div class="paragraph"> -<p>Next, the AWS CLI prompts us to complete configuration by specifying a default output format, default AWS Region, and name for our profile:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">CLI default client Region [None]: us-west-2 <ENTER>> -CLI default output format [None]: json <ENTER> -CLI profile name [123456789011_FullAccess]: my-dev-profile <ENTER></code></pre> -</div> -</div> -<div class="paragraph"> -<p>The AWS CLI displays a final message, showing how to use the named profile with the AWS CLI:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">To use this profile, specify the profile name using --profile, as shown: - -aws s3 ls --profile my-dev-profile</code></pre> -</div> -</div> -<div class="paragraph"> -<p>After completing this step, our <code class="path">config</code> file will look like the following:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre>[profile`my-dev-profile`] -sso_session =`my-sso`sso_account_id =`123456789011`sso_role_name =`fullAccess`region =`us-west-2`output =`json`[sso-session`my-sso`] -sso_region =`us-east-1`sso_start_url =`https://my-sso-portal.awsapps.com/start`sso_registration_scopes =`sso:account:access`</pre> -</div> -</div> -<div class="paragraph"> -<p>We can now use this <code>sso-session</code> and named profile to request security credentials.</p> -</div> -</div> -<div class="sect3"> -<h4 id="configure-access-sso-example-cli-credentials">9.6.3. Step 2: Use the AWS CLI to generate security credentials</h4> -<div class="paragraph"> -<p>For detailed instructions on this step, see <a href="https://docs.aws.amazon.com/cli/latest/userguide/sso-using-profile.html">Use an IAM Identity Center named profile</a> in the <em>AWS Command Line Interface User Guide</em>.</p> -</div> -<div class="paragraph"> -<p>We use the AWS CLI <code>aws sso login</code> command to request security credentials for our profile:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ aws sso login --profile my-dev-profile</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The AWS CLI attempts to open our default browser and verifies our IAM log in. If we are not currently signed into IAM Identity Center, we will be prompted to complete the sign in process. If the AWS CLI is unable to open our browser, instructions are provided to manually start the authorization process.</p> -</div> -<div class="paragraph"> -<p>After successfully logging in, the AWS CLI caches our IAM Identity Center session credentials. These credentials include an expiration timestamp. When they expire, the AWS CLI will request that we sign in to IAM Identity Center again.</p> -</div> -<div class="paragraph"> -<p>Using valid IAM Identity Center credentials, the AWS CLI securely retrieves AWS credentials for the IAM role specified in our profile. From here, we can use the AWS CDK <code class="noloc">CLI</code> with our credentials.</p> -</div> -</div> -<div class="sect3"> -<h4 id="configure-access-sso-example-cli-cdk">9.6.4. Step 3: Use the CDK <code class="noloc">CLI</code></h4> -<div class="paragraph"> -<p>With any CDK <code class="noloc">CLI</code> command, we use the <code><a href="#ref-cli-cmd-options-profile">--profile</a></code> option to specify the named profile that we generated credentials for. If our credentials are valid, the CDK <code class="noloc">CLI</code> will successfully perform the command. The following is an example:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk diff --profile my-dev-profile -Stack CdkAppStack -Hold on while we create a read-only change set to get a diff with accurate replacement information (use --no-change-set to use a less accurate but faster template-only diff) -Resources -[-] AWS::S3::Bucket amzn-s3-demo-bucket amzn-s3-demo-bucket5AF9C99B destroy - -Outputs -[-] Output BucketRegion: {"Value":{"Ref":"AWS::Region"}} - - -✨ Number of stacks with differences: 1</code></pre> -</div> -</div> -<div class="paragraph"> -<p>When our credentials expire, an error message like the following will display:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk diff --profile my-dev-profile -Stack CdkAppStack - -Unable to resolve AWS account to use. It must be either configured when you define your CDK Stack, or through the environment</code></pre> -</div> -</div> -<div class="paragraph"> -<p>To refresh our credentials, we use the AWS CLI <code>aws sso login</code> command:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ aws sso login --profile my-dev-profile</code></pre> -</div> -</div> -</div> -</div> -</div> -</div> -<div class="sect1 topic"> -<h2 id="configure-env">10. Configure environments to use with the AWS CDK</h2> -<div class="sectionbody"> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>You can configure AWS environments in multiple ways to use with the AWS Cloud Development Kit (AWS CDK). The best method of managing AWS environments will vary, based on your specific needs.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>You can configure AWS environments in multiple ways to use with the AWS Cloud Development Kit (AWS CDK). The best method of managing AWS environments will vary, based on your specific needs.</p> -</div> -<div class="paragraph"> -<p>Each CDK stack in your application must eventually be associated with an environment to determine where the stack gets deployed to.</p> -</div> -<div class="paragraph"> -<p>For an introduction to AWS environments, see <a href="#environments">Environments for the AWS CDK</a>.</p> -</div> -<div class="paragraph topiclist"> -<p>[[Topic List]]</p> -</div> -<div class="sect2"> -<h3 id="configure-env-where">10.1. Where you can specify environments from</h3> -<div class="paragraph"> -<p>You can specify environments in credentials and configuration files, or by using the <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html#env">env</a></code> property of the <code>Stack</code> construct from the AWS Construct Library.</p> -</div> -<div class="sect3"> -<h4 id="configure-env-where-files">10.1.1. Credentials and configuration files</h4> -<div class="paragraph"> -<p>You can use the AWS Command Line Interface (AWS CLI) to create <code class="path">credentials</code> and <code class="path">config</code> files that store, organize, and manage your AWS environment information. To learn more about these files, see <a href="https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html">Configuration and credential file settings</a> in the <em>AWS Command Line Interface User Guide</em>.</p> -</div> -<div class="paragraph"> -<p>Values stored in these files are organized by <em>profiles</em>. How you name your profiles and the key-value pairs in these files will vary based on your method of configuring programmatic access. To learn more about the different methods, see <a href="#configure-access">Configure security credentials for the AWS CDK CLI</a>.</p> -</div> -<div class="paragraph"> -<p>In general, the AWS CDK resolves AWS account information from your <code class="path">credentials</code> file and AWS Region information from your <code class="path">config</code> file.</p> -</div> -<div class="paragraph"> -<p>Once you have your <code class="path">credentials</code> and <code class="path">config</code> files configured, you can specify the environment to use with the AWS CDK <code class="noloc">CLI</code> and through environment variables.</p> -</div> -</div> -<div class="sect3"> -<h4 id="configure-env-where-env">10.1.2. env property of the Stack construct</h4> -<div class="paragraph"> -<p>You can specify the environment for each stack by using the <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html#env">env</a></code> property of the <code>Stack</code> construct. This property defines an account and Region to use. You can pass hard-coded values to this property or pass environment variables that are offered by the CDK.</p> -</div> -<div class="paragraph"> -<p>To pass environment variables, use the <code>AWS_DEFAULT_ACCOUNT</code> and <code>AWS_DEFAULT_REGION</code> environment variables. These environment variables can pass values from your <code class="path">credentials</code> and <code class="path">config</code> files. You can also use logic within your CDK code to determine the values of these environment variables.</p> -</div> -</div> -</div> -<div class="sect2"> -<h3 id="configure-env-precedence">10.2. Environment precedence with the AWS CDK</h3> -<div class="paragraph"> -<p>If you use multiple methods of specifying environments, the AWS CDK adheres to the following precedence:</p> -</div> -<div class="olist arabic"> -<ol class="arabic"> -<li> -<p>Hard-coded values specified with the <code>env</code> property of the <code>Stack</code> construct.</p> -</li> -<li> -<p><code>AWS_DEFAULT_ACCOUNT</code> and <code>AWS_DEFAULT_REGION</code> environment variables specified with the <code>env</code> property of the <code>Stack</code> construct.</p> -</li> -<li> -<p>Environment information associated with the profile from your <code class="path">credentials</code> and <code class="path">config</code> files and passed to the CDK <code class="noloc">CLI</code> using the <code>--profile</code> option.</p> -</li> -<li> -<p>The <code>default</code> profile from your <code class="path">credentials</code> and <code class="path">config</code> files.</p> -</li> -</ol> -</div> -</div> -<div class="sect2"> -<h3 id="configure-env-when">10.3. When to specify environments</h3> -<div class="paragraph"> -<p>When you develop with the CDK, you start by defining CDK stacks, which contain constructs that represent AWS resources. Next, you synthesize each CDK stack into an AWS CloudFormation template. You then deploy the CloudFormation template to your environment. How you specify environments determines when your environment information gets applied and can affect CDK behavior and outcomes.</p> -</div> -<div class="sect3"> -<h4 id="configure-env-when-synth">10.3.1. Specify environments at template synthesis</h4> -<div class="paragraph"> -<p>When you specify environment information using the <code>env</code> property of the <code>Stack</code> construct, your environment information is applied at template synthesis. Running <code>cdk synth</code> or <code>cdk deploy</code> produces an environment-specific CloudFormation template.</p> -</div> -<div class="paragraph"> -<p>If you use environment variables within the <code>env</code> property, you must use the <code>--profile</code> option with CDK <code class="noloc">CLI</code> commands to pass in the profile containing your environment information from your credentials and configuration files. This information will then be applied at template synthesis to produce an environment-specific template.</p> -</div> -<div class="paragraph"> -<p>Environment information within the CloudFormation template takes precedence over other methods. For example, if you provide a different environment with <code>cdk deploy --profile [replaceable]</code>profile````, the profile will be ignored.</p> -</div> -<div class="paragraph"> -<p>When you provide environment information in this way, you can use environment-dependent code and logic within your CDK app. This also means that the synthesized template could be different, based on the machine, user, or session that it’s synthesized under. This approach is often acceptable or desirable during development, but is not recommended for production use.</p> -</div> -</div> -<div class="sect3"> -<h4 id="configure-env-when-deploy">10.3.2. Specify environments at stack deployment</h4> -<div class="paragraph"> -<p>If you don’t specify an environment using the <code>env</code> property of the <code>Stack</code> construct, the CDK <code class="noloc">CLI</code> will produce an environment-agnostic CloudFormation template at synthesis. You can then specify the environment to deploy to by using <code>cdk deploy --profile [replaceable]</code>profile````.</p> -</div> -<div class="paragraph"> -<p>If you don’t specify a profile when deploying an environment-agnostic template, the CDK <code class="noloc">CLI</code> will attempt to use environment values from the <code>default</code> profile of your <code>credentials</code> and <code>config</code> files at deployment.</p> -</div> -<div class="paragraph"> -<p>If environment information is not available at deployment, AWS CloudFormation will attempt to resolve environment information at deployment through environment-related attributes such as <code>stack.account</code>, <code>stack.region</code>, and <code>stack.availabilityZones</code>.</p> -</div> -<div class="paragraph"> -<p>For environment-agnostic stacks, constructs within the stack cannot use environment information and you cannot use logic that requires environment information. For example, you cannot write code like <code>if (stack.region ==== 'us-east-1')</code> or use construct methods that require environment information such as <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.Vpc.html#static-fromwbrlookupscope-id-options">Vpc.fromLookup</a></code>. To use these features, you must specify an environment with the <code>env</code> property.</p> -</div> -<div class="paragraph"> -<p>For environment-agnostic stacks, any construct that uses Availability Zones will see two Availability Zones, allowing the stack to be deployed to any Region.</p> -</div> -</div> -</div> -<div class="sect2"> -<h3 id="configure-env-how">10.4. How to specify environments with the AWS CDK</h3> -<div class="sect3"> -<h4 id="configure-env-how-hard-coded">10.4.1. Specify hard-coded environments for each stack</h4> -<div class="paragraph"> -<p>Use the <code>env</code> property of the <code>Stack</code> construct to specify AWS environment values for your stack. The following is an example:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const envEU = { account: '2383838383', region: 'eu-west-1' }; -const envUSA = { account: '8373873873', region: 'us-west-2' }; - -new MyFirstStack(app, 'first-stack-us', { env: envUSA }); -new MyFirstStack(app, 'first-stack-eu', { env: envEU });</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const envEU = { account: '2383838383', region: 'eu-west-1' }; -const envUSA = { account: '8373873873', region: 'us-west-2' }; - -new MyFirstStack(app, 'first-stack-us', { env: envUSA }); -new MyFirstStack(app, 'first-stack-eu', { env: envEU });</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">env_EU = cdk.Environment(account="8373873873", region="eu-west-1") -env_USA = cdk.Environment(account="2383838383", region="us-west-2") - -MyFirstStack(app, "first-stack-us", env=env_USA) -MyFirstStack(app, "first-stack-eu", env=env_EU)</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">public class MyApp { - - // Helper method to build an environment - static Environment makeEnv(String account, String region) { - return Environment.builder() - .account(account) - .region(region) - .build(); - } - - public static void main(final String argv[]) { - App app = new App(); - - Environment envEU = makeEnv("8373873873", "eu-west-1"); - Environment envUSA = makeEnv("2383838383", "us-west-2"); - - new MyFirstStack(app, "first-stack-us", StackProps.builder() - .env(envUSA).build()); - new MyFirstStack(app, "first-stack-eu", StackProps.builder() - .env(envEU).build()); - - app.synth(); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">Amazon.CDK.Environment makeEnv(string account, string region) -{ - return new Amazon.CDK.Environment - { - Account = account, - Region = region - }; -} - -var envEU = makeEnv(account: "8373873873", region: "eu-west-1"); -var envUSA = makeEnv(account: "2383838383", region: "us-west-2"); - -new MyFirstStack(app, "first-stack-us", new StackProps { Env=envUSA }); -new MyFirstStack(app, "first-stack-eu", new StackProps { Env=envEU });</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">env_EU := awscdk.Environment{ - Account: jsii.String("8373873873"), - Region: jsii.String("eu-west-1"), -} - -env_USA := awscdk.Environment{ - Account: jsii.String("2383838383"), - Region: jsii.String("us-west-2"), -} - -MyFirstStack(app, "first-stack-us", &awscdk.StackProps{ - Env: &env_USA, -}) - -MyFirstStack(app, "first-stack-eu", &awscdk.StackProps{ - Env: &env_EU, -})</code></pre> -</div> -</div> -<div class="paragraph"> -<p>We recommend this approach for production environments. By explicitly specifying the environment in this way, you can ensure that the stack is always deployed to the specific environment.</p> -</div> -</div> -<div class="sect3"> -<h4 id="configure-env-how-env">10.4.2. Specify environments using environment variables</h4> -<div class="paragraph"> -<p>The AWS CDK provides two environment variables that you can use within your CDK code: <code>CDK_DEFAULT_ACCOUNT</code> and <code>CDK_DEFAULT_REGION</code>. When you use these environment variables within the <code>env</code> property of your stack instance, you can pass environment information from your credentials and configuration files using the CDK <code class="noloc">CLI</code><code>--profile</code> option.</p> -</div> -<div class="paragraph"> -<p>The following is an example of how to specify these environment variables:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Access environment variables via Node’s <code>process</code> object.</p> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -You need the <code>DefinitelyTyped</code> module to use <code>process</code> in TypeScript. <code>cdk init</code> installs this module for you. However, you should install this module manually if you are working with a project created before it was added, or if you didn’t set up your project using <code>cdk init</code>. -</td> -</tr> -</table> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">npm install @types/node</code></pre> -</div> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">new MyDevStack(app, 'dev', { - env: { - account: process.env.CDK_DEFAULT_ACCOUNT, - region: process.env.CDK_DEFAULT_REGION -}});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Access environment variables via Node’s <code>process</code> object.</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">new MyDevStack(app, 'dev', { - env: { - account: process.env.CDK_DEFAULT_ACCOUNT, - region: process.env.CDK_DEFAULT_REGION -}});</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Python</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Use the <code>os</code> module’s <code>environ</code> dictionary to access environment variables.</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">import os -MyDevStack(app, "dev", env=cdk.Environment( - account=os.environ["CDK_DEFAULT_ACCOUNT"], - region=os.environ["CDK_DEFAULT_REGION"]))</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Java</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Use <code>System.getenv()</code> to get the value of an environment variable.</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">public class MyApp { - - // Helper method to build an environment - static Environment makeEnv(String account, String region) { - account = (account == null) ? System.getenv("CDK_DEFAULT_ACCOUNT") : account; - region = (region == null) ? System.getenv("CDK_DEFAULT_REGION") : region; - - return Environment.builder() - .account(account) - .region(region) - .build(); - } - - public static void main(final String argv[]) { - App app = new App(); - - Environment envEU = makeEnv(null, null); - Environment envUSA = makeEnv(null, null); - - new MyDevStack(app, "first-stack-us", StackProps.builder() - .env(envUSA).build()); - new MyDevStack(app, "first-stack-eu", StackProps.builder() - .env(envEU).build()); - - app.synth(); - } -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">C#</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Use <code>System.Environment.GetEnvironmentVariable()</code> to get the value of an environment variable.</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">Amazon.CDK.Environment makeEnv(string account=null, string region=null) -{ - return new Amazon.CDK.Environment - { - Account = account ?? System.Environment.GetEnvironmentVariable("CDK_DEFAULT_ACCOUNT"), - Region = region ?? System.Environment.GetEnvironmentVariable("CDK_DEFAULT_REGION") - }; -} - -new MyDevStack(app, "dev", new StackProps { Env = makeEnv() });</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">import "os" - -MyDevStack(app, "dev", &awscdk.StackProps{ - Env: &awscdk.Environment{ - Account: jsii.String(os.Getenv("CDK_DEFAULT_ACCOUNT")), - Region: jsii.String(os.Getenv("CDK_DEFAULT_REGION")), - }, -})</code></pre> -</div> -</div> -<div class="paragraph"> -<p>By specifying environments using environment variables, you can have the same CDK stack synthesize to AWS CloudFormation templates for different environments. This means that you can deploy the same CDK stack to different AWS environments without having to modify your CDK code. You only have to specify the profile to use when running <code>cdk synth</code>.</p> -</div> -<div class="paragraph"> -<p>This approach is great for development environments when deploying the same stack to different environments. However, we do not recommend this approach for production environments since the same CDK code can synthesize different templates, depending on the machine, user, or session that it’s synthesized under.</p> -</div> -</div> -<div class="sect3"> -<h4 id="configure-env-how-files">10.4.3. Specify environments from your credentials and configuration files with the CDK <code class="noloc">CLI</code></h4> -<div class="paragraph"> -<p>When deploying an environment-agnostic template, use the <code>--profile</code> option with any CDK <code class="noloc">CLI</code> command to specify the profile to use. The following is an example that deploys a CDK stack named <code>myStack</code> using the <code>prod</code> profile that is defined in the <code class="path">credentials</code> and <code class="path">config</code> files:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk deploy myStack --profile prod</code></pre> -</div> -</div> -<div class="paragraph"> -<p>For more information on the <code>--profile</code> option, along with other CDK <code class="noloc">CLI</code> commands and options, see <a href="#ref-cli-cmd">AWS CDK CLI command reference</a>.</p> -</div> -</div> -</div> -<div class="sect2"> -<h3 id="configure-env-considerations">10.5. Considerations when configuring environments with the AWS CDK</h3> -<div class="paragraph"> -<p>Services that you define by using constructs within your stacks must support the Region that you are deploying to. For a list of supported AWS services per region, see <a href="https://aws.amazon.com/about-aws/global-infrastructure/regional-product-services/">AWS Services by Region</a>.</p> -</div> -<div class="paragraph"> -<p>You must have valid AWS Identity and Access Management (IAM) credentials to perform stack deployments with the AWS CDK into your specified environments.</p> -</div> -</div> -<div class="sect2"> -<h3 id="configure-env-examples">10.6. Examples</h3> -<div class="sect3"> -<h4 id="configure-env-examples-agnostic">10.6.1. Synthesize an environment–agnostic CloudFormation template from a CDK stack</h4> -<div class="paragraph"> -<p>In this example, we create an environment-agnostic CloudFormation template from our CDK stack. We can then deploy this template to any environment.</p> -</div> -<div class="paragraph"> -<p>The following is our example CDK stack. This stack defines an Amazon S3 bucket and a CloudFormation stack output for the bucket’s Region. For this example, <code>env</code> is not defined:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">export class CdkAppStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - // Create the S3 bucket - const bucket = new s3.Bucket(this, 'amzn-s3-demo-bucket', { - removalPolicy: cdk.RemovalPolicy.DESTROY, - }); - - // Create an output for the bucket's Region - new cdk.CfnOutput(this, 'BucketRegion', { - value: bucket.env.region, - }); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">class CdkAppStack extends cdk.Stack { - constructor(scope, id, props) { - super(scope, id, props); - - // Create the S3 bucket - const bucket = new s3.Bucket(this, 'amzn-s3-demo-bucket', { - removalPolicy: cdk.RemovalPolicy.DESTROY, - }); - - // Create an output for the bucket's Region - new cdk.CfnOutput(this, 'BucketRegion', { - value: bucket.env.region, - }); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">class CdkAppStack(cdk.Stack): - - def __init__(self, scope: cdk.Construct, id: str, **kwargs) -> None: - super().__init__(scope, id, **kwargs) - - # Create the S3 bucket - bucket = s3.Bucket(self, 'amzn-s3-demo-bucket', - removal_policy=cdk.RemovalPolicy.DESTROY - ) - - # Create an output for the bucket's Region - cdk.CfnOutput(self, 'BucketRegion', - value=bucket.env.region - )</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">public class CdkAppStack extends Stack { - - public CdkAppStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - // Create the S3 bucket - Bucket bucket = Bucket.Builder.create(this, "amzn-s3-demo-bucket") - .removalPolicy(RemovalPolicy.DESTROY) - .build(); - - // Create an output for the bucket's Region - CfnOutput.Builder.create(this, "BucketRegion") - .value(this.getRegion()) - .build(); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">namespace MyCdkApp -{ - public class CdkAppStack : Stack - { - public CdkAppStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) - { - // Create the S3 bucket - var bucket = new Bucket(this, "amzn-s3-demo-bucket", new BucketProps - { - RemovalPolicy = RemovalPolicy.DESTROY - }); - - // Create an output for the bucket's Region - new CfnOutput(this, "BucketRegion", new CfnOutputProps - { - Value = this.Region - }); - } - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">func NewCdkAppStack(scope constructs.Construct, id string, props *CdkAppStackProps) awscdk.Stack { - stack := awscdk.NewStack(scope, &id, &props.StackProps) - - // Create the S3 bucket - bucket := awss3.NewBucket(stack, jsii.String("amzn-s3-demo-bucket"), &awss3.BucketProps{ - RemovalPolicy: awscdk.RemovalPolicy_DESTROY, - }) - - // Create an output for the bucket's Region - awscdk.NewCfnOutput(stack, jsii.String("BucketRegion"), &awscdk.CfnOutputProps{ - Value: stack.Region(), - }) - - return stack -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>When we run <code>cdk synth</code>, the CDK <code class="noloc">CLI</code> produces a CloudFormation template with the pseudo parameter <code>AWS::Region</code> as the output value for the bucket’s Region. This parameter will be resolved at deployment:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-yaml" data-lang="yaml">Outputs: - BucketRegion: - Value: - Ref: AWS::Region</code></pre> -</div> -</div> -<div class="paragraph"> -<p>To deploy this stack to an environment that is specified in the <code>dev</code> profile of our credentials and configuration files, we run the following:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk deploy CdkAppStack --profile dev</code></pre> -</div> -</div> -<div class="paragraph"> -<p>If we don’t specify a profile, the CDK <code class="noloc">CLI</code> will attempt to use environment information from the <code>default</code> profile in our credentials and configuration files.</p> -</div> -</div> -<div class="sect3"> -<h4 id="configure-env-example-logic">10.6.2. Use logic to determine environment information at template synthesis</h4> -<div class="paragraph"> -<p>In this example, we configure the <code>env</code> property of our <code>stack</code> instance to use a valid expression. We specify two additional environment variables, <code>CDK_DEPLOY_ACCOUNT</code> and <code>CDK_DEPLOY_REGION</code>. These environment variables can override defaults at synthesis time if they exist:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">new MyDevStack(app, 'dev', { - env: { - account: process.env.CDK_DEPLOY_ACCOUNT || process.env.CDK_DEFAULT_ACCOUNT, - region: process.env.CDK_DEPLOY_REGION || process.env.CDK_DEFAULT_REGION -}});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">new MyDevStack(app, 'dev', { - env: { - account: process.env.CDK_DEPLOY_ACCOUNT || process.env.CDK_DEFAULT_ACCOUNT, - region: process.env.CDK_DEPLOY_REGION || process.env.CDK_DEFAULT_REGION -}});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">MyDevStack(app, "dev", env=cdk.Environment( - account=os.environ.get("CDK_DEPLOY_ACCOUNT", os.environ["CDK_DEFAULT_ACCOUNT"]), - region=os.environ.get("CDK_DEPLOY_REGION", os.environ["CDK_DEFAULT_REGION"])</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">public class MyApp { - - // Helper method to build an environment - static Environment makeEnv(String account, String region) { - account = (account == null) ? System.getenv("CDK_DEPLOY_ACCOUNT") : account; - region = (region == null) ? System.getenv("CDK_DEPLOY_REGION") : region; - account = (account == null) ? System.getenv("CDK_DEFAULT_ACCOUNT") : account; - region = (region == null) ? System.getenv("CDK_DEFAULT_REGION") : region; - - return Environment.builder() - .account(account) - .region(region) - .build(); - } - - public static void main(final String argv[]) { - App app = new App(); - - Environment envEU = makeEnv(null, null); - Environment envUSA = makeEnv(null, null); - - new MyDevStack(app, "first-stack-us", StackProps.builder() - .env(envUSA).build()); - new MyDevStack(app, "first-stack-eu", StackProps.builder() - .env(envEU).build()); - - app.synth(); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">Amazon.CDK.Environment makeEnv(string account=null, string region=null) -{ - return new Amazon.CDK.Environment - { - Account = account ?? - System.Environment.GetEnvironmentVariable("CDK_DEPLOY_ACCOUNT") ?? - System.Environment.GetEnvironmentVariable("CDK_DEFAULT_ACCOUNT"), - Region = region ?? - System.Environment.GetEnvironmentVariable("CDK_DEPLOY_REGION") ?? - System.Environment.GetEnvironmentVariable("CDK_DEFAULT_REGION") - }; -} - -new MyDevStack(app, "dev", new StackProps { Env = makeEnv() });</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">var account, region string -var b bool - -if account, b = os.LookupEnv("CDK_DEPLOY_ACCOUNT"); !b || len(account) == 0 { - account = os.Getenv("CDK_DEFAULT_ACCOUNT") -} -if region, b = os.LookupEnv("CDK_DEPLOY_REGION"); !b || len(region) == 0 { - region = os.Getenv("CDK_DEFAULT_REGION") -} - -MyDevStack(app, "dev", &awscdk.StackProps{ - Env: &awscdk.Environment{ - Account: &account, - Region: &region, - }, -})</code></pre> -</div> -</div> -<div class="paragraph"> -<p>With our stack’s environment declared this way, we can then write a short script or batch file and set variables from command line arguments, then call <code>cdk deploy</code>. The following is an example. Any arguments beyond the first two are passed through to <code>cdk deploy</code> to specify command line options or arguments:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">macOS/Linux</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-bash" data-lang="bash">#!/usr/bin/env bash -if [[ $# -ge 2 ]]; then - export CDK_DEPLOY_ACCOUNT=$1 - export CDK_DEPLOY_REGION=$2 - shift; shift - npx cdk deploy "$@" - exit $? -else - echo 1>&2 "Provide account and region as first two args." - echo 1>&2 "Additional args are passed through to cdk deploy." - exit 1 -fi</code></pre> -</div> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p>Save the script as <code class="path">cdk-deploy-to.sh</code>, then execute <code>chmod +x cdk-deploy-to.sh</code> to make it executable.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Windows</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-bat" data-lang="bat">@findstr /B /V @ %~dpnx0 > %~dpn0.ps1 && powershell -ExecutionPolicy Bypass %~dpn0.ps1 %* -@exit /B %ERRORLEVEL% -if ($args.length -ge 2) { - $env:CDK_DEPLOY_ACCOUNT, $args = $args - $env:CDK_DEPLOY_REGION, $args = $args - npx cdk deploy $args - exit $lastExitCode -} else { - [console]::error.writeline("Provide account and region as first two args.") - [console]::error.writeline("Additional args are passed through to cdk deploy.") - exit 1 -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p>The Windows version of the script uses PowerShell to provide the same functionality as the macOS/Linux version. It also contains instructions to allow it to be run as a batch file so it can be easily invoked from a command line. It should be saved as <code class="path">cdk-deploy-to.bat</code>. The file <code class="path">cdk-deploy-to.ps1</code> will be created when the batch file is invoked.</p> -</div> -<div class="paragraph"> -<p>We can then write additional scripts that use the <code class="path">cdk-deploy-to</code> script to deploy to specific environments. The following is an example:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">macOS/Linux</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-bash" data-lang="bash">#!/usr/bin/env bash -# cdk-deploy-to-test.sh -./cdk-deploy-to.sh 123457689 us-east-1 "$@"</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Windows</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-bat" data-lang="bat">@echo off -rem cdk-deploy-to-test.bat -cdk-deploy-to 135792469 us-east-1 %*</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The following is an example that uses the <code class="path">cdk-deploy-to</code> script to deploy to multiple environments. If the first deployment fails, the process stops:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">macOS/Linux</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-bash" data-lang="bash">#!/usr/bin/env bash -# cdk-deploy-to-prod.sh -./cdk-deploy-to.sh 135792468 us-west-1 "$@" || exit -./cdk-deploy-to.sh 246813579 eu-west-1 "$@"</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Windows</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-bat" data-lang="bat">@echo off -rem cdk-deploy-to-prod.bat -cdk-deploy-to 135792469 us-west-1 %* || exit /B -cdk-deploy-to 245813579 eu-west-1 %*</code></pre> -</div> -</div> -</div> -</div> -</div> -</div> -<div class="sect1 topic"> -<h2 id="bootstrapping-env">11. Bootstrap your environment for use with the AWS CDK</h2> -<div class="sectionbody"> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Bootstrap your AWS environment before using the AWS Cloud Development Kit (AWS CDK) to deploy CDK stacks into your environment.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>Bootstrap your AWS environment to prepare it for AWS Cloud Development Kit (AWS CDK) stack deployments.</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>For an introduction to environments, see <a href="#environments">Environments for the AWS CDK</a>.</p> -</li> -<li> -<p>For an introduction to bootstrapping, see <a href="#bootstrapping">AWS CDK bootstrapping</a>.</p> -</li> -</ul> -</div> -<div class="sect2"> -<h3 id="bootstrapping-howto">11.1. How to bootstrap your environment</h3> -<div class="paragraph"> -<p>You can use the AWS CDK Command Line Interface (AWS CDK <code class="noloc">CLI</code>) or your preferred AWS CloudFormation deployment tool to bootstrap your environment.</p> -</div> -<div class="sect3"> -<h4 id="bootstrapping-howto-cli">11.1.1. Use the CDK <code class="noloc">CLI</code></h4> -<div class="paragraph"> -<p>You can use the CDK <code class="noloc">CLI</code><code>cdk bootstrap</code> command to bootstrap your environment. This is the method that we recommend if you don’t require significant modifications to bootstrapping.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Bootstrap from any working directory</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>To bootstrap from any working directory, provide the environment to bootstrap as a command line argument. The following is an example:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk bootstrap aws://123456789012/us-east-1</code></pre> -</div> -</div> -<div class="admonitionblock tip"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-tip" title="Tip"></i> -</td> -<td class="content"> -If you don’t have your AWS account number, you can get it from the AWS Management Console. You can also use the following AWS CLI command to display your default account information, including your account number: -</td> -</tr> -</table> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ aws sts get-caller-identity</code></pre> -</div> -</div> -<div class="paragraph"> -<p>If you have named profiles in your AWS <code class="path">config</code> and <code class="path">credentials</code> files, use the <code>--profile</code> option to retrieve account information for a specific profile. The following is an example:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ aws sts get-caller-identity --profile prod</code></pre> -</div> -</div> -<div class="paragraph"> -<p>To display the default Region, use the <code>aws configure get</code> command:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ aws configure get region -$ aws configure get region --profile prod</code></pre> -</div> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p>When providing an argument, the <code>aws://</code> prefix is optional. The following is valid:</p> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk bootstrap 123456789012/us-east-1</code></pre> -</div> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p>To bootstrap multiple environments at the same time, provide multiple arguments:</p> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk bootstrap aws://123456789012/us-east-1 aws://123456789012/us-east-2</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Bootstrap from the parent directory of a CDK project</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>You can run <code>cdk bootstrap</code> from the parent directory of a CDK project containing a <code class="path">cdk.json</code> file. If you don’t provide an environment as an argument, the CDK <code class="noloc">CLI</code> will obtain environment information from default sources, such as your <code class="path">config</code> and <code class="path">credentials</code> files or any environment information specified for your CDK stack.</p> -<div class="paragraph"> -<p>When you bootstrap from the parent directory of a CDK project, environments provided from command line arguments take precedence over other sources.</p> -</div> -<div class="paragraph"> -<p>To bootstrap an environment that is specified in your <code class="path">config</code> and <code class="path">credentials</code> files, use the <code>--profile</code> option:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk bootstrap --profile prod</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div class="paragraph"> -<p>For more information on the <code>cdk bootstrap</code> command and supported options, see <a href="#ref-cli-cmd-bootstrap">cdk bootstrap</a>.</p> -</div> -</div> -<div class="sect3"> -<h4 id="bootstrapping-howto-cfn">11.1.2. Use any AWS CloudFormation tool</h4> -<div class="paragraph"> -<p>You can copy the <a href="https://github.com/aws/aws-cdk-cli/blob/main/packages/aws-cdk/lib/api/bootstrap/bootstrap-template.yaml">bootstrap template</a> from the <em>aws-cdk-cli <code class="noloc">GitHub</code> repository</em> or obtain the template with the <code>cdk bootstrap --show-template</code> command. Then, use any AWS CloudFormation tool to deploy the template into your environment.</p> -</div> -<div class="paragraph"> -<p>With this method, you can use AWS CloudFormation StackSets or AWS Control Tower. You can also use the AWS CloudFormation console or the AWS Command Line Interface (AWS CLI). You can make modifications to your template before you deploy it. This method may be more flexible and suitable for large-scale deployments.</p> -</div> -<div class="paragraph"> -<p>The following is an example of using the <code>--show-template</code> option to retrieve and save the bootstrap template to your local machine:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">macOS/Linux</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk bootstrap --show-template > bootstrap-template.yaml</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Windows</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>On Windows, PowerShell must be used to preserve the encoding of the template.</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">powershell "cdk bootstrap --show-template | Out-File -encoding utf8 bootstrap-template.yaml"</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>If CDK notices are appearing in your AWS CloudFormation template output, provide the <code>--no-notices</code> option with your command.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>To deploy this template using the CDK <code class="noloc">CLI</code>, you can run the following:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk bootstrap --template bootstrap-template.yaml</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The following is an example of using the AWS CLI to deploy the template:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">macOS/Linux</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">aws cloudformation create-stack \ - --stack-name CDKToolkit \ - --template-body file://path/to/bootstrap-template.yaml \ - --capabilities CAPABILITY_NAMED_IAM \ - --region us-west-1</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Windows</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">aws cloudformation create-stack ^ - --stack-name CDKToolkit ^ - --template-body file://path/to/bootstrap-template.yaml ^ - --capabilities CAPABILITY_NAMED_IAM ^ - --region us-west-1</code></pre> -</div> -</div> -<div class="paragraph"> -<p>For information on using CloudFormation StackSets to bootstrap multiple environments, see <a href="https://aws.amazon.com/blogs/mt/bootstrapping-multiple-aws-accounts-for-aws-cdk-using-cloudformation-stacksets/">Bootstrapping multiple AWS accounts for AWS CDK using CloudFormation StackSets</a> in the <em>AWS Cloud Operations & Migrations Blog</em>.</p> -</div> -</div> -</div> -<div class="sect2"> -<h3 id="bootstrapping-env-when">11.2. When to bootstrap your environment</h3> -<div class="paragraph"> -<p>You must bootstrap each AWS environment before you deploy into the environment. We recommend that you proactively bootstrap each environment that you plan to use. You can do this before you plan on actually deploying CDK apps into the environment. By proactively bootstrapping your environments, you prevent potential future issues such as Amazon S3 bucket name conflicts or deploying CDK apps into environments that haven’t been bootstrapped.</p> -</div> -<div class="paragraph"> -<p>It’s okay to bootstrap an environment more than once. If an environment has already been bootstrapped, the bootstrap stack will be upgraded if necessary. Otherwise, nothing will happen.</p> -</div> -<div class="paragraph"> -<p>If you attempt to deploy a CDK stack into an environment that hasn’t been bootstrapped, you will see an error like the following:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk deploy - -✨ Synthesis time: 2.02s - - ❌ Deployment failed: Error: BootstrapExampleStack: SSM parameter /cdk-bootstrap/hnb659fds/version not found. Has the environment been bootstrapped? Please run 'cdk bootstrap' (see https://docs.aws.amazon.com/cdk/latest/guide/bootstrapping.html)</code></pre> -</div> -</div> -<div class="sect3"> -<h4 id="bootstrapping-env-when-update">11.2.1. Update your bootstrap stack</h4> -<div class="paragraph"> -<p>Periodically, the CDK team will update the bootstrap template to a new version. When this happens, we recommend that you update your bootstrap stack. If you haven’t customized the bootstrapping process, you can update your bootstrap stack by following the same steps that you took to originally bootstrap your environment. For more information, see <a href="#bootstrap-template-history">Bootstrap template version history</a>.</p> -</div> -</div> -</div> -<div class="sect2"> -<h3 id="bootstrapping-env-default">11.3. Default resources created during bootstrapping</h3> -<div class="sect3"> -<h4 id="bootstrapping-env-roles">11.3.1. IAM roles created during bootstrapping</h4> -<div class="paragraph"> -<p>By default, bootstrapping provisions the following AWS Identity and Access Management (IAM) roles in your environment:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><code>CloudFormationExecutionRole</code></p> -</li> -<li> -<p><code>DeploymentActionRole</code></p> -</li> -<li> -<p><code>FilePublishingRole</code></p> -</li> -<li> -<p><code>ImagePublishingRole</code></p> -</li> -<li> -<p><code>LookupRole</code></p> -</li> -</ul> -</div> -<div id="bootstrapping-env-roles-cfn" class="dlist"> -<dl> -<dt class="hdlist1"><code>CloudFormationExecutionRole</code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>This IAM role is a CloudFormation service role that grants CloudFormation permission to perform stack deployments on your behalf. This role gives CloudFormation permission to perform AWS API calls in your account, including deploying stacks.</p> -<div class="paragraph"> -<p>By using a service role, the permissions provisioned for the service role determine what actions can be performed on your CloudFormation resources. Without this service role, the security credentials you provide with the CDK <code class="noloc">CLI</code> would determine what CloudFormation is allowed to do.</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="bootstrapping-env-roles-deploy" class="dlist"> -<dl> -<dt class="hdlist1"><code>DeploymentActionRole</code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>This IAM role grants permission to perform deployments into your environment. It is assumed by the CDK <code class="noloc">CLI</code> during deployments.</p> -<div class="paragraph"> -<p>By using a role for deployments, you can perform cross-account deployments since the role can be assumed by AWS identities in a different account.</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="bootstrapping-env-roles-s3" class="dlist"> -<dl> -<dt class="hdlist1"><code>FilePublishingRole</code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>This IAM role grants permission to perform actions against the bootstrapped Amazon Simple Storage Service (Amazon S3) bucket, including uploading and deleting assets. It is assumed by the CDK <code class="noloc">CLI</code> during deployments.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="bootstrapping-env-roles-ecr" class="dlist"> -<dl> -<dt class="hdlist1"><code>ImagePublishingRole</code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>This IAM role grants permission to perform actions against the bootstrapped Amazon Elastic Container Registry (Amazon ECR) repository. It is assumed by the CDK <code class="noloc">CLI</code> during deployments.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="bootstrapping-env-roles-lookup" class="dlist"> -<dl> -<dt class="hdlist1"><code>LookupRole</code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>This IAM role grants <code>readOnly</code> permission to look up <a href="#context">context values</a> from the AWS environment. It is assumed by the CDK <code class="noloc">CLI</code> when performing tasks such as template synthesis and deployments.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect3"> -<h4 id="bootstrapping-env-default-id">11.3.2. Resource IDs created during bootstrapping</h4> -<div class="paragraph"> -<p>When you deploy the default bootstrap template, physical IDs for bootstrap resources are created using the following structure: <code>cdk-[replaceable]</code>qualifier<code>-[replaceable]</code>description<code>-[replaceable]</code>account-ID<code>-[replaceable]</code>Region````.</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><strong>Qualifier</strong> – A nine character unique string value of <code>hnb659fds</code>. The actual value has no significance.</p> -</li> -<li> -<p><strong>Description</strong> – A short description of the resource. For example, <code>container-assets</code>.</p> -</li> -<li> -<p><strong>Account ID</strong> – The AWS account ID of the environment.</p> -</li> -<li> -<p><strong>Region</strong> – The AWS Region of the environment.</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>The following is an example physical ID of the Amazon S3 staging bucket created during bootstrapping: <code>cdk-hnb659fds-assets-012345678910-us-west-1</code>.</p> -</div> -</div> -</div> -<div class="sect2"> -<h3 id="bootstrapping-env-permissions">11.4. Permissions to use when bootstrapping your environment</h3> -<div class="paragraph"> -<p>When bootstrapping an AWS environment, the IAM identity performing the bootstrapping must have at least the following permissions:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-json" data-lang="json">{ - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Action": [ - "cloudformation:*", - "ecr:*", - "ssm:*", - "s3:*", - "iam:*" - ], - "Resource": "*" - } - ] -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Over time, the bootstrap stack, including the resources that are created and permissions they require, may change. With future changes, you may need to modify the permissions required to bootstrap an environment.</p> -</div> -</div> -<div class="sect2"> -<h3 id="bootstrapping-env-customize">11.5. Customize bootstrapping</h3> -<div class="paragraph"> -<p>If the default bootstrap template doesn’t suit your needs, you can customize the bootstrapping of resources into your environment in the following ways:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Use command line options with the <code>cdk bootstrap</code> command – This method is best for making small, specific changes that are supported through command line options.</p> -</li> -<li> -<p>Modify the default bootstrap template and deploy it – This method is best for making complex changes or if you want complete control over the configuration of resources provisioned during bootstrapping.</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>For more information on customizing bootstrapping, see <a href="#bootstrapping-customizing">Customize AWS CDK bootstrapping</a>.</p> -</div> -</div> -<div class="sect2"> -<h3 id="bootstrapping-env-pipelines">11.6. Bootstrapping with CDK Pipelines</h3> -<div class="paragraph"> -<p>If you are using CDK Pipelines to deploy into another account’s environment, and you receive a message like the following:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre>Policy contains a statement with one or more invalid principals</pre> -</div> -</div> -<div class="paragraph"> -<p>This error message means that the appropriate IAM roles do not exist in the other environment. The most likely cause is that the environment has not been bootstrapped. Bootstrap the environment and try again.</p> -</div> -<div class="sect3"> -<h4 id="bootstrapping-env-pipelines-protect">11.6.1. Protecting your bootstrap stack from deletion</h4> -<div class="paragraph"> -<p>If a bootstrap stack is deleted, the AWS resources that were originally provisioned in the environment to support CDK deployments will also be deleted. This will cause the pipeline to stop working. If this happens, there is no general solution for recovery.</p> -</div> -<div class="paragraph"> -<p>After your environment is bootstrapped, do not delete and recreate the environment’s bootstrap stack. Instead, try to update the bootstrap stack to a new version by running the <code>cdk bootstrap</code> command again.</p> -</div> -<div class="paragraph"> -<p>To protect against accidental deletion of your bootstrap stack, we recommend that you provide the <code>--termination-protection</code> option with the <code>cdk bootstrap</code> command to enable termination protection. You can enable termination protection on new or existing bootstrap stacks. For instructions on enabling termination protection, see <a href="#bootstrapping-customizing-cli-protection">Enable termination protection for the bootstrap stack</a>.</p> -</div> -</div> -</div> -<div class="sect2"> -<h3 id="bootstrap-template-history">11.7. Bootstrap template version history</h3> -<div class="paragraph"> -<p>The bootstrap template is versioned and evolves over time with the AWS CDK itself. If you provide your own bootstrap template, keep it up to date with the canonical default template. You want to make sure that your template continues to work with all CDK features.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>Earlier versions of the bootstrap template created an AWS KMS key in each bootstrapped environment by default. To avoid charges for the KMS key, re-bootstrap these environments using <code>--no-bootstrap-customer-key</code>. The current default is no KMS key, which helps avoid these charges.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>This section contains a list of the changes made in each version.</p> -</div> -<table class="tableblock frame-all grid-all stretch"> -<colgroup> -<col style="width: 33.3333%;"> -<col style="width: 33.3333%;"> -<col style="width: 33.3334%;"> -</colgroup> -<thead> -<tr> -<th class="tableblock halign-left valign-top">Template version</th> -<th class="tableblock halign-left valign-top">AWS CDK version</th> -<th class="tableblock halign-left valign-top">Changes</th> -</tr> -</thead> -<tbody> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>1</strong></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">1.40.0</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Initial version of template with Bucket, Key, Repository, and Roles.</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>2</strong></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">1.45.0</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Split asset publishing role into separate file and image publishing roles.</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>3</strong></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">1.46.0</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Add <code>FileAssetKeyArn</code> export to be able to add decrypt permissions to asset consumers.</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>4</strong></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">1.61.0</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">AWS KMS permissions are now implicit via Amazon S3 and no longer require <code>FileAsetKeyArn</code>. Add <code>CdkBootstrapVersion</code> SSM parameter so the bootstrap stack version can be verified without knowing the stack name.</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>5</strong></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">1.87.0</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Deployment role can read SSM parameter.</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>6</strong></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">1.108.0</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Add lookup role separate from deployment role.</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>6</strong></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">1.109.0</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Attach <code>aws-cdk:bootstrap-role</code> tag to deployment, file publishing, and image publishing roles.</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>7</strong></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">1.110.0</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Deployment role can no longer read Buckets in the target account directly. (However, this role is effectively an administrator, and could always use its AWS CloudFormation permissions to make the bucket readable anyway).</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>8</strong></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">1.114.0</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">The lookup role has full read-only permissions to the target environment, and has a <code>aws-cdk:bootstrap-role</code> tag as well.</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>9</strong></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">2.1.0</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Fixes Amazon S3 asset uploads from being rejected by commonly referenced encryption SCP.</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>10</strong></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">2.4.0</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Amazon ECR ScanOnPush is now enabled by default.</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>11</strong></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">2.18.0</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Adds policy allowing Lambda to pull from Amazon ECR repos so it survives re-bootstrapping.</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>12</strong></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">2.20.0</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Adds support for experimental <strong class="command">cdk import</strong>.</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>13</strong></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">2.25.0</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Makes container images in bootstrap-created Amazon ECR repositories immutable.</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>14</strong></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">2.34.0</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Turns off Amazon ECR image scanning at the repository level by default to allow bootstrapping Regions that do not support image scanning.</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>15</strong></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">2.60.0</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">KMS keys cannot be tagged.</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>16</strong></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">2.69.0</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Addresses Security Hub finding <a href="https://docs.aws.amazon.com/securityhub/latest/userguide/kms-controls.html#kms-2">KMS.2</a>.</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>17</strong></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">2.72.0</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Addresses Security Hub finding <a href="https://docs.aws.amazon.com/securityhub/latest/userguide/ecr-controls.html#ecr-3">ECR.3</a>.</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>18</strong></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">2.80.0</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Reverted changes made for version 16 as they don’t work in all partitions and are are not recommended.</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>19</strong></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">2.106.1</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Reverted changes made to version 18 where AccessControl property was removed from the template. (<a href="https://github.com/aws/aws-cdk/issues/27964">#27964</a>)</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>20</strong></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">2.119.0</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Add <code>ssm:GetParameters</code> action to the AWS CloudFormation deploy IAM role. For more information, see <a href="https://github.com/aws/aws-cdk/pull/28336/files#diff-4fdac38426c4747aa17d515b01af4994d3d2f12c34f7b6655f24328259beb7bf">#28336</a>.</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>21</strong></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">2.149.0</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Add condition to the file publishing role.</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>22</strong></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">2.160.0</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Add <code>sts:TagSession</code> permissions to the trust policy of bootstrap IAM roles.</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>23</strong></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">2.161.0</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Add <code>cloudformation:RollbackStack</code> and <code>cloudformation:ContinueUpdateRollback</code> permissions to the trust policy of the deploy IAM role. This provides permissions for the <code>cdk rollback</code> command.</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>24</strong></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">2.165.0</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Change the duration of days that noncurrent objects in the bootstrap bucket will be retained, from 365 to 30 days. Since the new <code>cdk gc</code> command introduces the ability to delete objects in the bootstrap bucket, this new behavior ensures that deleted objects remain in the bootstrap bucket for 30 days instead of 365 days. For more information on this change, see <code>aws-cdk</code> PR <a href="https://github.com/aws/aws-cdk/pull/31949">#31949</a>.</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>25</strong></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">2.165.0</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Add support to the bootstrap bucket for the removal of incomplete multipart uploads. Incomplete multipart uploads will be deleted after 1 day. For more information on this change, see <code>aws-cdk</code> PR <a href="https://github.com/aws/aws-cdk/pull/31956">#31956</a>.</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>26</strong></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">2.1002.0</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Add two deletion-related policies (<code>UpdateReplacePolicy</code> and <code>DeletionPolicy</code> to the <code>FileAssetsBucketEncryptionKey</code>) resource. These policies ensure that the old AWS KMS key resource will be properly deleted when the bootstrap stack is updated or deleted. For more information on this change, see <code>aws-cdk-cli</code> PR <a href="https://github.com/aws/aws-cdk-cli/pull/100">#100</a>.</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>27</strong></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">2.1003.0</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Add new Amazon ECR resource policy to grant Amazon EMR Serverless specific permissions for retrieving container images. For more information on this change, see <code>aws-cdk-cli</code> PR <a href="https://github.com/aws/aws-cdk-cli/pull/112">#112</a>.</p></td> -</tr> -</tbody> -</table> -</div> -<div class="sect2"> -<h3 id="bootstrapping-template">11.8. Upgrade from legacy to modern bootstrap template</h3> -<div class="paragraph"> -<p>The AWS CDK v1 supported two bootstrapping templates, legacy and modern. CDK v2 supports only the modern template. For reference, here are the high-level differences between these two templates.</p> -</div> -<table class="tableblock frame-all grid-all stretch"> -<colgroup> -<col style="width: 33.3333%;"> -<col style="width: 33.3333%;"> -<col style="width: 33.3334%;"> -</colgroup> -<thead> -<tr> -<th class="tableblock halign-left valign-top">Feature</th> -<th class="tableblock halign-left valign-top">Legacy (v1 only)</th> -<th class="tableblock halign-left valign-top">Modern (v1 and v2)</th> -</tr> -</thead> -<tbody> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Cross-account deployments</strong></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Not allowed</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Allowed</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>AWS CloudFormation Permissions</strong></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Deploys using current user’s permissions (determined by AWS profile, environment variables, etc.)</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Deploys using the permissions specified when the bootstrap stack was provisioned (for example, by using <code>--trust</code>)</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Versioning</strong></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Only one version of bootstrap stack is available</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Bootstrap stack is versioned; new resources can be added in future versions, and AWS CDK apps can require a minimum version</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Resources</strong>*</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Amazon S3 bucket</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Amazon S3 bucket</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">AWS KMS key</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">IAM roles</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Amazon ECR repository</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Resource naming</strong></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Automatically generated</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Deterministic</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Bucket encryption</strong></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Default key</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">AWS managed key by default. You can customize to use a customer managed key.</p></td> -</tr> -</tbody> -</table> -<div class="ulist"> -<ul> -<li> -<p><em>We will add additional resources to the bootstrap template as needed.</em></p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>An environment that was bootstrapped using the legacy template must be upgraded to use the modern template for CDK v2 by re-bootstrapping. Re-deploy all AWS CDK applications in the environment at least once before deleting the legacy bucket.</p> -</div> -</div> -<div class="sect2"> -<h3 id="bootstrapping-securityhub">11.9. Address Security Hub Findings</h3> -<div class="paragraph"> -<p>If you are using AWS Security Hub, you may see findings reported on some of the resources created by the AWS CDK bootstrapping process. Security Hub findings help you find resource configurations you should double-check for accuracy and safety. We have reviewed these specific resource configurations with AWS Security and are confident they do not constitute a security problem.</p> -</div> -<div class="sect3"> -<h4 id="bootstrapping-securityhub-kms2">11.9.1. [KMS.2] IAM principals should not have IAM inline policies that allow decryption actions on all KMS keys</h4> -<div class="paragraph"> -<p>The <em>deploy role</em> (<code>DeploymentActionRole</code>) grants permission to read encrypted data, which is necessary for cross-account deployments with CDK Pipelines. Policies in this role do not grant permission to all data. It only grants permission to read encrypted data from Amazon S3 and AWS KMS, and only when those resources allow it through their bucket or key policy.</p> -</div> -<div class="paragraph"> -<p>The following is a snippet of these two statements in the <em>deploy role</em> from the bootstrap template:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-yaml" data-lang="yaml">DeploymentActionRole: - Type: AWS::IAM::Role - Properties: - ... - Policies: - - PolicyDocument: - Statement: - ... - - Sid: PipelineCrossAccountArtifactsBucket - Effect: Allow - Action: - - s3:GetObject* - - s3:GetBucket* - - s3:List* - - s3:Abort* - - s3:DeleteObject* - - s3:PutObject* - Resource: "*" - Condition: - StringNotEquals: - s3:ResourceAccount: - Ref: AWS::AccountId - - Sid: PipelineCrossAccountArtifactsKey - Effect: Allow - Action: - - kms:Decrypt - - kms:DescribeKey - - kms:Encrypt - - kms:ReEncrypt* - - kms:GenerateDataKey* - Resource: "*" - Condition: - StringEquals: - kms:ViaService: - Fn::Sub: s3.${AWS::Region}.amazonaws.com - ...</code></pre> -</div> -</div> -<div class="sect4"> -<h5 id="bootstrapping-securityhub-kms2-why">Why does Security Hub flag this?</h5> -<div class="paragraph"> -<p>The policies contain a <code>Resource: <strong></code> combined with a <code>Condition</code> clause. Security Hub flags the <code>\</strong></code> wildcard. This wildcard is used because at the time the account is bootstrapped, the AWS KMS key created by CDK Pipelines for the CodePipeline artifact bucket does not exist yet, and therefore, can’t be referenced on the bootstrap template by ARN. In addition, Security Hub does not consider the <code>Condition</code> clause when raising this flag. This <code>Condition</code> restricts <code>Resource: *</code> to requests made from the same AWS account of the AWS KMS key. These requests must come from Amazon S3 in the same AWS Region as the AWS KMS key.</p> -</div> -</div> -<div class="sect4"> -<h5 id="bootstrapping-securityhub-kms2-decide">Do I need to fix this finding?</h5> -<div class="paragraph"> -<p>As long as you have not modified the AWS KMS key on your bootstrap template to be overly permissive, the <em>deploy role</em> does not allow more access than it needs. Therefore, it is not necessary to fix this finding.</p> -</div> -</div> -<div class="sect4"> -<h5 id="bootstrapping-securityhub-kms2-fix">What if I want to fix this finding?</h5> -<div class="paragraph"> -<p>How you fix this finding depends on whether or not you will be using CDK Pipelines for cross-account deployments.</p> -</div> -<div class="olist arabic"> -<ol class="arabic"> -<li> -<p>If you have not done so, deploy the CDK bootstrap stack using the <code>cdk bootstrap</code> command.</p> -</li> -<li> -<p>If you have not done so, create and deploy your CDK <code class="noloc">Pipeline</code>. For instructions, see <a href="#cdk-pipeline">Continuous integration and delivery (CI/CD) using CDK Pipelines</a>.</p> -</li> -<li> -<p>Obtain the AWS KMS key ARN of the CodePipeline artifact bucket. This resource is created during pipeline creation.</p> -</li> -<li> -<p>Obtain a copy of the CDK bootstrap template to modify it. The following is an example, using the AWS CDK <code class="noloc">CLI</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk bootstrap --show-template > bootstrap-template.yaml</code></pre> -</div> -</div> -</li> -<li> -<p>Modify the template by replacing <code>Resource: *</code> of the <code>PipelineCrossAccountArtifactsKey</code> statement with your ARN value.</p> -</li> -<li> -<p>Deploy the template to update your bootstrap stack. The following is an example, using the CDK <code class="noloc">CLI</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk bootstrap aws://account-id/region --template bootstrap-template.yaml</code></pre> -</div> -</div> -</li> -<li> -<p>Obtain a copy of the CDK bootstrap template to modify it. The following is an example, using the CDK <code class="noloc">CLI</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk bootstrap --show-template > bootstrap-template.yaml</code></pre> -</div> -</div> -</li> -<li> -<p>Delete the <code>PipelineCrossAccountArtifactsBucket</code> and <code>PipelineCrossAccountArtifactsKey</code> statements from the template.</p> -</li> -<li> -<p>Deploy the template to update your bootstrap stack. The following is an example, using the CDK <code class="noloc">CLI</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk bootstrap aws://account-id/region --template bootstrap-template.yaml</code></pre> -</div> -</div> -</li> -</ol> -</div> -</div> -</div> -</div> -<div class="sect2"> -<h3 id="bootstrapping-env-considerations">11.10. Considerations</h3> -<div class="paragraph"> -<p>Since bootstrapping provisions resources in your environment, you may incur AWS charges when those resources are used with the AWS CDK.</p> -</div> -</div> -<div class="sect2 topic"> -<h3 id="bootstrapping-customizing">11.11. Customize AWS CDK bootstrapping</h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>You can customize AWS Cloud Development Kit (AWS CDK) bootstrapping by using the AWS CDK Command Line Interface (AWS CDK <code class="noloc">CLI</code>) or by modifying and deploying the AWS CloudFormation bootstrap template.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>You can customize AWS Cloud Development Kit (AWS CDK) bootstrapping by using the AWS CDK Command Line Interface (AWS CDK <code class="noloc">CLI</code>) or by modifying and deploying the AWS CloudFormation bootstrap template.</p> -</div> -<div class="paragraph"> -<p>For an introduction to bootstrapping, see <a href="#bootstrapping">AWS CDK bootstrapping</a>.</p> -</div> -<div class="paragraph topiclist"> -<p>[[Topic List]]</p> -</div> -<div class="sect3"> -<h4 id="bootstrapping-customizing-cli">11.11.1. Use the CDK <code class="noloc">CLI</code> to customize bootstrapping</h4> -<div class="paragraph"> -<p>The following are a few examples of how you can customize bootstrapping by using the CDK <code class="noloc">CLI</code>. For a list of all <code>cdk bootstrap</code> options, see <a href="#ref-cli-cmd-bootstrap">cdk bootstrap</a>.</p> -</div> -<div id="bootstrapping-customizing-cli-s3-name" class="dlist"> -<dl> -<dt class="hdlist1">Override the name of the Amazon S3 bucket</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Use the <code>--bootstrap-bucket-name</code> option to override the default Amazon S3 bucket name. This may require that you modify template synthesis. For more information, see <a href="#bootstrapping-custom-synth">Customize CDK stack synthesis</a>.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="bootstrapping-customizing-keys" class="dlist"> -<dl> -<dt class="hdlist1">Modify server-side encryption keys for the Amazon S3 bucket</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>By default, the Amazon S3 bucket in the bootstrap stack is configure to use AWS managed keys for server-side encryption. To use an existing customer managed key, use the <code>--bootstrap-kms-key-id</code> option and provide a value for the AWS Key Management Service (AWS KMS) key to use. If you want more control over the encryption key, provide <code>--bootstrap-customer-key</code> to use a customer managed key.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="bootstrapping-customizing-cli-deploy-role" class="dlist"> -<dl> -<dt class="hdlist1">Attach managed policies to the deployment role assumed by AWS CloudFormation</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>By default, stacks are deployed with full administrator permissions using the <code>AdministratorAccess</code> policy. To use your own managed policies, use the <code>--cloudformation-execution-policies</code> option and provide the ARNs of the managed policies to attach to the deployment role.</p> -<div class="paragraph"> -<p>To provide multiple policies, pass them a single string, separated by commas:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk bootstrap --cloudformation-execution-policies "arn:aws:iam::aws:policy/AWSLambda_FullAccess,arn:aws:iam::aws:policy/AWSCodeDeployFullAccess"</code></pre> -</div> -</div> -<div class="paragraph"> -<p>To avoid deployment failures, be sure that the policies you specify are sufficient for any deployments that you will perform into the environment being bootstrapped.</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="bootstrapping-customizing-cli-qualifier" class="dlist"> -<dl> -<dt class="hdlist1">Change the qualifier that is added to the names of resources in your bootstrap stack</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>By default, the <code>hnb659fds</code> qualifier is added to the physical ID of resources in your bootstrap stack. To change this value, use the <code>--qualifier</code> option.</p> -<div class="paragraph"> -<p>This modification is useful when provisioning multiple bootstrap stacks in the same environment to avoid name clashes.</p> -</div> -<div class="paragraph"> -<p>Changing the qualifier is intended for name isolation between automated tests of the CDK itself. Unless you can very precisely scope down the IAM permissions given to the CloudFormation execution role, there are no permission isolation benefits to having two different bootstrap stacks in a single account. Therefore, there’s usually no need to change this value.</p> -</div> -<div class="paragraph"> -<p>When you change the qualifier, your CDK app must pass the changed value to the stack synthesizer. For more information, see <a href="#bootstrapping-custom-synth">Customize CDK stack synthesis</a>.</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="bootstrapping-customizing-cli-tags" class="dlist"> -<dl> -<dt class="hdlist1">Add tags to the bootstrap stack</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Use the <code>--tags</code> option in the format of <code>KEY=VALUE</code> to add CloudFormation tags to your bootstrap stack.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="bootstrapping-customizing-cli-accounts-deploy" class="dlist"> -<dl> -<dt class="hdlist1">Specify additional AWS accounts that can deploy into the environment being bootstrapped</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Use the <code>--trust</code> option to provide additional AWS accounts that are allowed to deploy into the environment being bootstrapped. By default, the account performing the bootstrapping will always be trusted.</p> -<div class="paragraph"> -<p>This option is useful when you are bootstrapping an environment that a CDK <code class="noloc">Pipeline</code> from another environment will deploy into.</p> -</div> -<div class="paragraph"> -<p>When you use this option, you must also provide <code>--cloudformation-execution-policies</code>.</p> -</div> -<div class="paragraph"> -<p>To add trusted accounts to an existing bootstrap stack, you must specify all of the accounts to trust, including those that you may have previously provided. If you only provide new accounts to trust, the previously trusted accounts will be removed.</p> -</div> -<div class="paragraph"> -<p>The following is an example that trusts two accounts:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk bootstrap aws://123456789012/us-west-2 --trust 234567890123 --trust 987654321098 --cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess - ⏳ Bootstrapping environment aws://123456789012/us-west-2... -Trusted accounts for deployment: 234567890123, 987654321098 -Trusted accounts for lookup: (none) -Execution policies: arn:aws:iam::aws:policy/AdministratorAccess -CDKToolkit: creating CloudFormation changeset... - ✅ Environment aws://123456789012/us-west-2 bootstrapped.</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="bootstrapping-customizing-cli-accounts-lookup" class="dlist"> -<dl> -<dt class="hdlist1">Specify additional AWS accounts that can look up information in the environment being bootstrapped</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Use the <code>--trust-for-lookup</code> option to specify AWS accounts that are allowed to look up context information from the environment being bootstrapped. This option is useful to give accounts permission to synthesize stacks that will be deployed into the environment, without actually giving them permission to deploy those stacks directly.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="bootstrapping-customizing-cli-protection" class="dlist"> -<dl> -<dt class="hdlist1">Enable termination protection for the bootstrap stack</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>If a bootstrap stack is deleted, the AWS resources that were originally provisioned in the environment will also be deleted. After your environment is bootstrapped, we recommend that you don’t delete and recreate the environment’s bootstrap stack, unless you are intentionally doing so. Instead, try to update the bootstrap stack to a new version by running the <code>cdk bootstrap</code> command again.</p> -<div class="paragraph"> -<p>Use the <code>--termination-protection</code> option to manage termination protection settings for the bootstrap stack. By enabling termination protection, you prevent the bootstrap stack and its resources from being accidentally deleted. This is especially important if you use CDK <code class="noloc">Pipelines</code> since there is no general recovery option if you accidentally delete the bootstrap stack.</p> -</div> -<div class="paragraph"> -<p>After enabling termination protection, you can use the AWS CLI or AWS CloudFormation console to verify.</p> -</div> -<div class="olist loweralpha"> -<ol class="loweralpha" type="a"> -<li> -<p>Run the following command to enable termination protection on a new or existing bootstrap stack:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk bootstrap --termination-protection</code></pre> -</div> -</div> -</li> -<li> -<p>Use the AWS CLI or CloudFormation console to verify. The following is an example, using the AWS CLI. If you modified your bootstrap stack name, replace <code>CDKToolkit</code> with your stack name:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ aws cloudformation describe-stacks --stack-name CDKToolkit --query "Stacks[0].EnableTerminationProtection" -true</code></pre> -</div> -</div> -</li> -</ol> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect3"> -<h4 id="bootstrapping-customizing-template">11.11.2. Modify the default bootstrap template</h4> -<div class="paragraph"> -<p>When you need more customization than the CDK <code class="noloc">CLI</code> can provide, you can modify the bootstrap template as needed. Then, deploy the template to bootstrap your environment.</p> -</div> -<div class="olist arabic"> -<ol class="arabic"> -<li> -<p>Obtain the default bootstrap template using the <code>--show-template</code> option. By default, the CDK <code class="noloc">CLI</code> will output the template in your terminal window. You can modify the CDK <code class="noloc">CLI</code> command to save the template to your local machine. The following is an example:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk bootstrap --show-template > my-bootstrap-template.yaml</code></pre> -</div> -</div> -</li> -<li> -<p>Modify the bootstrap template as needed. Any changes that you make should adhere to the bootstrapping template contract. For more information on the bootstrapping template contract, see <a href="#bootstrapping-contract">Follow the bootstrap contract</a>.</p> -<div class="paragraph"> -<p>To ensure that your customizations are not accidentally overwritten later by someone running <code>cdk bootstrap</code> using the default template, change the default value of the <code>BootstrapVariant</code> template parameter. The CDK <code class="noloc">CLI</code> will only allow overwriting the bootstrap stack with templates that have the same <code>BootstrapVariant</code> and an equal or higher version than the template that is currently deployed.</p> -</div> -</li> -<li> -<p>Deploy your modified template using your preferred AWS CloudFormation deployment method. The following is an example that uses the CDK <code class="noloc">CLI</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk bootstrap --template my-bootstrap-template.yaml</code></pre> -</div> -</div> -</li> -</ol> -</div> -</div> -<div class="sect3"> -<h4 id="bootstrapping-contract">11.11.3. Follow the bootstrap contract</h4> -<div class="paragraph"> -<p>For your CDK apps to properly deploy, the CloudFormation templates produced during synthesis must correctly specify the resources created during bootstrapping. These resources are commonly referred to as <em>bootstrap resources</em>. Bootstrapping creates resources in your AWS environment that are used by the AWS CDK to perform deployments and manage application assets. Synthesis produces CloudFormation templates from each CDK stack in your application. These templates don’t just define the AWS resources that will be provisioned from your application. They also specify the bootstrap resources to use during deployment.</p> -</div> -<div class="paragraph"> -<p>During synthesis, the CDK <code class="noloc">CLI</code> doesn’t know specifically how your AWS environment has been bootstrapped. Instead, the CDK <code class="noloc">CLI</code> produces CloudFormation templates based on the synthesizer that you configure. Therefore, when you customize bootstrapping, you may need to customize synthesis. For instructions on customizing synthesis, see <a href="#bootstrapping-custom-synth">Customize CDK stack synthesis</a>. The purpose is to ensure that your synthesized CloudFormation templates are compatible with your bootstrapped environment. This compatibility is referred to as the <em>bootstrap contract</em>.</p> -</div> -<div class="paragraph"> -<p>The simplest method to customize stack synthesis is by modifying the <code>DefaultStackSynthesizer</code> class in your <code>Stack</code> instance. If you require customization beyond what this class can offer, you can write your own synthesizer as a class that implements <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.IStackSynthesizer.html">IStackSynthesizer</a></code> (perhaps deriving from <code>DefaultStackSynthesizer</code>).</p> -</div> -<div class="paragraph"> -<p>When you customize bootstrapping, follow the bootstrap template contract to remain compatible with <code>DefaultStackSynthesizer</code>. If you modify bootstrapping beyond the bootstrap template contract, you will need to write your own synthesizer.</p> -</div> -<div class="sect4"> -<h5 id="bootstrapping-contract-versioning">Versioning</h5> -<div class="paragraph"> -<p>The bootstrap template should contain a resource to create an Amazon EC2 Systems Manager (SSM) parameter with a well-known name and an output to reflect the template’s version:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-yaml" data-lang="yaml">Resources: - CdkBootstrapVersion: - Type: AWS::SSM::Parameter - Properties: - Type: String - Name: - Fn::Sub: '/cdk-bootstrap/${Qualifier}/version' - Value: 4 -Outputs: - BootstrapVersion: - Value: - Fn::GetAtt: [CdkBootstrapVersion, Value]</code></pre> -</div> -</div> -</div> -<div class="sect4"> -<h5 id="bootstrapping-contract-roles">Roles</h5> -<div class="paragraph"> -<p>The <code>DefaultStackSynthesizer</code> requires five IAM roles for five different purposes. If you are not using the default roles, you must specify your IAM role ARNs within your <code>DefaultStackSynthesizer</code> object. The roles are as follows:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>The <em>deployment role</em> is assumed by the CDK <code class="noloc">CLI</code> and by AWS CodePipeline to deploy into an environment. Its <code>AssumeRolePolicy</code> controls who can deploy into the environment. In the template, you can see the permissions that this role needs.</p> -</li> -<li> -<p>The <em>lookup role</em> is assumed by the CDK <code class="noloc">CLI</code> to perform context lookups in an environment. Its <code>AssumeRolePolicy</code> controls who can deploy into the environment. The permissions this role needs can be seen in the template.</p> -</li> -<li> -<p>The <em>file publishing role</em> and the <em>image publishing role</em> are assumed by the CDK <code class="noloc">CLI</code> and by AWS CodeBuild projects to publish assets into an environment. They’re used to write to the Amazon S3 bucket and the Amazon ECR repository, respectively. These roles require write access to these resources.</p> -</li> -<li> -<p><em>The AWS CloudFormation execution role</em> is passed to AWS CloudFormation to perform the actual deployment. Its permissions are the permissions that the deployment will execute under. The permissions are passed to the stack as a parameter that lists managed policy ARNs.</p> -</li> -</ul> -</div> -</div> -<div class="sect4"> -<h5 id="bootstrapping-contract-outputs">Outputs</h5> -<div class="paragraph"> -<p>The CDK <code class="noloc">CLI</code> requires that the following CloudFormation outputs exist on the bootstrap stack:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><code>BucketName</code> – The name of the file asset bucket.</p> -</li> -<li> -<p><code>BucketDomainName</code> – The file asset bucket in domain name format.</p> -</li> -<li> -<p><code>BootstrapVersion</code> – The current version of the bootstrap stack.</p> -</li> -</ul> -</div> -</div> -<div class="sect4"> -<h5 id="bootstrapping-contract-history">Template history</h5> -<div class="paragraph"> -<p>The bootstrap template is versioned and evolves over time with the AWS CDK itself. If you provide your own bootstrap template, keep it up to date with the canonical default template. You want to make sure that your template continues to work with all CDK features. For more information, see <a href="#bootstrap-template-history">Bootstrap template version history</a>.</p> -</div> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="customize-permissions-boundaries">11.12. Create and apply permissions boundaries for the AWS CDK</h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>A <em>permissions boundary</em> is an AWS Identity and Access Management (IAM) advanced feature that you can use to set the maximum permissions that an IAM entity, such as a user or role, can have. You can use permissions boundaries to restrict the actions that IAM entities can perform when using the AWS Cloud Development Kit (AWS CDK).</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>A <em>permissions boundary</em> is an AWS Identity and Access Management (IAM) advanced feature that you can use to set the maximum permissions that an IAM entity, such as a user or role, can have. You can use permissions boundaries to restrict the actions that IAM entities can perform when using the AWS Cloud Development Kit (AWS CDK).</p> -</div> -<div class="paragraph"> -<p>To learn more about permissions boundaries, see <a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html">Permissions boundaries for IAM entities</a> in the <em>IAM User Guide</em>.</p> -</div> -<div class="sect3"> -<h4 id="customize-permissions-boundaries-when">11.12.1. When to use permissions boundaries with the AWS CDK</h4> -<div class="paragraph"> -<p>Consider applying permissions boundaries when you need to restrict developers in your organization from performing certain actions with the AWS CDK. For example, if there are specific resources in your AWS environment that you don’t want developers to modify, you can create and apply a permissions boundary.</p> -</div> -</div> -<div class="sect3"> -<h4 id="customize-permissions-boundaries-how">11.12.2. How to apply permissions boundaries with the AWS CDK</h4> -<div class="sect4"> -<h5 id="customize-permissions-boundaries-how-create">Create the permissions boundary</h5> -<div class="paragraph"> -<p>First, you create the permissions boundary, using an AWS managed policy or a customer managed policy to set the boundary for an IAM entity (user or role). This policy limits the maximum permissions for the user or role. For instructions on creating permissions boundaries, see <a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html">Permissions boundaries for IAM entities</a> in the <em>IAM User Guide</em>.</p> -</div> -<div class="paragraph"> -<p>Permissions boundaries set the maximum permissions that an IAM entity can have, but don’t grant permissions on their own. You must use permissions boundaries with IAM policies to effectively limit and grant the proper permissions for your organization. You must also prevent IAM entities from being able to escape the boundaries that you set. For an example, see <a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html#access_policies_boundaries-delegate">Delegating responsibility to others using permissions boundaries</a> in the <em>IAM User Guide</em>.</p> -</div> -</div> -<div class="sect4"> -<h5 id="customize-permissions-boundaries-how-apply">Apply the permissions boundary during bootstrapping</h5> -<div class="paragraph"> -<p>After creating the permissions boundary, you can enforce it for the AWS CDK by applying it during bootstrapping.</p> -</div> -<div class="paragraph"> -<p>Use the <code><a href="#ref-cli-cmd-bootstrap-options-custom-permissions-boundary">--custom-permissions-boundary</a></code> option and specify the name of the permissions boundary to apply. The following is an example that applies a permissions boundary named <code>cdk-permissions-boundary</code>:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk bootstrap --custom-permissions-boundary cdk-permissions-boundary</code></pre> -</div> -</div> -<div class="paragraph"> -<p>By default, the CDK uses the <code>CloudFormationExecutionRole</code> IAM role, defined in the bootstrap template, to receive permissions for performing deployments. By applying the custom permissions boundary during bootstrapping, the permissions boundary gets attached to this role. The permissions boundary will then set the maximum permissions that can be performed by developers in your organization when using the AWS CDK. To learn more about this role, see <a href="#bootstrapping-env-roles">IAM roles created during bootstrapping</a>.</p> -</div> -<div class="paragraph"> -<p>When you apply permissions boundaries in this way, they are applied to the specific environment that you bootstrap. To use the same permissions boundary across multiple environments, you must apply the permissions boundary for each environment during bootstrapping. You can also apply different permissions boundaries for different environments.</p> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="customize-permissions-boundaries-learn">11.12.3. Learn more</h4> -<div class="paragraph"> -<p>For more information on permissions boundaries, see <a href="https://aws.amazon.com/blogs/security/when-and-where-to-use-iam-permissions-boundaries/">When and where to use IAM permissions boundaries</a> in the <em>AWS Security Blog</em>.</p> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="bootstrapping-troubleshoot">11.13. Troubleshoot AWS CDK bootstrapping issues</h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Troubleshoot common issues when bootstrapping your environment with the AWS Cloud Development Kit (AWS CDK).</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>Troubleshoot common issues when bootstrapping your environment with the AWS Cloud Development Kit (AWS CDK).</p> -</div> -<div class="paragraph"> -<p>For an introduction to bootstrapping, see <a href="#bootstrapping">AWS CDK bootstrapping</a>.</p> -</div> -<div class="paragraph"> -<p>For instructions on bootstrapping, see <a href="#bootstrapping-env">Bootstrap your environment for use with the AWS CDK</a>.</p> -</div> -<div class="sect3"> -<h4 id="bootstrapping-troubleshoot-s3-bucket-name">11.13.1. When bootstrapping using the default template, you get a 'CREATE_FAILED' error for the Amazon S3 bucket</h4> -<div class="paragraph"> -<p>When bootstrapping using the AWS CDK Command Line Interface (CDK <code class="noloc">CLI</code>) <code>cdk bootstrap</code> command with the default bootstrap template, you receive the following error:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">CREATE_FAILED | AWS::S3::Bucket | BucketName already exists</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Before troubleshooting, ensure that you are using the latest version of the CDK <code class="noloc">CLI</code>.</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>To check your version, run <code>cdk --version</code>.</p> -</li> -<li> -<p>To install the latest version, run <code>npm install -g aws-cdk</code>.</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>After installing the latest version, try bootstrapping your environment again. If you still receive the same error, continue with troubleshooting.</p> -</div> -<div class="sect4"> -<h5 id="bootstrapping-troubleshoot-s3-bucket-name-causes">Common causes</h5> -<div class="paragraph"> -<p>When you bootstrap your environment, the AWS CDK generates physical IDs for your bootstrap resources. For more information, see <a href="#bootstrapping-env-default-id">Resource IDs created during bootstrapping</a>.</p> -</div> -<div class="paragraph"> -<p>Unlike the other bootstrap resources, Amazon S3 bucket names are global. This means that each bucket name must be unique across all AWS accounts in all AWS Regions within a partition. For more information, see <a href="https://docs.aws.amazon.com/AmazonS3/latest/userguide/UsingBucket.html">Buckets overview</a> in the <em>Amazon S3 User Guide</em>. Therefore, the most common cause of this error is that the physical ID generated as your bucket name already exists somewhere within the partition. This could be within your account or another account.</p> -</div> -<div class="paragraph"> -<p>The following is an example bucket name: <code>cdk-hnb659fds-assets-012345678910-us-west-1</code>. While unlikely, due to the qualifier and account ID being a part of the name, it is possible that this name for an Amazon S3 bucket is used by another AWS account. Since bucket names are globally scoped, it can’t be used by you if its used by a different account in the same partition. Most likely, a bucket with the same name exists somewhere in your account. This could be in the Region you are attempting to bootstrap, or another Region.</p> -</div> -<div class="paragraph"> -<p>Generally, the resolution is to locate this bucket in your account and determine what to do with it, or customize bootstrapping to create bootstrap resources of a different name.</p> -</div> -</div> -<div class="sect4"> -<h5 id="bootstrapping-troubleshoot-s3-bucket-name-resolution">Resolution</h5> -<div class="paragraph"> -<p>First, determine if a bucket with the same name exists within your AWS account. Using an AWS identity with valid permissions to lookup Amazon S3 buckets in your account, you can do this in the following ways:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Use the AWS Command Line Interface (AWS CLI) <code>aws s3 ls</code> command to view a list of all your buckets.</p> -</li> -<li> -<p>Look up bucket names for each Region in your account using the <a href="https://console.aws.amazon.com/s3">Amazon S3 console</a>.</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>If a bucket with the same name exists, determine if it’s being used. If it’s not being used, consider deleting the bucket and attempting to bootstrap your environment again.</p> -</div> -<div class="paragraph"> -<p>If a bucket with the same name exists and you don’t want to delete it, determine if it’s already associated with a bootstrap stack in your account. You may have to check multiple Regions. The Region in the Amazon S3 bucket name doesn’t necessarily mean that the bucket is in that Region. To check if it’s associated with the <code>CDKToolkit</code> bootstrap stack, you can do either of the following for each Region:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Use the AWS CLI <code>aws cloudformation describe-stack-resources --stack-name <code class="replaceable">CDKToolkit</code> --region <code class="replaceable">Region</code></code> command to view the resources in your bootstrap stack and check if the bucket is listed.</p> -</li> -<li> -<p>In the <a href="https://console.aws.amazon.com/cloudformation">AWS CloudFormation console</a>, locate the <code>CDKToolkit</code> stack. Then, on the <strong>Resources</strong> tab, check if the bucket exists.</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>If the bucket is associated with a bootstrap stack, determine if the bootstrap stack is in the same Region that you are attempting to bootstrap. If it is, your environment is already bootstrapped and you should be able to start using the CDK to deploy applications into your environment. If the Amazon S3 bucket is associated with a bootstrap stack in a different Region, you’ll need to determine what to do. Possible resolutions include renaming the existing Amazon S3 bucket, deleting the current Amazon S3 bucket if its not being used, or using a new name for the Amazon S3 bucket you are attempting to create.</p> -</div> -<div class="paragraph"> -<p>If you are unable to locate an Amazon S3 bucket with the same name in your account, it may exist in a different account. To resolve this, you’ll need to customize bootstrapping to create new names for all of your bootstrap resources or for just your Amazon S3 bucket. To create new names for all bootstrap resources, you can modify the qualifier. To create a new name for only your Amazon S3 bucket, you can provide a new bucket name.</p> -</div> -<div class="paragraph"> -<p>To customize bootstrapping, you can use options with the CDK <code class="noloc">CLI</code><code>cdk bootstrap</code> command or by modifying the bootstrap template. For instructions, see <a href="#bootstrapping-customizing">Customize AWS CDK bootstrapping</a>.</p> -</div> -<div class="paragraph"> -<p>If you customize bootstrapping, you will need to apply the same changes to synthesis before you can properly deploy an application. For instructions, see <a href="#bootstrapping-custom-synth">Customize CDK stack synthesis</a>.</p> -</div> -<div class="paragraph"> -<p>For example, you can provide a new qualifier with <code>cdk bootstrap</code>:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ cdk bootstrap --qualifier abcde0123</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The following is an example Amazon S3 bucket name that will be created with this modification: <code>cdk-abcde0123-assets-012345678910-us-west-1</code>. All bootstrap resources created during bootstrapping will use this qualifier.</p> -</div> -<div class="paragraph"> -<p>When developing your CDK app, you must specify your custom qualifier in your synthesizer. This helps the CDK with identifying your bootstrap resources during synthesis and deployment. The following is an example of customizing the default synthesizer for your stack instance:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">new MyStack(this, 'MyStack', { - synthesizer: new DefaultStackSynthesizer({ - qualifier: 'abcde0123', - }), -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">new MyStack(this, 'MyStack', { - synthesizer: new DefaultStackSynthesizer({ - qualifier: 'abcde0123', - }), -})</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">MyStack(self, "MyStack", - synthesizer=DefaultStackSynthesizer( - qualifier="abcde0123" -))</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">new MyStack(app, "MyStack", StackProps.builder() - .synthesizer(DefaultStackSynthesizer.Builder.create() - .qualifier("abcde0123") - .build()) - .build();</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">new MyStack(app, "MyStack", new StackProps -{ - Synthesizer = new DefaultStackSynthesizer(new DefaultStackSynthesizerProps - { - Qualifier = "abcde0123" - }) -});</code></pre> -</div> -</div> -</dd> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">func NewMyStack(scope constructs.Construct, id string, props *MyStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - stack := awscdk.NewStack(scope, &id, &sprops) - - synth := awscdk.NewDefaultStackSynthesizer(&awscdk.DefaultStackSynthesizerProps{ - Qualifier: jsii.String("abcde0123"), - }) - - stack.SetSynthesizer(synth) - - return stack -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>You can also specify the new qualifier in the <code class="path">cdk.json</code> file of your CDK project:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-json" data-lang="json">{ - "app": "...", - "context": { - "@aws-cdk/core:bootstrapQualifier": "abcde0123" - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>To modify only the Amazon S3 bucket name, you can use the <code><a href="#ref-cli-cmd-bootstrap-options-bootstrap-bucket-name">--bootstrap-bucket-name</a></code> option. The following is an example:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ cdk bootstrap --bootstrap-bucket-name 'my-new-bucket-name'</code></pre> -</div> -</div> -<div class="paragraph"> -<p>When developing your CDK app, you must specify your new bucket name in your synthesizer. The following is an example of customizing the default synthesizer for your stack instance:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">new MyStack(this, 'MyStack', { - synthesizer: new DefaultStackSynthesizer({ - fileAssetsBucketName: 'my-new-bucket-name', - }), -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">new MyStack(this, 'MyStack', { - synthesizer: new DefaultStackSynthesizer({ - fileAssetsBucketName: 'my-new-bucket-name', - }), -})</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">MyStack(self, "MyStack", - synthesizer=DefaultStackSynthesizer( - file_assets_bucket_name='my-new-bucket-name' -))</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">new MyStack(app, "MyStack", StackProps.builder() - .synthesizer(DefaultStackSynthesizer.Builder.create() - .fileAssetsBucketName("my-new-bucket-name") - .build()) - .build();</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">new MyStack(app, "MyStack", new StackProps -{ - Synthesizer = new DefaultStackSynthesizer(new DefaultStackSynthesizerProps - { - FileAssetsBucketName = "my-new-bucket-name" - }) -});</code></pre> -</div> -</div> -</dd> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">func NewMyStack(scope constructs.Construct, id string, props *MyStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - stack := awscdk.NewStack(scope, &id, &sprops) - - synth := awscdk.NewDefaultStackSynthesizer(&awscdk.DefaultStackSynthesizerProps{ - FileAssetsBucketName: jsii.String("my-new-bucket-name"), - }) - - stack.SetSynthesizer(synth) - - return stack -}</code></pre> -</div> -</div> -</div> -<div class="sect4"> -<h5 id="bootstrapping-troubleshoot-s3-bucket-name-prevention">Prevention</h5> -<div class="paragraph"> -<p>We recommend that you proactively bootstrap each AWS environment that you plan to use. For more information, see <a href="#bootstrapping-env-when">When to bootstrap your environment</a>. Specifically for the Amazon S3 bucket naming issue, this will create Amazon S3 buckets in each AWS environment and prevent others from using your Amazon S3 bucket name.</p> -</div> -</div> -</div> -</div> -</div> -</div> -<div class="sect1 topic"> -<h2 id="develop">12. Develop AWS CDK applications</h2> -<div class="sectionbody"> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Manage your infrastructure on AWS by developing applications using the AWS Cloud Development Kit (AWS CDK).</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>Manage your infrastructure on AWS by developing applications using the AWS Cloud Development Kit (AWS CDK).</p> -</div> -<div class="sect2"> -<h3 id="develop-prerequisites">12.1. Prerequisites</h3> -<div class="paragraph"> -<p>Before you can start developing applications, complete all set up steps in <a href="#getting-started">Getting started with the AWS CDK</a>.</p> -</div> -</div> -<div class="sect2"> -<h3 id="develop-overview">12.2. Developing AWS CDK applications overview</h3> -<div class="paragraph"> -<p>At a high-level, developing CDK applications involves the following steps:</p> -</div> -<div class="olist arabic"> -<ol class="arabic"> -<li> -<p><strong>Create a CDK project</strong> – A CDK <a href="#projects">project</a> consists of the files and folders that store and organize your CDK code.</p> -</li> -<li> -<p><strong>Create a CDK app</strong> – Within a CDK project, you use the <code>App</code> construct to define a CDK <a href="#apps">application</a>.</p> -</li> -<li> -<p><strong>Create a CDK stack</strong> – Within the scope of your CDK app, you define one or more CDK <a href="#stacks">stacks</a>.</p> -</li> -<li> -<p><strong>Define your infrastructure</strong> – Within the scope of a CDK stack, you use <a href="#constructs">constructs</a> from the AWS Construct Library to define the AWS resources and properties that will become your infrastructure. Using a general-purpose programming <a href="#languages">language</a> of your choice, you can use logic, such as conditional statements and loops, to define your infrastructure based on certain conditions.</p> -</li> -</ol> -</div> -</div> -<div class="sect2"> -<h3 id="develop-gs">12.3. Get started with developing CDK applications</h3> -<div class="paragraph"> -<p>To get started, you can use the AWS CDK Command Line Interface (AWS CDK <code class="noloc">CLI</code>) <code>cdk init</code> command. Provide the <code>--language</code> option to specify the programming language to use. This command creates a starting CDK project and imports the main AWS Construct Library and core modules.</p> -</div> -</div> -<div class="sect2"> -<h3 id="develop-library">12.4. Import and use the AWS CDK Library</h3> -<div class="paragraph"> -<p>After you create a CDK project, import and use constructs from the AWS CDK Library to begin defining your infrastructure. For instructions, see <a href="#work-with">Work with the AWS CDK library</a>.</p> -</div> -</div> -<div class="sect2"> -<h3 id="develop-next">12.5. Next steps</h3> -<div class="paragraph"> -<p>When ready to deploy your application, use the CDK <code class="noloc">CLI</code><code>cdk deploy</code> command. For instructions, see <a href="#deploy">Deploy AWS CDK applications</a>.</p> -</div> -</div> -<div class="sect2 topic"> -<h3 id="usage-data">12.6. Configure AWS CDK usage data reporting</h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>The AWS Cloud Development Kit (AWS CDK) collects usage data from your CDK applications to gain insight into how the AWS CDK is being used. The CDK team uses this data to do the following:</p> -</div> -</blockquote> -</div> -<div class="sect3"> -<h4 id="usage-data-intro">12.6.1. What is CDK usage data reporting?</h4> -<div class="paragraph"> -<p>AWS Cloud Development Kit (AWS CDK) applications are configured to collect and report on usage data to gain insight into how the AWS CDK is being used. The CDK team uses this data to do the following:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><strong>Communicate with customers</strong> – Identify stacks using a construct with known security or reliability issues and send out communication on customer-impacting topics.</p> -</li> -<li> -<p><strong>Inform CDK development</strong> – Gain insight on CDK usage to better inform CDK development.</p> -</li> -<li> -<p><strong>Investigate CDK issues</strong> – When bugs are reported, usage data provides valuable insight to the CDK team when troubleshooting.</p> -</li> -</ul> -</div> -</div> -<div class="sect3"> -<h4 id="usage-data-categories">12.6.2. What usage data is collected?</h4> -<div class="paragraph"> -<p>There are two categories of usage data collected by the CDK:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>General usage data</p> -</li> -<li> -<p>Additional usage data</p> -</li> -</ul> -</div> -<div class="sect4"> -<h5 id="usage-data-categories-general">General usage data collection</h5> -<div class="paragraph"> -<p>The CDK collects the following types of general usage data from your CDK applications:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Versions of CDK libraries used.</p> -</li> -<li> -<p>Names of constructs used from the following <code>NPM</code> modules:</p> -<div class="ulist"> -<ul> -<li> -<p>AWS CDK core modules</p> -</li> -<li> -<p>AWS Construct Library modules</p> -</li> -<li> -<p>AWS Solutions Constructs module</p> -</li> -<li> -<p>AWS Render Farm Deployment Kit module</p> -</li> -</ul> -</div> -</li> -</ul> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>Before version 1.93.0, the AWS CDK reported the names and versions of the modules loaded during synthesis, instead of the constructs used in the stack.</p> -</div> -</td> -</tr> -</table> -</div> -</div> -<div class="sect4"> -<h5 id="usage-data-categories-additional">Additional usage data collection</h5> -<div class="paragraph"> -<p>Starting with CDK version 2.178.0, usage data collection expanded to include the following additional usage data:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><strong>CDK–defined property keys</strong> – When you use a built-in property of an L2 construct, the property key will be collected. This includes built-in property keys nested in dictionary objects.</p> -</li> -<li> -<p><strong>Boolean and enum property values from CDK–defined property keys</strong> – For CDK–defined property keys, property values of only Boolean and enum types will be collected. All other types, such as string values or construct references will be redacted.</p> -</li> -<li> -<p><strong>Method name, keys, and property values of Boolean and enum types</strong> – When you use an L2 construct method, we will collect the method name, property keys, and property values of Boolean and enum types.</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>For property keys and values that you uniquely create, the entire object will be redacted. For example, if you use <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_apigateway.InlineApiDefinition.html">InlineApiDefinition</a></code> to define an <code class="noloc">OpenAPI</code> specification and pass it into a <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_apigateway.RestApi.html">RestApi</a></code> construct, the entire <code>InlineApiDefinition</code> object will be redacted.</p> -</div> -<div class="paragraph"> -<p>For more information on additional usage data collection, including its benefits and potential concerns, see the <a href="https://github.com/aws/aws-cdk/discussions/33198">CDK Collecting Additional Metadata (under feature flag) #33198</a> discussion in the <em>aws-cdk repository</em>.</p> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="usage-data-how">12.6.3. How the CDK collects usage data</h4> -<div class="paragraph"> -<p>At synthesis, the CDK collects usage data from your application and stores it within the <code>AWS::CDK::Metadata</code> resource. The following is an example of this on a synthesized AWS CloudFormation template:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-yaml" data-lang="yaml">CDKMetadata: - Type: "AWS::CDK::Metadata" - Properties: - Analytics: "v2:deflate64:H4sIAND9SGAAAzXKSw5AMBAA0L1b2PdzBYnEAdio3RglglY60zQi7u6TWL/XKmNUlxeQSOKwaPTBqrNhwEWU3hGHiCzK0dWWfAxoL/Fd8mvk+QkS/0X6BdjnCdgmOOQKWz+AqqLDt2Y3YMnLYWwAAAA="</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The <code>Analytics</code> property is a gzipped, base64-encoded, prefix-encoded list of the constructs in the stack.</p> -</div> -</div> -<div class="sect3"> -<h4 id="usage-data-configure">12.6.4. How to opt out or opt in to usage data reporting</h4> -<div class="paragraph"> -<p>Your options to opt out or opt in to general usage data reporting and additional usage data reporting depends on the CDK version you used to originally create your app.</p> -</div> -<div class="paragraph"> -<p>By default, CDK applications are configured to automatically opt in to usage data reporting as follows:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><strong>All CDK apps</strong> – Opted in to general usage data reporting.</p> -</li> -<li> -<p><strong>CDK apps created with a version older than v2.178.0</strong> – Not automatically opted in to additional usage data reporting.</p> -</li> -<li> -<p><strong>CDK apps created with v2.178.0 or newer</strong> – Opted in to additional usage data reporting.</p> -</li> -</ul> -</div> -<div class="admonitionblock warning"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-warning" title="Warning"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>If you choose to opt out, the CDK will not be able to identify if you’ve been impacted by security issues and will not send you notifications for them.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="sect4"> -<h5 id="usage-data-configure-optout-all">Opt out of all usage data reporting</h5> -<div class="paragraph"> -<p>To opt out of all usage data reporting, you can use the AWS Cloud Development Kit (AWS CDK) Command Line Interface (<code class="noloc">CLI</code>) or configure your project’s <code class="path">cdk.json</code> file.</p> -</div> -<div class="olist arabic"> -<ol class="arabic"> -<li> -<p>Use the <code>--no-version-reporting</code> option with any CDK <code class="noloc">CLI</code> command to opt out for a single command. The following is an example of opting out during template synthesis:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ cdk synth --no-version-reporting</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Since the CDK synthesizes templates automatically when you run <code>cdk deploy</code>, you should also use <code>--no-version-reporting</code> with the <code>cdk deploy</code> command.</p> -</div> -</li> -<li> -<p>Set <code>versionReporting</code> to <code>false</code> in <code class="path">./cdk.json</code> or <code class="path">~/.cdk.json</code>. This opts you out by default. The following is an example:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-json" data-lang="json">{ - "app": "...", - "versionReporting": false -}</code></pre> -</div> -</div> -</li> -<li> -<p>After configuring, you can override this behavior and opt in by specifying <code>--version-reporting</code> on an individual command.</p> -</li> -</ol> -</div> -</div> -<div class="sect4"> -<h5 id="usage-data-configure-optout-additional">Opt out of only the additional usage data reporting</h5> -<div class="paragraph"> -<p>If your CDK app was created with a CDK version older than 2.178.0, you are automatically opted out of additional usage data reporting, even if you are opted in to general usage data reporting. You don’t have to do anything to opt out of additional usage data reporting.</p> -</div> -<div class="paragraph"> -<p>If your CDK app was created with CDK version 2.178.0 or newer, you must opt out of all usage data reporting. You can’t opt out of only the additional usage data reporting.</p> -</div> -</div> -<div class="sect4"> -<h5 id="usage-data-configure-optin">Opt in to usage data reporting</h5> -<div class="paragraph"> -<p>If your CDK app was created with CDK version 2.178.0 or newer, you can opt in to all usage data reporting by setting <code>versionReporting</code> to <code>true</code>. This is the default behavior of CDK apps.</p> -</div> -<div class="paragraph"> -<p>If your CDK app was created with a CDK version older than 2.178.0, you can opt in to general usage data reporting by setting <code>versionReporting</code> to <code>true</code>. To opt in to additional usage data reporting, you must enable a feature flag.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -These steps are for CDK apps originally created with a version older than 2.178.0 -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="olist arabic"> -<ol class="arabic"> -<li> -<p>Verify that you are now using CDK version 2.178.0 or newer.</p> -</li> -<li> -<p>In your CDK configuration file, specify <code>@aws-cdk/core:enableAdditionalMetadataCollection</code> as <code>true</code>. The following is an example:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-json" data-lang="json">{ - "context": { - "@aws-cdk/core:enableAdditionalMetadataCollection": "true" - } -}</code></pre> -</div> -</div> -</li> -<li> -<p>You can also use the <code>ENABLE_ADDITIONAL_METADATA_COLLECTION</code> value with the <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.FeatureFlags.html">FeatureFlags</a></code> class. The following is an example:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as cdk from 'aws-cdk-lib'; -import { FeatureFlags } from 'aws-cdk-lib'; -import * as cx_api from 'aws-cdk-lib/cx-api'; -import { Construct } from 'constructs'; - -export class MyStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - // Set the feature flag ENABLE_ADDITIONAL_METADATA_COLLECTION to true - FeatureFlags.of(this).add(cx_api.ENABLE_ADDITIONAL_METADATA_COLLECTION, true); - - // Your stack resources go here - new cdk.aws_s3.Bucket(this, 'MyBucket'); - } -} - -const app = new cdk.App(); -new MyStack(app, 'MyStack');</code></pre> -</div> -</div> -</li> -</ol> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="usage-data-examples">12.6.5. Examples</h4> -<div class="sect4"> -<h5 id="usage-data-examples-example1">General and additional usage data collected from a CDK application</h5> -<div class="paragraph"> -<p>The following is an example of a CDK app:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as cdk from 'aws-cdk-lib'; -import { Construct } from 'constructs'; -import * as s3 from 'aws-cdk-lib/aws-s3'; - -class MyStack extends cdk.Stack { - constructor(scope, id, props) { - super(scope, id, props); - - // Create an S3 bucket (L2 construct) - const myBucket = new s3.Bucket(this, 'MyBucket', { - bucketName: 'my-cdk-example-bucket', // String type - versioned: true, // Boolean type - removalPolicy: cdk.RemovalPolicy.DESTROY, // ENUM type - lifecycleRules: [{ // Array of object type - expirationDate: new Date('2019-10-01'), - objectSizeLessThan: 600, - objectSizeGreaterThan: 500, - }], - }); - - // Use a method of the L2 construct to define additional properties - myBucket.addLifecycleRule({ - id: 'ExpireOldObjects', - enabled: true, // Boolean - expiration: cdk.Duration.days(90), // Expire objects after 90 days - }); - } -} - -// Define the CDK app and stack -const app = new cdk.App(); -new MyStack(app, 'MyStack'); -app.synth();</code></pre> -</div> -</div> -<div class="paragraph"> -<p>At synthesis, usage data is collected, compressed, and stored in the <code>AWS::CDK::Metadata</code> resource.</p> -</div> -<div class="paragraph"> -<p>The following is an example of general usage data collected with a CDK version older than 2.178.0:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-json" data-lang="json">{ - "fqn": "aws-cdk-lib.aws-s3.Bucket", - "version": "v2.170.0" -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The following is an example of usage data collected, including the additional usage data introduced in CDK version 2.178.0:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-json" data-lang="json">{ - "fqn": "aws-cdk-lib.aws_s3.Bucket", - "version": "2.170.0", - "metadata": [ - { - "type": "aws:cdk:analytics:construct", - "data": { - "bucketName": "*", - "versioned": true, - "removalPolicy": "cdk.RemovalPolicy.DESTROY", - "lifecycleRules": [ - { - "expirationDate": "*", - "objectSizeLessThan": "*", - "objectSizeGreaterThan": "*" - } - ] - } - }, - { - "type": "aws:cdk:analytics:method", - "data": { - "name": "addLifecycleRule", - "prop": { - "id": "*", - "enabled": true, - "expiration": "*", - } - } - } - ] -}</code></pre> -</div> -</div> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="cfn-layer">12.7. Customize constructs from the AWS Construct Library</h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Customize constructs from the AWS Construct Library through escape hatches, raw overrides, and custom resources.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>Customize constructs from the AWS Construct Library through escape hatches, raw overrides, and custom resources.</p> -</div> -<div class="paragraph topiclist"> -<p>[[Topic List]]</p> -</div> -<div class="sect3"> -<h4 id="develop-customize-escape">12.7.1. Use escape hatches</h4> -<div class="paragraph"> -<p>The AWS Construct Library provides <a href="#constructs">constructs</a> of varying levels of abstraction.</p> -</div> -<div class="paragraph"> -<p>At the highest level, your AWS CDK application and the stacks in it are themselves abstractions of your entire cloud infrastructure, or significant chunks of it. They can be parameterized to deploy them in different environments or for different needs.</p> -</div> -<div class="paragraph"> -<p>Abstractions are powerful tools for designing and implementing cloud applications. The AWS CDK gives you the power not only to build with its abstractions, but also to create new abstractions. Using the existing open-source L2 and L3 constructs as guidance, you can build your own L2 and L3 constructs to reflect your own organization’s best practices and opinions.</p> -</div> -<div class="paragraph"> -<p>No abstraction is perfect, and even good abstractions cannot cover every possible use case. During development, you may find a construct that almost fits your needs, requiring a small or large customization.</p> -</div> -<div class="paragraph"> -<p>For this reason, the AWS CDK provides ways to <em>break out</em> of the construct model. This includes moving to a lower-level abstraction or to a different model entirely. Escape hatches let you <em>escape</em> the AWS CDK paradigm and customize it in ways that suit your needs. Then, you can wrap your changes in a new construct to abstract away the underlying complexity and provide a clean API for other developers.</p> -</div> -<div class="paragraph"> -<p>The following are examples of situations where you can use escape hatches:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>An AWS service feature is available through AWS CloudFormation, but there are no L2 constructs for it.</p> -</li> -<li> -<p>An AWS service feature is available through AWS CloudFormation, and there are L2 constructs for the service, but these don’t yet expose the feature. Because L2 constructs are curated by the CDK team, they may not be immediately available for new features.</p> -</li> -<li> -<p>The feature is not yet available through AWS CloudFormation at all.</p> -<div class="paragraph"> -<p>To determine whether a feature is available through AWS CloudFormation, see <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html">AWS Resource and Property Types Reference</a>.</p> -</div> -</li> -</ul> -</div> -<div class="sect4"> -<h5 id="develop-customize-escape-l1">Develop escape hatches for L1 constructs</h5> -<div class="paragraph"> -<p>If L2 constructs are not available for the service, you can use the automatically generated L1 constructs. These resources can be recognized by their name starting with <code>Cfn</code>, such as <code>CfnBucket</code> or <code>CfnRole</code>. You instantiate them exactly as you would use the equivalent AWS CloudFormation resource.</p> -</div> -<div class="paragraph"> -<p>For example, to instantiate a low-level Amazon S3 bucket L1 with analytics enabled, you would write something like the following.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">new s3.CfnBucket(this, 'amzn-s3-demo-bucket', { - analyticsConfigurations: [ - { - id: 'Config', - // ... - } - ] -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">new s3.CfnBucket(this, 'amzn-s3-demo-bucket', { - analyticsConfigurations: [ - { - id: 'Config' - // ... - } - ] -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">s3.CfnBucket(self, "amzn-s3-demo-bucket", - analytics_configurations: [ - dict(id="Config", - # ... - ) - ] -)</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">CfnBucket.Builder.create(this, "amzn-s3-demo-bucket") - .analyticsConfigurations(Arrays.asList(java.util.Map.of( // Java 9 or later - "id", "Config", // ... - ))).build();</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">new CfnBucket(this, 'amzn-s3-demo-bucket', new CfnBucketProps { - AnalyticsConfigurations = new Dictionary<string, string> - { - ["id"] = "Config", - // ... - } -});</code></pre> -</div> -</div> -<div class="paragraph"> -<p>There might be rare cases where you want to define a resource that doesn’t have a corresponding <code>CfnXxx</code> class. This could be a new resource type that hasn’t yet been published in the AWS CloudFormation resource specification. In cases like this, you can instantiate the <code>cdk.CfnResource</code> directly and specify the resource type and properties. This is shown in the following example.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">new cdk.CfnResource(this, 'amzn-s3-demo-bucket', { - type: 'AWS::S3::Bucket', - properties: { - // Note the PascalCase here! These are CloudFormation identifiers. - AnalyticsConfigurations: [ - { - Id: 'Config', - // ... - } - ] - } -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">new cdk.CfnResource(this, 'amzn-s3-demo-bucket', { - type: 'AWS::S3::Bucket', - properties: { - // Note the PascalCase here! These are CloudFormation identifiers. - AnalyticsConfigurations: [ - { - Id: 'Config' - // ... - } - ] - } -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">cdk.CfnResource(self, 'amzn-s3-demo-bucket', - type="AWS::S3::Bucket", - properties=dict( - # Note the PascalCase here! These are CloudFormation identifiers. - "AnalyticsConfigurations": [ - { - "Id": "Config", - # ... - } - ] - } -)</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">CfnResource.Builder.create(this, "amzn-s3-demo-bucket") - .type("AWS::S3::Bucket") - .properties(java.util.Map.of( // Map.of requires Java 9 or later - // Note the PascalCase here! These are CloudFormation identifiers - "AnalyticsConfigurations", Arrays.asList( - java.util.Map.of("Id", "Config", // ... - )))) - .build();</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">new CfnResource(this, "amzn-s3-demo-bucket", new CfnResourceProps -{ - Type = "AWS::S3::Bucket", - Properties = new Dictionary<string, object> - { // Note the PascalCase here! These are CloudFormation identifiers - ["AnalyticsConfigurations"] = new Dictionary<string, string>[] - { - new Dictionary<string, string> { - ["Id"] = "Config" - } - } - } -});</code></pre> -</div> -</div> -</div> -<div class="sect4"> -<h5 id="develop-customize-escape-l2">Develop escape hatches for L2 constructs</h5> -<div class="paragraph"> -<p>If an L2 construct is missing a feature or you’re trying to work around an issue, you can modify the L1 construct that’s encapsulated by the L2 construct.</p> -</div> -<div class="paragraph"> -<p>All L2 constructs contain within them the corresponding L1 construct. For example, the high-level <code>Bucket</code> construct wraps the low-level <code>CfnBucket</code> construct. Because the <code>CfnBucket</code> corresponds directly to the AWS CloudFormation resource, it exposes all features that are available through AWS CloudFormation.</p> -</div> -<div class="paragraph"> -<p>The basic approach to get access to the L1 construct is to use <code>construct.node.defaultChild</code> (Python: <code>default_child</code>), cast it to the right type (if necessary), and modify its properties. Again, let’s take the example of a <code>Bucket</code>.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">// Get the CloudFormation resource -const cfnBucket = bucket.node.defaultChild as s3.CfnBucket; - -// Change its properties -cfnBucket.analyticsConfiguration = [ - { - id: 'Config', - // ... - } -];</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">// Get the CloudFormation resource -const cfnBucket = bucket.node.defaultChild; - -// Change its properties -cfnBucket.analyticsConfiguration = [ - { - id: 'Config' - // ... - } -];</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python"># Get the CloudFormation resource -cfn_bucket = bucket.node.default_child - -# Change its properties -cfn_bucket.analytics_configuration = [ - { - "id": "Config", - # ... - } -]</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">// Get the CloudFormation resource -CfnBucket cfnBucket = (CfnBucket)bucket.getNode().getDefaultChild(); - -cfnBucket.setAnalyticsConfigurations( - Arrays.asList(java.util.Map.of( // Java 9 or later - "Id", "Config", // ... - ));</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">// Get the CloudFormation resource -var cfnBucket = (CfnBucket)bucket.Node.DefaultChild; - -cfnBucket.AnalyticsConfigurations = new List<object> { - new Dictionary<string, string> - { - ["Id"] = "Config", - // ... - } -};</code></pre> -</div> -</div> -<div class="paragraph"> -<p>You can also use this object to change AWS CloudFormation options such as <code>Metadata</code> and <code>UpdatePolicy</code>.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">cfnBucket.cfnOptions.metadata = { - MetadataKey: 'MetadataValue' -};</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">cfnBucket.cfnOptions.metadata = { - MetadataKey: 'MetadataValue' -};</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">cfn_bucket.cfn_options.metadata = { - "MetadataKey": "MetadataValue" -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">cfnBucket.getCfnOptions().setMetadata(java.util.Map.of( // Java 9+ - "MetadataKey", "Metadatavalue"));</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">cfnBucket.CfnOptions.Metadata = new Dictionary<string, object> -{ - ["MetadataKey"] = "Metadatavalue" -};</code></pre> -</div> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="develop-customize-unescape">12.7.2. Use un-escape hatches</h4> -<div class="paragraph"> -<p>The AWS CDK also provides the capability to go <em>up</em> an abstraction level, which we might refer to as an "un-escape" hatch. If you have an L1 construct, such as <code>CfnBucket</code>, you can create a new L2 construct (<code>Bucket</code> in this case) to wrap the L1 construct.</p> -</div> -<div class="paragraph"> -<p>This is convenient when you create an L1 resource but want to use it with a construct that requires an L2 resource. It’s also helpful when you want to use convenience methods like <code>.grantXxxxx()</code> that aren’t available on the L1 construct.</p> -</div> -<div class="paragraph"> -<p>You move to the higher abstraction level using a static method on the L2 class called <code>.fromCfnXxxxx()</code>--for example, <code>Bucket.fromCfnBucket()</code> for Amazon S3 buckets. The L1 resource is the only parameter.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">b1 = new s3.CfnBucket(this, "buck09", { ... }); -b2 = s3.Bucket.fromCfnBucket(b1);</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">b1 = new s3.CfnBucket(this, "buck09", { ...} ); -b2 = s3.Bucket.fromCfnBucket(b1);</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">b1 = s3.CfnBucket(self, "buck09", ...) - b2 = s3.from_cfn_bucket(b1)</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">CfnBucket b1 = CfnBucket.Builder.create(this, "buck09") - // .... - .build(); -IBucket b2 = Bucket.fromCfnBucket(b1);</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">var b1 = new CfnBucket(this, "buck09", new CfnBucketProps { ... }); -var v2 = Bucket.FromCfnBucket(b1);</code></pre> -</div> -</div> -<div class="paragraph"> -<p>L2 constructs created from L1 constructs are proxy objects that refer to the L1 resource, similar to those created from resource names, ARNs, or lookups. Modifications to these constructs do not affect the final synthesized AWS CloudFormation template (since you have the L1 resource, however, you can modify that instead). For more information on proxy objects, see <a href="#resources-external">Referencing resources in your AWS account</a>.</p> -</div> -<div class="paragraph"> -<p>To avoid confusion, do not create multiple L2 constructs that refer to the same L1 construct. For example, if you extract the <code>CfnBucket</code> from a <code>Bucket</code> using the technique in the <a href="#develop-customize-escape-l2">previous section</a>, you shouldn’t create a second <code>Bucket</code> instance by calling <code>Bucket.fromCfnBucket()</code> with that <code>CfnBucket</code>. It actually works as you’d expect (only one <code>AWS::S3::Bucket</code> is synthesized) but it makes your code more difficult to maintain.</p> -</div> -</div> -<div class="sect3"> -<h4 id="develop-customize-override">12.7.3. Use raw overrides</h4> -<div class="paragraph"> -<p>If there are properties that are missing from the L1 construct, you can bypass all typing using raw overrides. This also makes it possible to delete synthesized properties.</p> -</div> -<div class="paragraph"> -<p>Use one of the <code>addOverride</code> methods (Python: <code>add_override</code>) methods, as shown in the following example.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">// Get the CloudFormation resource -const cfnBucket = bucket.node.defaultChild as s3.CfnBucket; - -// Use dot notation to address inside the resource template fragment -cfnBucket.addOverride('Properties.VersioningConfiguration.Status', 'NewStatus'); -cfnBucket.addDeletionOverride('Properties.VersioningConfiguration.Status'); - -// use index (0 here) to address an element of a list -cfnBucket.addOverride('Properties.Tags.0.Value', 'NewValue'); -cfnBucket.addDeletionOverride('Properties.Tags.0'); - -// addPropertyOverride is a convenience function for paths starting with "Properties." -cfnBucket.addPropertyOverride('VersioningConfiguration.Status', 'NewStatus'); -cfnBucket.addPropertyDeletionOverride('VersioningConfiguration.Status'); -cfnBucket.addPropertyOverride('Tags.0.Value', 'NewValue'); -cfnBucket.addPropertyDeletionOverride('Tags.0');</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">// Get the CloudFormation resource -const cfnBucket = bucket.node.defaultChild ; - -// Use dot notation to address inside the resource template fragment -cfnBucket.addOverride('Properties.VersioningConfiguration.Status', 'NewStatus'); -cfnBucket.addDeletionOverride('Properties.VersioningConfiguration.Status'); - -// use index (0 here) to address an element of a list -cfnBucket.addOverride('Properties.Tags.0.Value', 'NewValue'); -cfnBucket.addDeletionOverride('Properties.Tags.0'); - -// addPropertyOverride is a convenience function for paths starting with "Properties." -cfnBucket.addPropertyOverride('VersioningConfiguration.Status', 'NewStatus'); -cfnBucket.addPropertyDeletionOverride('VersioningConfiguration.Status'); -cfnBucket.addPropertyOverride('Tags.0.Value', 'NewValue'); -cfnBucket.addPropertyDeletionOverride('Tags.0');</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python"># Get the CloudFormation resource -cfn_bucket = bucket.node.default_child - -# Use dot notation to address inside the resource template fragment -cfn_bucket.add_override("Properties.VersioningConfiguration.Status", "NewStatus") -cfn_bucket.add_deletion_override("Properties.VersioningConfiguration.Status") - -# use index (0 here) to address an element of a list -cfn_bucket.add_override("Properties.Tags.0.Value", "NewValue") -cfn_bucket.add_deletion_override("Properties.Tags.0") - -# addPropertyOverride is a convenience function for paths starting with "Properties." -cfn_bucket.add_property_override("VersioningConfiguration.Status", "NewStatus") -cfn_bucket.add_property_deletion_override("VersioningConfiguration.Status") -cfn_bucket.add_property_override("Tags.0.Value", "NewValue") -cfn_bucket.add_property_deletion_override("Tags.0")</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">// Get the CloudFormation resource -CfnBucket cfnBucket = (CfnBucket)bucket.getNode().getDefaultChild(); - -// Use dot notation to address inside the resource template fragment -cfnBucket.addOverride("Properties.VersioningConfiguration.Status", "NewStatus"); -cfnBucket.addDeletionOverride("Properties.VersioningConfiguration.Status"); - -// use index (0 here) to address an element of a list -cfnBucket.addOverride("Properties.Tags.0.Value", "NewValue"); -cfnBucket.addDeletionOverride("Properties.Tags.0"); - -// addPropertyOverride is a convenience function for paths starting with "Properties." -cfnBucket.addPropertyOverride("VersioningConfiguration.Status", "NewStatus"); -cfnBucket.addPropertyDeletionOverride("VersioningConfiguration.Status"); -cfnBucket.addPropertyOverride("Tags.0.Value", "NewValue"); -cfnBucket.addPropertyDeletionOverride("Tags.0");</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">// Get the CloudFormation resource -var cfnBucket = (CfnBucket)bucket.node.defaultChild; - -// Use dot notation to address inside the resource template fragment -cfnBucket.AddOverride("Properties.VersioningConfiguration.Status", "NewStatus"); -cfnBucket.AddDeletionOverride("Properties.VersioningConfiguration.Status"); - -// use index (0 here) to address an element of a list -cfnBucket.AddOverride("Properties.Tags.0.Value", "NewValue"); -cfnBucket.AddDeletionOverride("Properties.Tags.0"); - -// addPropertyOverride is a convenience function for paths starting with "Properties." -cfnBucket.AddPropertyOverride("VersioningConfiguration.Status", "NewStatus"); -cfnBucket.AddPropertyDeletionOverride("VersioningConfiguration.Status"); -cfnBucket.AddPropertyOverride("Tags.0.Value", "NewValue"); -cfnBucket.AddPropertyDeletionOverride("Tags.0");</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="develop-customize-custom">12.7.4. Use custom resources</h4> -<div class="paragraph"> -<p>If the feature isn’t available through AWS CloudFormation, but only through a direct API call, you must write an AWS CloudFormation Custom Resource to make the API call you need. You can use the AWS CDK to write custom resources and wrap them into a regular construct interface. From the perspective of a consumer of your construct, the experience will feel native.</p> -</div> -<div class="paragraph"> -<p>Building a custom resource involves writing a Lambda function that responds to a resource’s <code>CREATE</code>, <code>UPDATE</code>, and <code>DELETE</code> lifecycle events. If your custom resource needs to make only a single API call, consider using the <a href="https://github.com/awslabs/aws-cdk/tree/master/packages/%40aws-cdk/custom-resources">AwsCustomResource</a>. This makes it possible to perform arbitrary SDK calls during an AWS CloudFormation deployment. Otherwise, you should write your own Lambda function to perform the work you need to get done.</p> -</div> -<div class="paragraph"> -<p>The subject is too broad to cover completely here, but the following links should get you started:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-custom-resources.html">Custom Resources</a></p> -</li> -<li> -<p><a href="https://github.com/aws-samples/aws-cdk-examples/tree/master/typescript/custom-resource/">Custom-Resource Example</a></p> -</li> -<li> -<p>For a more fully fledged example, see the <a href="https://github.com/awslabs/aws-cdk/blob/master/packages/@aws-cdk/aws-certificatemanager/lib/dns-validated-certificate.ts">DnsValidatedCertificate</a> class in the CDK standard library. This is implemented as a custom resource.</p> -</li> -</ul> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="get-env-var">12.8. Get a value from an environment variable</h3> -<div class="paragraph"> -<p>To get the value of an environment variable, use code like the following. This code gets the value of the environment variable <code>amzn-s3-demo-bucket</code>.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">// Sets bucket_name to undefined if environment variable not set -var bucket_name = process.env.amzn-s3-demo-bucket; - -// Sets bucket_name to a default if env var doesn't exist -var bucket_name = process.env.amzn-s3-demo-bucket || "DefaultName";</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">// Sets bucket_name to undefined if environment variable not set -var bucket_name = process.env.amzn-s3-demo-bucket; - -// Sets bucket_name to a default if env var doesn't exist -var bucket_name = process.env.amzn-s3-demo-bucket || "DefaultName";</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">import os - -# Raises KeyError if environment variable doesn't exist -bucket_name = os.environ["amzn-s3-demo-bucket"] - -# Sets bucket_name to None if environment variable doesn't exist -bucket_name = os.getenv("amzn-s3-demo-bucket") - -# Sets bucket_name to a default if env var doesn't exist -bucket_name = os.getenv("amzn-s3-demo-bucket", "DefaultName")</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">// Sets bucketName to null if environment variable doesn't exist -String bucketName = System.getenv("amzn-s3-demo-bucket"); - -// Sets bucketName to a default if env var doesn't exist -String bucketName = System.getenv("amzn-s3-demo-bucket"); -if (bucketName == null) bucketName = "DefaultName";</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using System; - -// Sets bucket name to null if environment variable doesn't exist -string bucketName = Environment.GetEnvironmentVariable("amzn-s3-demo-bucket"); - -// Sets bucket_name to a default if env var doesn't exist -string bucketName = Environment.GetEnvironmentVariable("amzn-s3-demo-bucket") ?? "DefaultName";</code></pre> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="get-cfn-param">12.9. Use CloudFormation parameters to get a CloudFormation value</h3> -<div class="paragraph"> -<p>Use AWS CloudFormation parameters within AWS Cloud Development Kit (AWS CDK) applications to input custom values into your synthesized CloudFormation templates at deployment.</p> -</div> -<div class="paragraph"> -<p>For an introduction, see <a href="#parameters">Parameters and the AWS CDK</a>.</p> -</div> -<div class="sect3"> -<h4 id="parameters-define">12.9.1. Define parameters in your CDK app</h4> -<div class="paragraph"> -<p>Use the <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.CfnParameter.html">CfnParameter</a> class to define a parameter. You’ll want to specify at least a type and a description for most parameters, though both are technically optional. The description appears when the user is prompted to enter the parameter’s value in the AWS CloudFormation console. For more information on the available types, see <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html#parameters-section-structure-properties-type">Types</a>.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>You can define parameters in any scope. However, we recommend defining parameters at the stack level so that their logical ID doesn’t change when you refactor your code.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const uploadBucketName = new CfnParameter(this, "uploadBucketName", { - type: "String", - description: "The name of the Amazon S3 bucket where uploaded files will be stored."});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const uploadBucketName = new CfnParameter(this, "uploadBucketName", { - type: "String", - description: "The name of the Amazon S3 bucket where uploaded files will be stored."});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">upload_bucket_name = CfnParameter(self, "uploadBucketName", type="String", - description="The name of the Amazon S3 bucket where uploaded files will be stored.")</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">CfnParameter uploadBucketName = CfnParameter.Builder.create(this, "uploadBucketName") - .type("String") - .description("The name of the Amazon S3 bucket where uploaded files will be stored") - .build();</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">var uploadBucketName = new CfnParameter(this, "uploadBucketName", new CfnParameterProps -{ - Type = "String", - Description = "The name of the Amazon S3 bucket where uploaded files will be stored" -});</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="parameters-use">12.9.2. Use parameters</h4> -<div class="paragraph"> -<p>A <code>CfnParameter</code> instance exposes its value to your CDK app via a <a href="#tokens">token</a>. Like all tokens, the parameter’s token is resolved at synthesis time. But it resolves to a reference to the parameter defined in the AWS CloudFormation template (which will be resolved at deploy time), rather than to a concrete value.</p> -</div> -<div class="paragraph"> -<p>You can retrieve the token as an instance of the <code>Token</code> class, or in string, string list, or numeric encoding. Your choice depends on the kind of value required by the class or method that you want to use the parameter with.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<table class="tableblock frame-all grid-all stretch"> -<colgroup> -<col style="width: 50%;"> -<col style="width: 50%;"> -</colgroup> -<thead> -<tr> -<th class="tableblock halign-left valign-top">Property</th> -<th class="tableblock halign-left valign-top">kind of value</th> -</tr> -</thead> -<tbody> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>value</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>Token</code> class instance</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>valueAsList</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">The token represented as a string list</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>valueAsNumber</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">The token represented as a number</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>valueAsString</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">The token represented as a string</p></td> -</tr> -</tbody> -</table> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<table class="tableblock frame-all grid-all stretch"> -<colgroup> -<col style="width: 50%;"> -<col style="width: 50%;"> -</colgroup> -<thead> -<tr> -<th class="tableblock halign-left valign-top">Property</th> -<th class="tableblock halign-left valign-top">kind of value</th> -</tr> -</thead> -<tbody> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>value</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>Token</code> class instance</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>valueAsList</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">The token represented as a string list</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>valueAsNumber</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">The token represented as a number</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>valueAsString</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">The token represented as a string</p></td> -</tr> -</tbody> -</table> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<table class="tableblock frame-all grid-all stretch"> -<colgroup> -<col style="width: 50%;"> -<col style="width: 50%;"> -</colgroup> -<thead> -<tr> -<th class="tableblock halign-left valign-top">Property</th> -<th class="tableblock halign-left valign-top">kind of value</th> -</tr> -</thead> -<tbody> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>value</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>Token</code> class instance</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>value_as_list</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">The token represented as a string list</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>value_as_number</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">The token represented as a number</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>value_as_string</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">The token represented as a string</p></td> -</tr> -</tbody> -</table> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<table class="tableblock frame-all grid-all stretch"> -<colgroup> -<col style="width: 50%;"> -<col style="width: 50%;"> -</colgroup> -<thead> -<tr> -<th class="tableblock halign-left valign-top">Property</th> -<th class="tableblock halign-left valign-top">kind of value</th> -</tr> -</thead> -<tbody> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>getValue()</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>Token</code> class instance</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>getValueAsList()</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">The token represented as a string list</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>getValueAsNumber()</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">The token represented as a number</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>getValueAsString()</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">The token represented as a string</p></td> -</tr> -</tbody> -</table> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<table class="tableblock frame-all grid-all stretch"> -<colgroup> -<col style="width: 50%;"> -<col style="width: 50%;"> -</colgroup> -<thead> -<tr> -<th class="tableblock halign-left valign-top">Property</th> -<th class="tableblock halign-left valign-top">kind of value</th> -</tr> -</thead> -<tbody> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>Value</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>Token</code> class instance</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>ValueAsList</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">The token represented as a string list</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>ValueAsNumber</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">The token represented as a number</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>ValueAsString</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">The token represented as a string</p></td> -</tr> -</tbody> -</table> -<div class="paragraph"> -<p>For example, to use a parameter in a <code>Bucket</code> definition:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const bucket = new Bucket(this, "amzn-s3-demo-bucket", - { bucketName: uploadBucketName.valueAsString});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const bucket = new Bucket(this, "amzn-s3-demo-bucket", - { bucketName: uploadBucketName.valueAsString});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">bucket = Bucket(self, "amzn-s3-demo-bucket", - bucket_name=upload_bucket_name.value_as_string)</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">Bucket bucket = Bucket.Builder.create(this, "amzn-s3-demo-bucket") - .bucketName(uploadBucketName.getValueAsString()) - .build();</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">var bucket = new Bucket(this, "amzn-s3-demo-bucket") -{ - BucketName = uploadBucketName.ValueAsString -};</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="parameters-deploy">12.9.3. Deploy CDK apps containing parameters</h4> -<div class="paragraph"> -<p>When you deploy a generated AWS CloudFormation template through the AWS CloudFormation console, you will be prompted to provide the values for each parameter.</p> -</div> -<div class="paragraph"> -<p>You can also provide parameter values using the CDK <code class="noloc">CLI</code><code>cdk deploy</code> command, or by specifying parameter values in your CDK project’s stack file.</p> -</div> -<div class="sect4"> -<h5 id="parameters-deploy-cli">Provide parameter values with <code class="noloc">cdk deploy</code></h5> -<div class="paragraph"> -<p>When you deploy using the CDK <code class="noloc">CLI</code><code>cdk deploy</code> command, you can provide parameter values at deployment with the <code>--parameters</code> option.</p> -</div> -<div class="paragraph"> -<p>The following is an example of the <code>cdk deploy</code> command structure:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk deploy stack-logical-id --parameters stack-name:parameter-name=parameter-value</code></pre> -</div> -</div> -<div class="paragraph"> -<p>If your CDK app contains a single stack, you don’t have to provide the stack logical ID argument or the <code><code class="replaceable">stack-name</code></code> value in the <code>--parameters</code> option. The CDK <code class="noloc">CLI</code> will automatically find and provide these values. The following is an example that specifies an <code>uploadbucket</code> value for the <code>uploadBucketName</code> parameter of the single stack in our CDK app:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk deploy --parameters uploadBucketName=uploadbucket</code></pre> -</div> -</div> -</div> -<div class="sect4"> -<h5 id="parameters-deploy-cli-multi-stack">Provide parameter values with cdk deploy for multi-stack applications</h5> -<div class="paragraph"> -<p>The following is an example CDK application in <code class="noloc">TypeScript</code> that contains two CDK stacks. Each stack contains an Amazon S3 bucket instance and a parameter to set the Amazon S3 bucket name:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as cdk from 'aws-cdk-lib'; -import { Construct } from 'constructs'; -import * as s3 from 'aws-cdk-lib/aws-s3'; - -// Define the CDK app -const app = new cdk.App(); - -// First stack -export class MyFirstStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - // Set a default parameter name - const bucketNameParam = new cdk.CfnParameter(this, 'bucketNameParam', { - type: 'String', - default: 'myfirststackdefaultbucketname' - }); - - // Define an S3 bucket - new s3.Bucket(this, 'MyFirstBucket', { - bucketName: bucketNameParam.valueAsString - }); - } -} - -// Second stack -export class MySecondStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - // Set a default parameter name - const bucketNameParam = new cdk.CfnParameter(this, 'bucketNameParam', { - type: 'String', - default: 'mysecondstackdefaultbucketname' - }); - - // Define an S3 bucket - new s3.Bucket(this, 'MySecondBucket', { - bucketName: bucketNameParam.valueAsString - }); - } -} - -// Instantiate the stacks -new MyFirstStack(app, 'MyFirstStack', { - stackName: 'MyFirstDeployedStack', -}); - -new MySecondStack(app, 'MySecondStack', { - stackName: 'MySecondDeployedStack', -});</code></pre> -</div> -</div> -<div class="paragraph"> -<p>For CDK apps that contain multiple stacks, you can do the following:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><strong>Deploy one stack with parameters</strong> – To deploy a single stack from a multi-stack application, provide the stack logical ID as an argument.</p> -<div class="paragraph"> -<p>The following is an example that deploys <code>MySecondStack</code> with <code>mynewbucketname</code> as the parameter value for <code>bucketNameParam</code>:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk deploy MySecondStack --parameters bucketNameParam='mynewbucketname'</code></pre> -</div> -</div> -</li> -<li> -<p><strong>Deploy all stacks and specify parameter values for each stack</strong> – Provide the <code>'*'</code> wildcard or the <code>--all</code> option to deploy all stacks. Provide the <code>--parameters</code> option multiple times in a single command to specify parameter values for each stack. The following is an example:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk deploy '*' --parameters MyFirstDeployedStack:bucketNameParam='mynewfirststackbucketname' --parameters MySecondDeployedStack:bucketNameParam='mynewsecondstackbucketname'</code></pre> -</div> -</div> -</li> -<li> -<p><strong>Deploy all stacks and specify parameter values for a single stack</strong> – Provide the <code>'*'</code> wildcard or the <code>--all</code> option to deploy all stacks. Then, specify the stack to define the parameter for in the <code>--parameters</code> option. The following are examples that deploys all stacks in a CDK app and specifies a parameter value for the <code>MySecondDeployedStack</code> AWS CloudFormation stack. All other stacks will deploy and use the default parameter value:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk deploy '*' --parameters MySecondDeployedStack:bucketNameParam='mynewbucketname' -$ cdk deploy --all --parameters MySecondDeployedStack:bucketNameParam='mynewbucketname'</code></pre> -</div> -</div> -</li> -</ul> -</div> -</div> -<div class="sect4"> -<h5 id="parameters-deploy-cli-nested-stack">Provide parameter values with <code class="noloc">cdk deploy</code> for applications with nested stacks</h5> -<div class="paragraph"> -<p>The CDK <code class="noloc">CLI</code> behavior when working with applications containing nested stacks is similar to multi-stack applications. The main difference is, if you want to deploy all nested stacks, use the <code>'<strong>'</code> wildcard. The <code>'*'</code> wildcard deploys all stacks but will not deploy nested stacks. The <code>'</strong>'</code> wildcard deploys all stacks, including nested stacks.</p> -</div> -<div class="paragraph"> -<p>The following is an example that deploys nested stacks while specifying the parameter value for one nested stack:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk deploy '**' --parameters MultiStackCdkApp/SecondStack:bucketNameParam='mysecondstackbucketname'</code></pre> -</div> -</div> -<div class="paragraph"> -<p>For more information on <code>cdk deploy</code> command options, see <a href="#ref-cli-cmd-deploy">cdk deploy</a>.</p> -</div> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="use-cfn-template">12.10. Import an existing AWS CloudFormation template</h3> -<div class="paragraph"> -<p>Import resources from an AWS CloudFormation template into your AWS Cloud Development Kit (AWS CDK) applications by using the <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.cloudformation_include-readme.html">cloudformation-include.CfnInclude</a> construct to convert resources to L1 constructs.</p> -</div> -<div class="paragraph"> -<p>After import, you can work with these resources in your app in the same way that you would if they were originally defined in AWS CDK code. You can also use these L1 constructs within higher-level AWS CDK constructs. For example, this can let you use the L2 permission grant methods with the resources they define.</p> -</div> -<div class="paragraph"> -<p>The <code>cloudformation-include.CfnInclude</code> construct essentially adds an AWS CDK API wrapper to any resource in your AWS CloudFormation template. Use this capability to import your existing AWS CloudFormation templates to the AWS CDK a piece at a time. By doing this, you can manage your existing resources using AWS CDK constructs to utilize the benefits of higher-level abstractions. You can also use this feature to vend your AWS CloudFormation templates to AWS CDK developers by providing an AWS CDK construct API.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>AWS CDK v1 also included <a href="https://docs.aws.amazon.com/cdk/api/latest/docs/aws-cdk-lib.CfnInclude.html">aws-cdk-lib.CfnInclude</a>, which was previously used for the same general purpose. However, it lacks much of the functionality of <code>cloudformation-include.CfnInclude</code>.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph topiclist"> -<p>[[Topic List]]</p> -</div> -<div class="sect3"> -<h4 id="w94aac53c46c19">12.10.1. Import an AWS CloudFormation template</h4> -<div class="paragraph"> -<p>The following is a sample AWS CloudFormation template that we will use to provide examples in this topic. Copy and save the template as <code class="path">my-template.json</code> to follow along. After working through these examples, you can explore further by using any of your existing deployed AWS CloudFormation templates. You can obtain them from the AWS CloudFormation console.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-json" data-lang="json">{ - "Resources": { - "amzn-s3-demo-bucket": { - "Type": "AWS::S3::Bucket", - "Properties": { - "BucketName": "amzn-s3-demo-bucket", - } - } - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>You can work with either JSON or YAML templates. We recommend JSON if available since YAML parsers can vary slightly in what they accept.</p> -</div> -<div class="paragraph"> -<p>The following is an example of how to import the sample template into your AWS CDK app using <code>cloudformation-include</code>. Templates are imported within the context of an CDK stack.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as cdk from 'aws-cdk-lib'; -import * as cfninc from 'aws-cdk-lib/cloudformation-include'; -import { Construct } from 'constructs'; - -export class MyStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - const template = new cfninc.CfnInclude(this, 'Template', { - templateFile: 'my-template.json', - }); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const cdk = require('aws-cdk-lib'); -const cfninc = require('aws-cdk-lib/cloudformation-include'); - -class MyStack extends cdk.Stack { - constructor(scope, id, props) { - super(scope, id, props); - - const template = new cfninc.CfnInclude(this, 'Template', { - templateFile: 'my-template.json', - }); - } -} - -module.exports = { MyStack }</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">import aws_cdk as cdk -from aws_cdk import cloudformation_include as cfn_inc -from constructs import Construct - -class MyStack(cdk.Stack): - - def __init__(self, scope: Construct, id: str, **kwargs) -> None: - super().__init__(scope, id, **kwargs) - - template = cfn_inc.CfnInclude(self, "Template", - template_file="my-template.json")</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">import software.amazon.awscdk.Stack; -import software.amazon.awscdk.StackProps; -import software.amazon.awscdk.cloudformation.include.CfnInclude; -import software.constructs.Construct; - -public class MyStack extends Stack { - public MyStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public MyStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - CfnInclude template = CfnInclude.Builder.create(this, "Template") - .templateFile("my-template.json") - .build(); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; -using Constructs; -using cfnInc = Amazon.CDK.CloudFormation.Include; - -namespace MyApp -{ - public class MyStack : Stack - { - internal MyStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) - { - var template = new cfnInc.CfnInclude(this, "Template", new cfnInc.CfnIncludeProps - { - TemplateFile = "my-template.json" - }); - } - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>By default, importing a resource preserves the resource’s original logical ID from the template. This behavior is suitable for importing an AWS CloudFormation template into the AWS CDK, where logical IDs must be retained. AWS CloudFormation needs this information to recognize these imported resources as the same resources from the AWS CloudFormation template.</p> -</div> -<div class="paragraph"> -<p>If you are developing an AWS CDK construct wrapper for the template so that it can be used by other AWS CDK developers, have the AWS CDK generate new resource IDs instead. By doing this, the construct can be used multiple times in a stack without name conflicts. To do this, set the <code>preserveLogicalIds</code> property to <code>false</code> when importing the template. The following is an example:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const template = new cfninc.CfnInclude(this, 'MyConstruct', { - templateFile: 'my-template.json', - preserveLogicalIds: false -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const template = new cfninc.CfnInclude(this, 'MyConstruct', { - templateFile: 'my-template.json', - preserveLogicalIds: false -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">template = cfn_inc.CfnInclude(self, "Template", - template_file="my-template.json", - preserve_logical_ids=False)</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">CfnInclude template = CfnInclude.Builder.create(this, "Template") - .templateFile("my-template.json") - .preserveLogicalIds(false) - .build();</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">var template = new cfnInc.CfnInclude(this, "Template", new cfn_inc.CfnIncludeProps -{ - TemplateFile = "my-template.json", - PreserveLogicalIds = false -});</code></pre> -</div> -</div> -<div class="paragraph"> -<p>To put imported resources under the control of your AWS CDK app, add the stack to the <code>App</code>:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as cdk from 'aws-cdk-lib'; -import { MyStack } from '../lib/my-stack'; - -const app = new cdk.App(); -new MyStack(app, 'MyStack');</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const cdk = require('aws-cdk-lib'); -const { MyStack } = require('../lib/my-stack'); - -const app = new cdk.App(); -new MyStack(app, 'MyStack');</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">import aws_cdk as cdk -from mystack.my_stack import MyStack - -app = cdk.App() -MyStack(app, "MyStack")</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">import software.amazon.awscdk.App; - -public class MyApp { - public static void main(final String[] args) { - App app = new App(); - - new MyStack(app, "MyStack"); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; - -namespace CdkApp -{ - sealed class Program - { - public static void Main(string[] args) - { - var app = new App(); - new MyStack(app, "MyStack"); - } - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>To verify that there won’t be any unintended changes to the AWS resources in the stack, you can perform a diff. Use the AWS CDK <code class="noloc">CLI</code><code>cdk diff</code> command and omit any AWS CDK-specific metadata. The following is an example:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk diff --no-version-reporting --no-path-metadata --no-asset-metadata</code></pre> -</div> -</div> -<div class="paragraph"> -<p>After you import an AWS CloudFormation template, the AWS CDK app should become the source of truth for your imported resources. To make changes to your resources, modify them in your AWS CDK app and deploy with the AWS CDK <code class="noloc">CLI</code><strong class="command">cdk deploy</strong> command.</p> -</div> -</div> -<div class="sect3"> -<h4 id="use-cfn-template-cfninclude-access">12.10.2. Access imported resources</h4> -<div class="paragraph"> -<p>The name <code>template</code> in the example code represents the imported AWS CloudFormation template. To access a resource from it, use the object’s <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.cloudformation_include.CfnInclude.html#getwbrresourcelogicalid">getResource()</a> method. To access the returned resource as a specific kind of resource, cast the result to the desired type. This isn’t necessary in Python or JavaScript. The following is an example:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const cfnBucket = template.getResource('amzn-s3-demo-bucket') as s3.CfnBucket;</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const cfnBucket = template.getResource('amzn-s3-demo-bucket');</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">cfn_bucket = template.get_resource("amzn-s3-demo-bucket")</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">CfnBucket cfnBucket = (CfnBucket)template.getResource("amzn-s3-demo-bucket");</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">var cfnBucket = (CfnBucket)template.GetResource("amzn-s3-demo-bucket");</code></pre> -</div> -</div> -<div class="paragraph"> -<p>From this example, <code>cfnBucket</code> is now an instance of the <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html">aws-s3.CfnBucket</a> class. This is an L1 construct that represents the corresponding AWS CloudFormation resource. You can treat it like any other resource of its type. For example, you can get its ARN value with the <code>bucket.attrArn</code> property.</p> -</div> -<div class="paragraph"> -<p>To wrap the L1 <code>CfnBucket</code> resource in an L2 <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html">aws-s3.Bucket</a> instance instead, use the static methods <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html#static-fromwbrbucketwbrarnscope-id-bucketarn">fromBucketArn()</a>, <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html#static-fromwbrbucketwbrattributesscope-id-attrs">fromBucketAttributes()</a>, or <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html#static-fromwbrbucketwbrnamescope-id-bucketname">fromBucketName()</a>. Usually, the <code>fromBucketName()</code> method is most convenient. The following is an example:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const bucket = s3.Bucket.fromBucketName(this, 'Bucket', cfnBucket.ref);</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const bucket = s3.Bucket.fromBucketName(this, 'Bucket', cfnBucket.ref);</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">bucket = s3.Bucket.from_bucket_name(self, "Bucket", cfn_bucket.ref)</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">Bucket bucket = (Bucket)Bucket.fromBucketName(this, "Bucket", cfnBucket.getRef());</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">var bucket = (Bucket)Bucket.FromBucketName(this, "Bucket", cfnBucket.Ref);</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Other L2 constructs have similar methods for creating the construct from an existing resource.</p> -</div> -<div class="paragraph"> -<p>When you wrap an L1 construct in an L2 construct, it doesn’t create a new resource. From our example, we are not creating a second S3; bucket. Instead, the new <code>Bucket</code> instance encapsulates the existing <code>CfnBucket</code>.</p> -</div> -<div class="paragraph"> -<p>From the example, the <code>bucket</code> is now an L2 <code>Bucket</code> construct that behaves like any other L2 construct. For example, you can grant an AWS Lambda function write access to the bucket by using the bucket’s convenient <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html#grantwbrwriteidentity-objectskeypattern">grantWrite()</a> method. You don’t have to define the necessary AWS Identity and Access Management (IAM) policy manually. The following is an example:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">bucket.grantWrite(lambdaFunc);</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">bucket.grantWrite(lambdaFunc);</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">bucket.grant_write(lambda_func)</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">bucket.grantWrite(lambdaFunc);</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">bucket.GrantWrite(lambdaFunc);</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="use-cfn-template-cfninclude-params">12.10.3. Replace parameters</h4> -<div class="paragraph"> -<p>If your AWS CloudFormation template contains parameters, you can replace them with build time values at import by using the <code>parameters</code> property. In the following example, we replace the <code>UploadBucket</code> parameter with the ARN of a bucket defined elsewhere in our AWS CDK code.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const template = new cfninc.CfnInclude(this, 'Template', { - templateFile: 'my-template.json', - parameters: { - 'UploadBucket': bucket.bucketArn, - }, -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const template = new cfninc.CfnInclude(this, 'Template', { - templateFile: 'my-template.json', - parameters: { - 'UploadBucket': bucket.bucketArn, - }, -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">template = cfn_inc.CfnInclude(self, "Template", - template_file="my-template.json", - parameters=dict(UploadBucket=bucket.bucket_arn) -)</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">CfnInclude template = CfnInclude.Builder.create(this, "Template") - .templateFile("my-template.json") - .parameters(java.util.Map.of( // Map.of requires Java 9+ - "UploadBucket", bucket.getBucketArn())) - .build();</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">var template = new cfnInc.CfnInclude(this, "Template", new cfnInc.CfnIncludeProps -{ - TemplateFile = "my-template.json", - Parameters = new Dictionary<string, string> - { - { "UploadBucket", bucket.BucketArn } - } -});</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="use-cfn-template-cfninclude-other">12.10.4. Import other template elements</h4> -<div class="paragraph"> -<p>You can import any AWS CloudFormation template element, not just resources. The imported elements become a part of the AWS CDK stack. To import these elements, use the following methods of the <code>CfnInclude</code> object:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.cloudformation_include.CfnInclude.html#getwbrconditionconditionname">getCondition()</a> – AWS CloudFormation <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/conditions-section-structure.html">conditions</a>.</p> -</li> -<li> -<p><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.cloudformation_include.CfnInclude.html#getwbrhookhooklogicalid">getHook()</a> – AWS CloudFormation <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/blue-green.html">hooks</a> for blue/green deployments.</p> -</li> -<li> -<p><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.cloudformation_include.CfnInclude.html#getwbrmappingmappingname">getMapping()</a> – AWS CloudFormation <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/mappings-section-structure.html">mappings</a>.</p> -</li> -<li> -<p><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.cloudformation_include.CfnInclude.html#getwbroutputlogicalid">getOutput()</a> – AWS CloudFormation <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html">outputs</a>.</p> -</li> -<li> -<p><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.cloudformation_include.CfnInclude.html#getwbrparameterparametername">getParameter()</a> – AWS CloudFormation <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html">parameters</a>.</p> -</li> -<li> -<p><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.cloudformation_include.CfnInclude.html#getwbrrulerulename">getRule()</a> – AWS CloudFormation <a href="https://docs.aws.amazon.com/servicecatalog/latest/adminguide/reference-template_constraint_rules.html">rules</a> for AWS Service Catalog templates.</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>Each of these methods return an instance of a class that represents the specific type of AWS CloudFormation element. These objects are mutable. Changes that you make to them will appear in the template that gets generated from the AWS CDK stack. The following is an example that imports a parameter from the template and modifies its default value:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const param = template.getParameter('MyParameter'); -param.default = "AWS CDK"</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const param = template.getParameter('MyParameter'); -param.default = "AWS CDK"</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">param = template.get_parameter("MyParameter") -param.default = "AWS CDK"</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">CfnParameter param = template.getParameter("MyParameter"); -param.setDefaultValue("AWS CDK")</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">var cfnBucket = (CfnBucket)template.GetResource("amzn-s3-demo-bucket"); -var param = template.GetParameter("MyParameter"); -param.Default = "AWS CDK";</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="use-cfn-template-cfninclude-nested">12.10.5. Import nested stacks</h4> -<div class="paragraph"> -<p>You can import <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-nested-stacks.html">nested stacks</a> by specifying them either when you import their main template, or at some later point. The nested template must be stored in a local file, but referenced as a <code>NestedStack</code> resource in the main template. Also, the resource name used in the AWS CDK code must match the name used for the nested stack in the main template.</p> -</div> -<div class="paragraph"> -<p>Given this resource definition in the main template, the following code shows how to import the referenced nested stack both ways.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-json" data-lang="json">"NestedStack": { - "Type": "AWS::CloudFormation::Stack", - "Properties": { - "TemplateURL": "https://my-s3-template-source.s3.amazonaws.com/nested-stack.json" - }</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">// include nested stack when importing main stack -const mainTemplate = new cfninc.CfnInclude(this, 'MainStack', { - templateFile: 'main-template.json', - loadNestedStacks: { - 'NestedStack': { - templateFile: 'nested-template.json', - }, - }, -}); - -// or add it some time after importing the main stack -const nestedTemplate = mainTemplate.loadNestedStack('NestedTemplate', { - templateFile: 'nested-template.json', -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">// include nested stack when importing main stack -const mainTemplate = new cfninc.CfnInclude(this, 'MainStack', { - templateFile: 'main-template.json', - loadNestedStacks: { - 'NestedStack': { - templateFile: 'nested-template.json', - }, - }, -}); - -// or add it some time after importing the main stack -const nestedTemplate = mainTemplate.loadNestedStack('NestedStack', { - templateFile: 'my-nested-template.json', -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python"># include nested stack when importing main stack -main_template = cfn_inc.CfnInclude(self, "MainStack", - template_file="main-template.json", - load_nested_stacks=dict(NestedStack= - cfn_inc.CfnIncludeProps(template_file="nested-template.json"))) - -# or add it some time after importing the main stack -nested_template = main_template.load_nested_stack("NestedStack", - template_file="nested-template.json")</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">CfnInclude mainTemplate = CfnInclude.Builder.create(this, "MainStack") - .templateFile("main-template.json") - .loadNestedStacks(java.util.Map.of( // Map.of requires Java 9+ - "NestedStack", CfnIncludeProps.builder() - .templateFile("nested-template.json").build())) - .build(); - -// or add it some time after importing the main stack -IncludedNestedStack nestedTemplate = mainTemplate.loadNestedStack("NestedTemplate", CfnIncludeProps.builder() - .templateFile("nested-template.json") - .build());</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">// include nested stack when importing main stack -var mainTemplate = new cfnInc.CfnInclude(this, "MainStack", new cfnInc.CfnIncludeProps -{ - TemplateFile = "main-template.json", - LoadNestedStacks = new Dictionary<string, cfnInc.ICfnIncludeProps> - { - { "NestedStack", new cfnInc.CfnIncludeProps { TemplateFile = "nested-template.json" } } - } -}); - -// or add it some time after importing the main stack -var nestedTemplate = mainTemplate.LoadNestedStack("NestedTemplate", new cfnInc.CfnIncludeProps { - TemplateFile = 'nested-template.json' -});</code></pre> -</div> -</div> -<div class="paragraph"> -<p>You can import multiple nested stacks with either methods. When importing the main template, you provide a mapping between the resource name of each nested stack and its template file. This mapping can contain any number of entries. To do it after the initial import, call <code>loadNestedStack()</code> once for each nested stack.</p> -</div> -<div class="paragraph"> -<p>After importing a nested stack, you can access it using the main template’s <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.cloudformation_include.CfnInclude.html#getwbrnestedwbrstacklogicalid">getNestedStack()</a> method.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const nestedStack = mainTemplate.getNestedStack('NestedStack').stack;</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const nestedStack = mainTemplate.getNestedStack('NestedStack').stack;</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">nested_stack = main_template.get_nested_stack("NestedStack").stack</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">NestedStack nestedStack = mainTemplate.getNestedStack("NestedStack").getStack();</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">var nestedStack = mainTemplate.GetNestedStack("NestedStack").Stack;</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The <code>getNestedStack()</code> method returns an <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.cloudformation_include.CfnInclude.html#getwbrnestedwbrstacklogicalid">IncludedNestedStack</a> instance. From this instance, you can access the AWS CDK <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.NestedStack.html">NestedStack</a> instance via the <code>stack</code> property, as shown in the example. You can also access the original AWS CloudFormation template object via <code>includedTemplate</code>, from which you can load resources and other AWS CloudFormation elements.</p> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="get-ssm-value">12.11. Get a value from the Systems Manager Parameter Store</h3> -<div class="paragraph"> -<p>The AWS Cloud Development Kit (AWS CDK) can retrieve the value of AWS Systems Manager Parameter Store attributes. During synthesis, the AWS CDK produces a <a href="#tokens">token</a> that is resolved by AWS CloudFormation during deployment.</p> -</div> -<div class="paragraph"> -<p>The AWS CDK supports retrieving both plain and secure values. You may request a specific version of either kind of value. For plain values, you may omit the version from your request to retrieve the latest version. For secure values, you must specify the version when requesting the value of the secure attribute.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>This topic shows how to read attributes from the AWS Systems Manager Parameter Store. You can also read secrets from the AWS Secrets Manager (see <a href="#get-secrets-manager-value">Get a value from AWS Secrets Manager</a>).</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph topiclist"> -<p>[[Topic List]]</p> -</div> -<div class="sect3"> -<h4 id="ssm-read-at-deploy">12.11.1. Read Systems Manager values at deployment time</h4> -<div class="paragraph"> -<p>To read values from the Systems Manager Parameter Store, use the <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ssm.StringParameter.html#static-valuewbrforwbrstringwbrparameterscope-parametername-version">valueForStringParameter</a> and <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ssm.StringParameter.html#static-valuewbrforwbrsecurewbrstringwbrparameterscope-parametername-version">valueForSecureStringParameter</a> methods. Choose a method based on whether the attribute you want is a plain string or a secure string value. These methods return <a href="#tokens">tokens</a>, not the actual value. The value is resolved by AWS CloudFormation during deployment. The following is an example:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as ssm from 'aws-cdk-lib/aws-ssm'; - -// Get latest version or specified version of plain string attribute -const latestStringToken = ssm.StringParameter.valueForStringParameter( - this, 'my-plain-parameter-name'); // latest version -const versionOfStringToken = ssm.StringParameter.valueForStringParameter( - this, 'my-plain-parameter-name', 1); // version 1 - -// Get specified version of secure string attribute -const secureStringToken = ssm.StringParameter.valueForSecureStringParameter( - this, 'my-secure-parameter-name', 1); // must specify version</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const ssm = require('aws-cdk-lib/aws-ssm'); - -// Get latest version or specified version of plain string attribute -const latestStringToken = ssm.StringParameter.valueForStringParameter( - this, 'my-plain-parameter-name'); // latest version -const versionOfStringToken = ssm.StringParameter.valueForStringParameter( - this, 'my-plain-parameter-name', 1); // version 1 - -// Get specified version of secure string attribute -const secureStringToken = ssm.StringParameter.valueForSecureStringParameter( - this, 'my-secure-parameter-name', 1); // must specify version</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">import aws_cdk.aws_ssm as ssm - -# Get latest version or specified version of plain string attribute -latest_string_token = ssm.StringParameter.value_for_string_parameter( - self, "my-plain-parameter-name") -latest_string_token = ssm.StringParameter.value_for_string_parameter( - self, "my-plain-parameter-name", 1) - -# Get specified version of secure string attribute -secure_string_token = ssm.StringParameter.value_for_secure_string_parameter( - self, "my-secure-parameter-name", 1) # must specify version</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">import software.amazon.awscdk.services.ssm.StringParameter; - -//Get latest version or specified version of plain string attribute -String latestStringToken = StringParameter.valueForStringParameter( - this, "my-plain-parameter-name"); // latest version -String versionOfStringToken = StringParameter.valueForStringParameter( - this, "my-plain-parameter-name", 1); // version 1 - -//Get specified version of secure string attribute -String secureStringToken = StringParameter.valueForSecureStringParameter( - this, "my-secure-parameter-name", 1); // must specify version</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK.AWS.SSM; - -// Get latest version or specified version of plain string attribute -var latestStringToken = StringParameter.ValueForStringParameter( - this, "my-plain-parameter-name"); // latest version -var versionOfStringToken = StringParameter.ValueForStringParameter( - this, "my-plain-parameter-name", 1); // version 1 - -// Get specified version of secure string attribute -var secureStringToken = StringParameter.ValueForSecureStringParameter( - this, "my-secure-parameter-name", 1); // must specify version</code></pre> -</div> -</div> -<div class="paragraph"> -<p>A <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/dynamic-references.html#template-parameters-dynamic-patterns-resources">limited number of AWS services</a> currently support this feature.</p> -</div> -</div> -<div class="sect3"> -<h4 id="ssm-read-at-synth">12.11.2. Read Systems Manager values at synthesis time</h4> -<div class="paragraph"> -<p>At times, it’s useful to provide a parameter at synthesis time. By doing this, the AWS CloudFormation template will always use the same value instead of resolving the value during deployment.</p> -</div> -<div class="paragraph"> -<p>To read a value from the Systems Manager Parameter Store at synthesis time, use the <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ssm.StringParameter.html#static-valuewbrfromwbrlookupscope-parametername">valueFromLookup</a> method (Python: <code>value_from_lookup</code>). This method returns the actual value of the parameter as a <a href="#context">Context values and the AWS CDK</a> value. If the value is not already cached in <code class="path">cdk.json</code> or passed on the command line, it is retrieved from the current AWS account. For this reason, the stack <em>must</em> be synthesized with explicit AWS environment information.</p> -</div> -<div class="paragraph"> -<p>The following is an example:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as ssm from 'aws-cdk-lib/aws-ssm'; - -const stringValue = ssm.StringParameter.valueFromLookup(this, 'my-plain-parameter-name');</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const ssm = require('aws-cdk-lib/aws-ssm'); - -const stringValue = ssm.StringParameter.valueFromLookup(this, 'my-plain-parameter-name');</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">import aws_cdk.aws_ssm as ssm - -string_value = ssm.StringParameter.value_from_lookup(self, "my-plain-parameter-name")</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">import software.amazon.awscdk.services.ssm.StringParameter; - -String stringValue = StringParameter.valueFromLookup(this, "my-plain-parameter-name");</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK.AWS.SSM; - -var stringValue = StringParameter.ValueFromLookup(this, "my-plain-parameter-name");</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Only plain Systems Manager strings may be retrieved. Secure strings cannot be retrieved. The latest version will always be returned. Specific versions cannot be requested.</p> -</div> -<div class="admonitionblock important"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-important" title="Important"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>The retrieved value will end up in your synthesized AWS CloudFormation template. This might be a security risk, depending on who has access to your AWS CloudFormation templates and what kind of value it is. Generally, don’t use this feature for passwords, keys, or other values you want to keep private.</p> -</div> -</td> -</tr> -</table> -</div> -</div> -<div class="sect3"> -<h4 id="ssm-write">12.11.3. Write values to Systems Manager</h4> -<div class="paragraph"> -<p>You can use the AWS CLI, the AWS Management Console, or an AWS SDK to set Systems Manager parameter values. The following examples use the <a href="https://docs.aws.amazon.com/cli/latest/reference/ssm/put-parameter.html">ssm put-parameter</a> CLI command.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">aws ssm put-parameter --name "parameter-name" --type "String" --value "parameter-value" -aws ssm put-parameter --name "secure-parameter-name" --type "SecureString" --value "secure-parameter-value"</code></pre> -</div> -</div> -<div class="paragraph"> -<p>When updating an SSM value that already exists, also include the <code>--overwrite</code> option.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">aws ssm put-parameter --overwrite --name "parameter-name" --type "String" --value "parameter-value" -aws ssm put-parameter --overwrite --name "secure-parameter-name" --type "SecureString" --value "secure-parameter-value"</code></pre> -</div> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="get-secrets-manager-value">12.12. Get a value from AWS Secrets Manager</h3> -<div class="paragraph"> -<p>To use values from AWS Secrets Manager in your AWS CDK app, use the <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_secretsmanager.Secret.html#static-fromwbrsecretwbrattributesscope-id-attrs">fromSecretAttributes()</a> method. It represents a value that is retrieved from Secrets Manager and used at AWS CloudFormation deployment time. The following is an example:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as sm from "aws-cdk-lib/aws-secretsmanager"; - -export class SecretsManagerStack extends cdk.Stack { - constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - const secret = sm.Secret.fromSecretAttributes(this, "ImportedSecret", { - secretCompleteArn: - "arn:aws:secretsmanager:<region>:<account-id-number>:secret:<secret-name>-<random-6-characters>" - // If the secret is encrypted using a KMS-hosted CMK, either import or reference that key: - // encryptionKey: ... - });</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const sm = require("aws-cdk-lib/aws-secretsmanager"); - -class SecretsManagerStack extends cdk.Stack { - constructor(scope, id, props) { - super(scope, id, props); - - const secret = sm.Secret.fromSecretAttributes(this, "ImportedSecret", { - secretCompleteArn: - "arn:aws:secretsmanager:<region>:<account-id-number>:secret:<secret-name>-<random-6-characters>" - // If the secret is encrypted using a KMS-hosted CMK, either import or reference that key: - // encryptionKey: ... - }); - } -} - -module.exports = { SecretsManagerStack }</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">import aws_cdk.aws_secretsmanager as sm - -class SecretsManagerStack(cdk.Stack): - def __init__(self, scope: cdk.App, id: str, **kwargs): - super().__init__(scope, name, **kwargs) - - secret = sm.Secret.from_secret_attributes(self, "ImportedSecret", - secret_complete_arn="arn:aws:secretsmanager:<region>:<account-id-number>:secret:<secret-name>-<random-6-characters>", - # If the secret is encrypted using a KMS-hosted CMK, either import or reference that key: - # encryption_key=.... - )</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">import software.amazon.awscdk.services.secretsmanager.Secret; -import software.amazon.awscdk.services.secretsmanager.SecretAttributes; - -public class SecretsManagerStack extends Stack { - public SecretsManagerStack(App scope, String id) { - this(scope, id, null); - } - - public SecretsManagerStack(App scope, String id, StackProps props) { - super(scope, id, props); - - Secret secret = (Secret)Secret.fromSecretAttributes(this, "ImportedSecret", SecretAttributes.builder() - .secretCompleteArn("arn:aws:secretsmanager:<region>:<account-id-number>:secret:<secret-name>-<random-6-characters>") - // If the secret is encrypted using a KMS-hosted CMK, either import or reference that key: - // .encryptionKey(...) - .build()); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK.AWS.SecretsManager; - -public class SecretsManagerStack : Stack -{ - public SecretsManagerStack(App scope, string id, StackProps props) : base(scope, id, props) { - - var secret = Secret.FromSecretAttributes(this, "ImportedSecret", new SecretAttributes { - SecretCompleteArn = "arn:aws:secretsmanager:<region>:<account-id-number>:secret:<secret-name>-<random-6-characters>" - // If the secret is encrypted using a KMS-hosted CMK, either import or reference that key: - // encryptionKey = ..., - }); - }</code></pre> -</div> -</div> -<div class="admonitionblock tip"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-tip" title="Tip"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>Use the AWS CLI <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_secretsmanager.Secret.html">create-secret</a> CLI command to create a secret from the command line, such as when testing:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">aws secretsmanager create-secret --name ImportedSecret --secret-string mygroovybucket</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The command returns an ARN that you can use with the preceding example.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>Once you have created a <code>Secret</code> instance, you can get the secret’s value from the instance’s <code>secretValue</code> attribute. The value is represented by a <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.SecretValue.html">SecretValue</a></code> instance, a special type of <a href="#tokens">Tokens and the AWS CDK</a>. Because it’s a token, it has meaning only after resolution. Your CDK app does not need to access its actual value. Instead, the app can pass the <code>SecretValue</code> instance (or its string or numeric representation) to whatever CDK method needs the value.</p> -</div> -</div> -<div class="sect2 topic"> -<h3 id="how-to-set-cw-alarm">12.13. Set a CloudWatch alarm</h3> -<div class="paragraph"> -<p>Use the <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_cloudwatch-readme.html">aws-cloudwatch</a> package to set up Amazon CloudWatch alarms on CloudWatch metrics. You can use predefined metrics or create your own.</p> -</div> -<div class="paragraph topiclist"> -<p>[[Topic List]]</p> -</div> -<div class="sect3"> -<h4 id="how-to-set-cw-alarm-use-metric">12.13.1. Use an existing metric</h4> -<div class="paragraph"> -<p>Many AWS Construct Library modules let you set an alarm on an existing metric by passing the metric’s name to a convenience method on an instance of an object that has metrics. For example, given an Amazon SQS queue, you can get the metric <strong>ApproximateNumberOfMessagesVisible</strong> from the queue’s <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_sqs.Queue.html#metricmetricname-props">metric()</a> method:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const metric = queue.metric("ApproximateNumberOfMessagesVisible");</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const metric = queue.metric("ApproximateNumberOfMessagesVisible");</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">metric = queue.metric("ApproximateNumberOfMessagesVisible")</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">Metric metric = queue.metric("ApproximateNumberOfMessagesVisible");</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">var metric = queue.Metric("ApproximateNumberOfMessagesVisible");</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="how-to-set-cw-alarm-new-metric">12.13.2. Create your own metric</h4> -<div class="paragraph"> -<p>Create your own <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_cloudwatch.Metric.html">metric</a> as follows, where the <em>namespace</em> value should be something like <strong>AWS/SQS</strong> for an Amazon SQS queue. You also need to specify your metric’s name and dimension:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const metric = new cloudwatch.Metric({ - namespace: 'MyNamespace', - metricName: 'MyMetric', - dimensionsMap: { MyDimension: 'MyDimensionValue' } -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const metric = new cloudwatch.Metric({ - namespace: 'MyNamespace', - metricName: 'MyMetric', - dimensionsMap: { MyDimension: 'MyDimensionValue' } -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">metric = cloudwatch.Metric( - namespace="MyNamespace", - metric_name="MyMetric", - dimensionsMap=dict(MyDimension="MyDimensionValue") -)</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">Metric metric = Metric.Builder.create() - .namespace("MyNamespace") - .metricName("MyMetric") - .dimensionsMap(java.util.Map.of( // Java 9 or later - "MyDimension", "MyDimensionValue")) - .build();</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">var metric = new Metric(this, "Metric", new MetricProps -{ - Namespace = "MyNamespace", - MetricName = "MyMetric", - Dimensions = new Dictionary<string, object> - { - { "MyDimension", "MyDimensionValue" } - } -});</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="how-to-set-cw-alarm-create">12.13.3. Create the alarm</h4> -<div class="paragraph"> -<p>Once you have a metric, either an existing one or one you defined, you can create an alarm. In this example, the alarm is raised when there are more than 100 of your metric in two of the last three evaluation periods. You can use comparisons such as less-than in your alarms via the <code>comparisonOperator</code> property. Greater-than-or-equal-to is the AWS CDK default, so we don’t need to specify it.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const alarm = new cloudwatch.Alarm(this, 'Alarm', { - metric: metric, - threshold: 100, - evaluationPeriods: 3, - datapointsToAlarm: 2, -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const alarm = new cloudwatch.Alarm(this, 'Alarm', { - metric: metric, - threshold: 100, - evaluationPeriods: 3, - datapointsToAlarm: 2 -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">alarm = cloudwatch.Alarm(self, "Alarm", - metric=metric, - threshold=100, - evaluation_periods=3, - datapoints_to_alarm=2 -)</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">import software.amazon.awscdk.services.cloudwatch.Alarm; -import software.amazon.awscdk.services.cloudwatch.Metric; - -Alarm alarm = Alarm.Builder.create(this, "Alarm") - .metric(metric) - .threshold(100) - .evaluationPeriods(3) - .datapointsToAlarm(2).build();</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">var alarm = new Alarm(this, "Alarm", new AlarmProps -{ - Metric = metric, - Threshold = 100, - EvaluationPeriods = 3, - DatapointsToAlarm = 2 -});</code></pre> -</div> -</div> -<div class="paragraph"> -<p>An alternative way to create an alarm is using the metric’s <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_cloudwatch.Metric.html#createwbralarmscope-id-props">createAlarm()</a> method, which takes essentially the same properties as the <code>Alarm</code> constructor. You don’t need to pass in the metric, because it’s already known.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">metric.createAlarm(this, 'Alarm', { - threshold: 100, - evaluationPeriods: 3, - datapointsToAlarm: 2, -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">metric.createAlarm(this, 'Alarm', { - threshold: 100, - evaluationPeriods: 3, - datapointsToAlarm: 2, -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">metric.create_alarm(self, "Alarm", - threshold=100, - evaluation_periods=3, - datapoints_to_alarm=2 -)</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">metric.createAlarm(this, "Alarm", new CreateAlarmOptions.Builder() - .threshold(100) - .evaluationPeriods(3) - .datapointsToAlarm(2) - .build());</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">metric.CreateAlarm(this, "Alarm", new CreateAlarmOptions -{ - Threshold = 100, - EvaluationPeriods = 3, - DatapointsToAlarm = 2 -});</code></pre> -</div> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="get-context-var">12.14. Save and retrieve context variable values</h3> -<div class="paragraph"> -<p>You can specify context variables with the AWS Cloud Development Kit (AWS CDK) <code class="noloc">CLI</code> or in the <code class="path">cdk.json</code> file. Then, use the <code>TryGetContext</code> method to retrieve values.</p> -</div> -<div class="paragraph topiclist"> -<p>[[Topic List]]</p> -</div> -<div class="sect3"> -<h4 id="develop-context-specify">12.14.1. Specify context variables</h4> -<div class="paragraph"> -<p>You can specify a context variable either as part of an AWS CDK <code class="noloc">CLI</code> command, or in <code class="path">cdk.json</code>.</p> -</div> -<div class="paragraph"> -<p>To create a command line context variable, use the <strong>--context</strong> (<strong>-c</strong>) option, as shown in the following example.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk synth -c bucket_name=mygroovybucket</code></pre> -</div> -</div> -<div class="paragraph"> -<p>To specify the same context variable and value in the <code>cdk.json</code> file, use the following code.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-json" data-lang="json">{ - "context": { - "bucket_name": "myotherbucket" - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>If you specify a context variable using both the AWS CDK <code class="noloc">CLI</code> and <code class="path">cdk.json</code> file, the AWS CDK <code class="noloc">CLI</code> value takes precedence.</p> -</div> -</div> -<div class="sect3"> -<h4 id="develop-context-retrieve">12.14.2. Retrieve context variable values</h4> -<div class="paragraph"> -<p>To get the value of a context variable in your app, use the <code>TryGetContext</code> method in the context of a construct. (That is, when <code>this</code>, or <code>self</code> in Python, is an instance of some construct.)</p> -</div> -<div class="paragraph"> -<p>In this example, we retrieve the value of the <code>bucket_name</code> context variable. If the requested value is not defined, <code>TryGetContext</code> returns <code>undefined</code> (<code>None</code> in Python; <code>null</code> in Java and C#; <code>nil</code> in Go) rather than raising an exception.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const bucket_name = this.node.tryGetContext('bucket_name');</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const bucket_name = this.node.tryGetContext('bucket_name');</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">bucket_name = self.node.try_get_context("bucket_name")</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">String bucketName = (String)this.getNode().tryGetContext("bucket_name");</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">var bucketName = this.Node.TryGetContext("bucket_name");</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Outside the context of a construct, you can access the context variable from the app object, like this.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const app = new cdk.App(); -const bucket_name = app.node.tryGetContext('bucket_name')</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const app = new cdk.App(); -const bucket_name = app.node.tryGetContext('bucket_name');</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">app = cdk.App() -bucket_name = app.node.try_get_context("bucket_name")</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">App app = App(); -String bucketName = (String)app.getNode().tryGetContext("bucket_name");</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">app = App(); -var bucketName = app.Node.TryGetContext("bucket_name");</code></pre> -</div> -</div> -<div class="paragraph"> -<p>For more details on working with context variables, see <a href="#context">Context values and the AWS CDK</a>.</p> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="use-cfn-public-registry">12.15. Use resources from the AWS CloudFormation Public Registry</h3> -<div class="paragraph"> -<p>The AWS CloudFormation Public Registry lets you manage extensions, both public and private, such as resources, modules, and hooks that are available for use in your AWS account. You can use public resource extensions in your AWS Cloud Development Kit (AWS CDK) applications with the <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.CfnResource.html">CfnResource</a> construct.</p> -</div> -<div class="paragraph"> -<p>To learn more about the AWS CloudFormation Public Registry, see <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/registry.html">Using the AWS CloudFormation registry</a> in the <em>AWS CloudFormation User Guide</em>.</p> -</div> -<div class="paragraph"> -<p>All public extensions published by AWS are available to all accounts in all Regions without any action on your part. However, you must activate each third-party extension you want to use, in each account and Region where you want to use it.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>When you use AWS CloudFormation with third-party resource types, you will incur charges. Charges are based on the number of handler operations you run per month and handler operation duration. See <a href="https://aws.amazon.com/cloudformation/pricing/">CloudFormation pricing</a> for complete details.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>To learn more about public extensions, see <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/registry-public.html">Using public extensions in CloudFormation</a> in the <em>AWS CloudFormation User Guide</em></p> -</div> -<div class="paragraph topiclist"> -<p>[[Topic List]]</p> -</div> -<div class="sect3"> -<h4 id="use-cfn-public-registry-activate">12.15.1. Activate a third-party resource in your account and Region</h4> -<div class="paragraph"> -<p>Extensions published by AWS do not require activation. They are always available in every account and Region. You can activate a third-party extension through the AWS Management Console, via the AWS Command Line Interface, or by deploying a special AWS CloudFormation resource.</p> -</div> -<div class="imageblock"> -<div class="content"> -<img src="images/activate-cfn-extension.png" alt="activate cfn extension"> -</div> -</div> -<div class="olist arabic"> -<ol class="arabic"> -<li> -<p>Sign in to the AWS account in which you want to use the extension, then switch to the Region where you want to use it.</p> -</li> -<li> -<p>Navigate to the CloudFormation console via the <strong>Services</strong> menu.</p> -</li> -<li> -<p>Choose <strong>Public extensions</strong> on the navigation bar, then activate the <strong>Third party</strong> radio button under <strong>Publisher</strong>. A list of the available third-party public extensions appears. (You may also choose <strong>AWS</strong> to see a list of the public extensions published by AWS, though you don’t need to activate them.)</p> -</li> -<li> -<p>Browse the list and find the extension you want to activate. Alternatively, search for it, then activate the radio button in the upper right corner of the extension’s card.</p> -</li> -<li> -<p>Choose the <strong>Activate</strong> button at the top of the list to activate the selected extension. The extension’s <strong>Activate</strong> page appears.</p> -</li> -<li> -<p>In the <strong>Activate</strong> page, you can override the extension’s default name and specify an execution role and logging configuration. You can also choose whether to automatically update the extension when a new version is released. When you have set these options as you like, choose <strong>Activate extension</strong> at the bottom of the page.</p> -</li> -<li> -<p>Use the <code>activate-type</code> command. Substitute the ARN of the custom type you want to use where indicated.</p> -<div class="paragraph"> -<p>The following is an example:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">aws cloudformation activate-type --public-type-arn public_extension_ARN --auto-update-activated</code></pre> -</div> -</div> -</li> -<li> -<p>Deploy a resource of type <code>AWS::CloudFormation::TypeActivation</code> and specify the following properties:</p> -<div class="olist loweralpha"> -<ol class="loweralpha" type="a"> -<li> -<p><code>TypeName</code> - The name of the type, such as <code>AWSQS::EKS::Cluster</code>.</p> -</li> -<li> -<p><code>MajorVersion</code> - The major version number of the extension that you want. Omit if you want the latest version.</p> -</li> -<li> -<p><code>AutoUpdate</code> - Whether to automatically update this extension when a new minor version is released by the publisher. (Major version updates require explicitly changing the <code>MajorVersion</code> property.)</p> -</li> -<li> -<p><code>ExecutionRoleArn</code> - The ARN of the IAM role under which this extension will run.</p> -</li> -<li> -<p><code>LoggingConfig</code> - The logging configuration for the extension.</p> -</li> -</ol> -</div> -<div class="paragraph"> -<p>The <code>TypeActivation</code> resource can be deployed by the CDK using the <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.CfnResource.html">CfnResource</a> construct. This is shown for the actual extensions in the following section.</p> -</div> -</li> -</ol> -</div> -</div> -<div class="sect3"> -<h4 id="use-cfn-public-registry-add">12.15.2. Add a resource from the AWS CloudFormation Public Registry to your CDK app</h4> -<div class="paragraph"> -<p>Use the <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.CfnResource.html">CfnResource</a> construct to include a resource from the AWS CloudFormation Public Registry in your application. This construct is in the CDK’s <code>aws-cdk-lib</code> module.</p> -</div> -<div class="paragraph"> -<p>For example, suppose that there is a public resource named <code>MY::S5::UltimateBucket</code> that you want to use in your AWS CDK application. This resource takes one property: the bucket name. The corresponding <code>CfnResource</code> instantiation looks like this.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const ubucket = new CfnResource(this, 'MyUltimateBucket', { - type: 'MY::S5::UltimateBucket::MODULE', - properties: { - BucketName: 'UltimateBucket' - } -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const ubucket = new CfnResource(this, 'MyUltimateBucket', { - type: 'MY::S5::UltimateBucket::MODULE', - properties: { - BucketName: 'UltimateBucket' - } -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">ubucket = CfnResource(self, "MyUltimateBucket", - type="MY::S5::UltimateBucket::MODULE", - properties=dict( - BucketName="UltimateBucket"))</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">CfnResource.Builder.create(this, "MyUltimateBucket") - .type("MY::S5::UltimateBucket::MODULE") - .properties(java.util.Map.of( // Map.of requires Java 9+ - "BucketName", "UltimateBucket")) - .build();</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">new CfnResource(this, "MyUltimateBucket", new CfnResourceProps -{ - Type = "MY::S5::UltimateBucket::MODULE", - Properties = new Dictionary<string, object> - { - ["BucketName"] = "UltimateBucket" - } -});</code></pre> -</div> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="define-iam-l2">12.16. Define permissions for L2 constructs with the AWS CDK</h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Define AWS Identity and Access Management (IAM) roles and policies for L2 constructs when using the AWS Cloud Development Kit (AWS CDK).</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>Define AWS Identity and Access Management (IAM) roles and policies for L2 constructs when using the AWS Cloud Development Kit (AWS CDK).</p> -</div> -<div class="sect3"> -<h4 id="define-iam-l2-grant">12.16.1. Use grant methods to define permissions</h4> -<div class="paragraph"> -<p>When you define your infrastructure using L2 constructs from the AWS Construct Library, you can use the provided <em>grant methods</em> to specify the permissions your resources will require. The AWS CDK will automatically create the IAM roles needed for all AWS resources that require them.</p> -</div> -<div class="paragraph"> -<p>The following is an example that defines permissions between an AWS Lambda function and Amazon Simple Storage Service (Amazon S3) bucket. Here, the <code>grantRead</code> method of the Bucket L2 construct is used to define these permissions:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as cdk from 'aws-cdk-lib'; -import { Construct } from 'constructs'; -import * as s3 from 'aws-cdk-lib/aws-s3'; -import * as lambda from 'aws-cdk-lib/aws-lambda'; -import * as kms from 'aws-cdk-lib/aws-kms'; - -export class CdkDemoStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - const key = new kms.Key(this, 'BucketKey'); - const bucket = new s3.Bucket(this, 'Bucket', { - encryptionKey: key, - }); - const handler = new lambda.Function(this, 'Handler', { - runtime: lambda.Runtime.NODEJS_20_X, - handler: 'index.handler', - code: lambda.Code.fromAsset('lambda'), - }); - - // Define permissions between function and S3 bucket using grantRead method - bucket.grantRead(handler); - - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const { Stack, Duration } = require('aws-cdk-lib'); -const s3 = require('aws-cdk-lib/aws-s3'); -const lambda = require('aws-cdk-lib/aws-lambda'); -const kms = require('aws-cdk-lib/aws-kms'); - -class CdkDemoStack extends Stack { - - constructor(scope, id, props) { - super(scope, id, props); - - const key = new kms.Key(this, 'BucketKey'); - const bucket = new s3.Bucket(this, 'Bucket', { - encryptionKey: key, - }); - const handler = new lambda.Function(this, 'Handler', { - runtime: lambda.Runtime.NODEJS_20_X, - handler: 'index.handler', - code: lambda.Code.fromAsset('lambda'), - }); - - // Define permissions between function and S3 bucket using grantRead method - bucket.grantRead(handler); - - } -} - -// ...</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">from aws_cdk import ( - Stack, - aws_s3 as s3, - aws_lambda as _lambda, - aws_kms as kms, -) -from constructs import Construct - -class CdkDemoStack(Stack): - - def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: - super().__init__(scope, construct_id, **kwargs) - - key = kms.Key(self, 'BucketKey') - bucket = s3.Bucket(self, 'Bucket') - handler = _lambda.Function( - self, - 'Handler', - runtime = _lambda.Runtime.NODEJS_20_X, - handler = 'index.handler', - code = _lambda.Code.from_asset('lambda'), - ) - - # Define permissions between function and S3 bucket using grantRead method - bucket.grantRead(handler)</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">package com.myorg; - -import software.amazon.awscdk.core.App; -import software.amazon.awscdk.core.Stack; -import software.amazon.awscdk.core.StackProps; -import software.amazon.awscdk.services.kms.Key; -import software.amazon.awscdk.services.kms.KeyProps; -import software.amazon.awscdk.services.s3.Bucket; -import software.amazon.awscdk.services.s3.BucketProps; -import software.amazon.awscdk.services.lambda.Function; -import software.amazon.awscdk.services.lambda.FunctionProps; -import software.amazon.awscdk.services.lambda.Runtime; -import software.amazon.awscdk.services.lambda.Code; -import software.constructs.Construct; - -public class CdkDemoStack extends Stack { - public CdkDemoStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public CdkDemoStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - Key key = new Key(this, "BucketKey", KeyProps.builder().build()); - - Bucket bucket = new Bucket(this, "Bucket", BucketProps.builder() - .encryptionKey(key) - .build()); - - Function handler = new Function(this, "Handler", FunctionProps.builder() - .runtime(Runtime.NODEJS_20_X) - .handler("index.handler") - .code(Code.fromAsset("lambda")) - .build()); - - // Define permissions between function and S3 bucket using grantRead method - bucket.grantRead(handler); - } - - public static void main(final String[] args) { - App app = new App(); - - new CdkDemoStack(app, "CdkDemoStack"); - - app.synth(); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; -using Amazon.CDK.AWS.KMS; -using Amazon.CDK.AWS.S3; -using Amazon.CDK.AWS.Lambda; - -namespace CdkDemo -{ - public class CdkDemoStack : Stack - { - internal CdkDemoStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) - { - var key = new Key(this, "BucketKey"); - - var bucket = new Bucket(this, "Bucket", new BucketProps - { - EncryptionKey = key - }); - - var handler = new Function(this, "Handler", new FunctionProps - { - Runtime = Runtime.NODEJS_20_X, - Handler = "index.handler", - Code = Code.FromAsset("lambda") - }); - - // Define permissions between function and S3 bucket using grantRead method - bucket.GrantRead(handler); - } - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">package main -import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/aws-cdk-go/awscdk/v2/awskms" - "github.com/aws/aws-cdk-go/awscdk/v2/awss3" - "github.com/aws/aws-cdk-go/awscdk/v2/awslambda" - "github.com/aws/constructs-go/constructs/v10" - "github.com/aws/jsii-runtime-go" -) -// ... -func NewCdkDemoStack(scope constructs.Construct, id string, props *CdkDemoStackProps) awscdk.Stack { - stack := awscdk.NewStack(scope, &id, &props.StackProps) - key := awskms.NewKey(stack, jsii.String("BucketKey"), nil) - bucket := awss3.NewBucket(stack, jsii.String("Bucket"), &awss3.BucketProps{ - EncryptionKey: key, - }) - handler := awslambda.NewFunction(stack, jsii.String("Handler"), &awslambda.FunctionProps{ - Runtime: awslambda.Runtime_NODEJS_20_X(), - Handler: jsii.String("index.handler"), - Code: awslambda.Code_FromAsset(jsii.String("lambda"), &awss3assets.AssetOptions{}), - }) - bucket.GrantRead(handler) - return stack -} -// ...</code></pre> -</div> -</div> -<div class="paragraph"> -<p>When you use grant methods of L2 constructs to define permissions between resources, the AWS CDK will create roles with least privilege policies based on the method you specify. As a security best practice, we recommend that you use the method that applies only the permissions that you require. For example, if you only need to grant permissions for a Lambda function to read from an Amazon S3 bucket, use the <code>grantRead</code> method instead of <code>grantReadWrite</code>.</p> -</div> -<div class="paragraph"> -<p>For each method that you use, the CDK creates a unique IAM role for the specified resources. If necessary, you can also directly modify the policy that will be attached to the role. The following is an example:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import { aws_iam as iam } from 'aws-cdk-lib'; - -handler.addToRolePolicy(new iam.PolicyStatement({ - actions: ['s3:GetObject', 's3:List*'], - resources: [ - bucket.bucketArn, - bucket.arnForObjects('*'), - ] -}));</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const iam = require('aws-cdk-lib/aws-iam'); - -handler.addToRolePolicy(new iam.PolicyStatement({ - actions: ['s3:GetObject', 's3:List*'], - resources: [ - bucket.bucketArn, - bucket.arnForObjects('*'), - ] -}));</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">from aws_cdk import aws_iam as iam - -handler.add_to_role_policy(iam.PolicyStatement( - actions=['s3:GetObject', 's3:List*'], - resources=[ - bucket.bucket_arn, - bucket.arn_for_objects('*'), - ] -))</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">import software.amazon.awscdk.services.iam.PolicyStatement; -import software.amazon.awscdk.services.iam.PolicyStatementProps; - -handler.addToRolePolicy(PolicyStatement.Builder.create() - .actions(Arrays.asList("s3:GetObject", "s3:List*")) - .resources(Arrays.asList( - bucket.getBucketArn(), - bucket.arnForObjects("*") - )) - .build());</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK.AWS.IAM; -using Amazon.CDK.AWS.S3; -using Amazon.CDK.AWS.Lambda; - -handler.AddToRolePolicy(new PolicyStatement(new PolicyStatementProps -{ - Actions = new[] { "s3:GetObject", "s3:List*" }, - Resources = new[] { bucket.BucketArn, bucket.ArnForObjects("*") } -}));</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">package main - -import ( - // ... - "github.com/aws/aws-cdk-go/awscdk/v2/awsiam" - // ... -) - -// ... - -func NewCdkDemoStack(scope constructs.Construct, id string, props *CdkDemoStackProps) awscdk.Stack { - // ... - - handler.AddToRolePolicy(awsiam.NewPolicyStatement(&awsiam.PolicyStatementProps{ - Actions: jsii.Strings("s3:GetObject", "s3:List*"), - Resources: jsii.Strings(bucket.BucketArn(), bucket.ArnForObjects("*")), - })) - - // ...</code></pre> -</div> -</div> -<div class="paragraph"> -<p>However, we recommend that you use the <code>grant</code> methods when available.</p> -</div> -</div> -<div class="sect3"> -<h4 id="define-iam-l2-manual">12.16.2. Manually create and use IAM roles</h4> -<div class="paragraph"> -<p>If you prefer not to use the CDK <code>grant</code> methods to create and manage permissions, you must manually create and configure them. You can create IAM roles using the AWS Management Console, AWS CLI, or AWS SDKs. Then, you can pass them into your CDK application manually or use the <em>role customization</em> feature.</p> -</div> -<div class="sect4"> -<h5 id="define-iam-l2-manual-role">Reference and manage all roles manually</h5> -<div class="paragraph"> -<p>Constructs that require a role have an optional <code>role</code> property that you can use to pass in a role object.</p> -</div> -<div class="olist arabic"> -<ol class="arabic"> -<li> -<p>Use <code>Role.fromRoleName()</code> to reference your pre-existing role. The following is an example:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const existingRole = Role.fromRoleName(stack, 'Role', 'my-pre-existing-role', { - mutable: false // Prevent CDK from attempting to add policies to this role -}</code></pre> -</div> -</div> -</li> -<li> -<p>Pass the pre-existing role when defining your resource. The following is an example:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const handler = new lambda.Function(stack, 'Handler', { runtime: lambda.Runtime.NODEJS_20_XZ, handler: - 'index.handler', code: lambda.Code.fromAsset(path.join(__dirname, 'lambda-handler')), // Pass in pre-existing role - role: existingRole, });</code></pre> -</div> -</div> -</li> -</ol> -</div> -</div> -<div class="sect4"> -<h5 id="define-iam-l2-manual-customization">Use the role customization feature</h5> -<div class="paragraph"> -<p>The AWS CDK <em>role customization</em> feature generates a report of roles and policies in your CDK app. You can use this feature to generate a report. Then you can substitute pre-created roles for them.</p> -</div> -<div class="olist arabic"> -<ol class="arabic"> -<li> -<p>Add <code>Role.customizeRoles()</code> somewhere towards the top of your CDK application. The following is an example:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const stack = new Stack(app, 'LambdaStack'); - -// Add this to use the role customization feature -iam.Role.customizeRoles(stack); - -// Define your resources using L2 constructs -const key = new kms.Key(stack, 'BucketKey'); -const bucket = new s3.Bucket(stack, 'Bucket', { - encryptionKey: key, -}); -const handler = new lambda.Function(stack, 'Handler', { - runtime: lambda.Runtime.NODEJS_16_X, - handler: 'index.handler', - code: lambda.Code.fromAsset(path.join(__dirname, 'lambda-handler')), -}); - -// The grantRead() is still important. Even though it actually doesn't mutate -// any policies, it indicates the need for them. -bucket.grantRead(handler);</code></pre> -</div> -</div> -</li> -<li> -<p>When you synthesize your application, the CDK will throw an error, indicating that you need to provide the pre-created role name to <code>Role.customizeRoles()</code>. The following is an example of the generated report:</p> -<div class="listingblock"> -<div class="content"> -<pre><missing role> (LambdaStack/Handler/ServiceRole) - -AssumeRole Policy: -[ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "lambda.amazonaws.com" - } - } -] - -Managed Policy ARNs: -[ - "arn:(PARTITION):iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" -] - -Managed Policies Statements: -NONE - -Identity Policy Statements: -[ - { - "Action": [ - "s3:GetObject*", - "s3:GetBucket*", - "s3:List*" - ], - "Effect": "Allow", - "Resource": [ - "(LambdaStack/Bucket/Resource.Arn)", - "(LambdaStack/Bucket/Resource.Arn)/*" - ] - } -]</pre> -</div> -</div> -</li> -<li> -<p>Once the role is created, you can pass it into your application for the resource that it applies to. For example, if the name of the role created for <code>LambdaStack/Handler/ServiceRole</code> is <code>lambda-service-role</code>, you would update your CDK app as follows:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const stack = new Stack(app, 'LambdaStack'); - -// Add this to pass in the role -iam.Role.customizeRoles(stack, { - usePrecreatedRoles: { - 'LambdaStack/Handler/ServiceRole': 'lambda-service-role', - }, -});</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The CDK will now use the pre-created role name anywhere that the role is referenced in the CDK application. It will also continue to generate the report so that any future policy changes can be referenced.</p> -</div> -<div class="paragraph"> -<p>You will notice that the reference to the Amazon S3 bucket ARN in the report is rendered as (<code>LambdaStack/Bucket/Resource.Arn</code>) instead of the actual ARN of the bucket. This is because the bucket ARN is a deploy time value that is not known at synthesis (the bucket hasn’t been created yet). This is another example of why we recommend allowing CDK to manage IAM roles and permissions by using the provided <code>grant</code> methods. In order to create the role with the initial policy, the admin will have to create the policy with broader permissions (for example, <code>arn:aws:s3:::*</code>).</p> -</div> -</li> -</ol> -</div> -</div> -</div> -</div> -</div> -</div> -<div class="sect1 topic"> -<h2 id="configure-synth">13. Configure and perform CDK stack synthesis</h2> -<div class="sectionbody"> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Before you can deploy an AWS Cloud Development Kit (AWS CDK) stack, it must first be synthesized. Stack synthesis is the process of creating an AWS CloudFormation template from a CDK stack. The CloudFormation template is what you then deploy to provision your resources on AWS.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>Before you can deploy an AWS Cloud Development Kit (AWS CDK) stack, it must first be synthesized. <em>Stack synthesis</em> is the process of producing an AWS CloudFormation template and deployment artifacts from a CDK stack. The template and artifacts are known as the <em>cloud assembly</em>. The cloud assembly is what gets deployed to provision your resources on AWS. For more information on how deployments work, see <a href="#deploy-how">How AWS CDK deployments work</a>.</p> -</div> -<div class="sect2"> -<h3 id="configure-synth-bootstrap">13.1. How synthesis and bootstrapping work together</h3> -<div class="paragraph"> -<p>For your CDK apps to properly deploy, the CloudFormation templates produced during synthesis must correctly specify the resources created during bootstrapping. Therefore, bootstrapping and synthesis must complement one another for a deployment to be successful:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Bootstrapping is a one-time process of setting up an AWS environment for AWS CDK deployments. It configures specific AWS resources in your environment that are used by the CDK for deployments. These are commonly referred to as <em>bootstrap resources</em>. For instructions on bootstrapping, see <a href="#bootstrapping-env">Bootstrap your environment for use with the AWS CDK</a>.</p> -</li> -<li> -<p>CloudFormation templates produced during synthesis include information on which bootstrap resources to use. During synthesis, the CDK <code class="noloc">CLI</code> doesn’t know specifically how your AWS environment has been bootstrapped. Instead, the CDK <code class="noloc">CLI</code> produces CloudFormation templates based on the synthesizer you configure for each CDK stack. For a deployment to be successful, the synthesizer must produce CloudFormation templates that reference the correct bootstrap resources to use.</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>The CDK comes with a default synthesizer and bootstrapping configuration that are designed to work together. If you customize one, you must apply relevant customizations to the other.</p> -</div> -</div> -<div class="sect2"> -<h3 id="bootstrapping-synthesizers">13.2. How to configure CDK stack synthesis</h3> -<div class="paragraph"> -<p>You configure CDK stack synthesis using the <code>synthesizer</code> property of your <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html">Stack</a></code> instance. This property specifies how your CDK stacks will be synthesized. You provide an instance of a class that implements <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.IStackSynthesizer.html">IStackSynthesizer</a></code> or <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.IReusableStackSynthesizer.html">IReusableStackSynthesizer</a></code>. Its methods will be invoked every time an asset is added to the stack or when the stack is synthesized. The following is a basic example of using this property within your stack:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">new MyStack(this, 'MyStack', { - // stack properties - synthesizer: new DefaultStackSynthesizer({ - // synthesizer properties - }), -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">new MyStack(this, 'MyStack', { - // stack properties - synthesizer: new DefaultStackSynthesizer({ - // synthesizer properties - }), -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">MyStack(self, "MyStack", - # stack properties - synthesizer=DefaultStackSynthesizer( - # synthesizer properties -))</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">new MyStack(app, "MyStack", StackProps.builder() - // stack properties - .synthesizer(DefaultStackSynthesizer.Builder.create() - // synthesizer properties - .build()) - .build();</code></pre> -</div> -</div> -</dd> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">new MyStack(app, "MyStack", new StackProps -// stack properties -{ - Synthesizer = new DefaultStackSynthesizer(new DefaultStackSynthesizerProps - { - // synthesizer properties - }) -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">func main() { - app := awscdk.NewApp(nil) - - NewMyStack(app, "MyStack", &MyStackProps{ - StackProps: awscdk.StackProps{ - Synthesizer: awscdk.NewDefaultStackSynthesizer(&awscdk.DefaultStackSynthesizerProps{ - // synthesizer properties - }), - }, - }) - - app.Synth(nil) -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>You can also configure a synthesizer for all CDK stacks in your CDK app using the <code>defaultStackSynthesizer</code> property of your <code>App</code> instance:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import { App, Stack, DefaultStackSynthesizer } from 'aws-cdk-lib'; - -const app = new App({ - // Configure for all stacks in this app - defaultStackSynthesizer: new DefaultStackSynthesizer({ - /* ... */ - }), -});</code></pre> -</div> -</div> -</dd> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const { App, Stack, DefaultStackSynthesizer } = require('aws-cdk-lib'); - -const app = new App({ - // Configure for all stacks in this app - defaultStackSynthesizer: new DefaultStackSynthesizer({ - /* ... */ - }), -});</code></pre> -</div> -</div> -</dd> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">from aws_cdk import App, Stack, DefaultStackSynthesizer - -app = App( - default_stack_synthesizer=DefaultStackSynthesizer( - # Configure for all stacks in this app - # ... - ) -)</code></pre> -</div> -</div> -</dd> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">import software.amazon.awscdk.App; -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.DefaultStackSynthesizer; - -public class Main { - public static void main(final String[] args) { - App app = new App(AppProps.builder() - // Configure for all stacks in this app - .defaultStackSynthesizer(DefaultStackSynthesizer.Builder.create().build()) - .build() - ); - } -}</code></pre> -</div> -</div> -</dd> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; -using Amazon.CDK.Synthesizers; - -namespace MyNamespace -{ - sealed class Program - { - public static void Main(string[] args) - { - var app = new App(new AppProps - { - // Configure for all stacks in this app - DefaultStackSynthesizer = new DefaultStackSynthesizer(new DefaultStackSynthesizerProps - { - // ... - }) - }); - } - } -}</code></pre> -</div> -</div> -</dd> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">package main - -import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/constructs-go/constructs/v10" - "github.com/aws/jsii-runtime-go" -) - -func main() { - defer jsii.Close() - - app := awscdk.NewApp(&awscdk.AppProps{ - // Configure for all stacks in this app - DefaultStackSynthesizer: awscdk.NewDefaultStackSynthesizer(&awscdk.DefaultStackSynthesizerProps{ - // ... - }), - }) -}</code></pre> -</div> -</div> -</dd> -</dl> -</div> -<div class="paragraph"> -<p>By default, the AWS CDK uses <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.DefaultStackSynthesizer.html">DefaultStackSynthesizer</a></code>. If you don’t configure a synthesizer, this synthesizer will be used.</p> -</div> -<div class="paragraph"> -<p>If you don’t modify bootstrapping, such as making changes to the bootstrap stack or template, you don’t have to modify stack synthesis. You don’t even have to provide a synthesizer. The CDK will use the default <code>DefaultStackSynthesizer</code> class to configure CDK stack synthesis to properly interact with your bootstrap stack.</p> -</div> -</div> -<div class="sect2"> -<h3 id="configure-synth-stack">13.3. How to synthesize a CDK stack</h3> -<div class="paragraph"> -<p>To synthesize a CDK stack, use the AWS CDK Command Line Interface (AWS CDK <code class="noloc">CLI</code>) <code>cdk synth</code> command. For more information about this command, including options that you can use with this command, see <a href="#ref-cli-cmd-synth">cdk synthesize</a>.</p> -</div> -<div class="paragraph"> -<p>If your CDK app contains a single stack, or to synthesize all stacks, you don’t have to provide the CDK stack name as an argument. By default, the CDK <code class="noloc">CLI</code> will synthesize your CDK stacks into AWS CloudFormation templates. A <code class="path">json</code> formatted template for each stack is saved to the <code class="path">cdk.out</code> directory. If your app contains a single stack, a <code class="path">yaml</code> formatted template is printed to <code>stdout</code>. The following is an example:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk synth -Resources: - CDKMetadata: - Type: AWS::CDK::Metadata - Properties: - Analytics: v2:deflate64:H4sIAAAAAAAA/unique-identifier - Metadata: - aws:cdk:path: CdkAppStack/CDKMetadata/Default - Condition: CDKMetadataAvailable - ...</code></pre> -</div> -</div> -<div class="paragraph"> -<p>If your CDK app contains multiple stacks, you can provide the logical ID of a stack to synthesize a single stack. The following is an example:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk synth MyStackName</code></pre> -</div> -</div> -<div class="paragraph"> -<p>If you don’t synthesize a stack and run <code>cdk deploy</code>, the CDK <code class="noloc">CLI</code> will automatically synthesize your stack before deployment.</p> -</div> -</div> -<div class="sect2"> -<h3 id="how-synth-default">13.4. How synthesis works by default</h3> -<div class="sect3"> -<h4 id="how-synth-default-logical-ids">13.4.1. Generated logical IDs in your AWS CloudFormation template</h4> -<div class="paragraph"> -<p>When you synthesize a CDK stack to produce a CloudFormation template, logical IDs are generated from the following sources, formatted as <code class="replaceable"><construct-path><construct-ID><unique-hash></code>:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><strong>Construct path</strong> – The entire path to the construct in your CDK app. This path excludes the ID of the L1 construct, which is always <code>Resource</code> or <code>Default</code>, and the ID of the top-level stack that it’s a part of.</p> -</li> -<li> -<p><strong>Construct ID</strong> – The ID that you provide as the second argument when instantiating your construct.</p> -</li> -<li> -<p><strong>Unique hash</strong> – The AWS CDK generates an 8 character unique hash using a deterministic hashing algorithm. This unique hash helps to ensure that logical ID values in your template are unique from one another. The deterministic behavior of this hash generation ensures that the generated logical ID value for each construct remains the same every time that you perform synthesis. The hash value will only change if you modify specific construct values such as your construct’s ID or its path.</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>Logical IDs have a maximum length of 255 characters. Therefore, the AWS CDK will truncate the construct path and construct ID if necessary to keep within that limit.</p> -</div> -<div class="paragraph"> -<p>The following is an example of a construct that defines an Amazon Simple Storage Service (Amazon S3) bucket. Here, we pass <code>myBucket</code> as the ID for our construct:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as cdk from 'aws-cdk-lib'; -import { Construct} from 'constructs'; -import * as s3 from 'aws-cdk-lib/aws-s3'; - -export class MyCdkAppStack extends cdk.Stack { - constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - // Define the S3 bucket - new s3.Bucket(this, 'myBucket', { - versioned: true, - removalPolicy: cdk.RemovalPolicy.DESTROY, - }); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const cdk = require('aws-cdk-lib'); -const s3 = require('aws-cdk-lib/aws-s3'); - -class MyCdkAppStack extends cdk.Stack { - - constructor(scope, id, props) { - super(scope, id, props); - - new s3.Bucket(this, 'myBucket', { - versioned: true, - removalPolicy: cdk.RemovalPolicy.DESTROY, - }); - } -} - -module.exports = { MyCdkAppStack }</code></pre> -</div> -</div> -</dd> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">import aws_cdk as cdk -from constructs import Construct -from aws_cdk import Stack -from aws_cdk import aws_s3 as s3 - -class MyCdkAppStack(Stack): - def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: - super().__init__(scope, construct_id, **kwargs) - - s3.Bucket(self, 'MyBucket', - versioned=True, - removal_policy=cdk.RemovalPolicy.DESTROY - )</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">package com.myorg; - -import software.constructs.Construct; -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.StackProps; -import software.amazon.awscdk.services.s3.Bucket; -import software.amazon.awscdk.services.s3.BucketProps; -import software.amazon.awscdk.RemovalPolicy; - -public class MyCdkAppStack extends Stack { - public MyCdkAppStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public MyCdkAppStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - Bucket.Builder.create(this, "myBucket") - .versioned(true) - .removalPolicy(RemovalPolicy.DESTROY) - .build(); - } -}</code></pre> -</div> -</div> -</dd> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; -using Constructs; -using Amazon.CDK.AWS.S3; - -namespace MyCdkApp -{ - public class MyCdkAppStack : Stack - { - public MyCdkAppStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) - { - new Bucket(this, "myBucket", new BucketProps - { - Versioned = true, - RemovalPolicy = RemovalPolicy.DESTROY - }); - } - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">package main - -import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/aws-cdk-go/awscdk/v2/awss3" - "github.com/aws/constructs-go/constructs/v10" - "github.com/aws/jsii-runtime-go" -) - -type MyCdkAppStackProps struct { - awscdk.StackProps -} - -func NewMyCdkAppStack(scope constructs.Construct, id string, props *MyCdkAppStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - stack := awscdk.NewStack(scope, &id, &sprops) - - awss3.NewBucket(stack, jsii.String("myBucket"), &awss3.BucketProps{ - Versioned: jsii.Bool(true), - RemovalPolicy: awscdk.RemovalPolicy_DESTROY, - }) - - return stack -} - -// ...</code></pre> -</div> -</div> -<div class="paragraph"> -<p>When we run <code>cdk synth</code>, a logical ID in the format of <code>myBucket<code class="replaceable">unique-hash</code></code> gets generated. The following is an example of this resource in the generated AWS CloudFormation template:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-yaml" data-lang="yaml">Resources: - myBucket5AF9C99B: - Type: AWS::S3::Bucket - Properties: - VersioningConfiguration: - Status: Enabled - UpdateReplacePolicy: Delete - DeletionPolicy: Delete - Metadata: - aws:cdk:path: S3BucketAppStack/myBucket/Resource</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The following is an example of a custom construct named <code>Bar</code> that defines an Amazon S3 bucket. The <code>Bar</code> construct includes the custom construct <code>Foo</code> in its path:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as cdk from 'aws-cdk-lib'; -import { Construct } from 'constructs'; -import * as s3 from 'aws-cdk-lib/aws-s3'; - -// Define the Bar construct -export class Bar extends Construct { - constructor(scope: Construct, id: string) { - super(scope, id); - - // Define an S3 bucket inside of Bar - new s3.Bucket(this, 'Bucket', { - versioned: true, - removalPolicy: cdk.RemovalPolicy.DESTROY, - } ); - } -} - -// Define the Foo construct -export class Foo extends Construct { - constructor(scope: Construct, id: string) { - super(scope, id); - - // Create an instance of Bar inside Foo - new Bar(this, 'Bar'); - } -} - -// Define the CDK stack -export class MyCustomAppStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - // Instantiate Foo construct in the stack - new Foo(this, 'Foo'); - } -}</code></pre> -</div> -</div> -</dd> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const cdk = require('aws-cdk-lib'); -const s3 = require('aws-cdk-lib/aws-s3'); -const { Construct } = require('constructs'); - -// Define the Bar construct -class Bar extends Construct { - constructor(scope, id) { - super(scope, id); - - // Define an S3 bucket inside of Bar - new s3.Bucket(this, 'Bucket', { - versioned: true, - removalPolicy: cdk.RemovalPolicy.DESTROY, - }); - } -} - -// Define the Foo construct -class Foo extends Construct { - constructor(scope, id) { - super(scope, id); - - // Create an instance of Bar inside Foo - new Bar(this, 'Bar'); - } -} - -// Define the CDK stack -class MyCustomAppStack extends cdk.Stack { - constructor(scope, id, props) { - super(scope, id, props); - - // Instantiate Foo construct in the stack - new Foo(this, 'Foo'); - } -} - -module.exports = { MyCustomAppStack }</code></pre> -</div> -</div> -</dd> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">import aws_cdk as cdk -from constructs import Construct -from aws_cdk import ( - Stack, - aws_s3 as s3, - RemovalPolicy, -) - -# Define the Bar construct -class Bar(Construct): - def __init__(self, scope: Construct, id: str) -> None: - super().__init__(scope, id) - - # Define an S3 bucket inside of Bar - s3.Bucket(self, 'Bucket', - versioned=True, - removal_policy=RemovalPolicy.DESTROY - ) - -# Define the Foo construct -class Foo(Construct): - def __init__(self, scope: Construct, id: str) -> None: - super().__init__(scope, id) - - # Create an instance of Bar inside Foo - Bar(self, 'Bar') - -# Define the CDK stack -class MyCustomAppStack(Stack): - def __init__(self, scope: Construct, id: str, **kwargs) -> None: - super().__init__(scope, id, **kwargs) - - # Instantiate Foo construct in the stack - Foo(self, 'Foo')</code></pre> -</div> -</div> -</dd> -<dt class="hdlist1">Java</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>In <code class="path">my-custom-app/src/main/java/com/myorg/Bar.java</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">package com.myorg; - -import software.constructs.Construct; -import software.amazon.awscdk.services.s3.Bucket; -import software.amazon.awscdk.services.s3.BucketProps; -import software.amazon.awscdk.RemovalPolicy; - -public class Bar extends Construct { - public Bar(final Construct scope, final String id) { - super(scope, id); - - // Define an S3 bucket inside Bar - Bucket.Builder.create(this, "Bucket") - .versioned(true) - .removalPolicy(RemovalPolicy.DESTROY) - .build(); - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>In <code class="path">my-custom-app/src/main/java/com/myorg/Foo.java</code>:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">package com.myorg; - -import software.constructs.Construct; - -public class Foo extends Construct { - public Foo(final Construct scope, final String id) { - super(scope, id); - - // Create an instance of Bar inside Foo - new Bar(this, "Bar"); - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>In <code class="path">my-custom-app/src/main/java/com/myorg/MyCustomAppStack.java</code>:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">package com.myorg; - -import software.constructs.Construct; -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.StackProps; - -public class MyCustomAppStack extends Stack { - public MyCustomAppStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - // Instantiate Foo construct in the stack - new Foo(this, "Foo"); - } - - // Overload constructor in case StackProps is not provided - public MyCustomAppStack(final Construct scope, final String id) { - this(scope, id, null); - } -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; -using Constructs; -using Amazon.CDK.AWS.S3; - -namespace MyCustomApp -{ - // Define the Bar construct - public class Bar : Construct - { - public Bar(Construct scope, string id) : base(scope, id) - { - // Define an S3 bucket inside Bar - new Bucket(this, "Bucket", new BucketProps - { - Versioned = true, - RemovalPolicy = RemovalPolicy.DESTROY - }); - } - } - - // Define the Foo construct - public class Foo : Construct - { - public Foo(Construct scope, string id) : base(scope, id) - { - // Create an instance of Bar inside Foo - new Bar(this, "Bar"); - } - } - - // Define the CDK Stack - public class MyCustomAppStack : Stack - { - public MyCustomAppStack(Construct scope, string id, StackProps props = null) : base(scope, id, props) - { - // Instantiate Foo construct in the stack - new Foo(this, "Foo"); - } - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">package main - -import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/aws-cdk-go/awscdk/v2/awss3" - "github.com/aws/constructs-go/constructs/v10" - "github.com/aws/jsii-runtime-go" -) - -// Define the Bar construct -type Bar struct { - constructs.Construct -} - -func NewBar(scope constructs.Construct, id string) constructs.Construct { - bar := constructs.NewConstruct(scope, &id) - - // Define an S3 bucket inside Bar - awss3.NewBucket(bar, jsii.String("Bucket"), &awss3.BucketProps{ - Versioned: jsii.Bool(true), - RemovalPolicy: awscdk.RemovalPolicy_DESTROY, - }) - - return bar -} - -// Define the Foo construct -type Foo struct { - constructs.Construct -} - -func NewFoo(scope constructs.Construct, id string) constructs.Construct { - foo := constructs.NewConstruct(scope, &id) - - // Create an instance of Bar inside Foo - NewBar(foo, "Bar") - - return foo -} - -// Define the CDK Stack -type MyCustomAppStackProps struct { - awscdk.StackProps -} - -func NewMyCustomAppStack(scope constructs.Construct, id string, props *MyCustomAppStackProps) awscdk.Stack { - stack := awscdk.NewStack(scope, &id, &props.StackProps) - - // Instantiate Foo construct in the stack - NewFoo(stack, "Foo") - - return stack -} - -// Define the CDK App -func main() { - app := awscdk.NewApp(nil) - - NewMyCustomAppStack(app, "MyCustomAppStack", &MyCustomAppStackProps{ - StackProps: awscdk.StackProps{}, - }) - - app.Synth(nil) -}</code></pre> -</div> -</div> -</dd> -</dl> -</div> -<div class="paragraph"> -<p>When we run <code>cdk synth</code>, a logical ID in the format of <code>FooBarBucket<code class="replaceable">unique-hash</code></code> gets generated. The following is an example of this resource in the generated AWS CloudFormation template:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-yaml" data-lang="yaml">Resources: - FooBarBucketBA3ED1FA: - Type: AWS::S3::Bucket - Properties: - VersioningConfiguration: - Status: Enabled - UpdateReplacePolicy: Delete - DeletionPolicy: Delete - # ...</code></pre> -</div> -</div> -</div> -</div> -<div class="sect2"> -<h3 id="bootstrapping-custom-synth">13.5. Customize CDK stack synthesis</h3> -<div class="paragraph"> -<p>If the default CDK synthesis behavior doesn’t suit your needs, you can customize CDK synthesis. To do this, you modify <code>DefaultStackSynthesizer</code>, use other available built-in synthesizers, or create your own synthesizer. For instructions, see <a href="#customize-synth">Customize CDK stack synthesis</a>.</p> -</div> -</div> -</div> -</div> -<div class="sect1 topic"> -<h2 id="deploy">14. Deploy AWS CDK applications</h2> -<div class="sectionbody"> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>An AWS Cloud Development Kit (AWS CDK) deployment is the process of provisioning your infrastructure on AWS.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>An AWS Cloud Development Kit (AWS CDK) deployment is the process of provisioning your infrastructure on AWS.</p> -</div> -<div class="sect2"> -<h3 id="deploy-how">14.1. How AWS CDK deployments work</h3> -<div class="paragraph"> -<p>The AWS CDK utilizes the AWS CloudFormation service to perform deployments. Before you deploy, you synthesize your CDK stacks. This creates a CloudFormation template and deployment artifacts for each CDK stack in your app. Deployments are initiated from a local development machine or from a <em>continuous integration and continuous delivery (CI/CD)</em> environment. During deployment, assets are uploaded to the bootstrapped resources and the CloudFormation template is submitted to CloudFormation to provision your AWS resources.</p> -</div> -<div class="paragraph"> -<p>For a deployment to be successful, the following is required:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>The AWS CDK Command Line Interface (AWS CDK <code class="noloc">CLI</code>) must be provided with valid permissions.</p> -</li> -<li> -<p>The AWS environment must be bootstrapped.</p> -</li> -<li> -<p>The AWS CDK must know the bootstrapped resources to upload assets into.</p> -</li> -</ul> -</div> -</div> -<div class="sect2"> -<h3 id="deploy-prerequisites">14.2. Prerequisites for CDK deployments</h3> -<div class="paragraph"> -<p>Before you can deploy an AWS CDK application, you must complete the following:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Configure security credentials for the CDK <code class="noloc">CLI</code>.</p> -</li> -<li> -<p>Bootstrap your AWS environment.</p> -</li> -<li> -<p>Configure an AWS environment for each of your CDK stacks.</p> -</li> -<li> -<p>Develop your CDK app.</p> -</li> -</ul> -</div> -<div class="sect3"> -<h4 id="deploy-prerequisites-creds">14.2.1. Configure security credentials</h4> -<div class="paragraph"> -<p>To use the CDK <code class="noloc">CLI</code> to interact with AWS, you must configure security credentials on your local machine. For instructions, see <a href="#configure-access">Configure security credentials for the AWS CDK CLI</a>.</p> -</div> -</div> -<div class="sect3"> -<h4 id="deploy-prerequisites-bootstrap">14.2.2. Bootstrap your AWS environment</h4> -<div class="paragraph"> -<p>A deployment is always associated with one or more AWS <a href="#environments">environments</a>. Before you can deploy, the environment must first be <a href="#bootstrapping">bootstrapped</a>. Bootstrapping provisions resources in your environment that the CDK uses to perform and manage deployments. These resources include an Amazon Simple Storage Service (Amazon S3) bucket and Amazon Elastic Container Registry (Amazon ECR) repository to store and manage <a href="#assets">assets</a>. These resources also include AWS Identity and Access Management (IAM) roles that are used to provide permissions during development and deployment.</p> -</div> -<div class="paragraph"> -<p>We recommend that you use the AWS CDK Command Line Interface (AWS CDK <code class="noloc">CLI</code>) <code>cdk bootstrap</code> command to bootstrap your environment. You can customize bootstrapping or manually create these resources in your environment if necessary. For instructions, see <a href="#bootstrapping-env">Bootstrap your environment for use with the AWS CDK</a>.</p> -</div> -</div> -<div class="sect3"> -<h4 id="deploy-prerequisites-env">14.2.3. Configure AWS environments</h4> -<div class="paragraph"> -<p>Each CDK stack must be associated with an environment to determine where the stack is deployed to. For instructions, see <a href="#configure-env">Configure environments to use with the AWS CDK</a>.</p> -</div> -</div> -<div class="sect3"> -<h4 id="deploy-prerequisites-develop">14.2.4. Develop your CDK app</h4> -<div class="paragraph"> -<p>Within a CDK <a href="#projects">project</a>, you create and develop your CDK app. Within your app, you create one or more CDK <a href="#stacks">stacks</a>. Within your stacks, you import and use <a href="#constructs">constructs</a> from the AWS Construct Library to define your infrastructure. Before you can deploy, your CDK app must contain at least one stack.</p> -</div> -</div> -</div> -<div class="sect2"> -<h3 id="deploy-how-synth">14.3. CDK app synthesis</h3> -<div class="paragraph"> -<p>To perform synthesis, we recommend that you use the CDK <code class="noloc">CLI</code><code>cdk synth</code> command. The <code>cdk deploy</code> command will also perform synthesis before initiating deployment. However, by using <code>cdk synth</code>, you can validate your CDK app and catch errors before initiating deployment.</p> -</div> -<div class="paragraph"> -<p>Synthesis behavior is determined by the <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib-readme.html#stack-synthesizers">stack synthesizer</a> that you configure for your CDK stack. If you don’t configure a synthesizer, <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.DefaultStackSynthesizer.html">DefaultStackSynthesizer</a></code> will be used. You can also configure and customize synthesis to meet your needs. For instructions, see <a href="#configure-synth">Configure and perform CDK stack synthesis</a>.</p> -</div> -<div class="paragraph"> -<p>For your synthesized CloudFormation template to deploy successfully into your environment, it must be compatible with how your environment was bootstrapped. For example, your CloudFormation template must specify the correct Amazon S3 bucket to deploy assets into. If you use the default method of bootstrapping your environment, the default stack synthesizer will work. If you customize CDK behavior, such as customizing bootstrapping or synthesis, CDK deployment behavior may vary.</p> -</div> -<div class="sect3"> -<h4 id="deploy-how-synth-app">14.3.1. The app lifecycle</h4> -<div class="paragraph"> -<p>When you perform synthesis, your CDK app is run through the following phases, known as the <em>app lifecycle</em>:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Construction (or Initialization)</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Your code instantiates all of the defined constructs and then links them together. In this stage, all of the constructs (app, stacks, and their child constructs) are instantiated and the constructor chain is run. Most of your app code is run in this stage.</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Preparation</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>All constructs that have implemented the <code>prepare</code> method participate in a final round of modifications, to set up their final state. The preparation phase happens automatically. As a user, you don’t see any feedback from this phase. It’s rare to need to use the "prepare" hook, and generally not recommended. Be very careful when mutating the construct tree during this phase, because the order of operations could impact behavior.</p> -<div class="paragraph"> -<p>During this phase, once the construct tree has been built, any <a href="#aspects">aspects</a> that you have configured are applied as well.</p> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Validation</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>All constructs that have implemented the <code>validate</code> method can validate themselves to ensure that they’re in a state that will correctly deploy. You will get notified of any validation failures that happen during this phase. Generally, we recommend performing validation as soon as possible (usually as soon as you get some input) and throwing exceptions as early as possible. Performing validation early improves reliability as stack traces will be more accurate, and ensures that your code can continue to execute safely.</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Synthesis</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>This is the final stage of running your CDK app. It’s triggered by a call to <code>app.synth()</code>, and it traverses the construct tree and invokes the <code>synthesize</code> method on all constructs. Constructs that implement <code>synthesize</code> can participate in synthesis and produce deployment artifacts to the resulting cloud assembly. These artifacts include CloudFormation templates, AWS Lambda application bundles, file and <code class="noloc">Docker</code> image assets, and other deployment artifacts. In most cases, you won’t need to implement the <code>synthesize</code> method.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect3"> -<h4 id="deploy-how-synth-run">14.3.2. Running your app</h4> -<div class="paragraph"> -<p>The CDK <code class="noloc">CLI</code> needs to know how to run your CDK app. If you created the project from a template using the <code>cdk init</code> command, your app’s <code class="path">cdk.json</code> file includes an <code>app</code> key. This key specifies the necessary command for the language that the app is written in. If your language requires compilation, the command line performs this step before running the app automatically.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-json" data-lang="json">{ - "app": "npx ts-node --prefer-ts-exts bin/my-app.ts" -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-json" data-lang="json">{ - "app": "node bin/my-app.js" -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-json" data-lang="json">{ - "app": "python app.py" -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-json" data-lang="json">{ - "app": "mvn -e -q compile exec:java" -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-json" data-lang="json">{ - "app": "dotnet run -p src/MyApp/MyApp.csproj" -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-json" data-lang="json">{ - "app": "go mod download && go run my-app.go" -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>If you didn’t create your project using the CDK <code class="noloc">CLI</code>, or if you want to override the command line given in <code class="path">cdk.json</code>, you can provide the <code><a href="#ref-cli-cmd-options-app">--app</a></code> option when running the <code>cdk</code> command.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk --app 'executable' cdk-command ...</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The <code class="replaceable">executable</code> part of the command indicates the command that should be run to execute your CDK application. Use quotation marks as shown, since such commands contain spaces. The <code class="replaceable">cdk-command</code> is a subcommand like <code>synth</code> or <code>deploy</code> that tells the CDK <code class="noloc">CLI</code> what you want to do with your app. Follow this with any additional options needed for that subcommand.</p> -</div> -<div class="paragraph"> -<p>The CDK <code class="noloc">CLI</code> can also interact directly with an already-synthesized cloud assembly. To do that, pass the directory in which the cloud assembly is stored in <code>--app</code>. The following example lists the stacks defined in the cloud assembly stored under <code class="path">./my-cloud-assembly</code>.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk --app ./my-cloud-assembly ls</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="deploy-how-synth-assemblies">14.3.3. Cloud assemblies</h4> -<div class="paragraph"> -<p>The call to <code>app.synth()</code> is what tells the AWS CDK to synthesize a cloud assembly from an app. Typically you don’t interact directly with cloud assemblies. They are files that include everything needed to deploy your app to a cloud environment. For example, it includes an AWS CloudFormation template for each stack in your app. It also includes a copy of any file assets or <code class="noloc">Docker</code> images that you reference in your app.</p> -</div> -<div class="paragraph"> -<p>See the <a href="https://github.com/aws/aws-cdk/blob/master/design/cloud-assembly.md">cloud assembly specification</a> for details on how cloud assemblies are formatted.</p> -</div> -<div class="paragraph"> -<p>To interact with the cloud assembly that your AWS CDK app creates, you typically use the AWS CDK <code class="noloc">CLI</code>. However, any tool that can read the cloud assembly format can be used to deploy your app.</p> -</div> -</div> -</div> -<div class="sect2"> -<h3 id="deploy-how-deploy">14.4. Deploy your application</h3> -<div class="paragraph"> -<p>To deploy your application, we recommend that you use the CDK <code class="noloc">CLI</code><code>cdk deploy</code> command to initiate deployments or to configure automated deployments.</p> -</div> -<div class="paragraph"> -<p>When you run <code>cdk deploy</code>, the CDK <code class="noloc">CLI</code> initiates <code>cdk synth</code> to prepare for deployment. The following diagram illustrates the app lifecycle in the context of a deployment:</p> -</div> -<div class="imageblock"> -<div class="content"> -<img src="images/app-lifecycle_cdk-flowchart.png" alt="Flowchart of the AWS CDK app lifecycle."> -</div> -</div> -<div class="paragraph"> -<p>During deployment, the CDK <code class="noloc">CLI</code> takes the cloud assembly produced by synthesis and deploys it to an AWS environment. Assets are uploaded to Amazon S3 and Amazon ECR and the CloudFormation template is submitted to AWS CloudFormation for deployment.</p> -</div> -<div class="paragraph"> -<p>By the time the AWS CloudFormation deployment phase starts, your CDK app has already finished running and exited. This has the following implications:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>The CDK app can’t respond to events that happen during deployment, such as a resource being created or the whole deployment finishing. To run code during the deployment phase, you must inject it into the AWS CloudFormation template as a <a href="#develop-customize-custom">custom resource</a>. For more information about adding a custom resource to your app, see the <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_cloudformation-readme.html">AWS CloudFormation module</a>, or the <a href="https://github.com/aws-samples/aws-cdk-examples/tree/master/typescript/custom-resource/">custom-resource</a> example. You can also configure the <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.triggers-readme.html">Triggers</a> module to run code during deployments.</p> -</li> -<li> -<p>The CDK app might have to work with values that can’t be known at the time it runs. For example, if the AWS CDK app defines an Amazon S3 bucket with an automatically generated name, and you retrieve the <code>bucket.bucketName</code> (Python: <code>bucket_name</code>) attribute, that value is not the name of the deployed bucket. Instead, you get a <code>Token</code> value. To determine whether a particular value is available, call <code>cdk.isUnresolved(value)</code> (Python: <code>is_unresolved</code>). See <a href="#tokens">Tokens and the AWS CDK</a> for details.</p> -</li> -</ul> -</div> -<div class="sect3"> -<h4 id="deploy-how-deploy-permissions">14.4.1. Deployment permissions</h4> -<div class="paragraph"> -<p>Before deployment can be performed, permissions must be established. The following diagram illustrates the permissions that are used during a default deployment, when using the default bootstrapping process and stack synthesizer:</p> -</div> -<div class="imageblock"> -<div class="content"> -<img src="images/default-deploy-process_cdk_flowchart.png" alt="Flowchart of the default AWS CDK deployment process."> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Actor initiates deployment</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Deployments are initiated by an <em>actor</em>, using the CDK <code class="noloc">CLI</code>. An actor can either be a person, or a service such as AWS CodePipeline.</p> -<div class="paragraph"> -<p>If necessary, the CDK <code class="noloc">CLI</code> runs <code>cdk synth</code> when you run <code>cdk deploy</code>. During synthesis, the AWS identity assumes the <code>LookupRole</code> to perform context lookups in the AWS environment.</p> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Permissions are established</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>First, the actor’s security credentials are used to authenticate to AWS and obtain the first IAM identity in the process. For human actors, how security credentials are configured and obtained depends on how you or your organization manages users. For more information, see <a href="#configure-access">Configure security credentials for the AWS CDK CLI</a>. For service actors, such as CodePipeline, an IAM execution role is assumed and used.</p> -<div class="paragraph"> -<p>Next, the IAM roles created in your AWS environment during bootstrapping are used to establish permissions to perform the actions needed for deployment. For more information about these roles and what they grant permissions for, see <a href="#bootstrapping-env-roles">IAM roles created during bootstrapping</a>. This process includes the following:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>The AWS identity assumes the <code>DeploymentActionRole</code> role and passes the <code>CloudFormationExecutionRole</code> role to CloudFormation, ensuring that CloudFormation assumes the role when it performs any actions in your AWS environment. <code>DeploymentActionRole</code> grants permission to perform deployments into your environment and <code>CloudFormationExecutionRole</code> determines what actions CloudFormation can perform.</p> -</li> -<li> -<p>The AWS identity assumes the <code>FilePublishingRole</code>, which determines the actions that can be performed on the Amazon S3 bucket created during bootstrapping.</p> -</li> -<li> -<p>The AWS identity assumes the <code>ImagePublishingRole</code>, which determines the actions that can be performed on the Amazon ECR repository created during bootstrapping.</p> -</li> -<li> -<p>If necessary, the AWS identity assumes the <code>LookupRole</code> to perform context lookups in the AWS environment. This action may also be performed during template synthesis.</p> -</li> -</ul> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Deployment is performed</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>During deployment, the CDK <code class="noloc">CLI</code> reads the bootstrap version parameter to confirm the bootstrap version number. AWS CloudFormation also reads this parameter at deployment time to confirm. If permissions across the deployment workflow are valid, deployment is performed. Assets are uploaded to the bootstrapped resources and the CloudFormation template produced at synthesis is deployed using the CloudFormation service as a CloudFormation stack to provision your resources.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="policy-validation-synthesis">14.5. AWS CDK policy validation at synthesis time</h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>By using the appropriate policy validation plugin, you can make the AWS CDK application check the generated AWS CloudFormation template against your policies immediately after synthesis.</p> -</div> -</blockquote> -</div> -<div class="paragraph topiclist"> -<p>[[Topic List]]</p> -</div> -<div class="sect3"> -<h4 id="policy-validation">14.5.1. Policy validation at synthesis time</h4> -<div class="paragraph"> -<p>If you or your organization use any policy validation tool, such as <a href="https://docs.aws.amazon.com/cfn-guard/latest/ug/what-is-guard.html">AWS CloudFormation Guard</a> or <a href="https://www.openpolicyagent.org/">OPA</a>, to define constraints on your AWS CloudFormation template, you can integrate them with the AWS CDK at synthesis time. By using the appropriate policy validation plugin, you can make the AWS CDK application check the generated AWS CloudFormation template against your policies immediately after synthesis. If there are any violations, the synthesis will fail and a report will be printed to the console.</p> -</div> -<div class="paragraph"> -<p>The validation performed by the AWS CDK at synthesis time validate controls at one point in the deployment lifecycle, but they can’t affect actions that occur outside synthesis. Examples include actions taken directly in the console or via service APIs. They aren’t resistant to alteration of AWS CloudFormation templates after synthesis. Some other mechanism to validate the same rule set more authoritatively should be set up independently, like <a href="https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/hooks.html">AWS CloudFormation hooks</a> or <a href="https://docs.aws.amazon.com/config/latest/developerguide/WhatIsConfig.html">AWS Config</a>. Nevertheless, the ability of the AWS CDK to evaluate the rule set during development is still useful as it will improve detection speed and developer productivity.</p> -</div> -<div class="paragraph"> -<p>The goal of AWS CDK policy validation is to minimize the amount of set up needed during development, and make it as easy as possible.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>This feature is considered experimental, and both the plugin API and the format of the validation report are subject to change in the future.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph topiclist"> -<p>[[Topic List]]</p> -</div> -</div> -<div class="sect3"> -<h4 id="for-application-developers">14.5.2. For application developers</h4> -<div class="paragraph"> -<p>To use one or more validation plugins in your application, use the <code>policyValidationBeta1</code> property of <code>Stage</code>:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import { CfnGuardValidator } from '@cdklabs/cdk-validator-cfnguard'; -const app = new App({ - policyValidationBeta1: [ - new CfnGuardValidator() - ], -}); -// only apply to a particular stage -const prodStage = new Stage(app, 'ProdStage', { - policyValidationBeta1: [...], -});</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Immediately after synthesis, all plugins registered this way will be invoked to validate all the templates generated in the scope you defined. In particular, if you register the templates in the <code>App</code> object, all templates will be subject to validation.</p> -</div> -<div class="admonitionblock warning"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-warning" title="Warning"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>Other than modifying the cloud assembly, plugins can do anything that your AWS CDK application can. They can read data from the filesystem, access the network etc. It’s your responsibility as the consumer of a plugin to verify that it’s secure to use.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="sect4"> -<h5 id="cfnguard-plugin">AWS CloudFormation Guard plugin</h5> -<div class="paragraph"> -<p>Using the <a href="https://github.com/cdklabs/cdk-validator-cfnguard">CfnGuardValidator</a> plugin allows you to use <a href="https://github.com/aws-cloudformation/cloudformation-guard">AWS CloudFormation Guard</a> to perform policy validations. The <code>CfnGuardValidator</code> plugin comes with a select set of <a href="https://docs.aws.amazon.com/controltower/latest/userguide/proactive-controls.html">AWS Control Tower proactive controls</a> built in. The current set of rules can be found in the <a href="https://github.com/cdklabs/cdk-validator-cfnguard/blob/main/README.md">project documentation</a>. As mentioned in <a href="#policy-validation">Policy validation at synthesis time</a>, we recommend that organizations set up a more authoritative method of validation using <a href="https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/hooks.html">AWS CloudFormation hooks</a>.</p> -</div> -<div class="paragraph"> -<p>Forhttps://docs.aws.amazon.com/controltower/latest/userguide/what-is-control-tower.html[AWS Control Tower] customers, these same proactive controls can be deployed across your organization. When you enable AWS Control Tower proactive controls in your AWS Control Tower environment, the controls can stop the deployment of non-compliant resources deployed via AWS CloudFormation. For more information about managed proactive controls and how they work, see the <a href="https://docs.aws.amazon.com/controltower/latest/userguide/proactive-controls.html">AWS Control Tower documentation</a>.</p> -</div> -<div class="paragraph"> -<p>These AWS CDK bundled controls and managed AWS Control Tower proactive controls are best used together. In this scenario you can configure this validation plugin with the same proactive controls that are active in your AWS Control Tower cloud environment. You can then quickly gain confidence that your AWS CDK application will pass the AWS Control Tower controls by running <code>cdk synth</code> locally.</p> -</div> -</div> -<div class="sect4"> -<h5 id="validation-report">Validation Report</h5> -<div class="paragraph"> -<p>When you synthesize the AWS CDK app the validator plugins will be called and the results will be printed. An example report is showing below.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">Validation Report (CfnGuardValidator) -------------------------------------- -(Summary) -╔═══════════╤════════════════════════╗ -║ Status │ failure ║ -╟───────────┼────────────────────────╢ -║ Plugin │ CfnGuardValidator ║ -╚═══════════╧════════════════════════╝ -(Violations) -Ensure S3 Buckets are encrypted with a KMS CMK (1 occurrences) -Severity: medium - Occurrences: - - - Construct Path: MyStack/MyCustomL3Construct/Bucket - - Stack Template Path: ./cdk.out/MyStack.template.json - - Creation Stack: - └── MyStack (MyStack) - │ Library: aws-cdk-lib.Stack - │ Library Version: 2.50.0 - │ Location: Object.<anonymous> (/home/johndoe/tmp/cdk-tmp-app/src/main.ts:25:20) - └── MyCustomL3Construct (MyStack/MyCustomL3Construct) - │ Library: N/A - (Local Construct) - │ Library Version: N/A - │ Location: new MyStack (/home/johndoe/tmp/cdk-tmp-app/src/main.ts:15:20) - └── Bucket (MyStack/MyCustomL3Construct/Bucket) - │ Library: aws-cdk-lib/aws-s3.Bucket - │ Library Version: 2.50.0 - │ Location: new MyCustomL3Construct (/home/johndoe/tmp/cdk-tmp-app/src/main.ts:9:20) - - Resource Name: amzn-s3-demo-bucket - - Locations: - > BucketEncryption/ServerSideEncryptionConfiguration/0/ServerSideEncryptionByDefault/SSEAlgorithm - Recommendation: Missing value for key `SSEAlgorithm` - must specify `aws:kms` - How to fix: - > Add to construct properties for `cdk-app/MyStack/Bucket` - `encryption: BucketEncryption.KMS` - -Validation failed. See above reports for details</code></pre> -</div> -</div> -<div class="paragraph"> -<p>By default, the report will be printed in a human readable format. If you want a report in JSON format, enable it usingthe <code>@aws-cdk/core:validationReportJson</code>via the CLI or passing it directly to the application:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const app = new App({ - context: { '@aws-cdk/core:validationReportJson': true }, -});</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Alternatively, you can set this context key-value pair using the <code>cdk.json</code> or <code>cdk.context.json</code> files in your project directory (see <a href="#context">Context values and the AWS CDK</a>).</p> -</div> -<div class="paragraph"> -<p>If you choose the JSON format, the AWS CDK will print the policy validation report to a file called <code>policy-validation-report.json</code> in the cloud assembly directory. For the default, human-readable format, the report will be printed to the standard output.</p> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="plugin-authors">14.5.3. For plugin authors</h4> -<div class="sect4"> -<h5 id="plugins">Plugins</h5> -<div class="paragraph"> -<p>The AWS CDK core framework is responsible for registering and invoking plugins and then displaying the formatted validation report. The responsibility of the plugin is to act as the translation layer between the AWS CDK framework and the policy validation tool. A plugin can be created in any language supported by AWS CDK. If you are creating a plugin that might be consumed by multiple languages then it’s recommended that you create the plugin in <code>TypeScript</code> so that you can use JSII to publish the plugin in each AWS CDK language.</p> -</div> -</div> -<div class="sect4"> -<h5 id="creating-plugins">Creating plugins</h5> -<div class="paragraph"> -<p>The communication protocol between the AWS CDK core module and your policy tool is defined by the <code>IPolicyValidationPluginBeta1</code>interface. To create a new plugin you must write a class that implements this interface. There are two things you need to implement: the plugin name (by overriding the <code>name</code> property), and the <code>validate()</code> method.</p> -</div> -<div class="paragraph"> -<p>The framework will call <code>validate()</code>, passing an <code>IValidationContextBeta1</code> object. The location of the templates to be validated is given by <code>templatePaths</code>. The plugin should return an instance of <code>ValidationPluginReportBeta1</code>. This object represents the report that the user wil receive at the end of the synthesis.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">validate(context: IPolicyValidationContextBeta1): PolicyValidationReportBeta1 { - // First read the templates using context.templatePaths... - // ...then perform the validation, and then compose and return the report. - // Using hard-coded values here for better clarity: - return { - success: false, - violations: [{ - ruleName: 'CKV_AWS_117', - description: 'Ensure that AWS Lambda function is configured inside a VPC', - fix: 'https://docs.bridgecrew.io/docs/ensure-that-aws-lambda-function-is-configured-inside-a-vpc-1', - violatingResources: [{ - resourceName: 'MyFunction3BAA72D1', - templatePath: '/home/johndoe/myapp/cdk.out/MyService.template.json', - locations: 'Properties/VpcConfig', - }], - }], - }; -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Note that plugins aren’t allowed to modify anything in the cloud assembly. Any attempt to do so will result in synthesis failure.</p> -</div> -<div class="paragraph"> -<p>If your plugin depends on an external tool, keep in mind that some developers may not have that tool installed in their workstations yet. To minimize friction, we highly recommend that you provide some installation script along with your plugin package, to automate the whole process. Better yet, run that script as part of the installation of your package. With <code>npm</code>, for example, you can add it to the <code>postinstall`https://docs.npmjs.com/cli/v9/using-npm/scripts[script] in the `package.json</code> file.</p> -</div> -</div> -<div class="sect4"> -<h5 id="handling-exemptions">Handling Exemptions</h5> -<div class="paragraph"> -<p>If your organization has a mechanism for handling exemptions, it can be implemented as part of the validator plugin.</p> -</div> -<div class="paragraph"> -<p>An example scenario to illustrate a possible exemption mechanism:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>An organization has a rule that public Amazon S3 buckets aren’t allowed, <em>except</em> for under certain scenarios.</p> -</li> -<li> -<p>A developer is creating an Amazon S3 bucket that falls under one of those scenarios and requests an exemption (create a ticket for example).</p> -</li> -<li> -<p>Security tooling knows how to read from the internal system that registers exemptions</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>In this scenario the developer would request an exception in the internal system and then will need some way of "registering" that exception. Adding on to the guard plugin example, you could create a plugin that handles exemptions by filtering out the violations that have a matching exemption in an internal ticketing system.</p> -</div> -<div class="paragraph"> -<p>See the existing plugins for example implementations.</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><a href="https://github.com/cdklabs/cdk-validator-cfnguard">@cdklabs/cdk-validator-cfnguard</a></p> -</li> -</ul> -</div> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="cdk-pipeline">14.6. Continuous integration and delivery (CI/CD) using CDK Pipelines</h3> -<div class="paragraph"> -<p>Use the <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.pipelines-readme.html">CDK Pipelines</a> module from the AWS Construct Library to configure continuous delivery of AWS CDK applications. When you commit your CDK app’s source code into AWS CodeCommit, <code class="noloc">GitHub</code>, or AWS CodeStar, CDK Pipelines can automatically build, test, and deploy your new version.</p> -</div> -<div class="paragraph"> -<p>CDK Pipelines are self-updating. If you add application stages or stacks, the pipeline automatically reconfigures itself to deploy those new stages or stacks.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>CDK Pipelines supports two APIs. One is the original API that was made available in the CDK Pipelines Developer Preview. The other is a modern API that incorporates feedback from CDK customers received during the preview phase. The examples in this topic use the modern API. For details on the differences between the two supported APIs, see <a href="https://github.com/aws/aws-cdk/blob/master/packages/@aws-cdk/pipelines/ORIGINAL_API.md">CDK Pipelines original API</a> in the <em>aws-cdk <code class="noloc">GitHub</code> repository</em>.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph topiclist"> -<p>[[Topic List]]</p> -</div> -<div class="sect3"> -<h4 id="cdk-pipeline-bootstrap">14.6.1. Bootstrap your AWS environments</h4> -<div class="paragraph"> -<p>Before you can use CDK Pipelines, you must bootstrap the AWS <a href="#environments">environment</a> that you will deploy your stacks to.</p> -</div> -<div class="paragraph"> -<p>A CDK Pipeline involves at least two environments. The first environment is where the pipeline is provisioned. The second environment is where you want to deploy the application’s stacks or stages to (stages are groups of related stacks). These environments can be the same, but a best practice recommendation is to isolate stages from each other in different environments.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>See <a href="#bootstrapping">AWS CDK bootstrapping</a> for more information on the kinds of resources created by bootstrapping and how to customize the bootstrap stack.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>Continuous deployment with CDK Pipelines requires the following to be included in the CDK Toolkit stack:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>An Amazon Simple Storage Service (Amazon S3) bucket.</p> -</li> -<li> -<p>An Amazon ECR repository.</p> -</li> -<li> -<p>IAM roles to give the various parts of a pipeline the permissions they need.</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>The CDK Toolkit will upgrade your existing bootstrap stack or creates a new one if necessary.</p> -</div> -<div class="paragraph"> -<p>To bootstrap an environment that can provision an AWS CDK pipeline, invoke <code>cdk bootstrap</code> as shown in the following example. Invoking the AWS CDK Toolkit via the <code>npx</code> command temporarily installs it if necessary. It will also use the version of the Toolkit installed in the current project, if one exists.</p> -</div> -<div class="paragraph"> -<p><code>--cloudformation-execution-policies</code> specifies the ARN of a policy under which future CDK Pipelines deployments will execute. The default <code>AdministratorAccess</code> policy makes sure that your pipeline can deploy every type of AWS resource. If you use this policy, make sure you trust all the code and dependencies that make up your AWS CDK app.</p> -</div> -<div class="paragraph"> -<p>Most organizations mandate stricter controls on what kinds of resources can be deployed by automation. Check with the appropriate department within your organization to determine the policy your pipeline should use.</p> -</div> -<div class="paragraph"> -<p>You can omit the <code>--profile</code> option if your default AWS profile contains the necessary authentication configuration and AWS Region.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">macOS/Linux</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">npx cdk bootstrap aws://ACCOUNT-NUMBER/REGION --profile ADMIN-PROFILE \ - --cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Windows</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">npx cdk bootstrap aws://ACCOUNT-NUMBER/REGION --profile ADMIN-PROFILE ^ - --cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess</code></pre> -</div> -</div> -<div class="paragraph"> -<p>To bootstrap additional environments into which AWS CDK applications will be deployed by the pipeline, use the following commands instead. The <code>--trust</code> option indicates which other account should have permissions to deploy AWS CDK applications into this environment. For this option, specify the pipeline’s AWS account ID.</p> -</div> -<div class="paragraph"> -<p>Again, you can omit the <code>--profile</code> option if your default AWS profile contains the necessary authentication configuration and AWS Region.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">macOS/Linux</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">npx cdk bootstrap aws://ACCOUNT-NUMBER/REGION --profile ADMIN-PROFILE \ - --cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess \ - --trust PIPELINE-ACCOUNT-NUMBER</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Windows</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">npx cdk bootstrap aws://ACCOUNT-NUMBER/REGION --profile ADMIN-PROFILE ^ - --cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess ^ - --trust PIPELINE-ACCOUNT-NUMBER</code></pre> -</div> -</div> -<div class="admonitionblock tip"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-tip" title="Tip"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>Use administrative credentials only to bootstrap and to provision the initial pipeline. Afterward, use the pipeline itself, not your local machine, to deploy changes.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>If you are upgrading a legacy bootstrapped environment, the previous Amazon S3 bucket is orphaned when the new bucket is created. Delete it manually by using the Amazon S3 console.</p> -</div> -<div class="sect4"> -<h5 id="cdk-pipeline-protect">Protecting your bootstrap stack from deletion</h5> -<div class="paragraph"> -<p>If a bootstrap stack is deleted, the AWS resources that were originally provisioned in the environment to support CDK deployments will also be deleted. This will cause the pipeline to stop working. If this happens, there is no general solution for recovery.</p> -</div> -<div class="paragraph"> -<p>After your environment is bootstrapped, do not delete and recreate the environment’s bootstrap stack. Instead, try to update the bootstrap stack to a new version by running the <code>cdk bootstrap</code> command again.</p> -</div> -<div class="paragraph"> -<p>To protect against accidental deletion of your bootstrap stack, we recommend that you provide the <code>--termination-protection</code> option with the <code>cdk bootstrap</code> command to enable termination protection. You can enable termination protection on new or existing bootstrap stacks. To learn more about this option, see <code><a href="#ref-cli-cmd-bootstrap-options-termination-protection">--termination-protection</a></code>.</p> -</div> -<div class="paragraph"> -<p>After enabling termination protection, you can use the AWS CLI or CloudFormation console to verify.</p> -</div> -<div class="olist arabic"> -<ol class="arabic"> -<li> -<p>Run the following command to enable termination protection on a new or existing bootstrap stack:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk bootstrap --termination-protection</code></pre> -</div> -</div> -</li> -<li> -<p>Use the AWS CLI or CloudFormation console to verify. The following is an example, using the AWS CLI. If you modified your bootstrap stack name, replace <code>CDKToolkit</code> with your stack name:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ aws cloudformation describe-stacks --stack-name CDKToolkit --query "Stacks[0].EnableTerminationProtection" -true</code></pre> -</div> -</div> -</li> -</ol> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="cdk-pipeline-init">14.6.2. Initialize a project</h4> -<div class="paragraph"> -<p>Create a new, empty <code class="noloc">GitHub</code> project and clone it to your workstation in the <code class="path">my-pipeline</code> directory. (Our code examples in this topic use GitHub. You can also use AWS CodeStar or AWS CodeCommit.)</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">git clone GITHUB-CLONE-URL my-pipeline -cd my-pipeline</code></pre> -</div> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>You can use a name other than <code>my-pipeline</code> for your app’s main directory. However, if you do so, you will have to tweak the file and class names later in this topic. This is because the AWS CDK Toolkit bases some file and class names on the name of the main directory.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>After cloning, initialize the project as usual.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ cdk init app --language typescript</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ cdk init app --language javascript</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ cdk init app --language python</code></pre> -</div> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p>After the app has been created, also enter the following two commands. These activate the app’s Python virtual environment and install the AWS CDK core dependencies.</p> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ source .venv/bin/activate # On Windows, run `.\venv\Scripts\activate` instead -$ python -m pip install -r requirements.txt</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ cdk init app --language java</code></pre> -</div> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p>If you are using an IDE, you can now open or import the project. In Eclipse, for example, choose <strong>File</strong> > <strong>Import</strong> > <strong>Maven</strong> > <strong>Existing Maven Projects</strong>. Make sure that the project settings are set to use Java 8 (1.8).</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ cdk init app --language csharp</code></pre> -</div> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p>If you are using Visual Studio, open the solution file in the <code class="path">src</code> directory.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ cdk init app --language go</code></pre> -</div> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p>After the app has been created, also enter the following command to install the AWS Construct Library modules that the app requires.</p> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ go get</code></pre> -</div> -</div> -<div class="admonitionblock important"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-important" title="Important"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>Be sure to commit your <code class="path">cdk.json</code> and <code class="path">cdk.context.json</code> files to source control. The context information (such as feature flags and cached values retrieved from your AWS account) are part of your project’s state. The values may be different in another environment, which can cause unexpected changes in your results. For more information, see <a href="#context">Context values and the AWS CDK</a>.</p> -</div> -</td> -</tr> -</table> -</div> -</div> -<div class="sect3"> -<h4 id="cdk-pipeline-define">14.6.3. Define a pipeline</h4> -<div class="paragraph"> -<p>Your CDK Pipelines application will include at least two stacks: one that represents the pipeline itself, and one or more stacks that represent the application deployed through it. Stacks can also be grouped into <em>stages</em>, which you can use to deploy copies of infrastructure stacks to different environments. For now, we’ll consider the pipeline, and later delve into the application it will deploy.</p> -</div> -<div class="paragraph"> -<p>The construct <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.pipelines.CodePipeline.html">CodePipeline</a> is the construct that represents a CDK Pipeline that uses AWS CodePipeline as its deployment engine. When you instantiate <code>CodePipeline</code> in a stack, you define the source location for the pipeline (such as a GitHub repository). You also define the commands to build the app.</p> -</div> -<div class="paragraph"> -<p>For example, the following defines a pipeline whose source is stored in a GitHub repository. It also includes a build step for a TypeScript CDK application. Fill in the information about your GitHub repo where indicated.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>By default, the pipeline authenticates to GitHub using a personal access token stored in Secrets Manager under the name <code class="path">github-token</code>.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>You’ll also need to update the instantiation of the pipeline stack to specify the AWS account and Region.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>In <code class="path">lib/my-pipeline-stack.ts</code> (may vary if your project folder isn’t named <code class="path">my-pipeline</code>):</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as cdk from 'aws-cdk-lib'; -import { Construct } from 'constructs'; -import { CodePipeline, CodePipelineSource, ShellStep } from 'aws-cdk-lib/pipelines'; - -export class MyPipelineStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - const pipeline = new CodePipeline(this, 'Pipeline', { - pipelineName: 'MyPipeline', - synth: new ShellStep('Synth', { - input: CodePipelineSource.gitHub('OWNER/REPO', 'main'), - commands: ['npm ci', 'npm run build', 'npx cdk synth'] - }) - }); - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>In <code class="path">bin/my-pipeline.ts</code> (may vary if your project folder isn’t named <code class="path">my-pipeline</code>):</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">#!/usr/bin/env node -import * as cdk from 'aws-cdk-lib'; -import { MyPipelineStack } from '../lib/my-pipeline-stack'; - -const app = new cdk.App(); -new MyPipelineStack(app, 'MyPipelineStack', { - env: { - account: '111111111111', - region: 'eu-west-1', - } -}); - -app.synth();</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">JavaScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>In <code class="path">lib/my-pipeline-stack.js</code> (may vary if your project folder isn’t named <code class="path">my-pipeline</code>):</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const cdk = require('aws-cdk-lib'); -const { CodePipeline, CodePipelineSource, ShellStep } = require('aws-cdk-lib/pipelines'); - - class MyPipelineStack extends cdk.Stack { - constructor(scope, id, props) { - super(scope, id, props); - - const pipeline = new CodePipeline(this, 'Pipeline', { - pipelineName: 'MyPipeline', - synth: new ShellStep('Synth', { - input: CodePipelineSource.gitHub('OWNER/REPO', 'main'), - commands: ['npm ci', 'npm run build', 'npx cdk synth'] - }) - }); - } -} - -module.exports = { MyPipelineStack }</code></pre> -</div> -</div> -<div class="paragraph"> -<p>In <code class="path">bin/my-pipeline.js</code> (may vary if your project folder isn’t named <code class="path">my-pipeline</code>):</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">#!/usr/bin/env node - -const cdk = require('aws-cdk-lib'); -const { MyPipelineStack } = require('../lib/my-pipeline-stack'); - -const app = new cdk.App(); -new MyPipelineStack(app, 'MyPipelineStack', { - env: { - account: '111111111111', - region: 'eu-west-1', - } -}); - -app.synth();</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Python</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>In <code class="path">my-pipeline/my-pipeline-stack.py</code> (may vary if your project folder isn’t named <code class="path">my-pipeline</code>):</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">import aws_cdk as cdk -from constructs import Construct -from aws_cdk.pipelines import CodePipeline, CodePipelineSource, ShellStep - -class MyPipelineStack(cdk.Stack): - - def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: - super().__init__(scope, construct_id, **kwargs) - - pipeline = CodePipeline(self, "Pipeline", - pipeline_name="MyPipeline", - synth=ShellStep("Synth", - input=CodePipelineSource.git_hub("OWNER/REPO", "main"), - commands=["npm install -g aws-cdk", - "python -m pip install -r requirements.txt", - "cdk synth"] - ) - )</code></pre> -</div> -</div> -<div class="paragraph"> -<p>In <code class="path">app.py</code>:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">#!/usr/bin/env python3 -import aws_cdk as cdk -from my_pipeline.my_pipeline_stack import MyPipelineStack - -app = cdk.App() -MyPipelineStack(app, "MyPipelineStack", - env=cdk.Environment(account="111111111111", region="eu-west-1") -) - -app.synth()</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Java</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>In <code class="path">src/main/java/com/myorg/MyPipelineStack.java</code> (may vary if your project folder isn’t named <code class="path">my-pipeline</code>):</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">package com.myorg; - -import java.util.Arrays; -import software.constructs.Construct; -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.StackProps; -import software.amazon.awscdk.pipelines.CodePipeline; -import software.amazon.awscdk.pipelines.CodePipelineSource; -import software.amazon.awscdk.pipelines.ShellStep; - -public class MyPipelineStack extends Stack { - public MyPipelineStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public MyPipelineStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - CodePipeline pipeline = CodePipeline.Builder.create(this, "pipeline") - .pipelineName("MyPipeline") - .synth(ShellStep.Builder.create("Synth") - .input(CodePipelineSource.gitHub("OWNER/REPO", "main")) - .commands(Arrays.asList("npm install -g aws-cdk", "cdk synth")) - .build()) - .build(); - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>In <code class="path">src/main/java/com/myorg/MyPipelineApp.java</code> (may vary if your project folder isn’t named <code class="path">my-pipeline</code>):</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">package com.myorg; - -import software.amazon.awscdk.App; -import software.amazon.awscdk.Environment; -import software.amazon.awscdk.StackProps; - -public class MyPipelineApp { - public static void main(final String[] args) { - App app = new App(); - - new MyPipelineStack(app, "PipelineStack", StackProps.builder() - .env(Environment.builder() - .account("111111111111") - .region("eu-west-1") - .build()) - .build()); - - app.synth(); - } -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">C#</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>In <code class="path">src/MyPipeline/MyPipelineStack.cs</code> (may vary if your project folder isn’t named <code class="path">my-pipeline</code>):</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; -using Amazon.CDK.Pipelines; - -namespace MyPipeline -{ - public class MyPipelineStack : Stack - { - internal MyPipelineStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) - { - var pipeline = new CodePipeline(this, "pipeline", new CodePipelineProps - { - PipelineName = "MyPipeline", - Synth = new ShellStep("Synth", new ShellStepProps - { - Input = CodePipelineSource.GitHub("OWNER/REPO", "main"), - Commands = new string[] { "npm install -g aws-cdk", "cdk synth" } - }) - }); - } - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>In <code class="path">src/MyPipeline/Program.cs</code> (may vary if your project folder isn’t named <code class="path">my-pipeline</code>):</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; - -namespace MyPipeline -{ - sealed class Program - { - public static void Main(string[] args) - { - var app = new App(); - new MyPipelineStack(app, "MyPipelineStack", new StackProps - { - Env = new Amazon.CDK.Environment { - Account = "111111111111", Region = "eu-west-1" } - }); - - app.Synth(); - } - } -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">package main - -import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - codebuild "github.com/aws/aws-cdk-go/awscdk/v2/awscodebuild" - ssm "github.com/aws/aws-cdk-go/awscdk/v2/awsssm" - pipeline "github.com/aws/aws-cdk-go/awscdk/v2/pipelines" - "github.com/aws/constructs-go/constructs/v10" - "github.com/aws/jsii-runtime-go" - "os" -) - -// my CDK Stack with resources -func NewCdkStack(scope constructs.Construct, id *string, props *awscdk.StackProps) awscdk.Stack { - stack := awscdk.NewStack(scope, id, props) - - // create an example ssm parameter - _ = ssm.NewStringParameter(stack, jsii.String("ssm-test-param"), &ssm.StringParameterProps{ - ParameterName: jsii.String("/testparam"), - Description: jsii.String("ssm parameter for demo"), - StringValue: jsii.String("my test param"), - }) - - return stack -} - -// my CDK Application -func NewCdkApplication(scope constructs.Construct, id *string, props *awscdk.StageProps) awscdk.Stage { - stage := awscdk.NewStage(scope, id, props) - - _ = NewCdkStack(stage, jsii.String("cdk-stack"), &awscdk.StackProps{Env: props.Env}) - - return stage -} - -// my CDK Pipeline -func NewCdkPipeline(scope constructs.Construct, id *string, props *awscdk.StackProps) awscdk.Stack { - stack := awscdk.NewStack(scope, id, props) - - // GitHub repo with owner and repository name - githubRepo := pipeline.CodePipelineSource_GitHub(jsii.String("owner/repo"), jsii.String("main"), &pipeline.GitHubSourceOptions{ - Authentication: awscdk.SecretValue_SecretsManager(jsii.String("my-github-token"), nil), - }) - - // self mutating pipeline - myPipeline := pipeline.NewCodePipeline(stack, jsii.String("cdkPipeline"), &pipeline.CodePipelineProps{ - PipelineName: jsii.String("CdkPipeline"), - // self mutation true - pipeline changes itself before application deployment - SelfMutation: jsii.Bool(true), - CodeBuildDefaults: &pipeline.CodeBuildOptions{ - BuildEnvironment: &codebuild.BuildEnvironment{ - // image version 6.0 recommended for newer go version - BuildImage: codebuild.LinuxBuildImage_FromCodeBuildImageId(jsii.String("aws/codebuild/standard:6.0")), - }, - }, - Synth: pipeline.NewCodeBuildStep(jsii.String("Synth"), &pipeline.CodeBuildStepProps{ - Input: githubRepo, - Commands: &[]*string{ - jsii.String("npm install -g aws-cdk"), - jsii.String("cdk synth"), - }, - }), - }) - - // deployment of actual CDK application - myPipeline.AddStage(NewCdkApplication(stack, jsii.String("MyApplication"), &awscdk.StageProps{ - Env: targetAccountEnv(), - }), &pipeline.AddStageOpts{ - Post: &[]pipeline.Step{ - pipeline.NewCodeBuildStep(jsii.String("Manual Steps"), &pipeline.CodeBuildStepProps{ - Commands: &[]*string{ - jsii.String("echo \"My CDK App deployed, manual steps go here ... \""), - }, - }), - }, - }) - - return stack -} - -// main app -func main() { - defer jsii.Close() - - app := awscdk.NewApp(nil) - - // call CDK Pipeline - NewCdkPipeline(app, jsii.String("CdkPipelineStack"), &awscdk.StackProps{ - Env: pipelineEnv(), - }) - - app.Synth(nil) -} - -// env determines the AWS environment (account+region) in which our stack is to -// be deployed. For more information see: https://docs.aws.amazon.com/cdk/latest/guide/environments.html -func pipelineEnv() *awscdk.Environment { - return &awscdk.Environment{ - Account: jsii.String(os.Getenv("CDK_DEFAULT_ACCOUNT")), - Region: jsii.String(os.Getenv("CDK_DEFAULT_REGION")), - } -} - -func targetAccountEnv() *awscdk.Environment { - return &awscdk.Environment{ - Account: jsii.String(os.Getenv("CDK_DEFAULT_ACCOUNT")), - Region: jsii.String(os.Getenv("CDK_DEFAULT_REGION")), - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>You must deploy a pipeline manually once. After that, the pipeline keeps itself up to date from the source code repository. So be sure that the code in the repo is the code you want deployed. Check in your changes and push to GitHub, then deploy:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">git add --all -git commit -m "initial commit" -git push -cdk deploy</code></pre> -</div> -</div> -<div class="admonitionblock tip"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-tip" title="Tip"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>Now that you’ve done the initial deployment, your local AWS account no longer needs administrative access. This is because all changes to your app will be deployed via the pipeline. All you need to be able to do is push to GitHub.</p> -</div> -</td> -</tr> -</table> -</div> -</div> -<div class="sect3"> -<h4 id="cdk-pipeline-stages">14.6.4. Application stages</h4> -<div class="paragraph"> -<p>To define a multi-stack AWS application that can be added to the pipeline all at once, define a subclass of <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stage.html">Stage</a></code>. (This is different from <code>CdkStage</code> in the CDK Pipelines module.)</p> -</div> -<div class="paragraph"> -<p>The stage contains the stacks that make up your application. If there are dependencies between the stacks, the stacks are automatically added to the pipeline in the right order. Stacks that don’t depend on each other are deployed in parallel. You can add a dependency relationship between stacks by calling <code>stack1.addDependency(stack2)</code>.</p> -</div> -<div class="paragraph"> -<p>Stages accept a default <code>env</code> argument, which becomes the default environment for the stacks inside it. (Stacks can still have their own environment specified.).</p> -</div> -<div class="paragraph"> -<p>An application is added to the pipeline by calling <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.pipelines.CodePipeline.html#addwbrstagestage-optionss">addStage</a>()</code> with instances of <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stage.html">Stage</a>. A stage can be instantiated and added to the pipeline multiple times to define different stages of your DTAP or multi-Region application pipeline.</p> -</div> -<div class="paragraph"> -<p>We will create a stack containing a simple Lambda function and place that stack in a stage. Then we will add the stage to the pipeline so it can be deployed.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Create the new file <code class="path">lib/my-pipeline-lambda-stack.ts</code> to hold our application stack containing a Lambda function.</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as cdk from 'aws-cdk-lib'; -import { Construct } from 'constructs'; -import { Function, InlineCode, Runtime } from 'aws-cdk-lib/aws-lambda'; - -export class MyLambdaStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - new Function(this, 'LambdaFunction', { - runtime: Runtime.NODEJS_18_X, - handler: 'index.handler', - code: new InlineCode('exports.handler = _ => "Hello, CDK";') - }); - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Create the new file <code class="path">lib/my-pipeline-app-stage.ts</code> to hold our stage.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as cdk from 'aws-cdk-lib'; -import { Construct } from "constructs"; -import { MyLambdaStack } from './my-pipeline-lambda-stack'; - -export class MyPipelineAppStage extends cdk.Stage { - - constructor(scope: Construct, id: string, props?: cdk.StageProps) { - super(scope, id, props); - - const lambdaStack = new MyLambdaStack(this, 'LambdaStack'); - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Edit <code class="path">lib/my-pipeline-stack.ts</code> to add the stage to our pipeline.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as cdk from 'aws-cdk-lib'; -import { Construct } from 'constructs'; -import { CodePipeline, CodePipelineSource, ShellStep } from 'aws-cdk-lib/pipelines'; -import { MyPipelineAppStage } from './my-pipeline-app-stage'; - -export class MyPipelineStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - const pipeline = new CodePipeline(this, 'Pipeline', { - pipelineName: 'MyPipeline', - synth: new ShellStep('Synth', { - input: CodePipelineSource.gitHub('OWNER/REPO', 'main'), - commands: ['npm ci', 'npm run build', 'npx cdk synth'] - }) - }); - - pipeline.addStage(new MyPipelineAppStage(this, "test", { - env: { account: "111111111111", region: "eu-west-1" } - })); - } -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">JavaScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Create the new file <code class="path">lib/my-pipeline-lambda-stack.js</code> to hold our application stack containing a Lambda function.</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const cdk = require('aws-cdk-lib'); -const { Function, InlineCode, Runtime } = require('aws-cdk-lib/aws-lambda'); - -class MyLambdaStack extends cdk.Stack { - constructor(scope, id, props) { - super(scope, id, props); - - new Function(this, 'LambdaFunction', { - runtime: Runtime.NODEJS_18_X, - handler: 'index.handler', - code: new InlineCode('exports.handler = _ => "Hello, CDK";') - }); - } -} - -module.exports = { MyLambdaStack }</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Create the new file <code class="path">lib/my-pipeline-app-stage.js</code> to hold our stage.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const cdk = require('aws-cdk-lib'); -const { MyLambdaStack } = require('./my-pipeline-lambda-stack'); - -class MyPipelineAppStage extends cdk.Stage { - - constructor(scope, id, props) { - super(scope, id, props); - - const lambdaStack = new MyLambdaStack(this, 'LambdaStack'); - } -} - -module.exports = { MyPipelineAppStage };</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Edit <code class="path">lib/my-pipeline-stack.ts</code> to add the stage to our pipeline.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const cdk = require('aws-cdk-lib'); -const { CodePipeline, CodePipelineSource, ShellStep } = require('aws-cdk-lib/pipelines'); -const { MyPipelineAppStage } = require('./my-pipeline-app-stage'); - - class MyPipelineStack extends cdk.Stack { - constructor(scope, id, props) { - super(scope, id, props); - - const pipeline = new CodePipeline(this, 'Pipeline', { - pipelineName: 'MyPipeline', - synth: new ShellStep('Synth', { - input: CodePipelineSource.gitHub('OWNER/REPO', 'main'), - commands: ['npm ci', 'npm run build', 'npx cdk synth'] - }) - }); - - pipeline.addStage(new MyPipelineAppStage(this, "test", { - env: { account: "111111111111", region: "eu-west-1" } - })); - - } -} - -module.exports = { MyPipelineStack }</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Python</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Create the new file <code class="path">my_pipeline/my_pipeline_lambda_stack.py</code> to hold our application stack containing a Lambda function.</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">import aws_cdk as cdk -from constructs import Construct -from aws_cdk.aws_lambda import Function, InlineCode, Runtime - -class MyLambdaStack(cdk.Stack): - def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: - super().__init__(scope, construct_id, **kwargs) - - Function(self, "LambdaFunction", - runtime=Runtime.NODEJS_18_X, - handler="index.handler", - code=InlineCode("exports.handler = _ => 'Hello, CDK';") - )</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Create the new file <code class="path">my_pipeline/my_pipeline_app_stage.py</code> to hold our stage.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">import aws_cdk as cdk -from constructs import Construct -from my_pipeline.my_pipeline_lambda_stack import MyLambdaStack - -class MyPipelineAppStage(cdk.Stage): - def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: - super().__init__(scope, construct_id, **kwargs) - - lambdaStack = MyLambdaStack(self, "LambdaStack")</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Edit <code class="path">my_pipeline/my-pipeline-stack.py</code> to add the stage to our pipeline.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">import aws_cdk as cdk -from constructs import Construct -from aws_cdk.pipelines import CodePipeline, CodePipelineSource, ShellStep -from my_pipeline.my_pipeline_app_stage import MyPipelineAppStage - -class MyPipelineStack(cdk.Stack): - - def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: - super().__init__(scope, construct_id, **kwargs) - - pipeline = CodePipeline(self, "Pipeline", - pipeline_name="MyPipeline", - synth=ShellStep("Synth", - input=CodePipelineSource.git_hub("OWNER/REPO", "main"), - commands=["npm install -g aws-cdk", - "python -m pip install -r requirements.txt", - "cdk synth"])) - - pipeline.add_stage(MyPipelineAppStage(self, "test", - env=cdk.Environment(account="111111111111", region="eu-west-1")))</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Java</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Create the new file <code class="path">src/main/java/com.myorg/MyPipelineLambdaStack.java</code> to hold our application stack containing a Lambda function.</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">package com.myorg; - -import software.constructs.Construct; -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.StackProps; - -import software.amazon.awscdk.services.lambda.Function; -import software.amazon.awscdk.services.lambda.Runtime; -import software.amazon.awscdk.services.lambda.InlineCode; - -public class MyPipelineLambdaStack extends Stack { - public MyPipelineLambdaStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public MyPipelineLambdaStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - Function.Builder.create(this, "LambdaFunction") - .runtime(Runtime.NODEJS_18_X) - .handler("index.handler") - .code(new InlineCode("exports.handler = _ => 'Hello, CDK';")) - .build(); - - } - -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Create the new file <code class="path">src/main/java/com.myorg/MyPipelineAppStage.java</code> to hold our stage.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">package com.myorg; - -import software.constructs.Construct; -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.Stage; -import software.amazon.awscdk.StageProps; - -public class MyPipelineAppStage extends Stage { - public MyPipelineAppStage(final Construct scope, final String id) { - this(scope, id, null); - } - - public MyPipelineAppStage(final Construct scope, final String id, final StageProps props) { - super(scope, id, props); - - Stack lambdaStack = new MyPipelineLambdaStack(this, "LambdaStack"); - } - -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Edit <code class="path">src/main/java/com.myorg/MyPipelineStack.java</code> to add the stage to our pipeline.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">package com.myorg; - -import java.util.Arrays; -import software.constructs.Construct; -import software.amazon.awscdk.Environment; -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.StackProps; -import software.amazon.awscdk.StageProps; -import software.amazon.awscdk.pipelines.CodePipeline; -import software.amazon.awscdk.pipelines.CodePipelineSource; -import software.amazon.awscdk.pipelines.ShellStep; - -public class MyPipelineStack extends Stack { - public MyPipelineStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public MyPipelineStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - final CodePipeline pipeline = CodePipeline.Builder.create(this, "pipeline") - .pipelineName("MyPipeline") - .synth(ShellStep.Builder.create("Synth") - .input(CodePipelineSource.gitHub("OWNER/REPO", "main")) - .commands(Arrays.asList("npm install -g aws-cdk", "cdk synth")) - .build()) - .build(); - - pipeline.addStage(new MyPipelineAppStage(this, "test", StageProps.builder() - .env(Environment.builder() - .account("111111111111") - .region("eu-west-1") - .build()) - .build())); - } -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">C#</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Create the new file <code class="path">src/MyPipeline/MyPipelineLambdaStack.cs</code> to hold our application stack containing a Lambda function.</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; -using Constructs; -using Amazon.CDK.AWS.Lambda; - -namespace MyPipeline -{ - class MyPipelineLambdaStack : Stack - { - public MyPipelineLambdaStack(Construct scope, string id, StackProps props=null) : base(scope, id, props) - { - new Function(this, "LambdaFunction", new FunctionProps - { - Runtime = Runtime.NODEJS_18_X, - Handler = "index.handler", - Code = new InlineCode("exports.handler = _ => 'Hello, CDK';") - }); - } - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Create the new file <code class="path">src/MyPipeline/MyPipelineAppStage.cs</code> to hold our stage.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; -using Constructs; - -namespace MyPipeline -{ - class MyPipelineAppStage : Stage - { - public MyPipelineAppStage(Construct scope, string id, StageProps props=null) : base(scope, id, props) - { - Stack lambdaStack = new MyPipelineLambdaStack(this, "LambdaStack"); - } - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Edit <code class="path">src/MyPipeline/MyPipelineStack.cs</code> to add the stage to our pipeline.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; -using Constructs; -using Amazon.CDK.Pipelines; - -namespace MyPipeline -{ - public class MyPipelineStack : Stack - { - internal MyPipelineStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) - { - var pipeline = new CodePipeline(this, "pipeline", new CodePipelineProps - { - PipelineName = "MyPipeline", - Synth = new ShellStep("Synth", new ShellStepProps - { - Input = CodePipelineSource.GitHub("OWNER/REPO", "main"), - Commands = new string[] { "npm install -g aws-cdk", "cdk synth" } - }) - }); - - pipeline.AddStage(new MyPipelineAppStage(this, "test", new StageProps - { - Env = new Environment - { - Account = "111111111111", Region = "eu-west-1" - } - })); - } - } -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div class="paragraph"> -<p>Every application stage added by <code>addStage()</code> results in the addition of a corresponding pipeline stage, represented by a <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.pipelines.StageDeployment.html">StageDeployment</a> instance returned by the <code>addStage()</code> call. You can add pre-deployment or post-deployment actions to the stage by calling its <code>addPre()</code> or <code>addPost()</code> method.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">// import { ManualApprovalStep } from 'aws-cdk-lib/pipelines'; - -const testingStage = pipeline.addStage(new MyPipelineAppStage(this, 'testing', { - env: { account: '111111111111', region: 'eu-west-1' } -})); - - testingStage.addPost(new ManualApprovalStep('approval'));</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">// const { ManualApprovalStep } = require('aws-cdk-lib/pipelines'); - -const testingStage = pipeline.addStage(new MyPipelineAppStage(this, 'testing', { - env: { account: '111111111111', region: 'eu-west-1' } -})); - -testingStage.addPost(new ManualApprovalStep('approval'));</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python"># from aws_cdk.pipelines import ManualApprovalStep - -testing_stage = pipeline.add_stage(MyPipelineAppStage(self, "testing", - env=cdk.Environment(account="111111111111", region="eu-west-1"))) - -testing_stage.add_post(ManualApprovalStep('approval'))</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">// import software.amazon.awscdk.pipelines.StageDeployment; -// import software.amazon.awscdk.pipelines.ManualApprovalStep; - -StageDeployment testingStage = - pipeline.addStage(new MyPipelineAppStage(this, "test", StageProps.builder() - .env(Environment.builder() - .account("111111111111") - .region("eu-west-1") - .build()) - .build())); - -testingStage.addPost(new ManualApprovalStep("approval"));</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">var testingStage = pipeline.AddStage(new MyPipelineAppStage(this, "test", new StageProps -{ - Env = new Environment - { - Account = "111111111111", Region = "eu-west-1" - } -})); - -testingStage.AddPost(new ManualApprovalStep("approval"));</code></pre> -</div> -</div> -<div class="paragraph"> -<p>You can add stages to a <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.pipelines.Wave.html">Wave</a> to deploy them in parallel, for example when deploying a stage to multiple accounts or Regions.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const wave = pipeline.addWave('wave'); -wave.addStage(new MyApplicationStage(this, 'MyAppEU', { - env: { account: '111111111111', region: 'eu-west-1' } -})); -wave.addStage(new MyApplicationStage(this, 'MyAppUS', { - env: { account: '111111111111', region: 'us-west-1' } -}));</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const wave = pipeline.addWave('wave'); -wave.addStage(new MyApplicationStage(this, 'MyAppEU', { - env: { account: '111111111111', region: 'eu-west-1' } -})); -wave.addStage(new MyApplicationStage(this, 'MyAppUS', { - env: { account: '111111111111', region: 'us-west-1' } -}));</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">wave = pipeline.add_wave("wave") -wave.add_stage(MyApplicationStage(self, "MyAppEU", - env=cdk.Environment(account="111111111111", region="eu-west-1"))) -wave.add_stage(MyApplicationStage(self, "MyAppUS", - env=cdk.Environment(account="111111111111", region="us-west-1")))</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">// import software.amazon.awscdk.pipelines.Wave; -final Wave wave = pipeline.addWave("wave"); -wave.addStage(new MyPipelineAppStage(this, "MyAppEU", StageProps.builder() - .env(Environment.builder() - .account("111111111111") - .region("eu-west-1") - .build()) - .build())); -wave.addStage(new MyPipelineAppStage(this, "MyAppUS", StageProps.builder() - .env(Environment.builder() - .account("111111111111") - .region("us-west-1") - .build()) - .build()));</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">var wave = pipeline.AddWave("wave"); -wave.AddStage(new MyPipelineAppStage(this, "MyAppEU", new StageProps -{ - Env = new Environment - { - Account = "111111111111", Region = "eu-west-1" - } -})); -wave.AddStage(new MyPipelineAppStage(this, "MyAppUS", new StageProps -{ - Env = new Environment - { - Account = "111111111111", Region = "us-west-1" - } -}));</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="cdk-pipeline-validation">14.6.5. Testing deployments</h4> -<div class="paragraph"> -<p>You can add steps to a CDK Pipeline to validate the deployments that you’re performing. For example, you can use the CDK Pipeline library’s <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.pipelines.ShellStep.html">ShellStep</a></code> to perform tasks such as the following:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Trying to access a newly deployed Amazon API Gateway backed by a Lambda function</p> -</li> -<li> -<p>Checking a setting of a deployed resource by issuing an AWS CLI command</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>In its simplest form, adding validation actions looks like this:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">// stage was returned by pipeline.addStage - -stage.addPost(new ShellStep("validate", { - commands: ['../tests/validate.sh'], -}));</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">// stage was returned by pipeline.addStage - -stage.addPost(new ShellStep("validate", { - commands: ['../tests/validate.sh'], -}));</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python"># stage was returned by pipeline.add_stage - -stage.add_post(ShellStep("validate", - commands=[''../tests/validate.sh''] -))</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">// stage was returned by pipeline.addStage - -stage.addPost(ShellStep.Builder.create("validate") - .commands(Arrays.asList("'../tests/validate.sh'")) - .build());</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">// stage was returned by pipeline.addStage - -stage.AddPost(new ShellStep("validate", new ShellStepProps -{ - Commands = new string[] { "'../tests/validate.sh'" } -}));</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Many AWS CloudFormation deployments result in the generation of resources with unpredictable names. Because of this, CDK Pipelines provide a way to read AWS CloudFormation outputs after a deployment. This makes it possible to pass (for example) the generated URL of a load balancer to a test action.</p> -</div> -<div class="paragraph"> -<p>To use outputs, expose the <code>CfnOutput</code> object you’re interested in. Then, pass it in a step’s <code>envFromCfnOutputs</code> property to make it available as an environment variable within that step.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">// given a stack lbStack that exposes a load balancer construct as loadBalancer -this.loadBalancerAddress = new cdk.CfnOutput(lbStack, 'LbAddress', { - value: `https://${lbStack.loadBalancer.loadBalancerDnsName}/` -}); - -// pass the load balancer address to a shell step -stage.addPost(new ShellStep("lbaddr", { - envFromCfnOutputs: {lb_addr: lbStack.loadBalancerAddress}, - commands: ['echo $lb_addr'] -}));</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">// given a stack lbStack that exposes a load balancer construct as loadBalancer -this.loadBalancerAddress = new cdk.CfnOutput(lbStack, 'LbAddress', { - value: `https://${lbStack.loadBalancer.loadBalancerDnsName}/` -}); - -// pass the load balancer address to a shell step -stage.addPost(new ShellStep("lbaddr", { - envFromCfnOutputs: {lb_addr: lbStack.loadBalancerAddress}, - commands: ['echo $lb_addr'] -}));</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python"># given a stack lb_stack that exposes a load balancer construct as load_balancer -self.load_balancer_address = cdk.CfnOutput(lb_stack, "LbAddress", - value=f"https://{lb_stack.load_balancer.load_balancer_dns_name}/") - -# pass the load balancer address to a shell step -stage.add_post(ShellStep("lbaddr", - env_from_cfn_outputs={"lb_addr": lb_stack.load_balancer_address} - commands=["echo $lb_addr"]))</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">// given a stack lbStack that exposes a load balancer construct as loadBalancer -loadBalancerAddress = CfnOutput.Builder.create(lbStack, "LbAddress") - .value(String.format("https://%s/", - lbStack.loadBalancer.loadBalancerDnsName)) - .build(); - -stage.addPost(ShellStep.Builder.create("lbaddr") - .envFromCfnOutputs( // Map.of requires Java 9 or later - java.util.Map.of("lbAddr", loadBalancerAddress)) - .commands(Arrays.asList("echo $lbAddr")) - .build());</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">// given a stack lbStack that exposes a load balancer construct as loadBalancer -loadBalancerAddress = new CfnOutput(lbStack, "LbAddress", new CfnOutputProps -{ - Value = string.Format("https://{0}/", lbStack.loadBalancer.LoadBalancerDnsName) -}); - -stage.AddPost(new ShellStep("lbaddr", new ShellStepProps -{ - EnvFromCfnOutputs = new Dictionary<string, CfnOutput> - { - { "lbAddr", loadBalancerAddress } - }, - Commands = new string[] { "echo $lbAddr" } -}));</code></pre> -</div> -</div> -<div class="paragraph"> -<p>You can write simple validation tests right in the <code>ShellStep</code>, but this approach becomes unwieldy when the test is more than a few lines. For more complex tests, you can bring additional files (such as complete shell scripts, or programs in other languages) into the <code>ShellStep</code> via the <code>inputs</code> property. The inputs can be any step that has an output, including a source (such as a GitHub repo) or another <code>ShellStep</code>.</p> -</div> -<div class="paragraph"> -<p>Bringing in files from the source repository is appropriate if the files are directly usable in the test (for example, if they are themselves executable). In this example, we declare our GitHub repo as <code>source</code> (rather than instantiating it inline as part of the <code>CodePipeline</code>). Then, we pass this fileset to both the pipeline and the validation test.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const source = CodePipelineSource.gitHub('OWNER/REPO', 'main'); - -const pipeline = new CodePipeline(this, 'Pipeline', { - pipelineName: 'MyPipeline', - synth: new ShellStep('Synth', { - input: source, - commands: ['npm ci', 'npm run build', 'npx cdk synth'] - }) -}); - -const stage = pipeline.addStage(new MyPipelineAppStage(this, 'test', { - env: { account: '111111111111', region: 'eu-west-1' } -})); - -stage.addPost(new ShellStep('validate', { - input: source, - commands: ['sh ../tests/validate.sh'] -}));</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const source = CodePipelineSource.gitHub('OWNER/REPO', 'main'); - -const pipeline = new CodePipeline(this, 'Pipeline', { - pipelineName: 'MyPipeline', - synth: new ShellStep('Synth', { - input: source, - commands: ['npm ci', 'npm run build', 'npx cdk synth'] - }) -}); - -const stage = pipeline.addStage(new MyPipelineAppStage(this, 'test', { - env: { account: '111111111111', region: 'eu-west-1' } -})); - -stage.addPost(new ShellStep('validate', { - input: source, - commands: ['sh ../tests/validate.sh'] -}));</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">source = CodePipelineSource.git_hub("OWNER/REPO", "main") - -pipeline = CodePipeline(self, "Pipeline", - pipeline_name="MyPipeline", - synth=ShellStep("Synth", - input=source, - commands=["npm install -g aws-cdk", - "python -m pip install -r requirements.txt", - "cdk synth"])) - -stage = pipeline.add_stage(MyApplicationStage(self, "test", - env=cdk.Environment(account="111111111111", region="eu-west-1"))) - -stage.add_post(ShellStep("validate", input=source, - commands=["sh ../tests/validate.sh"], -))</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">final CodePipelineSource source = CodePipelineSource.gitHub("OWNER/REPO", "main"); - -final CodePipeline pipeline = CodePipeline.Builder.create(this, "pipeline") - .pipelineName("MyPipeline") - .synth(ShellStep.Builder.create("Synth") - .input(source) - .commands(Arrays.asList("npm install -g aws-cdk", "cdk synth")) - .build()) - .build(); - -final StageDeployment stage = - pipeline.addStage(new MyPipelineAppStage(this, "test", StageProps.builder() - .env(Environment.builder() - .account("111111111111") - .region("eu-west-1") - .build()) - .build())); - -stage.addPost(ShellStep.Builder.create("validate") - .input(source) - .commands(Arrays.asList("sh ../tests/validate.sh")) - .build());</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">var source = CodePipelineSource.GitHub("OWNER/REPO", "main"); - -var pipeline = new CodePipeline(this, "pipeline", new CodePipelineProps -{ - PipelineName = "MyPipeline", - Synth = new ShellStep("Synth", new ShellStepProps - { - Input = source, - Commands = new string[] { "npm install -g aws-cdk", "cdk synth" } - }) -}); - -var stage = pipeline.AddStage(new MyPipelineAppStage(this, "test", new StageProps -{ - Env = new Environment - { - Account = "111111111111", Region = "eu-west-1" - } -})); - -stage.AddPost(new ShellStep("validate", new ShellStepProps -{ - Input = source, - Commands = new string[] { "sh ../tests/validate.sh" } -}));</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Getting the additional files from the synth step is appropriate if your tests need to be compiled, which is done as part of synthesis.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const synthStep = new ShellStep('Synth', { - input: CodePipelineSource.gitHub('OWNER/REPO', 'main'), - commands: ['npm ci', 'npm run build', 'npx cdk synth'], -}); - -const pipeline = new CodePipeline(this, 'Pipeline', { - pipelineName: 'MyPipeline', - synth: synthStep -}); - -const stage = pipeline.addStage(new MyPipelineAppStage(this, 'test', { - env: { account: '111111111111', region: 'eu-west-1' } -})); - -// run a script that was transpiled from TypeScript during synthesis -stage.addPost(new ShellStep('validate', { - input: synthStep, - commands: ['node tests/validate.js'] -}));</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const synthStep = new ShellStep('Synth', { - input: CodePipelineSource.gitHub('OWNER/REPO', 'main'), - commands: ['npm ci', 'npm run build', 'npx cdk synth'], -}); - -const pipeline = new CodePipeline(this, 'Pipeline', { - pipelineName: 'MyPipeline', - synth: synthStep -}); - -const stage = pipeline.addStage(new MyPipelineAppStage(this, "test", { - env: { account: "111111111111", region: "eu-west-1" } -})); - -// run a script that was transpiled from TypeScript during synthesis -stage.addPost(new ShellStep('validate', { - input: synthStep, - commands: ['node tests/validate.js'] -}));</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">synth_step = ShellStep("Synth", - input=CodePipelineSource.git_hub("OWNER/REPO", "main"), - commands=["npm install -g aws-cdk", - "python -m pip install -r requirements.txt", - "cdk synth"]) - -pipeline = CodePipeline(self, "Pipeline", - pipeline_name="MyPipeline", - synth=synth_step) - -stage = pipeline.add_stage(MyApplicationStage(self, "test", - env=cdk.Environment(account="111111111111", region="eu-west-1"))) - -# run a script that was compiled during synthesis -stage.add_post(ShellStep("validate", - input=synth_step, - commands=["node test/validate.js"], -))</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">final ShellStep synth = ShellStep.Builder.create("Synth") - .input(CodePipelineSource.gitHub("OWNER/REPO", "main")) - .commands(Arrays.asList("npm install -g aws-cdk", "cdk synth")) - .build(); - -final CodePipeline pipeline = CodePipeline.Builder.create(this, "pipeline") - .pipelineName("MyPipeline") - .synth(synth) - .build(); - -final StageDeployment stage = - pipeline.addStage(new MyPipelineAppStage(this, "test", StageProps.builder() - .env(Environment.builder() - .account("111111111111") - .region("eu-west-1") - .build()) - .build())); - -stage.addPost(ShellStep.Builder.create("validate") - .input(synth) - .commands(Arrays.asList("node ./tests/validate.js")) - .build());</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">var synth = new ShellStep("Synth", new ShellStepProps -{ - Input = CodePipelineSource.GitHub("OWNER/REPO", "main"), - Commands = new string[] { "npm install -g aws-cdk", "cdk synth" } -}); - -var pipeline = new CodePipeline(this, "pipeline", new CodePipelineProps -{ - PipelineName = "MyPipeline", - Synth = synth -}); - -var stage = pipeline.AddStage(new MyPipelineAppStage(this, "test", new StageProps -{ - Env = new Environment - { - Account = "111111111111", Region = "eu-west-1" - } -})); - -stage.AddPost(new ShellStep("validate", new ShellStepProps -{ - Input = synth, - Commands = new string[] { "node ./tests/validate.js" } -}));</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="cdk-pipeline-security">14.6.6. Security notes</h4> -<div class="paragraph"> -<p>Any form of continuous delivery has inherent security risks. Under the AWS <a href="https://aws.amazon.com/compliance/shared-responsibility-model/">Shared Responsibility Model</a>, you are responsible for the security of your information in the AWS Cloud. The CDK Pipelines library gives you a head start by incorporating secure defaults and modeling best practices.</p> -</div> -<div class="paragraph"> -<p>However, by its very nature, a library that needs a high level of access to fulfill its intended purpose cannot assure complete security. There are many attack vectors outside of AWS and your organization.</p> -</div> -<div class="paragraph"> -<p>In particular, keep in mind the following:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Be mindful of the software you depend on. Vet all third-party software you run in your pipeline, because it can change the infrastructure that gets deployed.</p> -</li> -<li> -<p>Use dependency locking to prevent accidental upgrades. CDK Pipelines respects <code class="path">package-lock.json</code> and <code class="path">yarn.lock</code> to make sure that your dependencies are the ones you expect.</p> -</li> -<li> -<p>CDK Pipelines runs on resources created in your own account, and the configuration of those resources is controlled by developers submitting code through the pipeline. Therefore, CDK Pipelines by itself cannot protect against malicious developers trying to bypass compliance checks. If your threat model includes developers writing CDK code, you should have external compliance mechanisms in place like <a href="https://aws.amazon.com/blogs/mt/proactively-keep-resources-secure-and-compliant-with-aws-cloudformation-hooks/">AWS CloudFormation Hooks</a> (preventive) or <a href="https://aws.amazon.com/config/">AWS Config</a> (reactive) that the AWS CloudFormation Execution Role does not have permissions to disable.</p> -</li> -<li> -<p>Credentials for production environments should be short-lived. After bootstrapping and initial provisioning, there is no need for developers to have account credentials at all. Changes can be deployed through the pipeline. Reduce the possibility of credentials leaking by not needing them in the first place.</p> -</li> -</ul> -</div> -</div> -<div class="sect3"> -<h4 id="cdk-pipeline-troubleshooting">14.6.7. Troubleshooting</h4> -<div class="paragraph"> -<p>The following issues are commonly encountered while getting started with CDK Pipelines.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Pipeline: Internal Failure</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre>CREATE_FAILED | AWS::CodePipeline::Pipeline | Pipeline/Pipeline -Internal Failure</pre> -</div> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p>Check your GitHub access token. It might be missing, or might not have the permissions to access the repository.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Key: Policy contains a statement with one or more invalid principals</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre>CREATE_FAILED | AWS::KMS::Key | Pipeline/Pipeline/ArtifactsBucketEncryptionKey -Policy contains a statement with one or more invalid principals.</pre> -</div> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p>One of the target environments has not been bootstrapped with the new bootstrap stack. Make sure all your target environments are bootstrapped.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Stack is in ROLLBACK_COMPLETE state and can not be updated.</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre>Stack`STACK_NAME`is in ROLLBACK_COMPLETE state and can not be updated. (Service: -AmazonCloudFormation; Status Code: 400; Error Code: ValidationError; Request -ID: ...)</pre> -</div> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p>The stack failed its previous deployment and is in a non-retryable state. Delete the stack from the AWS CloudFormation console and retry the deployment.</p> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="build-containers">14.7. Build and deploy container image assets in CDK apps</h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>When you build container image assets with the AWS Cloud Development Kit (AWS CDK), <code class="noloc">Docker</code> is utilized by default to perform these actions. If you want to use a different container management tool, you can replace <code class="noloc">Docker</code> through the <code>CDK_DOCKER</code> environment variable.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>When you build container image assets with the AWS Cloud Development Kit (AWS CDK), <code class="noloc">Docker</code> is utilized by default to perform these actions. If you want to use a different container management tool, you can replace <code class="noloc">Docker</code> through the <code>CDK_DOCKER</code> environment variable.</p> -</div> -<div class="sect3"> -<h4 id="build-containers-intro-example">14.7.1. Example: Build and publish a container image asset with the AWS CDK</h4> -<div class="paragraph"> -<p>The following is a simple example of an AWS CDK app that builds and publishes a container asset to Amazon Elastic Container Registry (Amazon ECR) using <code class="noloc">Docker</code> by default:</p> -</div> -<div class="paragraph"> -<p><strong>Project structure</strong>:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">my-cdk-app/ -├── lib/ -│ ├── my-stack.ts -│ └── docker/ -│ ├── Dockerfile -│ └── app/ -│ └── index.js -├── bin/ -│ └── my-cdk-app.ts -├── package.json -├── tsconfig.json -└── cdk.json</code></pre> -</div> -</div> -<div class="paragraph"> -<p><strong><code class="noloc">Dockerfile</code>:</strong></p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-auto" data-lang="auto">FROM public.ecr.aws/lambda/nodejs:16 - -# Copy application code -COPY app/ /var/task/ - -# (Optional) Install dependencies -# RUN npm install - -# The AWS Lambda Node.js base image looks for index.handler by default</code></pre> -</div> -</div> -<div class="paragraph"> -<p><strong>Application code</strong>:</p> -</div> -<div class="paragraph"> -<p>In <code class="path">lib/docker/app/index.js</code>:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">console.log("Hello from inside the container!");</code></pre> -</div> -</div> -<div class="paragraph"> -<p><strong>CDK stack</strong>:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as cdk from 'aws-cdk-lib'; -import { Construct } from 'constructs'; -import * as ecr_assets from 'aws-cdk-lib/aws-ecr-assets'; - -export class MyStack extends cdk.Stack { - constructor(scope: Construct, id: string) { - super(scope, id); - - // Define a Docker image asset - const dockerImageAsset = new ecr_assets.DockerImageAsset(this, 'MyDockerImage', { - directory: 'lib/docker', // Path to the directory containing the Dockerfile - }); - - // Output the ECR URI - new cdk.CfnOutput(this, 'ECRImageUri', { - value: dockerImageAsset.imageUri, - }); - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p><strong>CDK app</strong>:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">#!/usr/bin/env node -import * as cdk from 'aws-cdk-lib'; -import { MyStack } from '../lib/my-stack'; - -const app = new cdk.App(); -new MyStack(app, 'MyStack');</code></pre> -</div> -</div> -<div class="paragraph"> -<p>When we run <code>cdk deploy</code>, the AWS Cloud Development Kit (AWS CDK) Command Line Interface (<code class="noloc">CLI</code>) does the following:</p> -</div> -<div class="olist arabic"> -<ol class="arabic"> -<li> -<p><strong>Build the <code class="noloc">Docker</code> image</strong> – Run <code>docker build</code> locally based on the <code class="path">Dockerfile</code> in the specified directory (<code class="path">lib/docker</code>).</p> -</li> -<li> -<p><strong>Tag the image</strong> – Run <code>docker tag</code> to tag the built image with a unique hash, based on the image contents.</p> -</li> -<li> -<p><strong>Publish to Amazon ECR</strong> – Run <code>docker push</code> to publish the container image to an Amazon ECR repository. This repository must already exist. It is created during the default bootstrapping process.</p> -</li> -<li> -<p><strong>Output the Image URI</strong> – After a successful deployment, the Amazon ECR URI of the published container image is output in your command prompt. This is the URI of our <code class="noloc">Docker</code> image in Amazon ECR.</p> -</li> -</ol> -</div> -</div> -<div class="sect3"> -<h4 id="build-container-replace">14.7.2. How to replace <code class="noloc">Docker</code> with another container management tool</h4> -<div class="paragraph"> -<p>Use the <code>CDK_DOCKER</code> environment variable to specify the path to the binary of your replacement container management tool. The following is an example of replacing <code class="noloc">Docker</code> with <code class="noloc">Finch</code>:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-auto" data-lang="auto">$ which finch -/usr/local/bin/finch # Locate the path to the binary - -$ export CDK_DOCKER='/usr/local/bin/finch' # Set the environment variable - -$ cdk deploy # Deploy using the replacement</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Aliasing or linking is not supported. To replace <code class="noloc">Docker</code>, you must use the <code>CDK_DOCKER</code> environment variable.</p> -</div> -</div> -<div class="sect3"> -<h4 id="build-container-supported">14.7.3. Supported <code class="noloc">Docker</code> drop-in replacement engines</h4> -<div class="paragraph"> -<p><code class="noloc">Finch</code> is supported, although there may be some <code class="noloc">Docker</code> features that are unavailable or may work differently as the tool evolves. For more information on Finch, see <a href="https://aws.amazon.com/blogs/opensource/ready-for-flight-announcing-finch-1-0-ga/">Ready for Flight: Announcing Finch 1.0 GA!</a> in the <em>AWS Open Source Blog</em>.</p> -</div> -<div class="paragraph"> -<p>Other container management tools may work. The CDK doesn’t check which <code class="noloc">Docker</code> replacement you are using to determine if it’s supported. If the tool has equivalent <code class="noloc">Docker</code> commands and behaves similarly, it should work.</p> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="deploy-troubleshoot">14.8. Troubleshoot AWS CDK deployments</h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Troubleshoot common issues when deploying AWS Cloud Development Kit (AWS CDK) applications.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>Troubleshoot common issues when deploying AWS Cloud Development Kit (AWS CDK) applications.</p> -</div> -<div class="sect3"> -<h4 id="deploy-troubleshoot-sp">14.8.1. Incorrect service principals are being created at deployment</h4> -<div class="paragraph"> -<p>When deploying CDK applications that contain AWS Identity and Access Management (IAM) roles with service principals, you find that incorrect domains for the service principals are being created.</p> -</div> -<div class="paragraph"> -<p>The following is a basic example of creating an IAM role that can be assumed by Amazon CloudWatch Logs using its service principal:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as cdk from 'aws-cdk-lib'; -import * as iam from 'aws-cdk-lib/aws-iam'; -import { Construct } from 'constructs'; - -export class MyCdkProjectStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - // Create an IAM role for CloudWatch Logs to assume - const cloudWatchLogsRole = new iam.Role(this, 'CloudWatchLogsRole', { - assumedBy: new iam.ServicePrincipal('logs.amazonaws.com'), // This is for CloudWatch Logs - managedPolicies: [ - iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSCloudWatchLogsFullAccess') - ] - }); - - // You can then use this role in other constructs or configurations where CloudWatch Logs needs to assume a role - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>When you deploy this stack, a service principal named <code>logs.amazonaws.com</code> should be created. In most cases, AWS services use the following naming for service principals: <code>[replaceable]</code>service<code>.amazonaws.com</code>.</p> -</div> -<div class="sect4"> -<h5 id="deploy-troubleshoot-sp-causes">Common causes</h5> -<div class="paragraph"> -<p>If you are using a version of the AWS CDK older than v2.150.0, you may encounter this bug. In older AWS CDK versions, the naming of service principals were not standardized, which could lead to the creation of service principals with incorrect domains.</p> -</div> -<div class="paragraph"> -<p>In AWS CDK v2.51.0, a fix was implemented by standardizing all automatically created service principals to use <code><code class="replaceable">service</code>.amazonaws.com</code> when possible. This fix was available by allowing the <code>@aws-cdk/aws-iam:standardizedServicePrincipals</code> feature flag.</p> -</div> -<div class="paragraph"> -<p>Starting in AWS CDK v2.150.0, this became default behavior.</p> -</div> -</div> -<div class="sect4"> -<h5 id="deploy-troubleshoot-sp-resolution">Resolution</h5> -<div class="paragraph"> -<p>Upgrade to AWS CDK v2.150.0 or newer.</p> -</div> -<div class="paragraph"> -<p>If you are unable to upgrade to AWS CDK v2.150.0 or newer, you must upgrade to at least v2.51.0 or newer. Then, allow the following feature flag in your <code class="path">cdk.json</code> file: <code>@aws-cdk/aws-iam:standardizedServicePrincipals</code>.</p> -</div> -</div> -</div> -</div> -</div> -</div> -<div class="sect1 topic"> -<h2 id="toolkit-library">15. Perform programmatic actions using the CDK Toolkit Library</h2> -<div class="sectionbody"> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>The AWS Cloud Development Kit (AWS CDK) Toolkit Library enables you to perform AWS CDK actions requiring programmatic access on AWS.</p> -</div> -</blockquote> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>[.banner.info]CDK Toolkit Library is in developer preview and is subject to change.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="sect2"> -<h3 id="toolkit-library-intro">15.1. What is the CDK Toolkit Library Library?</h3> -<div class="paragraph"> -<p>The AWS Cloud Development Kit (AWS CDK) Toolkit Library enables you to perform AWS CDK actions requiring programmatic access on AWS. You can use the CDK Toolkit Library to implement actions such as bootstrapping, synthesizing, and deploying through code rather than CDK <code class="noloc">CLI</code> commands. With this library, you can create custom tools, build specialized <code class="noloc">CLI</code> applications, and integrate CDK programmatic access capabilities into your development workflows.</p> -</div> -<div class="paragraph"> -<p>The following is an example, that installs the CDK Toolkit Library and uses it to deploy a cloud assembly of your CDK app:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import { Toolkit } from '@aws-cdk/toolkit-lib'; // Install the CDK Toolkit Library - -const cdk = new Toolkit(); // Create a CDK Toolkit instance - -// ... - -// Implement a deployment -await cdk.deploy(cloudAssembly, { - deploymentMethod: { method: "direct" }, // Configure deployment options - ... -}</code></pre> -</div> -</div> -</div> -<div class="sect2"> -<h3 id="toolkit-library-gs">15.2. Get started with the CDK Toolkit Library</h3> -<div class="paragraph"> -<p><em>To get started, see the <code class="path"><a href="https://www.npmjs.com/package/@aws-cdk/toolkit-lib">ReadMe</a></code> in the @aws-cdk/toolkit-lib</em><code>npm</code> package.</p> -</div> -<div class="paragraph"> -<p>For API reference information, see the <a href="https://docs.aws.amazon.com/cdk/api/toolkit-lib/">CDK Toolkit Library API reference</a>.</p> -</div> -</div> -</div> -</div> -<div class="sect1 topic"> -<h2 id="testing">16. Test AWS CDK applications</h2> -<div class="sectionbody"> -<div class="paragraph"> -<p>With the AWS CDK, your infrastructure can be as testable as any other code you write. You can test in the cloud and locally. This topic addresses how to test in the cloud. For guidance on local testing see <a href="#testing-locally">Locally test and build AWS CDK applications with the AWS SAM CLI</a>. The standard approach to testing AWS CDK apps uses the AWS CDK’s <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.assertions-readme.html">assertions</a> module and popular test frameworks like <a href="https://jestjs.io/">Jest</a> for TypeScript and JavaScript or <a href="https://docs.pytest.org/en/6.2.x/">Pytest</a> for Python.</p> -</div> -<div class="paragraph"> -<p>There are two categories of tests that you can write for AWS CDK apps.</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><strong>Fine-grained assertions</strong> test specific aspects of the generated AWS CloudFormation template, such as "this resource has this property with this value." These tests can detect regressions. They’re also useful when you’re developing new features using test-driven development. (You can write a test first, then make it pass by writing a correct implementation.) Fine-grained assertions are the most frequently used tests.</p> -</li> -<li> -<p><strong>Snapshot tests</strong> test the synthesized AWS CloudFormation template against a previously stored baseline template. Snapshot tests let you refactor freely, since you can be sure that the refactored code works exactly the same way as the original. If the changes were intentional, you can accept a new baseline for future tests. However, CDK upgrades can also cause synthesized templates to change, so you can’t rely only on snapshots to make sure that your implementation is correct.</p> -</li> -</ul> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>Complete versions of the TypeScript, Python, and Java apps used as examples in this topic are <a href="https://github.com/cdklabs/aws-cdk-testing-examples/">available on GitHub</a>.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="sect2 topic"> -<h3 id="testing-locally">16.1. Locally test and build AWS CDK applications with the AWS SAM <code class="noloc">CLI</code></h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>You can use AWS SAM to build and locally test your AWS CDK applications.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>You can use the AWS SAM <code class="noloc">CLI</code> to locally test and build serverless applications defined using the AWS Cloud Development Kit (AWS CDK). Because the AWS SAM <code class="noloc">CLI</code> works within the AWS CDK project structure, you can still use the <a href="#cli">AWS CDK CLI reference</a> for creating, modifying, and deploying your AWS CDK applications.</p> -</div> -<div class="paragraph"> -<p>For details on using AWS SAM, see <a href="https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-getting-started.html">Getting started with AWS SAM</a> in the <em>AWS Serverless Application Model Developer Guide</em>.</p> -</div> -<div class="paragraph topiclist"> -<p>[[Topic List]]</p> -</div> -<div class="sect3 topic"> -<h4 id="testing-locally-getting-started">16.1.1. Getting started with locally testing</h4> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Getting Started documentation that provides the prerequisites for using AWS CDK with AWS SAM, and tutorial for building, locally testing, and deploying a simple AWS CDK application.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>This topic describes what you need to use the AWS SAM <code class="noloc">CLI</code> with AWS CDK applications, and it provides instructions for building and locally testing a simple AWS CDK application.</p> -</div> -<div class="sect4"> -<h5 id="testing-locally-getting-started-prerequisites">Prerequisites</h5> -<div class="paragraph"> -<p>To test locally, you must install the AWS SAM <code class="noloc">CLI</code>. see <a href="https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/getting_started.html">Install the AWS SAM CLI</a> for installation instructions.</p> -</div> -</div> -<div class="sect4"> -<h5 id="testing-locally-getting-started-tutorial">Creating and locally testing an AWS CDK application</h5> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Learn how to use AWS SAM to download, build, and locally test a AWS CDK application.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>To locally test an AWS CDK application using the AWS SAM <code class="noloc">CLI</code>, you must have an AWS CDK application that contains a Lambda function. Use the following steps to create a basic AWS CDK application with a Lambda function. For more information, see <a href="https://docs.aws.amazon.com/cdk/latest/guide/serverless_example.html">Creating a serverless application using the AWS CDK</a> in the <em>AWS Cloud Development Kit (AWS CDK) Developer Guide</em>.</p> -</div> -<div class="sect5"> -<h6 id="testing-locally-getting-started-tutorial-init.title">Step 1: Create an AWS CDK application</h6> -<div class="paragraph"> -<p>For this tutorial, initialize an AWS CDK application that uses TypeScript.</p> -</div> -<div class="paragraph"> -<p>Command to run:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ mkdir cdk-sam-example -$ cd cdk-sam-example -$ cdk init app --language typescript</code></pre> -</div> -</div> -</div> -<div class="sect5"> -<h6 id="testing-locally-getting-started-tutorial-lambda.title">Step 2: Add a Lambda function to your application</h6> -<div class="paragraph"> -<p>Replace the code in <code class="path">lib/cdk-sam-example-stack.ts</code> with the following:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-typescript" data-lang="typescript">import { Stack, StackProps } from 'aws-cdk-lib'; -import { Construct } from 'constructs'; -import * as lambda from 'aws-cdk-lib/aws-lambda'; - -export class CdkSamExampleStack extends Stack { - constructor(scope: Construct, id: string, props?: StackProps) { - super(scope, id, props); - - new lambda.Function(this, 'MyFunction', { - runtime: lambda.Runtime.PYTHON_3_12, - handler: 'app.lambda_handler', - code: lambda.Code.fromAsset('./my_function'), - }); - } -}</code></pre> -</div> -</div> -</div> -<div class="sect5"> -<h6 id="testing-locally-getting-started-tutorial-code.title">Step 3: Add your Lambda function code</h6> -<div class="paragraph"> -<p>Create a directory named <code class="path">my_function</code>. In that directory, create a file named <code class="path">app.py</code>.</p> -</div> -<div class="paragraph"> -<p>Command to run:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">OS and Linux</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ mkdir my_function -$ cd my_function -$ touch app.py</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Windows</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ mkdir my_function -$ cd my_function -$ type nul > app.py</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">PowerShell</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ mkdir my_function -$ cd my_function -$ New-Item -Path "app.py”</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Add the following code to <code class="path">app.py</code>:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>def lambda_handler(event, context): - return "Hello from SAM and the CDK!"</code></pre> -</div> -</div> -</div> -<div class="sect5"> -<h6 id="testing-locally-getting-started-tutorial-function.title">Step 4: Test your Lambda function</h6> -<div class="paragraph"> -<p>You can use the AWS SAM <code class="noloc">CLI</code> to locally invoke a Lambda function that you define in an AWS CDK application. To do this, you need the function construct identifier and the path to your synthesized AWS CloudFormation template.</p> -</div> -<div class="paragraph"> -<p>Run the following command to go back to the <code>lib</code> directory:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cd ..</code></pre> -</div> -</div> -<div class="paragraph"> -<p><strong>Command to run:</strong></p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk synth --no-staging</code></pre> -</div> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ sam local invoke MyFunction --no-event -t ./cdk.out/CdkSamExampleStack.template.json</code></pre> -</div> -</div> -<div class="paragraph"> -<p><strong>Example output:</strong></p> -</div> -<div class="listingblock"> -<div class="content"> -<pre>Invoking app.lambda_handler (python3.9) - -START RequestId: 5434c093-7182-4012-9b06-635011cac4f2 Version: $LATEST -"Hello from SAM and the CDK!" -END RequestId: 5434c093-7182-4012-9b06-635011cac4f2 -REPORT RequestId: 5434c093-7182-4012-9b06-635011cac4f2 Init Duration: 0.32 ms Duration: 177.47 ms Billed Duration: 178 ms Memory Size: 128 MB Max Memory Used: 128 MB</pre> -</div> -</div> -</div> -</div> -</div> -<div class="sect3 topic"> -<h4 id="testing-locally-with-sam-cli">16.1.2. Local testing AWS CDK applications with AWS SAM</h4> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Use the <strong class="command">sam local</strong> command to locally test AWS CDK applications.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>You can use the AWS SAM <code class="noloc">CLI</code> to locally test your AWS CDK applications by running the following commands from the project root directory of your AWS CDK application:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><a href="https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-local-invoke.html">sam local invoke</a></p> -</li> -<li> -<p><a href="https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-local-start-api.html">sam local start-api</a></p> -</li> -<li> -<p><a href="https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-local-start-lambda.html">sam local start-lambda</a></p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>Before you run any of the <strong class="command">sam local</strong> commands with a AWS CDK application, you must run <code>cdk synth</code>.</p> -</div> -<div class="paragraph"> -<p>When running <strong class="command">sam local invoke</strong> you need the function construct identifier that you want to invoke, and the path to your synthesized AWS CloudFormation template. If your application uses nested stacks, to resolve naming conflicts, you also need the stack name where the function is defined.</p> -</div> -<div class="paragraph"> -<p><strong>Usage:</strong></p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code># Invoke the function FUNCTION_IDENTIFIER declared in the stack STACK_NAME -$ sam local invoke [OPTIONS] [STACK_NAME/FUNCTION_IDENTIFIER] - -# Start all APIs declared in the AWS CDK application -$ sam local start-api -t ./cdk.out/CdkSamExampleStack.template.json [OPTIONS] - -# Start a local endpoint that emulates AWS Lambda -$ sam local start-lambda -t ./cdk.out/CdkSamExampleStack.template.json [OPTIONS]</code></pre> -</div> -</div> -<div class="sect4"> -<h5 id="testing-cdk-applications-examples">Example</h5> -<div class="paragraph"> -<p>Consider stacks and functions that are declared with the following sample:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>app = new HelloCdkStack(app, "HelloCdkStack", - ... -) -class HelloCdkStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - ... - new lambda.Function(this, 'MyFunction', { - ... - }); - - new HelloCdkNestedStack(this, 'HelloNestedStack' ,{ - ... - }); -} - -class HelloCdkNestedStack extends cdk.NestedStack { - constructor(scope: Construct, id: string, props?: cdk.NestedStackProps) { - ... - new lambda.Function(this, 'MyFunction', { - ... - }); - new lambda.Function(this, 'MyNestedFunction', { - ... - }); -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The following commands locally invokes the Lambda functions defined in example presented above:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code># Invoke MyFunction from the HelloCdkStack -$ sam local invoke -t ./cdk.out/HelloCdkStack.template.json MyFunction</code></pre> -</div> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code># Invoke MyNestedFunction from the HelloCdkNestedStack -$ sam local invoke -t ./cdk.out/HelloCdkStack.template.json MyNestedFunction</code></pre> -</div> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code># Invoke MyFunction from the HelloCdkNestedStack -$ sam local invoke -t ./cdk.out/HelloCdkStack.template.json HelloNestedStack/MyFunction</code></pre> -</div> -</div> -</div> -</div> -<div class="sect3 topic"> -<h4 id="testing-locally-build-with-sam-cli">16.1.3. Building AWS CDK applications with AWS SAM</h4> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Use the <strong class="command">sam build</strong> command to build AWS CDK applications.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>The AWS SAM <code class="noloc">CLI</code> provides support for building Lambda functions and layers defined in your AWS CDK application with <a href="https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-build.html">sam build</a>.</p> -</div> -<div class="paragraph"> -<p>For Lambda functions that use zip artifacts, run <code>cdk synth</code> before you run <code>sam local</code> commands. <code>sam build</code> isn’t required.</p> -</div> -<div class="paragraph"> -<p>If your AWS CDK application uses functions with the image type, run <code>cdk synth</code> and then run <code>sam build</code> before you run <code>sam local</code> commands. When you run <code>sam build</code>, AWS SAM doesn’t build Lambda functions or layers that use runtime-specific constructs, for example, <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda_nodejs.NodejsFunction.html">NodejsFunction</a>. <code>sam build</code> doesn’t support <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.BundlingOptions.html">bundled assets</a>.</p> -</div> -<div class="sect4"> -<h5 id="testing-locally-build-with-sam-cli-examples">Example</h5> -<div class="paragraph"> -<p>Running the following command from the AWS CDK project root directory builds the application.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ sam build -t ./cdk.out/CdkSamExampleStack.template.json</code></pre> -</div> -</div> -</div> -</div> -</div> -<div class="sect2"> -<h3 id="testing-getting-started">16.2. Getting started</h3> -<div class="paragraph"> -<p>To illustrate how to write these tests, we’ll create a stack that contains an AWS Step Functions state machine and an AWS Lambda function. The Lambda function is subscribed to an Amazon SNS topic and simply forwards the message to the state machine.</p> -</div> -<div class="paragraph"> -<p>First, create an empty CDK application project using the CDK Toolkit and installing the libraries we’ll need. The constructs we’ll use are all in the main CDK package, which is a default dependency in projects created with the CDK Toolkit. However, you must install your testing framework.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ mkdir state-machine && cd state-machine -cdk init --language=typescript -npm install --save-dev jest @types/jest</code></pre> -</div> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p>Create a directory for your tests.</p> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ mkdir test</code></pre> -</div> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p>Edit the project’s <code class="path">package.json</code> to tell NPM how to run Jest, and to tell Jest what kinds of files to collect. The necessary changes are as follows.</p> -</div> -<div class="paragraph"> -<p>+ -<strong> Add a new <code>test</code> key to the <code>scripts</code> section -</strong> Add Jest and its types to the <code>devDependencies</code> section -** Add a new <code>jest</code> top-level key with a <code>moduleFileExtensions</code> declaration</p> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p>These changes are shown in the following outline. Place the new text where indicated in <code class="path">package.json</code>. The "…​" placeholders indicate existing parts of the file that should not be changed.</p> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-json" data-lang="json">{ - ... - "scripts": { - ... - "test": "jest" - }, - "devDependencies": { - ... - "@types/jest": "^24.0.18", - "jest": "^24.9.0" - }, - "jest": { - "moduleFileExtensions": ["js"] - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ mkdir state-machine && cd state-machine -$ cdk init --language=javascript -$ npm install --save-dev jest</code></pre> -</div> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p>Create a directory for your tests.</p> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ mkdir test</code></pre> -</div> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p>Edit the project’s <code class="path">package.json</code> to tell NPM how to run Jest, and to tell Jest what kinds of files to collect. The necessary changes are as follows.</p> -</div> -<div class="paragraph"> -<p>+ -<strong> Add a new <code>test</code> key to the <code>scripts</code> section -</strong> Add Jest to the <code>devDependencies</code> section -** Add a new <code>jest</code> top-level key with a <code>moduleFileExtensions</code> declaration</p> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p>These changes are shown in the following outline. Place the new text where indicated in <code class="path">package.json</code>. The "…​" placeholders indicate existing parts of the file that shouldn’t be changed.</p> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-json" data-lang="json">{ - ... - "scripts": { - ... - "test": "jest" - }, - "devDependencies": { - ... - "jest": "^24.9.0" - }, - "jest": { - "moduleFileExtensions": ["js"] - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ mkdir state-machine && cd state-machine -$ cdk init --language=python -$ source .venv/bin/activate # On Windows, run '.\venv\Scripts\activate' instead -$ python -m pip install -r requirements.txt -$ python -m pip install -r requirements-dev.txt</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ mkdir state-machine && cd-state-machine -$ cdk init --language=java</code></pre> -</div> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p>Open the project in your preferred Java IDE. (In Eclipse, use <strong>File</strong> > <strong>Import</strong> > Existing Maven Projects.)</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ mkdir state-machine && cd-state-machine -$ cdk init --language=csharp</code></pre> -</div> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p>Open <code class="path">src\StateMachine.sln</code> in Visual Studio.</p> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p>Right-click the solution in Solution Explorer and choose <strong>Add</strong> > <strong>New Project</strong>. Search for MSTest C# and add an <strong>MSTest Test Project</strong> for C#. (The default name <code class="path">TestProject1</code>is fine.)</p> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p>Right-click <code class="path">TestProject1</code> and choose <strong>Add</strong> > <strong>Project Reference</strong>, and add the <code class="path">StateMachine</code> project as a reference.</p> -</div> -</div> -<div class="sect2"> -<h3 id="testing-app">16.3. The example stack</h3> -<div class="paragraph"> -<p>Here’s the stack that will be tested in this topic. As we’ve previously described, it contains a Lambda function and a Step Functions state machine, and accepts one or more Amazon SNS topics. The Lambda function is subscribed to the Amazon SNS topics and forwards them to the state machine.</p> -</div> -<div class="paragraph"> -<p>You don’t have to do anything special to make the app testable. In fact, this CDK stack is not different in any important way from the other example stacks in this Guide.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Place the following code in <code class="path">lib/state-machine-stack.ts</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as cdk from "aws-cdk-lib"; -import * as sns from "aws-cdk-lib/aws-sns"; -import * as sns_subscriptions from "aws-cdk-lib/aws-sns-subscriptions"; -import * as lambda from "aws-cdk-lib/aws-lambda"; -import * as sfn from "aws-cdk-lib/aws-stepfunctions"; -import { Construct } from "constructs"; - -export interface StateMachineStackProps extends cdk.StackProps { - readonly topics: sns.Topic[]; -} - -export class StateMachineStack extends cdk.Stack { - constructor(scope: Construct, id: string, props: StateMachineStackProps) { - super(scope, id, props); - - // In the future this state machine will do some work... - const stateMachine = new sfn.StateMachine(this, "StateMachine", { - definition: new sfn.Pass(this, "StartState"), - }); - - // This Lambda function starts the state machine. - const func = new lambda.Function(this, "LambdaFunction", { - runtime: lambda.Runtime.NODEJS_18_X, - handler: "handler", - code: lambda.Code.fromAsset("./start-state-machine"), - environment: { - STATE_MACHINE_ARN: stateMachine.stateMachineArn, - }, - }); - stateMachine.grantStartExecution(func); - - const subscription = new sns_subscriptions.LambdaSubscription(func); - for (const topic of props.topics) { - topic.addSubscription(subscription); - } - } -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">JavaScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Place the following code in <code class="path">lib/state-machine-stack.js</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const cdk = require("aws-cdk-lib"); -const sns = require("aws-cdk-lib/aws-sns"); -const sns_subscriptions = require("aws-cdk-lib/aws-sns-subscriptions"); -const lambda = require("aws-cdk-lib/aws-lambda"); -const sfn = require("aws-cdk-lib/aws-stepfunctions"); - -class StateMachineStack extends cdk.Stack { - constructor(scope, id, props) { - super(scope, id, props); - - // In the future this state machine will do some work... - const stateMachine = new sfn.StateMachine(this, "StateMachine", { - definition: new sfn.Pass(this, "StartState"), - }); - - // This Lambda function starts the state machine. - const func = new lambda.Function(this, "LambdaFunction", { - runtime: lambda.Runtime.NODEJS_18_X, - handler: "handler", - code: lambda.Code.fromAsset("./start-state-machine"), - environment: { - STATE_MACHINE_ARN: stateMachine.stateMachineArn, - }, - }); - stateMachine.grantStartExecution(func); - - const subscription = new sns_subscriptions.LambdaSubscription(func); - for (const topic of props.topics) { - topic.addSubscription(subscription); - } - } -} - -module.exports = { StateMachineStack }</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Python</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Place the following code in <code class="path">state_machine/state_machine_stack.py</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">from typing import List - -import aws_cdk.aws_lambda as lambda_ -import aws_cdk.aws_sns as sns -import aws_cdk.aws_sns_subscriptions as sns_subscriptions -import aws_cdk.aws_stepfunctions as sfn -import aws_cdk as cdk - -class StateMachineStack(cdk.Stack): - def __init__( - self, - scope: cdk.Construct, - construct_id: str, - *, - topics: List[sns.Topic], - **kwargs - ) -> None: - super().__init__(scope, construct_id, **kwargs) - - # In the future this state machine will do some work... - state_machine = sfn.StateMachine( - self, "StateMachine", definition=sfn.Pass(self, "StartState") - ) - - # This Lambda function starts the state machine. - func = lambda_.Function( - self, - "LambdaFunction", - runtime=lambda_.Runtime.NODEJS_18_X, - handler="handler", - code=lambda_.Code.from_asset("./start-state-machine"), - environment={ - "STATE_MACHINE_ARN": state_machine.state_machine_arn, - }, - ) - state_machine.grant_start_execution(func) - - subscription = sns_subscriptions.LambdaSubscription(func) - for topic in topics: - topic.add_subscription(subscription)</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">package software.amazon.samples.awscdkassertionssamples; - -import software.constructs.Construct; -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.StackProps; -import software.amazon.awscdk.services.lambda.Code; -import software.amazon.awscdk.services.lambda.Function; -import software.amazon.awscdk.services.lambda.Runtime; -import software.amazon.awscdk.services.sns.ITopicSubscription; -import software.amazon.awscdk.services.sns.Topic; -import software.amazon.awscdk.services.sns.subscriptions.LambdaSubscription; -import software.amazon.awscdk.services.stepfunctions.Pass; -import software.amazon.awscdk.services.stepfunctions.StateMachine; - -import java.util.Collections; -import java.util.List; - -public class StateMachineStack extends Stack { - public StateMachineStack(final Construct scope, final String id, final List<Topic> topics) { - this(scope, id, null, topics); - } - - public StateMachineStack(final Construct scope, final String id, final StackProps props, final List<Topic> topics) { - super(scope, id, props); - - // In the future this state machine will do some work... - final StateMachine stateMachine = StateMachine.Builder.create(this, "StateMachine") - .definition(new Pass(this, "StartState")) - .build(); - - // This Lambda function starts the state machine. - final Function func = Function.Builder.create(this, "LambdaFunction") - .runtime(Runtime.NODEJS_18_X) - .handler("handler") - .code(Code.fromAsset("./start-state-machine")) - .environment(Collections.singletonMap("STATE_MACHINE_ARN", stateMachine.getStateMachineArn())) - .build(); - stateMachine.grantStartExecution(func); - - final ITopicSubscription subscription = new LambdaSubscription(func); - for (final Topic topic : topics) { - topic.addSubscription(subscription); - } - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; -using Amazon.CDK.AWS.Lambda; -using Amazon.CDK.AWS.StepFunctions; -using Amazon.CDK.AWS.SNS; -using Amazon.CDK.AWS.SNS.Subscriptions; -using Constructs; - -using System.Collections.Generic; - -namespace AwsCdkAssertionSamples -{ - public class StateMachineStackProps : StackProps - { - public Topic[] Topics; - } - - public class StateMachineStack : Stack - { - - internal StateMachineStack(Construct scope, string id, StateMachineStackProps props = null) : base(scope, id, props) - { - // In the future this state machine will do some work... - var stateMachine = new StateMachine(this, "StateMachine", new StateMachineProps - { - Definition = new Pass(this, "StartState") - }); - - // This Lambda function starts the state machine. - var func = new Function(this, "LambdaFunction", new FunctionProps - { - Runtime = Runtime.NODEJS_18_X, - Handler = "handler", - Code = Code.FromAsset("./start-state-machine"), - Environment = new Dictionary<string, string> - { - { "STATE_MACHINE_ARN", stateMachine.StateMachineArn } - } - }); - stateMachine.GrantStartExecution(func); - - foreach (Topic topic in props?.Topics ?? new Topic[0]) - { - var subscription = new LambdaSubscription(func); - } - - } - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>We’ll modify the app’s main entry point so that we don’t actually instantiate our stack. We don’t want to accidentally deploy it. Our tests will create an app and an instance of the stack for testing. This is a useful tactic when combined with test-driven development: make sure that the stack passes all tests before you enable deployment.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>In <code class="path">bin/state-machine.ts</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">#!/usr/bin/env node -import * as cdk from "aws-cdk-lib"; - -const app = new cdk.App(); - -// Stacks are intentionally not created here -- this application isn't meant to -// be deployed.</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">JavaScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>In <code class="path">bin/state-machine.js</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">#!/usr/bin/env node -const cdk = require("aws-cdk-lib"); - -const app = new cdk.App(); - -// Stacks are intentionally not created here -- this application isn't meant to -// be deployed.</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Python</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>In <code class="path">app.py</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">#!/usr/bin/env python3 -import os - -import aws_cdk as cdk - -app = cdk.App() - -# Stacks are intentionally not created here -- this application isn't meant to -# be deployed. - -app.synth()</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">package software.amazon.samples.awscdkassertionssamples; - -import software.amazon.awscdk.App; - -public class SampleApp { - public static void main(final String[] args) { - App app = new App(); - - // Stacks are intentionally not created here -- this application isn't meant to be deployed. - - app.synth(); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; - -namespace AwsCdkAssertionSamples -{ - sealed class Program - { - public static void Main(string[] args) - { - var app = new App(); - - // Stacks are intentionally not created here -- this application isn't meant to be deployed. - - app.Synth(); - } - } -}</code></pre> -</div> -</div> -</div> -<div class="sect2"> -<h3 id="testing-lambda">16.4. The Lambda function</h3> -<div class="paragraph"> -<p>Our example stack includes a Lambda function that starts our state machine. We must provide the source code for this function so the CDK can bundle and deploy it as part of creating the Lambda function resource.</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Create the folder <code class="path">start-state-machine</code> in the app’s main directory.</p> -</li> -<li> -<p>In this folder, create at least one file. For example, you can save the following code in <code class="path">start-state-machines/index.js</code>.</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">exports.handler = async function (event, context) { - return 'hello world'; -};</code></pre> -</div> -</div> -<div class="paragraph"> -<p>However, any file will work, since we won’t actually be deploying the stack.</p> -</div> -</li> -</ul> -</div> -</div> -<div class="sect2"> -<h3 id="testing-running-tests">16.5. Running tests</h3> -<div class="paragraph"> -<p>For reference, here are the commands you use to run tests in your AWS CDK app. These are the same commands that you’d use to run the tests in any project using the same testing framework. For languages that require a build step, include that to make sure that your tests have compiled.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">$ tsc && npm test</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">$ npm test</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ python -m pytest</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ mvn compile && mvn test</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Build your solution (F6) to discover the tests, then run the tests (<strong>Test</strong> > <strong>Run All Tests</strong>). To choose which tests to run, open Test Explorer (<strong>Test</strong> > <strong>Test Explorer</strong>).</p> -<div class="paragraph"> -<p>Or:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ dotnet test src</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect2"> -<h3 id="testing-fine-grained">16.6. Fine-grained assertions</h3> -<div class="paragraph"> -<p>The first step for testing a stack with fine-grained assertions is to synthesize the stack, because we’re writing assertions against the generated AWS CloudFormation template.</p> -</div> -<div class="paragraph"> -<p>Our <code>StateMachineStackStack</code> requires that we pass it the Amazon SNS topic to be forwarded to the state machine. So in our test, we’ll create a separate stack to contain the topic.</p> -</div> -<div class="paragraph"> -<p>Ordinarily, when writing a CDK app, you can subclass <code>Stack</code> and instantiate the Amazon SNS topic in the stack’s constructor. In our test, we instantiate <code>Stack</code> directly, then pass this stack as the <code>Topic</code>'s scope, attaching it to the stack. This is functionally equivalent and less verbose. It also helps make stacks that are used only in tests "look different" from the stacks that you intend to deploy.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import { Capture, Match, Template } from "aws-cdk-lib/assertions"; -import * as cdk from "aws-cdk-lib"; -import * as sns from "aws-cdk-lib/aws-sns"; -import { StateMachineStack } from "../lib/state-machine-stack"; - -describe("StateMachineStack", () => { - test("synthesizes the way we expect", () => { - const app = new cdk.App(); - - // Since the StateMachineStack consumes resources from a separate stack - // (cross-stack references), we create a stack for our SNS topics to live - // in here. These topics can then be passed to the StateMachineStack later, - // creating a cross-stack reference. - const topicsStack = new cdk.Stack(app, "TopicsStack"); - - // Create the topic the stack we're testing will reference. - const topics = [new sns.Topic(topicsStack, "Topic1", {})]; - - // Create the StateMachineStack. - const stateMachineStack = new StateMachineStack(app, "StateMachineStack", { - topics: topics, // Cross-stack reference - }); - - // Prepare the stack for assertions. - const template = Template.fromStack(stateMachineStack); - - -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const { Capture, Match, Template } = require("aws-cdk-lib/assertions"); -const cdk = require("aws-cdk-lib"); -const sns = require("aws-cdk-lib/aws-sns"); -const { StateMachineStack } = require("../lib/state-machine-stack"); - -describe("StateMachineStack", () => { - test("synthesizes the way we expect", () => { - const app = new cdk.App(); - - // Since the StateMachineStack consumes resources from a separate stack - // (cross-stack references), we create a stack for our SNS topics to live - // in here. These topics can then be passed to the StateMachineStack later, - // creating a cross-stack reference. - const topicsStack = new cdk.Stack(app, "TopicsStack"); - - // Create the topic the stack we're testing will reference. - const topics = [new sns.Topic(topicsStack, "Topic1", {})]; - - // Create the StateMachineStack. - const StateMachineStack = new StateMachineStack(app, "StateMachineStack", { - topics: topics, // Cross-stack reference - }); - - // Prepare the stack for assertions. - const template = Template.fromStack(stateMachineStack);</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">from aws_cdk import aws_sns as sns -import aws_cdk as cdk -from aws_cdk.assertions import Template - -from app.state_machine_stack import StateMachineStack - -def test_synthesizes_properly(): - app = cdk.App() - - # Since the StateMachineStack consumes resources from a separate stack - # (cross-stack references), we create a stack for our SNS topics to live - # in here. These topics can then be passed to the StateMachineStack later, - # creating a cross-stack reference. - topics_stack = cdk.Stack(app, "TopicsStack") - - # Create the topic the stack we're testing will reference. - topics = [sns.Topic(topics_stack, "Topic1")] - - # Create the StateMachineStack. - state_machine_stack = StateMachineStack( - app, "StateMachineStack", topics=topics # Cross-stack reference - ) - - # Prepare the stack for assertions. - template = Template.from_stack(state_machine_stack)</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">package software.amazon.samples.awscdkassertionssamples; - -import org.junit.jupiter.api.Test; -import software.amazon.awscdk.assertions.Capture; -import software.amazon.awscdk.assertions.Match; -import software.amazon.awscdk.assertions.Template; -import software.amazon.awscdk.App; -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.services.sns.Topic; - -import java.util.*; - -import static org.assertj.core.api.Assertions.assertThat; - -public class StateMachineStackTest { - @Test - public void testSynthesizesProperly() { - final App app = new App(); - - // Since the StateMachineStack consumes resources from a separate stack (cross-stack references), we create a stack - // for our SNS topics to live in here. These topics can then be passed to the StateMachineStack later, creating a - // cross-stack reference. - final Stack topicsStack = new Stack(app, "TopicsStack"); - - // Create the topic the stack we're testing will reference. - final List<Topic> topics = Collections.singletonList(Topic.Builder.create(topicsStack, "Topic1").build()); - - // Create the StateMachineStack. - final StateMachineStack stateMachineStack = new StateMachineStack( - app, - "StateMachineStack", - topics // Cross-stack reference - ); - - // Prepare the stack for assertions. - final Template template = Template.fromStack(stateMachineStack)</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Microsoft.VisualStudio.TestTools.UnitTesting; - -using Amazon.CDK; -using Amazon.CDK.AWS.SNS; -using Amazon.CDK.Assertions; -using AwsCdkAssertionSamples; - -using ObjectDict = System.Collections.Generic.Dictionary<string, object>; -using StringDict = System.Collections.Generic.Dictionary<string, string>; - -namespace TestProject1 -{ - [TestClass] - public class StateMachineStackTest - { - [TestMethod] - public void TestMethod1() - { - var app = new App(); - - // Since the StateMachineStack consumes resources from a separate stack (cross-stack references), we create a stack - // for our SNS topics to live in here. These topics can then be passed to the StateMachineStack later, creating a - // cross-stack reference. - var topicsStack = new Stack(app, "TopicsStack"); - - // Create the topic the stack we're testing will reference. - var topics = new Topic[] { new Topic(topicsStack, "Topic1") }; - - // Create the StateMachineStack. - var StateMachineStack = new StateMachineStack(app, "StateMachineStack", new StateMachineStackProps - { - Topics = topics - }); - - // Prepare the stack for assertions. - var template = Template.FromStack(stateMachineStack); - - // test will go here - } - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Now we can assert that the Lambda function and the Amazon SNS subscription were created.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript"> // Assert it creates the function with the correct properties... - template.hasResourceProperties("AWS::Lambda::Function", { - Handler: "handler", - Runtime: "nodejs14.x", - }); - - // Creates the subscription... - template.resourceCountIs("AWS::SNS::Subscription", 1);</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript"> // Assert it creates the function with the correct properties... - template.hasResourceProperties("AWS::Lambda::Function", { - Handler: "handler", - Runtime: "nodejs14.x", - }); - - // Creates the subscription... - template.resourceCountIs("AWS::SNS::Subscription", 1);</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python"># Assert that we have created the function with the correct properties - template.has_resource_properties( - "AWS::Lambda::Function", - { - "Handler": "handler", - "Runtime": "nodejs14.x", - }, - ) - - # Assert that we have created a subscription - template.resource_count_is("AWS::SNS::Subscription", 1)</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java"> // Assert it creates the function with the correct properties... - template.hasResourceProperties("AWS::Lambda::Function", Map.of( - "Handler", "handler", - "Runtime", "nodejs14.x" - )); - - // Creates the subscription... - template.resourceCountIs("AWS::SNS::Subscription", 1);</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp"> // Prepare the stack for assertions. - var template = Template.FromStack(stateMachineStack); - - // Assert it creates the function with the correct properties... - template.HasResourceProperties("AWS::Lambda::Function", new StringDict { - { "Handler", "handler"}, - { "Runtime", "nodejs14x" } - }); - - // Creates the subscription... - template.ResourceCountIs("AWS::SNS::Subscription", 1);</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Our Lambda function test asserts that two particular properties of the function resource have specific values. By default, the <code>hasResourceProperties</code> method performs a partial match on the resource’s properties as given in the synthesized CloudFormation template. This test requires that the provided properties exist and have the specified values, but the resource can also have other properties, which are not tested.</p> -</div> -<div class="paragraph"> -<p>Our Amazon SNS assertion asserts that the synthesized template contains a subscription, but nothing about the subscription itself. We included this assertion mainly to illustrate how to assert on resource counts. The <code>Template</code> class offers more specific methods to write assertions against the <code>Resources</code>, <code>Outputs</code>, and <code>Mapping</code> sections of the CloudFormation template.</p> -</div> -<div class="sect3"> -<h4 id="testing-fine-grained-matchers">16.6.1. Matchers</h4> -<div class="paragraph"> -<p>The default partial matching behavior of <code>hasResourceProperties</code> can be changed using <em>matchers</em> from the <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.assertions.Match.html#methods">Match</a> class.</p> -</div> -<div class="paragraph"> -<p>Matchers range from lenient (<code>Match.anyValue</code>) to strict (<code>Match.objectEquals</code>). They can be nested to apply different matching methods to different parts of the resource properties. Using <code>Match.objectEquals</code> and <code>Match.anyValue</code> together, for example, we can test the state machine’s IAM role more fully, while not requiring specific values for properties that may change.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript"> // Fully assert on the state machine's IAM role with matchers. - template.hasResourceProperties( - "AWS::IAM::Role", - Match.objectEquals({ - AssumeRolePolicyDocument: { - Version: "2012-10-17", - Statement: [ - { - Action: "sts:AssumeRole", - Effect: "Allow", - Principal: { - Service: { - "Fn::Join": [ - "", - ["states.", Match.anyValue(), ".amazonaws.com"], - ], - }, - }, - }, - ], - }, - }) - );</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript"> // Fully assert on the state machine's IAM role with matchers. - template.hasResourceProperties( - "AWS::IAM::Role", - Match.objectEquals({ - AssumeRolePolicyDocument: { - Version: "2012-10-17", - Statement: [ - { - Action: "sts:AssumeRole", - Effect: "Allow", - Principal: { - Service: { - "Fn::Join": [ - "", - ["states.", Match.anyValue(), ".amazonaws.com"], - ], - }, - }, - }, - ], - }, - }) - );</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">from aws_cdk.assertions import Match - - # Fully assert on the state machine's IAM role with matchers. - template.has_resource_properties( - "AWS::IAM::Role", - Match.object_equals( - { - "AssumeRolePolicyDocument": { - "Version": "2012-10-17", - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": { - "Fn::Join": [ - "", - [ - "states.", - Match.any_value(), - ".amazonaws.com", - ], - ], - }, - }, - }, - ], - }, - } - ), - )</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java"> // Fully assert on the state machine's IAM role with matchers. - template.hasResourceProperties("AWS::IAM::Role", Match.objectEquals( - Collections.singletonMap("AssumeRolePolicyDocument", Map.of( - "Version", "2012-10-17", - "Statement", Collections.singletonList(Map.of( - "Action", "sts:AssumeRole", - "Effect", "Allow", - "Principal", Collections.singletonMap( - "Service", Collections.singletonMap( - "Fn::Join", Arrays.asList( - "", - Arrays.asList("states.", Match.anyValue(), ".amazonaws.com") - ) - ) - ) - )) - )) - ));</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp"> // Fully assert on the state machine's IAM role with matchers. - template.HasResource("AWS::IAM::Role", Match.ObjectEquals(new ObjectDict - { - { "AssumeRolePolicyDocument", new ObjectDict - { - { "Version", "2012-10-17" }, - { "Action", "sts:AssumeRole" }, - { "Principal", new ObjectDict - { - { "Version", "2012-10-17" }, - { "Statement", new object[] - { - new ObjectDict { - { "Action", "sts:AssumeRole" }, - { "Effect", "Allow" }, - { "Principal", new ObjectDict - { - { "Service", new ObjectDict - { - { "", new object[] - { "states", Match.AnyValue(), ".amazonaws.com" } - } - } - } - } - } - } - } - } - } - } - } - } - }));</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Many CloudFormation resources include serialized JSON objects represented as strings. The <code>Match.serializedJson()</code> matcher can be used to match properties inside this JSON.</p> -</div> -<div class="paragraph"> -<p>For example, Step Functions state machines are defined using a string in the JSON-based <a href="https://docs.aws.amazon.com/step-functions/latest/dg/concepts-amazon-states-language.html">Amazon States Language</a>. We’ll use <code>Match.serializedJson()</code> to make sure that our initial state is the only step. Again, we’ll use nested matchers to apply different kinds of matching to different parts of the object.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript"> // Assert on the state machine's definition with the Match.serializedJson() - // matcher. - template.hasResourceProperties("AWS::StepFunctions::StateMachine", { - DefinitionString: Match.serializedJson( - // Match.objectEquals() is used implicitly, but we use it explicitly - // here for extra clarity. - Match.objectEquals({ - StartAt: "StartState", - States: { - StartState: { - Type: "Pass", - End: true, - // Make sure this state doesn't provide a next state -- we can't - // provide both Next and set End to true. - Next: Match.absent(), - }, - }, - }) - ), - });</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript"> // Assert on the state machine's definition with the Match.serializedJson() - // matcher. - template.hasResourceProperties("AWS::StepFunctions::StateMachine", { - DefinitionString: Match.serializedJson( - // Match.objectEquals() is used implicitly, but we use it explicitly - // here for extra clarity. - Match.objectEquals({ - StartAt: "StartState", - States: { - StartState: { - Type: "Pass", - End: true, - // Make sure this state doesn't provide a next state -- we can't - // provide both Next and set End to true. - Next: Match.absent(), - }, - }, - }) - ), - });</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python"> # Assert on the state machine's definition with the serialized_json matcher. - template.has_resource_properties( - "AWS::StepFunctions::StateMachine", - { - "DefinitionString": Match.serialized_json( - # Match.object_equals() is the default, but specify it here for clarity - Match.object_equals( - { - "StartAt": "StartState", - "States": { - "StartState": { - "Type": "Pass", - "End": True, - # Make sure this state doesn't provide a next state -- - # we can't provide both Next and set End to true. - "Next": Match.absent(), - }, - }, - } - ) - ), - }, - )</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java"> // Assert on the state machine's definition with the Match.serializedJson() matcher. - template.hasResourceProperties("AWS::StepFunctions::StateMachine", Collections.singletonMap( - "DefinitionString", Match.serializedJson( - // Match.objectEquals() is used implicitly, but we use it explicitly here for extra clarity. - Match.objectEquals(Map.of( - "StartAt", "StartState", - "States", Collections.singletonMap( - "StartState", Map.of( - "Type", "Pass", - "End", true, - // Make sure this state doesn't provide a next state -- we can't provide - // both Next and set End to true. - "Next", Match.absent() - ) - ) - )) - ) - ));</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp"> // Assert on the state machine's definition with the Match.serializedJson() matcher - template.HasResourceProperties("AWS::StepFunctions::StateMachine", new ObjectDict - { - { "DefinitionString", Match.SerializedJson( - // Match.objectEquals() is used implicitly, but we use it explicitly here for extra clarity. - Match.ObjectEquals(new ObjectDict { - { "StartAt", "StartState" }, - { "States", new ObjectDict - { - { "StartState", new ObjectDict { - { "Type", "Pass" }, - { "End", "True" }, - // Make sure this state doesn't provide a next state -- we can't provide - // both Next and set End to true. - { "Next", Match.Absent() } - }} - }} - }) - )}});</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="testing-fine-grained-capture">16.6.2. Capturing</h4> -<div class="paragraph"> -<p>It’s often useful to test properties to make sure they follow specific formats, or have the same value as another property, without needing to know their exact values ahead of time. The <code>assertions</code> module provides this capability in its <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.assertions.Capture.html">Capture</a> class.</p> -</div> -<div class="paragraph"> -<p>By specifying a <code>Capture</code> instance in place of a value in <code>hasResourceProperties</code>, that value is retained in the <code>Capture</code> object. The actual captured value can be retrieved using the object’s <code>as</code> methods, including <code>asNumber()</code>, <code>asString()</code>, and <code>asObject</code>, and subjected to test. Use <code>Capture</code> with a matcher to specify the exact location of the value to be captured within the resource’s properties, including serialized JSON properties.</p> -</div> -<div class="paragraph"> -<p>The following example tests to make sure that the starting state of our state machine has a name beginning with <code>Start</code>. It also tests that this state is present within the list of states in the machine.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript"> // Capture some data from the state machine's definition. - const startAtCapture = new Capture(); - const statesCapture = new Capture(); - template.hasResourceProperties("AWS::StepFunctions::StateMachine", { - DefinitionString: Match.serializedJson( - Match.objectLike({ - StartAt: startAtCapture, - States: statesCapture, - }) - ), - }); - - // Assert that the start state starts with "Start". - expect(startAtCapture.asString()).toEqual(expect.stringMatching(/^Start/)); - - // Assert that the start state actually exists in the states object of the - // state machine definition. - expect(statesCapture.asObject()).toHaveProperty(startAtCapture.asString());</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript"> // Capture some data from the state machine's definition. - const startAtCapture = new Capture(); - const statesCapture = new Capture(); - template.hasResourceProperties("AWS::StepFunctions::StateMachine", { - DefinitionString: Match.serializedJson( - Match.objectLike({ - StartAt: startAtCapture, - States: statesCapture, - }) - ), - }); - - // Assert that the start state starts with "Start". - expect(startAtCapture.asString()).toEqual(expect.stringMatching(/^Start/)); - - // Assert that the start state actually exists in the states object of the - // state machine definition. - expect(statesCapture.asObject()).toHaveProperty(startAtCapture.asString());</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">import re - - from aws_cdk.assertions import Capture - - # ... - - # Capture some data from the state machine's definition. - start_at_capture = Capture() - states_capture = Capture() - template.has_resource_properties( - "AWS::StepFunctions::StateMachine", - { - "DefinitionString": Match.serialized_json( - Match.object_like( - { - "StartAt": start_at_capture, - "States": states_capture, - } - ) - ), - }, - ) - - # Assert that the start state starts with "Start". - assert re.match("^Start", start_at_capture.as_string()) - - # Assert that the start state actually exists in the states object of the - # state machine definition. - assert start_at_capture.as_string() in states_capture.as_object()</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java"> // Capture some data from the state machine's definition. - final Capture startAtCapture = new Capture(); - final Capture statesCapture = new Capture(); - template.hasResourceProperties("AWS::StepFunctions::StateMachine", Collections.singletonMap( - "DefinitionString", Match.serializedJson( - Match.objectLike(Map.of( - "StartAt", startAtCapture, - "States", statesCapture - )) - ) - )); - - // Assert that the start state starts with "Start". - assertThat(startAtCapture.asString()).matches("^Start.+"); - - // Assert that the start state actually exists in the states object of the state machine definition. - assertThat(statesCapture.asObject()).containsKey(startAtCapture.asString());</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp"> // Capture some data from the state machine's definition. - var startAtCapture = new Capture(); - var statesCapture = new Capture(); - template.HasResourceProperties("AWS::StepFunctions::StateMachine", new ObjectDict - { - { "DefinitionString", Match.SerializedJson( - new ObjectDict - { - { "StartAt", startAtCapture }, - { "States", statesCapture } - } - )} - }); - - Assert.IsTrue(startAtCapture.ToString().StartsWith("Start")); - Assert.IsTrue(statesCapture.AsObject().ContainsKey(startAtCapture.ToString()));</code></pre> -</div> -</div> -</div> -</div> -<div class="sect2"> -<h3 id="testing-snapshot">16.7. Snapshot tests</h3> -<div class="paragraph"> -<p>In <em>snapshot testing</em>, you compare the entire synthesized CloudFormation template against a previously stored baseline (often called a "master") template. Unlike fine-grained assertions, snapshot testing isn’t useful in catching regressions. This is because snapshot testing applies to the entire template, and things besides code changes can cause small (or not-so-small) differences in synthesis results. These changes may not even affect your deployment, but they will still cause a snapshot test to fail.</p> -</div> -<div class="paragraph"> -<p>For example, you might update a CDK construct to incorporate a new best practice, which can cause changes to the synthesized resources or how they’re organized. Alternatively, you might update the CDK Toolkit to a version that reports additional metadata. Changes to context values can also affect the synthesized template.</p> -</div> -<div class="paragraph"> -<p>Snapshot tests can be of great help in refactoring, though, as long as you hold constant all other factors that might affect the synthesized template. You will know immediately if a change you made has unintentionally changed the template. If the change is intentional, simply accept the new template as the baseline.</p> -</div> -<div class="paragraph"> -<p>For example, if we have this <code>DeadLetterQueue</code> construct:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">export class DeadLetterQueue extends sqs.Queue { - public readonly messagesInQueueAlarm: cloudwatch.IAlarm; - - constructor(scope: Construct, id: string) { - super(scope, id); - - // Add the alarm - this.messagesInQueueAlarm = new cloudwatch.Alarm(this, 'Alarm', { - alarmDescription: 'There are messages in the Dead Letter Queue', - evaluationPeriods: 1, - threshold: 1, - metric: this.metricApproximateNumberOfMessagesVisible(), - }); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">class DeadLetterQueue extends sqs.Queue { - - constructor(scope, id) { - super(scope, id); - - // Add the alarm - this.messagesInQueueAlarm = new cloudwatch.Alarm(this, 'Alarm', { - alarmDescription: 'There are messages in the Dead Letter Queue', - evaluationPeriods: 1, - threshold: 1, - metric: this.metricApproximateNumberOfMessagesVisible(), - }); - } -} - -module.exports = { DeadLetterQueue }</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">class DeadLetterQueue(sqs.Queue): - def __init__(self, scope: Construct, id: str): - super().__init__(scope, id) - - self.messages_in_queue_alarm = cloudwatch.Alarm( - self, - "Alarm", - alarm_description="There are messages in the Dead Letter Queue.", - evaluation_periods=1, - threshold=1, - metric=self.metric_approximate_number_of_messages_visible(), - )</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">public class DeadLetterQueue extends Queue { - private final IAlarm messagesInQueueAlarm; - - public DeadLetterQueue(@NotNull Construct scope, @NotNull String id) { - super(scope, id); - - this.messagesInQueueAlarm = Alarm.Builder.create(this, "Alarm") - .alarmDescription("There are messages in the Dead Letter Queue.") - .evaluationPeriods(1) - .threshold(1) - .metric(this.metricApproximateNumberOfMessagesVisible()) - .build(); - } - - public IAlarm getMessagesInQueueAlarm() { - return messagesInQueueAlarm; - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">namespace AwsCdkAssertionSamples -{ - public class DeadLetterQueue : Queue - { - public IAlarm messagesInQueueAlarm; - - public DeadLetterQueue(Construct scope, string id) : base(scope, id) - { - messagesInQueueAlarm = new Alarm(this, "Alarm", new AlarmProps - { - AlarmDescription = "There are messages in the Dead Letter Queue.", - EvaluationPeriods = 1, - Threshold = 1, - Metric = this.MetricApproximateNumberOfMessagesVisible() - }); - } - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>We can test it like this:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import { Match, Template } from "aws-cdk-lib/assertions"; -import * as cdk from "aws-cdk-lib"; -import { DeadLetterQueue } from "../lib/dead-letter-queue"; - -describe("DeadLetterQueue", () => { - test("matches the snapshot", () => { - const stack = new cdk.Stack(); - new DeadLetterQueue(stack, "DeadLetterQueue"); - - const template = Template.fromStack(stack); - expect(template.toJSON()).toMatchSnapshot(); - }); -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const { Match, Template } = require("aws-cdk-lib/assertions"); -const cdk = require("aws-cdk-lib"); -const { DeadLetterQueue } = require("../lib/dead-letter-queue"); - -describe("DeadLetterQueue", () => { - test("matches the snapshot", () => { - const stack = new cdk.Stack(); - new DeadLetterQueue(stack, "DeadLetterQueue"); - - const template = Template.fromStack(stack); - expect(template.toJSON()).toMatchSnapshot(); - }); -});</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">import aws_cdk_lib as cdk -from aws_cdk_lib.assertions import Match, Template - -from app.dead_letter_queue import DeadLetterQueue - -def snapshot_test(): - stack = cdk.Stack() - DeadLetterQueue(stack, "DeadLetterQueue") - - template = Template.from_stack(stack) - assert template.to_json() == snapshot</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">package software.amazon.samples.awscdkassertionssamples; - -import org.junit.jupiter.api.Test; -import au.com.origin.snapshots.Expect; -import software.amazon.awscdk.assertions.Match; -import software.amazon.awscdk.assertions.Template; -import software.amazon.awscdk.Stack; - -import java.util.Collections; -import java.util.Map; - -public class DeadLetterQueueTest { - @Test - public void snapshotTest() { - final Stack stack = new Stack(); - new DeadLetterQueue(stack, "DeadLetterQueue"); - - final Template template = Template.fromStack(stack); - expect.toMatchSnapshot(template.toJSON()); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Microsoft.VisualStudio.TestTools.UnitTesting; - -using Amazon.CDK; -using Amazon.CDK.Assertions; -using AwsCdkAssertionSamples; - -using ObjectDict = System.Collections.Generic.Dictionary<string, object>; -using StringDict = System.Collections.Generic.Dictionary<string, string>; - -namespace TestProject1 -{ - [TestClass] - public class StateMachineStackTest - - [TestClass] - public class DeadLetterQueueTest - { - [TestMethod] - public void SnapshotTest() - { - var stack = new Stack(); - new DeadLetterQueue(stack, "DeadLetterQueue"); - - var template = Template.FromStack(stack); - - return Verifier.Verify(template.ToJSON()); - } - } -}</code></pre> -</div> -</div> -</div> -<div class="sect2"> -<h3 id="testing-tips">16.8. Tips for tests</h3> -<div class="paragraph"> -<p>Remember, your tests will live just as long as the code they test, and they will be read and modified just as often. Therefore, it pays to take a moment to consider how best to write them.</p> -</div> -<div class="paragraph"> -<p>Don’t copy and paste setup lines or common assertions. Instead, refactor this logic into fixtures or helper functions. Use good names that reflect what each test actually tests.</p> -</div> -<div class="paragraph"> -<p>Don’t try to do too much in one test. Preferably, a test should test one and only one behavior. If you accidentally break that behavior, exactly one test should fail, and the name of the test should tell you what failed. This is more an ideal to be striven for, however; sometimes you will unavoidably (or inadvertently) write tests that test more than one behavior. Snapshot tests are, for reasons we’ve already described, especially prone to this problem, so use them sparingly.</p> -</div> -</div> -</div> -</div> -<div class="sect1 topic"> -<h2 id="cli">17. AWS CDK <code class="noloc">CLI</code> reference</h2> -<div class="sectionbody"> -<div class="paragraph"> -<p>The AWS Cloud Development Kit (AWS CDK) Command Line Interface (AWS CDK <code class="noloc">CLI</code>), also known as the CDK <code class="noloc">Toolkit</code>, is the primary tool for interacting with your AWS CDK app. It executes your app, interrogates the application model you defined, and produces and deploys the AWS CloudFormation templates generated by the AWS CDK. It also provides other features useful for creating and working with AWS CDK projects. This topic contains information about common use cases of the CDK <code class="noloc">CLI</code>.</p> -</div> -<div class="paragraph"> -<p>The CDK <code class="noloc">CLI</code> is installed with the Node Package Manager. In most cases, we recommend installing it globally.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">npm install -g aws-cdk # install latest version -npm install -g aws-cdk@X.YY.Z # install specific version</code></pre> -</div> -</div> -<div class="admonitionblock tip"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-tip" title="Tip"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>If you regularly work with multiple versions of the AWS CDK, consider installing a matching version of the CDK <code class="noloc">CLI</code> in individual CDK projects. To do this, omit <code>-g</code> from the <code>npm install</code> command. Then use <code>npx aws-cdk</code> to invoke it. This runs the local version if one exists, falling back to a global version if not.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="sect2"> -<h3 id="cli-commands">17.1. CDK <code class="noloc">CLI</code> commands</h3> -<div class="paragraph"> -<p>All CDK <code class="noloc">CLI</code> commands start with <code>cdk</code>, which is followed by a subcommand (<code>list</code>, <code>synthesize</code>, <code>deploy</code>, etc.). Some subcommands have a shorter version (<code>ls</code>, <code>synth</code>, etc.) that is equivalent. Options and arguments follow the subcommand in any order.</p> -</div> -<div class="paragraph"> -<p>For a description of all subcommands, options, and arguments, see <a href="#ref-cli-cmd">AWS CDK CLI command reference</a>.</p> -</div> -</div> -<div class="sect2"> -<h3 id="cli-options">17.2. Specify options and their values</h3> -<div class="paragraph"> -<p>Command line options begin with two hyphens (<code>--</code>). Some frequently used options have single-letter synonyms that begin with a single hyphen (for example, <code>--app</code> has a synonym <code>-a</code>). The order of options in an CDK <code class="noloc">CLI</code> command is not important.</p> -</div> -<div class="paragraph"> -<p>All options accept a value, which must follow the option name. The value may be separated from the name by white space or by an equals sign <code>=</code>. The following two options are equivalent.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">--toolkit-stack-name MyBootstrapStack ---toolkit-stack-name=MyBootstrapStack</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Some options are flags (Booleans). You may specify <code>true</code> or <code>false</code> as their value. If you do not provide a value, the value is taken to be <code>true</code>. You may also prefix the option name with <code>no-</code> to imply <code>false</code>.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none"># sets staging flag to true ---staging ---staging=true ---staging true - -# sets staging flag to false ---no-staging ---staging=false ---staging false</code></pre> -</div> -</div> -<div class="paragraph"> -<p>A few options, namely <code>--context</code>, <code>--parameters</code>, <code>--plugin</code>, <code>--tags</code>, and <code>--trust</code>, may be specified more than once to specify multiple values. These are noted as having <code>[array]</code> type in the CDK <code class="noloc">CLI</code> help. For example:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk bootstrap --tags costCenter=0123 --tags responsibleParty=jdoe</code></pre> -</div> -</div> -</div> -<div class="sect2"> -<h3 id="cli-help">17.3. Built-in help</h3> -<div class="paragraph"> -<p>The CDK <code class="noloc">CLI</code> has integrated help. You can see general help about the utility and a list of the provided subcommands by issuing:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk --help</code></pre> -</div> -</div> -<div class="paragraph"> -<p>To see help for a particular subcommand, for example <code>deploy</code>, specify it before the <code>--help</code> flag.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk deploy --help</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Issue <code>cdk version</code> to display the version of the CDK <code class="noloc">CLI</code>. Provide this information when requesting support.</p> -</div> -</div> -<div class="sect2"> -<h3 id="version-reporting">17.4. Version reporting</h3> -<div class="paragraph"> -<p>To gain insight into how the AWS CDK is used, the constructs used by AWS CDK applications are collected and reported by using a resource identified as <code>AWS::CDK::Metadata</code>. To learn more, see <a href="#usage-data">Configure AWS CDK usage data reporting</a>.</p> -</div> -</div> -<div class="sect2"> -<h3 id="cli-auth">17.5. Authentication with AWS</h3> -<div class="paragraph"> -<p>There are different ways in which you can configure programmatic access to AWS resources, depending on the environment and the AWS access available to you.</p> -</div> -<div class="paragraph"> -<p>To choose your method of authentication and configure it for the CDK <code class="noloc">CLI</code>, see <a href="#configure-access">Configure security credentials for the AWS CDK CLI</a>.</p> -</div> -<div class="paragraph"> -<p>The recommended approach for new users developing locally, who are not given a method of authentication by their employer, is to set up AWS IAM Identity Center. This method includes installing the AWS CLI for ease of configuration and for regularly signing in to the AWS access portal. If you choose this method, your environment should contain the following elements after you complete the procedure for <a href="https://docs.aws.amazon.com/sdkref/latest/guide/access-sso.html">IAM Identity Center authentication</a> in the <em>AWS SDKs and Tools Reference Guide</em>:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>The AWS CLI, which you use to start an AWS access portal session before you run your application.</p> -</li> -<li> -<p>A <a href="https://docs.aws.amazon.com/sdkref/latest/guide/file-format.html">shared AWSconfig file</a> having a <code>[default]</code> profile with a set of configuration values that can be referenced from the AWS CDK. To find the location of this file, see <a href="https://docs.aws.amazon.com/sdkref/latest/guide/file-location.html">Location of the shared files</a> in the <em>AWS SDKs and Tools Reference Guide</em>.</p> -</li> -<li> -<p>The shared <code class="path">config</code> file sets the <a href="https://docs.aws.amazon.com/sdkref/latest/guide/feature-region.html">region</a> setting. This sets the default AWS Region the AWS CDK and CDK <code class="noloc">CLI</code> use for AWS requests.</p> -</li> -<li> -<p>The CDK <code class="noloc">CLI</code> uses the profile’s <a href="https://docs.aws.amazon.com/sdkref/latest/guide/feature-sso-credentials.html#feature-sso-credentials-profile">SSO token provider configuration</a> to acquire credentials before sending requests to AWS. The <code>sso_role_name</code> value, which is an IAM role connected to an IAM Identity Center permission set, should allow access to the AWS services used in your application.</p> -<div class="paragraph"> -<p>The following sample <code>config</code> file shows a default profile set up with SSO token provider configuration. The profile’s <code>sso_session</code> setting refers to the named <a href="https://docs.aws.amazon.com/sdkref/latest/guide/file-format.html#section-session">sso-session section</a>. The <code>sso-session</code> section contains settings to initiate an AWS access portal session.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>[default] -sso_session = my-sso -sso_account_id = 111122223333 -sso_role_name = SampleRole -region = us-east-1 -output = json - -[sso-session my-sso] -sso_region = us-east-1 -sso_start_url = https://provided-domain.awsapps.com/start -sso_registration_scopes = sso:account:access</code></pre> -</div> -</div> -</li> -</ul> -</div> -<div class="sect3"> -<h4 id="accessportal">17.5.1. Start an AWS access portal session</h4> -<div class="paragraph"> -<p>Before accessing AWS services, you need an active AWS access portal session for the CDK <code class="noloc">CLI</code> to use IAM Identity Center authentication to resolve credentials. Depending on your configured session lengths, your access will eventually expire and the CDK <code class="noloc">CLI</code> will encounter an authentication error. Run the following command in the AWS CLI to sign in to the AWS access portal.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-bash" data-lang="bash">aws sso login</code></pre> -</div> -</div> -<div class="paragraph"> -<p>If your SSO token provider configuration is using a named profile instead of the default profile, the command is <code>aws sso login --profile [replaceable]</code>NAME````. Also specify this profile when issuing <strong class="command">cdk</strong> commands using the <strong class="command">--profile</strong> option or the <code>AWS_PROFILE</code> environment variable.</p> -</div> -<div class="paragraph"> -<p>To test if you already have an active session, run the following AWS CLI command.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-bash" data-lang="bash">aws sts get-caller-identity</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The response to this command should report the IAM Identity Center account and permission set configured in the shared <code>config</code> file.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>If you already have an active AWS access portal session and run <code>aws sso login</code>, you will not be required to provide credentials.</p> -</div> -<div class="paragraph"> -<p>The sign in process may prompt you to allow the AWS CLI access to your data. Since the AWS CLI is built on top of the SDK for Python, permission messages may contain variations of the <code>botocore</code> name.</p> -</div> -</td> -</tr> -</table> -</div> -</div> -</div> -<div class="sect2"> -<h3 id="cli-environment">17.6. Specify Region and other configuration</h3> -<div class="paragraph"> -<p>The CDK <code class="noloc">CLI</code> needs to know the AWS Region that you’re deploying into and how to authenticate with AWS. This is needed for deployment operations and to retrieve context values during synthesis. Together, your account and Region make up the <em>environment</em>.</p> -</div> -<div class="paragraph"> -<p>Region may be specified using environment variables or in configuration files. These are the same variables and files used by other AWS tools such as the AWS CLI and the various AWS SDKs. The CDK <code class="noloc">CLI</code> looks for this information in the following order.</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>The <code>AWS_DEFAULT_REGION</code> environment variable.</p> -</li> -<li> -<p>A named profile defined in the standard AWS <code class="path">config</code> file and specified using the <code>--profile</code> option on <code>cdk</code> commands.</p> -</li> -<li> -<p>The <code>[default]</code> section of the standard AWS <code class="path">config</code> file.</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>Besides specifying AWS authentication and a Region in the <code>[default]</code> section, you can also add one or more <code><code class="profile [replaceable">NAME</code>]</code> sections, where <code class="replaceable">NAME</code> is the name of the profile. For more information about named profiles, see <a href="https://docs.aws.amazon.com/sdkref/latest/guide/file-format.html">Shared config and credentials files</a> in the <em>AWS SDKs and Tools Reference Guide</em>.</p> -</div> -<div class="paragraph"> -<p>The standard AWS <code class="path">config</code> file is located at <code class="path">~/.aws/config</code> (macOS/Linux) or <code class="path">%USERPROFILE%\.aws\config</code> (Windows). For details and alternate locations, see <a href="https://docs.aws.amazon.com/sdkref/latest/guide/file-location.html">Location of the shared config and credentials files</a> in the <em>AWS SDKs and Tools Reference Guide</em></p> -</div> -<div class="paragraph"> -<p>The environment that you specify in your AWS CDK app by using the stack’s <code>env</code> property is used during synthesis. It’s used to generate an environment-specific AWS CloudFormation template, and during deployment, it overrides the account or Region specified by one of the preceding methods. For more information, see <a href="#environments">Environments for the AWS CDK</a>.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>The AWS CDK uses credentials from the same source files as other AWS tools and SDKs, including the <a href="https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html">AWS Command Line Interface</a>. However, the AWS CDK might behave somewhat differently from these tools. It uses the AWS SDK for JavaScript under the hood. For complete details on setting up credentials for the AWS SDK for JavaScript, see <a href="https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/setting-credentials.html">Setting credentials</a>.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>You may optionally use the <code>--role-arn</code> (or <code>-r</code>) option to specify the ARN of an IAM role that should be used for deployment. This role must be assumable by the AWS account being used.</p> -</div> -</div> -<div class="sect2"> -<h3 id="cli-app-command">17.7. Specify the app command</h3> -<div class="paragraph"> -<p>Many features of the CDK <code class="noloc">CLI</code> require one or more AWS CloudFormation templates be synthesized, which in turn requires running your application. The AWS CDK supports programs written in a variety of languages. Therefore, it uses a configuration option to specify the exact command necessary to run your app. This option can be specified in two ways.</p> -</div> -<div class="paragraph"> -<p>First, and most commonly, it can be specified using the <code>app</code> key inside the file <code class="path">cdk.json</code>. This is in the main directory of your AWS CDK project. The CDK <code class="noloc">CLI</code> provides an appropriate command when creating a new project with <code>cdk init</code>. Here is the <code class="path">cdk.json</code> from a fresh TypeScript project, for instance.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-json" data-lang="json">{ - "app": "npx ts-node bin/hello-cdk.ts" -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The CDK <code class="noloc">CLI</code> looks for <code class="path">cdk.json</code> in the current working directory when attempting to run your app. Because of this, you might keep a shell open in your project’s main directory for issuing CDK <code class="noloc">CLI</code> commands.</p> -</div> -<div class="paragraph"> -<p>The CDK <code class="noloc">CLI</code> also looks for the app key in <code class="path">~/.cdk.json</code> (that is, in your home directory) if it can’t find it in <code>./cdk.json</code>. Adding the app command here can be useful if you usually work with CDK code in the same language.</p> -</div> -<div class="paragraph"> -<p>If you are in some other directory, or to run your app using a command other than the one in <code class="path">cdk.json</code>, use the <code>--app</code> (or <code>-a</code>) option to specify it.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk --app "npx ts-node bin/hello-cdk.ts" ls</code></pre> -</div> -</div> -<div class="paragraph"> -<p>When deploying, you may also specify a directory containing synthesized cloud assemblies, such as <code class="path">cdk.out</code>, as the value of <strong class="command">--app</strong>. The specified stacks are deployed from this directory; the app is not synthesized.</p> -</div> -</div> -<div class="sect2"> -<h3 id="cli-stacks">17.8. Specify stacks</h3> -<div class="paragraph"> -<p>Many CDK <code class="noloc">CLI</code> commands (for example, <code>cdk deploy</code>) work on stacks defined in your app. If your app contains only one stack, the CDK <code class="noloc">CLI</code> assumes you mean that one if you don’t specify a stack explicitly.</p> -</div> -<div class="paragraph"> -<p>Otherwise, you must specify the stack or stacks you want to work with. You can do this by specifying the desired stacks by ID individually on the command line. Recall that the ID is the value specified by the second argument when you instantiate the stack.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk synth PipelineStack LambdaStack</code></pre> -</div> -</div> -<div class="paragraph"> -<p>You may also use wildcards to specify IDs that match a pattern.</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><code>?</code> matches any single character</p> -</li> -<li> -<p><code>*</code> matches any number of characters (<code>\*</code> alone matches all stacks)</p> -</li> -<li> -<p><code>\**</code> matches everything in a hierarchy</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>You may also use the <strong class="command">--all</strong> option to specify all stacks.</p> -</div> -<div class="paragraph"> -<p>If your app uses <a href="#cdk-pipeline">CDK Pipelines</a>, the CDK <code class="noloc">CLI</code> understands your stacks and stages as a hierarchy. Also, the <strong class="command">--all</strong> option and the <code>*</code> wildcard only match top-level stacks. To match all the stacks, use <code>**</code>. Also use <code>\**</code> to indicate all the stacks under a particular hierarchy.</p> -</div> -<div class="paragraph"> -<p>When using wildcards, enclose the pattern in quotes, or escape the wildcards with <code>\</code>. If you don’t, your shell may try to expand the pattern to the names of files in the current directory. At best, this won’t do what you expect; at worst, you could deploy stacks you didn’t intend to. This isn’t strictly necessary on Windows because <code>cmd.exe</code> does not expand wildcards, but is good practice nonetheless.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk synth "*Stack" # PipelineStack, LambdaStack, etc. -cdk synth 'Stack?' # StackA, StackB, Stack1, etc. -cdk synth \* # All stacks in the app, or all top-level stacks in a CDK Pipelines app -cdk synth '**' # All stacks in a CDK Pipelines app -cdk synth 'PipelineStack/Prod/**' # All stacks in Prod stage in a CDK Pipelines app</code></pre> -</div> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>The order in which you specify the stacks is not necessarily the order in which they will be processed. The CDK <code class="noloc">CLI</code> accounts for dependencies between stacks when deciding the order in which to process them. For example, let’s say that one stack uses a value produced by another (such as the ARN of a resource defined in the second stack). In this case, the second stack is synthesized before the first one because of this dependency. You can add dependencies between stacks manually using the stack’s <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html#addwbrdependencytarget-reason">addDependency()</a> method.</p> -</div> -</td> -</tr> -</table> -</div> -</div> -<div class="sect2"> -<h3 id="cli-bootstrap">17.9. Bootstrap your AWS environment</h3> -<div class="paragraph"> -<p>Deploying stacks with the CDK requires special dedicated AWS CDK resources to be provisioned. The <code>cdk bootstrap</code> command creates the necessary resources for you. You only need to bootstrap if you are deploying a stack that requires these dedicated resources. See <a href="#bootstrapping">AWS CDK bootstrapping</a> for details.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk bootstrap</code></pre> -</div> -</div> -<div class="paragraph"> -<p>If issued with no arguments, as shown here, the <code>cdk bootstrap</code> command synthesizes the current app and bootstraps the environments its stacks will be deployed to. If the app contains environment-agnostic stacks, which don’t explicitly specify an environment, the default account and Region are bootstrapped, or the environment specified using <code>--profile</code>.</p> -</div> -<div class="paragraph"> -<p>Outside of an app, you must explicitly specify the environment to be bootstrapped. You may also do so to bootstrap an environment that’s not specified in your app or local AWS profile. Credentials must be configured (e.g. in <code class="path">~/.aws/credentials</code>) for the specified account and Region. You may specify a profile that contains the required credentials.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk bootstrap ACCOUNT-NUMBER/REGION # e.g. -cdk bootstrap 1111111111/us-east-1 -cdk bootstrap --profile test 1111111111/us-east-1</code></pre> -</div> -</div> -<div class="admonitionblock important"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-important" title="Important"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>Each environment (account/region combination) to which you deploy such a stack must be bootstrapped separately.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>You may incur AWS charges for what the AWS CDK stores in the bootstrapped resources. Additionally, if you use <code>-bootstrap-customer-key</code>, an AWS KMS key will be created, which also incurs charges per environment.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>Earlier versions of the bootstrap template created a KMS key by default. To avoid charges, re-bootstrap using <code>--no-bootstrap-customer-key</code>.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>CDK <code class="noloc">CLI</code> v2 does not support the original bootstrap template, dubbed the legacy template, used by default with CDK v1.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="admonitionblock important"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-important" title="Important"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>The modern bootstrap template effectively grants the permissions implied by the <code>--cloudformation-execution-policies</code> to any AWS account in the <code>--trust</code> list. By default, this extends permissions to read and write to any resource in the bootstrapped account. Make sure to <a href="#bootstrapping-customizing">configure the bootstrapping stack</a> with policies and trusted accounts that you are comfortable with.</p> -</div> -</td> -</tr> -</table> -</div> -</div> -<div class="sect2"> -<h3 id="cli-init">17.10. Create a new app</h3> -<div class="paragraph"> -<p>To create a new app, create a directory for it, then, inside the directory, issue <code>cdk init</code>.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">mkdir my-cdk-app -cd my-cdk-app -cdk init TEMPLATE --language LANGUAGE</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The supported languages (<code class="replaceable">LANGUAGE</code>) are:</p> -</div> -<table class="tableblock frame-all grid-all stretch"> -<colgroup> -<col style="width: 50%;"> -<col style="width: 50%;"> -</colgroup> -<thead> -<tr> -<th class="tableblock halign-left valign-top">Code</th> -<th class="tableblock halign-left valign-top">Language</th> -</tr> -</thead> -<tbody> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>typescript</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">TypeScript</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>javascript</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">JavaScript</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>python</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Python</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>java</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Java</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>csharp</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">C#</p></td> -</tr> -</tbody> -</table> -<div class="paragraph"> -<p><code class="replaceable">TEMPLATE</code> is an optional template. If the desired template is <em>app</em>, the default, you may omit it. The available templates are:</p> -</div> -<table class="tableblock frame-all grid-all stretch"> -<colgroup> -<col style="width: 50%;"> -<col style="width: 50%;"> -</colgroup> -<thead> -<tr> -<th class="tableblock halign-left valign-top">Template</th> -<th class="tableblock halign-left valign-top">Description</th> -</tr> -</thead> -<tbody> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>app</code> (default)</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Creates an empty AWS CDK app.</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>sample-app</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Creates an AWS CDK app with a stack containing an Amazon SQS queue and an Amazon SNS topic.</p></td> -</tr> -</tbody> -</table> -<div class="paragraph"> -<p>The templates use the name of the project folder to generate names for files and classes inside your new app.</p> -</div> -</div> -<div class="sect2"> -<h3 id="cli-list">17.11. List stacks</h3> -<div class="paragraph"> -<p>To see a list of the IDs of the stacks in your AWS CDK application, enter one of the following equivalent commands:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk list -cdk ls</code></pre> -</div> -</div> -<div class="paragraph"> -<p>If your application contains <a href="#cdk-pipeline">CDK Pipelines</a> stacks, the CDK <code class="noloc">CLI</code> displays stack names as paths according to their location in the pipeline hierarchy. (For example, <code class="path">PipelineStack</code>, <code class="path">PipelineStack/Prod</code>, and <code class="path">PipelineStack/Prod/MyService</code>.)</p> -</div> -<div class="paragraph"> -<p>If your app contains many stacks, you can specify full or partial stack IDs of the stacks to be listed. For more information, see <a href="#cli-stacks">Specify stacks</a>.</p> -</div> -<div class="paragraph"> -<p>Add the <code>--long</code> flag to see more information about the stacks, including the stack names and their environments (AWS account and Region).</p> -</div> -</div> -<div class="sect2"> -<h3 id="cli-synth">17.12. Synthesize stacks</h3> -<div class="paragraph"> -<p>The <code>cdk synthesize</code> command (almost always abbreviated <code>synth</code>) synthesizes a stack defined in your app into a CloudFormation template.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk synth # if app contains only one stack -cdk synth MyStack -cdk synth Stack1 Stack2 -cdk synth "*" # all stacks in app</code></pre> -</div> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>The CDK <code class="noloc">CLI</code> actually runs your app and synthesizes fresh templates before most operations (such as when deploying or comparing stacks). These templates are stored by default in the <code class="path">cdk.out</code> directory. The <code>cdk synth</code> command simply prints the generated templates for one or more specified stacks.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>See <code>cdk synth --help</code> for all available options. A few of the most frequently used options are covered in the following section.</p> -</div> -<div class="sect3"> -<h4 id="w94aac73c33c11">17.12.1. Specify context values</h4> -<div class="paragraph"> -<p>Use the <code>--context</code> or <code>-c</code> option to pass <a href="#context">runtime context</a> values to your CDK app.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none"># specify a single context value -cdk synth --context key=value MyStack - -# specify multiple context values (any number) -cdk synth --context key1=value1 --context key2=value2 MyStack</code></pre> -</div> -</div> -<div class="paragraph"> -<p>When deploying multiple stacks, the specified context values are normally passed to all of them. If you want, you can specify different values for each stack by prefixing the stack name to the context value.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none"># different context values for each stack -cdk synth --context Stack1:key=value Stack2:key=value Stack1 Stack2</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="w94aac73c33c13">17.12.2. Specify display format</h4> -<div class="paragraph"> -<p>By default, the synthesized template is displayed in YAML format. Add the <code>--json</code> flag to display it in JSON format instead.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk synth --json MyStack</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="w94aac73c33c15">17.12.3. Specify the output directory</h4> -<div class="paragraph"> -<p>Add the <code>--output</code> (<code>-o</code>) option to write the synthesized templates to a directory other than <code class="path">cdk.out</code>.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk synth --output=~/templates</code></pre> -</div> -</div> -</div> -</div> -<div class="sect2"> -<h3 id="cli-deploy">17.13. Deploy stacks</h3> -<div class="paragraph"> -<p>The <code>cdk deploy</code> subcommand deploys one or more specified stacks to your AWS account.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk deploy # if app contains only one stack -cdk deploy MyStack -cdk deploy Stack1 Stack2 -cdk deploy "*" # all stacks in app</code></pre> -</div> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>The CDK <code class="noloc">CLI</code> runs your app and synthesizes fresh AWS CloudFormation templates before deploying anything. Therefore, most command line options you can use with <code>cdk synth</code> (for example, <code>--context</code>) can also be used with <code>cdk deploy</code>.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>See <code>cdk deploy --help</code> for all available options. A few of the most useful options are covered in the following section.</p> -</div> -<div class="sect3"> -<h4 id="cli-deploy-nosynth">17.13.1. Skip synthesis</h4> -<div class="paragraph"> -<p>The <strong class="command">cdk deploy</strong> command normally synthesizes your app’s stacks before deploying to make sure that the deployment reflects the latest version of your app. If you know that you haven’t changed your code since your last <strong class="command">cdk synth</strong>, you can suppress the redundant synthesis step when deploying. To do so, specify your project’s <code class="path">cdk.out</code> directory in the <strong class="command">--app</strong> option.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>cdk deploy --app cdk.out StackOne StackTwo</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="cli-deploy-norollback">17.13.2. Disable rollback</h4> -<div class="paragraph"> -<p>AWS CloudFormation has the ability to roll back changes so that deployments are atomic. This means that they either succeed or fail as a whole. The AWS CDK inherits this capability because it synthesizes and deploys AWS CloudFormation templates.</p> -</div> -<div class="paragraph"> -<p>Rollback makes sure that your resources are in a consistent state at all times, which is vital for production stacks. However, while you’re still developing your infrastructure, some failures are inevitable, and rolling back failed deployments can slow you down.</p> -</div> -<div class="paragraph"> -<p>For this reason, the CDK <code class="noloc">CLI</code> lets you disable rollback by adding <code>--no-rollback</code> to your <code>cdk deploy</code> command. With this flag, failed deployments are not rolled back. Instead, resources deployed before the failed resource remain in place, and the next deployment starts with the failed resource. You’ll spend a lot less time waiting for deployments and a lot more time developing your infrastructure.</p> -</div> -</div> -<div class="sect3"> -<h4 id="cli-deploy-hotswap">17.13.3. Hot swapping</h4> -<div class="paragraph"> -<p>Use the <code>--hotswap</code> flag with <code>cdk deploy</code> to attempt to update your AWS resources directly instead of generating an AWS CloudFormation change set and deploying it. Deployment falls back to AWS CloudFormation deployment if hot swapping is not possible.</p> -</div> -<div class="paragraph"> -<p>Currently hot swapping supports Lambda functions, Step Functions state machines, and Amazon ECS container images. The <code>--hotswap</code> flag also disables rollback (i.e., implies <code>--no-rollback</code>).</p> -</div> -<div class="admonitionblock important"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-important" title="Important"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>Hot-swapping is not recommended for production deployments.</p> -</div> -</td> -</tr> -</table> -</div> -</div> -<div class="sect3"> -<h4 id="cli-deploy-watch">17.13.4. Watch mode</h4> -<div class="paragraph"> -<p>The CDK <code class="noloc">CLI</code>'s watch mode ( <strong class="command">cdk deploy --watch</strong>, or <strong class="command">cdk watch</strong> for short) continuously monitors your CDK app’s source files and assets for changes. It immediately performs a deployment of the specified stacks when a change is detected.</p> -</div> -<div class="paragraph"> -<p>By default, these deployments use the <code>--hotswap</code> flag, which fast-tracks deployment of changes to Lambda functions. It also falls back to deploying through AWS CloudFormation if you have changed infrastructure configuration. To have <code>cdk watch</code> always perform full AWS CloudFormation deployments, add the <code>--no-hotswap</code> flag to <code>cdk watch</code>.</p> -</div> -<div class="paragraph"> -<p>Any changes made while <code>cdk watch</code> is already performing a deployment are combined into a single deployment, which begins as soon as the in-progress deployment is complete.</p> -</div> -<div class="paragraph"> -<p>Watch mode uses the <code>"watch"</code> key in the project’s <code class="path">cdk.json</code> to determine which files to monitor. By default, these files are your application files and assets, but this can be changed by modifying the <code>"include"</code> and <code>"exclude"</code> entries in the <code>"watch"</code> key. The following <code class="path">cdk.json</code> file shows an example of these entries.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-json" data-lang="json">{ - "app": "mvn -e -q compile exec:java", - "watch": { - "include": "src/main/**", - "exclude": "target/*" - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p><code>cdk watch</code> executes the <code>"build"</code> command from <code class="path">cdk.json</code> to build your app before synthesis. If your deployment requires any commands to build or package your Lambda code (or anything else that’s not in your CDK app), add it here.</p> -</div> -<div class="paragraph"> -<p>Git-style wildcards, both <code>*</code> and <code>**</code>, can be used in the <code>"watch"</code> and <code>"build"</code> keys. Each path is interpreted relative to the parent directory of <code class="path">cdk.json</code>. The default value of <code>include</code> is <code>**/*</code>, meaning all files and directories in the project root directory. <code>exclude</code> is optional.</p> -</div> -<div class="admonitionblock important"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-important" title="Important"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>Watch mode is not recommended for production deployments.</p> -</div> -</td> -</tr> -</table> -</div> -</div> -<div class="sect3"> -<h4 id="w94aac73c35c19">17.13.5. Specify AWS CloudFormation parameters</h4> -<div class="paragraph"> -<p>The CDK <code class="noloc">CLI</code> supports specifying AWS CloudFormation <a href="#parameters">parameters</a> at deployment. You may provide these on the command line following the <code>--parameters</code> flag.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk deploy MyStack --parameters uploadBucketName=UploadBucket</code></pre> -</div> -</div> -<div class="paragraph"> -<p>To define multiple parameters, use multiple <code>--parameters</code> flags.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk deploy MyStack --parameters uploadBucketName=UpBucket --parameters downloadBucketName=DownBucket</code></pre> -</div> -</div> -<div class="paragraph"> -<p>If you are deploying multiple stacks, you can specify a different value of each parameter for each stack. To do so, prefix the name of the parameter with the stack name and a colon. Otherwise, the same value is passed to all stacks.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk deploy MyStack YourStack --parameters MyStack:uploadBucketName=UploadBucket --parameters YourStack:uploadBucketName=UpBucket</code></pre> -</div> -</div> -<div class="paragraph"> -<p>By default, the AWS CDK retains values of parameters from previous deployments and uses them in later deployments if they are not specified explicitly. Use the <code>--no-previous-parameters</code> flag to require all parameters to be specified.</p> -</div> -</div> -<div class="sect3"> -<h4 id="w94aac73c35c21">17.13.6. Specify outputs file</h4> -<div class="paragraph"> -<p>If your stack declares AWS CloudFormation outputs, these are normally displayed on the screen at the conclusion of deployment. To write them to a file in JSON format, use the <code>--outputs-file</code> flag.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk deploy --outputs-file outputs.json MyStack</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="cli-security">17.13.7. Approve security-related changes</h4> -<div class="paragraph"> -<p>To protect you against unintended changes that affect your security posture, the CDK <code class="noloc">CLI</code> prompts you to approve security-related changes before deploying them. You can specify the level of change that requires approval:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk deploy --require-approval LEVEL</code></pre> -</div> -</div> -<div class="paragraph"> -<p><code class="replaceable">LEVEL</code> can be one of the following:</p> -</div> -<table class="tableblock frame-all grid-all stretch"> -<colgroup> -<col style="width: 50%;"> -<col style="width: 50%;"> -</colgroup> -<thead> -<tr> -<th class="tableblock halign-left valign-top">Term</th> -<th class="tableblock halign-left valign-top">Meaning</th> -</tr> -</thead> -<tbody> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>never</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Approval is never required</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>any-change</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Requires approval on any IAM or security-group-related change</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>broadening</code> (default)</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Requires approval when IAM statements or traffic rules are added; removals don’t require approval</p></td> -</tr> -</tbody> -</table> -<div class="paragraph"> -<p>The setting can also be configured in the <code class="path">cdk.json</code> file.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-json" data-lang="json">{ - "app": "...", - "requireApproval": "never" -}</code></pre> -</div> -</div> -</div> -</div> -<div class="sect2"> -<h3 id="cli-diff">17.14. Compare stacks</h3> -<div class="paragraph"> -<p>The <code>cdk diff</code> command compares the current version of a stack (and its dependencies) defined in your app with the already-deployed versions, or with a saved AWS CloudFormation template, and displays a list of changes.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre>Stack HelloCdkStack -IAM Statement Changes -┌───┬──────────────────────────────┬────────┬──────────────────────────────┬──────────────────────────────┬───────────┐ -│ │ Resource │ Effect │ Action │ Principal │ Condition │ -├───┼──────────────────────────────┼────────┼──────────────────────────────┼──────────────────────────────┼───────────┤ -│ + │ ${Custom::S3AutoDeleteObject │ Allow │ sts:AssumeRole │ Service:lambda.amazonaws.com │ │ -│ │ sCustomResourceProvider/Role │ │ │ │ │ -│ │ .Arn} │ │ │ │ │ -├───┼──────────────────────────────┼────────┼──────────────────────────────┼──────────────────────────────┼───────────┤ -│ + │ ${MyFirstBucket.Arn} │ Allow │ s3:DeleteObject* │ AWS:${Custom::S3AutoDeleteOb │ │ -│ │ ${MyFirstBucket.Arn}/* │ │ s3:GetBucket* │ jectsCustomResourceProvider/ │ │ -│ │ │ │ s3:GetObject* │ Role.Arn} │ │ -│ │ │ │ s3:List* │ │ │ -└───┴──────────────────────────────┴────────┴──────────────────────────────┴──────────────────────────────┴───────────┘ -IAM Policy Changes -┌───┬────────────────────────────────────────────────────────┬────────────────────────────────────────────────────────┐ -│ │ Resource │ Managed Policy ARN │ -├───┼────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────┤ -│ + │ ${Custom::S3AutoDeleteObjectsCustomResourceProvider/Ro │ {"Fn::Sub":"arn:${AWS::Partition}:iam::aws:policy/serv │ -│ │ le} │ ice-role/AWSLambdaBasicExecutionRole"} │ -└───┴────────────────────────────────────────────────────────┴────────────────────────────────────────────────────────┘ -(NOTE: There may be security-related changes not in this list. See https://github.com/aws/aws-cdk/issues/1299) - -Parameters -[+] Parameter AssetParameters/4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392/S3Bucket AssetParameters4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392S3BucketBF7A7F3F: {"Type":"String","Description":"S3 bucket for asset \"4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392\""} -[+] Parameter AssetParameters/4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392/S3VersionKey AssetParameters4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392S3VersionKeyFAF93626: {"Type":"String","Description":"S3 key for asset version \"4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392\""} -[+] Parameter AssetParameters/4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392/ArtifactHash AssetParameters4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392ArtifactHashE56CD69A: {"Type":"String","Description":"Artifact hash for asset \"4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392\""} - -Resources -[+] AWS::S3::BucketPolicy MyFirstBucket/Policy MyFirstBucketPolicy3243DEFD -[+] Custom::S3AutoDeleteObjects MyFirstBucket/AutoDeleteObjectsCustomResource MyFirstBucketAutoDeleteObjectsCustomResourceC52FCF6E -[+] AWS::IAM::Role Custom::S3AutoDeleteObjectsCustomResourceProvider/Role CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092 -[+] AWS::Lambda::Function Custom::S3AutoDeleteObjectsCustomResourceProvider/Handler CustomS3AutoDeleteObjectsCustomResourceProviderHandler9D90184F -[~] AWS::S3::Bucket MyFirstBucket MyFirstBucketB8884501 - ├─ [~] DeletionPolicy - │ ├─ [-] Retain - │ └─ [+] Delete - └─ [~] UpdateReplacePolicy - ├─ [-] Retain - └─ [+] Delete</pre> -</div> -</div> -<div class="paragraph"> -<p>To compare your app’s stacks with the existing deployment:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk diff MyStack</code></pre> -</div> -</div> -<div class="paragraph"> -<p>To compare your app’s stacks with a saved CloudFormation template:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk diff --template ~/stacks/MyStack.old MyStack</code></pre> -</div> -</div> -</div> -<div class="sect2"> -<h3 id="cli-import">17.15. Import existing resources into a stack</h3> -<div class="paragraph"> -<p>You can use the <code>cdk import</code> command to bring resources under the management of CloudFormation for a particular AWS CDK stack. This is useful if you are migrating to AWS CDK, or are moving resources between stacks or changing their logical id. <code>cdk import</code> uses <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resource-import.html">CloudFormation resource imports</a>. See the <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resource-import-supported-resources.html">list of resources that can be imported here</a>.</p> -</div> -<div class="paragraph"> -<p>To import an existing resource into a AWS CDK stack, follow the following steps:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Make sure the resource is not currently being managed by any other CloudFormation stack. If it is, first set the removal policy to <code>RemovalPolicy.RETAIN</code> in the stack the resource is currently in and perform a deployment. Then, remove the resource from the stack and perform another deployment. This process will make sure that the resource is no longer managed by CloudFormation but does not delete it.</p> -</li> -<li> -<p>Run a <code>cdk diff</code> to make sure there are no pending changes to the AWS CDK stack you want to import resources into. The only changes allowed in an "import" operation are the addition of new resources which you want to import.</p> -</li> -<li> -<p>Add constructs for the resources you want to import to your stack. For example, if you want to import an Amazon S3 bucket, add something like <code>new s3.Bucket(this, 'ImportedS3Bucket', {});</code>. Do not make any modifications to any other resource.</p> -<div class="paragraph"> -<p>You must also make sure to exactly model the state that the resource currently has into the definition. For the example of the bucket, be sure to include AWS KMS keys, life cycle policies, and anything else that’s relevant about the bucket. If you do not, subsequent update operations may not do what you expect.</p> -</div> -<div class="paragraph"> -<p>You can choose whether or not to include the physical bucket name. We usually recommend to not include resource names into your AWS CDK resource definitions so that it becomes easier to deploy your resources multiple times.</p> -</div> -</li> -<li> -<p>Run <code>cdk import [replaceable]</code>STACKNAME````.</p> -</li> -<li> -<p>If the resource names are not in your model, the CLI will prompt you to pass in the actual names of the resources you are importing. After this, the import starts.</p> -</li> -<li> -<p>When <code>cdk import</code> reports success, the resource is now managed by AWS CDK and CloudFormation. Any subsequent changes you make to the resource properties in your AWS CDK app the construct configuration will be applied on the next deployment.</p> -</li> -<li> -<p>To confirm that the resource definition in your AWS CDK app matches the current state of the resource, you can start an <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-stack-drift.html">CloudFormation drift detection operation</a>.</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>This feature currently does not support importing resources into nested stacks.</p> -</div> -</div> -<div class="sect2"> -<h3 id="cli-config">17.16. Configuration (<code class="path">cdk.json</code>)</h3> -<div class="paragraph"> -<p>Default values for many CDK <code class="noloc">CLI</code> command line flags can be stored in a project’s <code class="path">cdk.json</code> file or in the <code class="path">.cdk.json</code> file in your user directory. Following is an alphabetical reference to the supported configuration settings.</p> -</div> -<table class="tableblock frame-all grid-all stretch"> -<colgroup> -<col style="width: 33.3333%;"> -<col style="width: 33.3333%;"> -<col style="width: 33.3334%;"> -</colgroup> -<thead> -<tr> -<th class="tableblock halign-left valign-top">Key</th> -<th class="tableblock halign-left valign-top">Notes</th> -<th class="tableblock halign-left valign-top">CDK CLI option</th> -</tr> -</thead> -<tbody> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>app</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">The command that executes the CDK application.</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong class="command">--app</strong></p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>assetMetadata</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">If <code>false</code>, CDK does not add metadata to resources that use assets.</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong class="command">--no-asset-metadata</strong></p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>bootstrapKmsKeyId</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Overrides the ID of the AWS KMS key used to encrypt the Amazon S3 deployment bucket.</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong class="command">--bootstrap-kms-key-id</strong></p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>build</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">The command that compiles or builds the CDK application before synthesis. Not permitted in <code class="path">~/.cdk.json</code>.</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong class="command">--build</strong></p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>browser</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">The command for launching a Web browser for the <code class="path">cdk docs</code> subcommand.</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong class="command">--browser</strong></p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>context</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">See <a href="#context">Context values and the AWS CDK</a>. Context values in a configuration file will not be erased by <strong class="command">cdk context --clear</strong>. (The CDK <code class="noloc">CLI</code> places cached context values in <code class="path">cdk.context.json</code>.)</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong class="command">--context</strong></p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>debug</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">If <code>true</code>, CDK <code class="noloc">CLI</code> emits more detailed information useful for debugging.</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong class="command">--debug</strong></p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>language</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">The language to be used for initializing new projects.</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong class="command">--language</strong></p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>lookups</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">If <code>false</code>, no context lookups are permitted. Synthesis will fail if any context lookups need to be performed.</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong class="command">--no-lookups</strong></p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>notices</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">If <code>false</code>, suppresses the display of messages about security vulnerabilities, regressions, and unsupported versions.</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong class="command">--no-notices</strong></p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>output</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">The name of the directory into which the synthesized cloud assembly will be emitted (default <code>"cdk.out"</code>).</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong class="command">--output</strong></p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>outputsFile</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">The file to which AWS CloudFormation outputs from deployed stacks will be written (in JSON format).</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong class="command">--outputs-file</strong></p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>pathMetadata</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">If <code>false</code>, CDK path metadata is not added to synthesized templates.</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong class="command">--no-path-metadata</strong></p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>plugin</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">JSON array specifying the package names or local paths of packages that extend the CDK</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong class="command">--plugin</strong></p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>profile</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Name of the default AWS profile used for specifying Region and account credentials.</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong class="command">--profile</strong></p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>progress</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">If set to <code>"events"</code>, the CDK <code class="noloc">CLI</code> displays all AWS CloudFormation events during deployment, rather than a progress bar.</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong class="command">--progress</strong></p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>requireApproval</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Default approval level for security changes. See <a href="#cli-security">Approve security-related changes</a></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong class="command">--require-approval</strong></p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>rollback</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">If <code>false</code>, failed deployments are not rolled back.</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong class="command">--no-rollback</strong></p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>staging</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">If <code>false</code>, assets are not copied to the output directory (use for local debugging of the source files with AWS SAM).</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong class="command">--no-staging</strong></p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>tags</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">JSON object containing tags (key-value pairs) for the stack.</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong class="command">--tags</strong></p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>toolkitBucketName</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">The name of the Amazon S3 bucket used for deploying assets such as Lambda functions and container images (see <a href="#cli-bootstrap">Bootstrap your AWS environment</a>.</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong class="command">--toolkit-bucket-name</strong></p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>toolkitStackName</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">The name of the bootstrap stack (see <a href="#cli-bootstrap">Bootstrap your AWS environment</a>.</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong class="command">--toolkit-stack-name</strong></p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>versionReporting</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">If <code>false</code>, opts out of version reporting.</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong class="command">--no-version-reporting</strong></p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock"><code>watch</code></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">JSON object containing <code>"include"</code> and <code>"exclude"</code> keys that indicate which files should (or should not) trigger a rebuild of the project when changed. See <a href="#cli-deploy-watch">Watch mode</a>.</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock"><strong class="command">--watch</strong></p></td> -</tr> -</tbody> -</table> -</div> -</div> -</div> -<div class="sect1 topic"> -<h2 id="ref-cli-cmd">18. AWS CDK <code class="noloc">CLI</code> command reference</h2> -<div class="sectionbody"> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>This section contains command reference information for the AWS Cloud Development Kit (AWS CDK) Command Line Interface (<code class="noloc">CLI</code>). The CDK <code class="noloc">CLI</code> is also referred to as the CDK Toolkit.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>This section contains command reference information for the AWS Cloud Development Kit (AWS CDK) Command Line Interface (<code class="noloc">CLI</code>). The CDK <code class="noloc">CLI</code> is also referred to as the CDK Toolkit.</p> -</div> -<div class="sect2"> -<h3 id="ref-cli-cmd-usage">18.1. Usage</h3> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk <command> <arguments> <options></code></pre> -</div> -</div> -</div> -<div class="sect2"> -<h3 id="ref-cli-cmd-commands">18.2. Commands</h3> -<div id="ref-cli-cmd-commands-acknowledge" class="dlist"> -<dl> -<dt class="hdlist1"><code><a href="#ref-cli-cmd-ack">acknowledge ack</a></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Acknowledge a notice by issue number and hide it from displaying again.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-commands-bootstrap" class="dlist"> -<dl> -<dt class="hdlist1"><code><a href="#ref-cli-cmd-bootstrap">bootstrap</a></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Prepare an AWS environment for CDK deployments by deploying the CDK bootstrap stack, named <code class="path">CDKToolkit</code>, into the AWS environment.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-commands-context" class="dlist"> -<dl> -<dt class="hdlist1"><code><a href="#ref-cli-cmd-context">context</a></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Manage cached context values for your CDK application.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-commands-deploy" class="dlist"> -<dl> -<dt class="hdlist1"><code><a href="#ref-cli-cmd-deploy">deploy</a></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Deploy one or more CDK stacks into your AWS environment.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-commands-destroy" class="dlist"> -<dl> -<dt class="hdlist1"><code><a href="#ref-cli-cmd-destroy">destroy</a></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Delete one or more CDK stacks from your AWS environment.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-commands-diff" class="dlist"> -<dl> -<dt class="hdlist1"><code><a href="#ref-cli-cmd-diff">diff</a></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Perform a diff to see infrastructure changes between CDK stacks.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-commands-docs" class="dlist"> -<dl> -<dt class="hdlist1"><code><a href="#ref-cli-cmd-docs">docs doc</a></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Open CDK documentation in your browser.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-commands-doctor" class="dlist"> -<dl> -<dt class="hdlist1"><code><a href="#ref-cli-cmd-doctor">doctor</a></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Inspect and display useful information about your local CDK project and development environment.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-commands-import" class="dlist"> -<dl> -<dt class="hdlist1"><code><a href="#ref-cli-cmd-import">import</a></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Use AWS CloudFormation resource imports to import existing AWS resources into a CDK stack.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-commands-init" class="dlist"> -<dl> -<dt class="hdlist1"><code><a href="#ref-cli-cmd-init">init</a></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Create a new CDK project from a template.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-commands-list" class="dlist"> -<dl> -<dt class="hdlist1"><code><a href="#ref-cli-cmd-list">list ls</a></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>List all CDK stacks and their dependencies from a CDK app.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-commands-metadata" class="dlist"> -<dl> -<dt class="hdlist1"><code><a href="#ref-cli-cmd-metadata">metadata</a></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Display metadata associated with a CDK stack.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-commands-migrate" class="dlist"> -<dl> -<dt class="hdlist1"><code><a href="#ref-cli-cdk-migrate">migrate</a></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Migrate AWS resources, AWS CloudFormation stacks, and AWS CloudFormation templates into a new CDK project.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-commands-notices" class="dlist"> -<dl> -<dt class="hdlist1"><code><a href="#ref-cli-cmd-notices">notices</a></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Display notices for your CDK application.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-commands-synthesize" class="dlist"> -<dl> -<dt class="hdlist1"><code><a href="#ref-cli-cmd-synth">synthesize synth</a></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Synthesize a CDK app to produce a cloud assembly, including an AWS CloudFormation template for each stack.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-commands-watch" class="dlist"> -<dl> -<dt class="hdlist1"><code><a href="#ref-cli-cmd-watch">watch</a></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Continuously watch a local CDK project for changes to perform deployments and hotswaps.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect2"> -<h3 id="ref-cli-cmd-options">18.3. Global options</h3> -<div class="paragraph"> -<p>The following options are compatible with all CDK <code class="noloc">CLI</code> commands.</p> -</div> -<div id="ref-cli-cmd-options-app" class="dlist"> -<dl> -<dt class="hdlist1"><code>--app, -a <code class="replaceable">STRING</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Provide the command for running your app or cloud assembly directory.</p> -<div class="paragraph"> -<p><em>Required</em>: Yes</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-options-asset-metadata" class="dlist"> -<dl> -<dt class="hdlist1"><code>--asset-metadata <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Include <code>aws:asset:*</code> AWS CloudFormation metadata for resources that use assets.</p> -<div class="paragraph"> -<p><em>Required</em>: No</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>true</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-options-build" class="dlist"> -<dl> -<dt class="hdlist1"><code>--build <code class="replaceable">STRING</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Command for running a pre-synthesis build.</p> -<div class="paragraph"> -<p><em>Required</em>: No</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-options-ca-bundle-path" class="dlist"> -<dl> -<dt class="hdlist1"><code>--ca-bundle-path <code class="replaceable">STRING</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Path to a CA certificate to use when validating HTTPS requests.</p> -<div class="paragraph"> -<p>If this option is not provided, the CDK <code class="noloc">CLI</code> will read from the <code>AWS_CA_BUNDLE</code> environment variable.</p> -</div> -<div class="paragraph"> -<p><em>Required</em>: Yes</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-options-ci" class="dlist"> -<dl> -<dt class="hdlist1"><code>--ci <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Indicate that CDK <code class="noloc">CLI</code> commands are being run in a continuous integration (CI) environment.</p> -<div class="paragraph"> -<p>This option modifies the behavior of the CDK <code class="noloc">CLI</code> to better suit automated operations that are typical in CI pipelines.</p> -</div> -<div class="paragraph"> -<p>When you provide this option, logs are sent to <code>stdout</code> instead of <code>stderr</code>.</p> -</div> -<div class="paragraph"> -<p><em>Required</em>: No</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>false</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-options-context" class="dlist"> -<dl> -<dt class="hdlist1"><code>--context, -c <code class="replaceable">ARRAY</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Add contextual string parameters as key-value pairs.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-options-debug" class="dlist"> -<dl> -<dt class="hdlist1"><code>--debug <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Enable detailed debugging information. This option produces a verbose output that includes a lot more detail about what the CDK <code class="noloc">CLI</code> is doing behind the scenes.</p> -<div class="paragraph"> -<p><em>Required</em>: No</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>false</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-options-ec2creds" class="dlist"> -<dl> -<dt class="hdlist1"><code>--ec2creds, -i <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Force the CDK <code class="noloc">CLI</code> to try and fetch Amazon EC2 instance credentials.</p> -<div class="paragraph"> -<p>By default, the CDK <code class="noloc">CLI</code> guesses the Amazon EC2 instance status.</p> -</div> -<div class="paragraph"> -<p><em>Required</em>: No</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>false</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-options-help" class="dlist"> -<dl> -<dt class="hdlist1"><code>--help, -h <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Show command reference information for the CDK <code class="noloc">CLI</code>.</p> -<div class="paragraph"> -<p><em>Required</em>: No</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>false</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-options-ignore-errors" class="dlist"> -<dl> -<dt class="hdlist1"><code>--ignore-errors <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Ignore synthesis errors, which will likely produce an output that is not valid.</p> -<div class="paragraph"> -<p><em>Required</em>: No</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>false</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-options-json" class="dlist"> -<dl> -<dt class="hdlist1"><code>--json, -j <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Use JSON instead of YAML for AWS CloudFormation templates that are printed to standard output (<code>stdout</code>).</p> -<div class="paragraph"> -<p><em>Required</em>: No</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>false</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-options-lookups" class="dlist"> -<dl> -<dt class="hdlist1"><code>--lookups <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Perform context lookups.</p> -<div class="paragraph"> -<p>Synthesis will fail if this value is <code>false</code> and context lookups need to be performed.</p> -</div> -<div class="paragraph"> -<p><em>Required</em>: No</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>true</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-options-no-color" class="dlist"> -<dl> -<dt class="hdlist1"><code>--no-color <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Remove color and other styling from the console output.</p> -<div class="paragraph"> -<p><em>Required</em>: No</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>false</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-options-notices" class="dlist"> -<dl> -<dt class="hdlist1"><code>--notices <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Show relevant notices.</p> -<div class="paragraph"> -<p><em>Required</em>: No</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>false</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-options-output" class="dlist"> -<dl> -<dt class="hdlist1"><code>--output, -o <code class="replaceable">STRING</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Specify the directory to output the synthesized cloud assembly to.</p> -<div class="paragraph"> -<p><em>Required</em>: Yes</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code class="path">cdk.out</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-options-path-metadata" class="dlist"> -<dl> -<dt class="hdlist1"><code>--path-metadata <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Include <code>aws::cdk::path</code> AWS CloudFormation metadata for each resource.</p> -<div class="paragraph"> -<p><em>Required</em>: No</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>true</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-options-plugin" class="dlist"> -<dl> -<dt class="hdlist1"><code>--plugin, -p <code class="replaceable">ARRAY</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Name or path of a <code class="noloc">node</code> package that extends CDK features. This option can be provided multiple times in a single command.</p> -<div class="paragraph"> -<p>You can configure this option in the project’s <code class="path">cdk.json</code> file or at <code class="path">~/.cdk.json</code> on your local development machine:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-json" data-lang="json">{ - // ... - "plugin": [ - "module_1", - "module_2" - ], - // ... -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p><em>Required</em>: No</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-options-profile" class="dlist"> -<dl> -<dt class="hdlist1"><code>--profile <code class="replaceable">STRING</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Specify the name of the AWS profile, containing your AWS environment information, to use with the CDK <code class="noloc">CLI</code>.</p> -<div class="paragraph"> -<p><em>Required</em>: Yes</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-options-proxy" class="dlist"> -<dl> -<dt class="hdlist1"><code>--proxy <code class="replaceable">STRING</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Use the indicated proxy.</p> -<div class="paragraph"> -<p>If this option is not provided, the CDK <code class="noloc">CLI</code> will read from the <code>HTTPS_PROXY</code> environment variable.</p> -</div> -<div class="paragraph"> -<p><em>Required</em>: Yes</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: Read from <code>HTTPS_PROXY</code> environment variable.</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-options-role-arn" class="dlist"> -<dl> -<dt class="hdlist1"><code>--role-arn, -r <code class="replaceable">STRING</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The ARN of the IAM role that the CDK <code class="noloc">CLI</code> will assume when interacting with AWS CloudFormation.</p> -<div class="paragraph"> -<p><em>Required</em>: No</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-options-staging" class="dlist"> -<dl> -<dt class="hdlist1"><code>--staging <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Copy assets to the output directory.</p> -<div class="paragraph"> -<p>Specify <code>false</code> to prevent the copying of assets to the output directory. This allows the AWS SAM <code class="noloc">CLI</code> to reference the original source files when performing local debugging.</p> -</div> -<div class="paragraph"> -<p><em>Required</em>: No</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>true</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-options-strict" class="dlist"> -<dl> -<dt class="hdlist1"><code>--strict <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Do not construct stacks that contain warnings.</p> -<div class="paragraph"> -<p><em>Required</em>: No</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>false</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-options-trace" class="dlist"> -<dl> -<dt class="hdlist1"><code>--trace <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Print trace for stack warnings.</p> -<div class="paragraph"> -<p><em>Required</em>: No</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>false</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-options-verbose" class="dlist"> -<dl> -<dt class="hdlist1"><code>--verbose, -v <code class="replaceable">COUNT</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Show debug logs. You can specify this option multiple times to increase verbosity.</p> -<div class="paragraph"> -<p><em>Required</em>: No</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-options-version" class="dlist"> -<dl> -<dt class="hdlist1"><code>--version <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Show the CDK <code class="noloc">CLI</code> version number.</p> -<div class="paragraph"> -<p><em>Required</em>: No</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>false</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-options-version-reporting" class="dlist"> -<dl> -<dt class="hdlist1"><code>--version-reporting <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Include the <code>AWS::CDK::Metadata</code> resource in synthesized AWS CloudFormation templates.</p> -<div class="paragraph"> -<p><em>Required</em>: No</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>true</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect2"> -<h3 id="ref-cli-cmd-configure">18.4. Providing and configuring options</h3> -<div class="paragraph"> -<p>You can pass options through command-line arguments. For most options, you can configure them in a <code class="path">cdk.json</code> configuration file. When you use multiple configuration sources, the CDK <code class="noloc">CLI</code> adheres to the following precedence:</p> -</div> -<div class="olist arabic"> -<ol class="arabic"> -<li> -<p><strong>Command-line values</strong> – Any option provided at the command-line overrides options configured in <code class="path">cdk.json</code> files.</p> -</li> -<li> -<p><strong>Project configuration file</strong> – The <code class="path">cdk.json</code> file in your CDK project’s directory.</p> -</li> -<li> -<p><strong>User configuration file</strong> – The <code class="path">cdk.json</code> file located at <code class="path">~/.cdk.json</code> on your local machine.</p> -</li> -</ol> -</div> -</div> -<div class="sect2"> -<h3 id="ref-cli-cmd-pass">18.5. Passing options at the command line</h3> -<div class="sect3"> -<h4 id="ref-cli-cmd-pass-bool">18.5.1. Passing boolean values</h4> -<div class="paragraph"> -<p>For options that accept a boolean value, you can specify them in the following ways:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Use <code>true</code> and <code>false</code> values – Provide the boolean value with the command. The following is an example:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk deploy --watch=true -$ cdk deploy --watch=false</code></pre> -</div> -</div> -</li> -<li> -<p>Provide the option’s counterpart – Modify the option name by adding <code>no</code> to specify a <code>false</code> value. The following is an example:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk deploy --watch -$ cdk deploy --no-watch</code></pre> -</div> -</div> -</li> -<li> -<p>For options that default to <code>true</code> or <code>false</code>, you don’t have to provide the option unless you want to change from the default.</p> -</li> -</ul> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="ref-cli-cmd-ack">18.6. <code class="noloc">cdk acknowledge</code></h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Acknowledge a notice by issue number and hide it from displaying again.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>Acknowledge a notice by issue number and hide it from displaying again.</p> -</div> -<div class="paragraph"> -<p>This is useful to hide notices that have been addressed or do not apply to you.</p> -</div> -<div class="paragraph"> -<p>Acknowledgements are saved at a CDK project level. If you acknowledge a notice in one CDK project, it will still display in other projects until acknowledged there.</p> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-ack-usage">18.6.1. Usage</h4> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk acknowledge <arguments> <options></code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-ack-args">18.6.2. Arguments</h4> -<div id="ref-cli-cmd-ack-args-notice-id" class="dlist"> -<dl> -<dt class="hdlist1">Notice ID</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The ID of the notice.</p> -<div class="paragraph"> -<p><em>Type</em>: String</p> -</div> -<div class="paragraph"> -<p><em>Required</em>: No</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-ack-options">18.6.3. Options</h4> -<div class="paragraph"> -<p>For a list of global options that work with all CDK <code class="noloc">CLI</code> commands, see <a href="#ref-cli-cmd-options">Global options</a>.</p> -</div> -<div id="ref-cli-cmd-ack-options-help" class="dlist"> -<dl> -<dt class="hdlist1"><code>--help, -h <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Show command reference information for the <code>cdk acknowledge</code> command.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-ack-examples">18.6.4. Examples</h4> -<div class="sect4"> -<h5 id="ref-cli-cmd-ack-examples-1">Acknowledge and hide a notice that displays when running another CDK <code class="noloc">CLI</code> command</h5> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk deploy -... # Normal output of the command - -NOTICES - -16603 Toggling off auto_delete_objects for Bucket empties the bucket - - Overview: If a stack is deployed with an S3 bucket with - auto_delete_objects=True, and then re-deployed with - auto_delete_objects=False, all the objects in the bucket - will be deleted. - - Affected versions: <1.126.0. - - More information at: https://github.com/aws/aws-cdk/issues/16603 - - -17061 Error when building EKS cluster with monocdk import - - Overview: When using monocdk/aws-eks to build a stack containing - an EKS cluster, error is thrown about missing - lambda-layer-node-proxy-agent/layer/package.json. - - Affected versions: >=1.126.0 <=1.130.0. - - More information at: https://github.com/aws/aws-cdk/issues/17061 - -$ cdk acknowledge 16603</code></pre> -</div> -</div> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="ref-cli-cmd-bootstrap">18.7. <code class="noloc">cdk bootstrap</code></h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Prepare an AWS environment for CDK deployments by deploying the CDK bootstrap stack, named <code class="path">CDKToolkit</code>, into the AWS environment.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>Prepare an AWS environment for CDK deployments by deploying the CDK bootstrap stack, named <code class="path">CDKToolkit</code>, into the AWS environment.</p> -</div> -<div class="paragraph"> -<p>The bootstrap stack is a CloudFormation stack that provisions an Amazon S3 bucket and Amazon ECR repository in the AWS environment. The AWS CDK <code class="noloc">CLI</code> uses these resources to store synthesized templates and related assets during deployment.</p> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-bootstrap-usage">18.7.1. Usage</h4> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk bootstrap <arguments> <options></code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-bootstrap-args">18.7.2. Arguments</h4> -<div id="ref-cli-cmd-bootstrap-args-env" class="dlist"> -<dl> -<dt class="hdlist1">AWS environment</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The target AWS environment to deploy the bootstrap stack to in the following format: <code>aws://<account-id>/<region></code>.</p> -<div class="paragraph"> -<p>Example: <code>aws://123456789012/us-east-1</code></p> -</div> -<div class="paragraph"> -<p>This argument can be provided multiple times in a single command to deploy the bootstrap stack to multiple environments.</p> -</div> -<div class="paragraph"> -<p>By default, the CDK <code class="noloc">CLI</code> will bootstrap all environments referenced in the CDK app or will determine an environment from default sources. This could be an environment specified using the <code>--profile</code> option, from environment variables, or default AWS CLI sources.</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-bootstrap-options">18.7.3. Options</h4> -<div class="paragraph"> -<p>For a list of global options that work with all CDK <code class="noloc">CLI</code> commands, see <a href="#ref-cli-cmd-options">Global options</a>.</p> -</div> -<div id="ref-cli-cmd-bootstrap-options-bootstrap-bucket-name" class="dlist"> -<dl> -<dt class="hdlist1"><code>--bootstrap-bucket-name, --toolkit-bucket-name, -b <code class="replaceable">STRING</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The name of the Amazon S3 bucket that will be used by the CDK <code class="noloc">CLI</code>. This bucket will be created and must not currently exist.</p> -<div class="paragraph"> -<p>Provide this option to override the default name of the Amazon S3 bucket.</p> -</div> -<div class="paragraph"> -<p>When you use this option, you may have to customize synthesis. To learn more, see <a href="#bootstrapping-custom-synth">Customize CDK stack synthesis</a>.</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: Undefined</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-bootstrap-options-bootstrap-customer-key" class="dlist"> -<dl> -<dt class="hdlist1"><code>--bootstrap-customer-key <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Create a Customer Master Key (CMK) for the bootstrap bucket (you will be charged but can customize permissions, modern bootstrapping only).</p> -<div class="paragraph"> -<p>This option is not compatible with <code>--bootstrap-kms-key-id</code>.</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: Undefined</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-bootstrap-options-bootstrap-kms-key-id" class="dlist"> -<dl> -<dt class="hdlist1"><code>--bootstrap-kms-key-id <code class="replaceable">STRING</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The AWS KMS master key ID to use for the <code class="noloc">SSE-KMS</code> encryption.</p> -<div class="paragraph"> -<p>Provide this option to override the default AWS KMS key used to encrypt the Amazon S3 bucket.</p> -</div> -<div class="paragraph"> -<p>This option is not compatible with <code>--bootstrap-customer-key</code>.</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: Undefined</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-bootstrap-options-cloudformation-execution-policies" class="dlist"> -<dl> -<dt class="hdlist1"><code>--cloudformation-execution-policies <code class="replaceable">ARRAY</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The managed IAM policy ARNs that should be attached to the deployment role assumed by AWS CloudFormation during deployment of your stacks.</p> -<div class="paragraph"> -<p>By default, stacks are deployed with full administrator permissions using the <code>AdministratorAccess</code> policy.</p> -</div> -<div class="paragraph"> -<p>You can provide this option multiple times in a single command. You can also provide multiple ARNs as a single string, with the individual ARNs separated by commas. The following is an example:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk bootstrap --cloudformation-execution-policies "arn:aws:iam::aws:policy/AWSLambda_FullAccess,arn:aws:iam::aws:policy/AWSCodeDeployFullAccess"</code></pre> -</div> -</div> -<div class="paragraph"> -<p>To avoid deployment failures, be sure that the policies you specify are sufficient for any deployments that you will perform into the environment being bootstrapped.</p> -</div> -<div class="paragraph"> -<p>This option applies to modern bootstrapping only.</p> -</div> -<div class="admonitionblock important"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-important" title="Important"></i> -</td> -<td class="content"> -The modern bootstrap template effectively grants the permissions implied by the <code>--cloudformation-execution-policies</code> to any AWS account in the <code>--trust</code> list. By default, this extends permissions to read and write to any resource in the bootstrapped account. Make sure to <a href="#bootstrapping-customizing">configure the bootstrapping stack</a> with policies and trusted accounts that you are comfortable with. -</td> -</tr> -</table> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>[]</code></p> -</div> -<div id="ref-cli-cmd-bootstrap-options-custom-permissions-boundary" class="dlist"> -<dl> -<dt class="hdlist1"><code>--custom-permissions-boundary, -cpb <code class="replaceable">STRING</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Specify the name of a permissions boundary to use.</p> -<div class="paragraph"> -<p>This option is not compatible with <code>--example-permissions-boundary</code>.</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: Undefined</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-bootstrap-options-example-permissions-boundary" class="dlist"> -<dl> -<dt class="hdlist1"><code>--example-permissions-boundary, -epb <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Use the example permissions boundary, supplied by the AWS CDK.</p> -<div class="paragraph"> -<p>This option is not compatible with <code>--custom-permissions-boundary</code>.</p> -</div> -<div class="paragraph"> -<p>The CDK supplied permissions boundary policy should be regarded as an example. Edit the content and reference the example policy if you are testing out the feature. Convert it into a new policy for actual deployments, if one does not already exist. The concern is to avoid drift. Most likely, a permissions boundary is maintained and has dedicated conventions, naming included.</p> -</div> -<div class="paragraph"> -<p>For more information on configuring permissions, including using permissions boundaries, see the <a href="https://github.com/aws/aws-cdk/wiki/Security-And-Safety-Dev-Guide">Security and Safety Dev Guide</a>.</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: Undefined</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-bootstrap-options-execute" class="dlist"> -<dl> -<dt class="hdlist1"><code>--execute <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Configure whether to execute the change set.</p> -<div class="paragraph"> -<p><em>Default value</em>: <code>true</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-bootstrap-options-force" class="dlist"> -<dl> -<dt class="hdlist1"><code>--force, -f <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Always bootstrap, even if it would downgrade the bootstrap template version.</p> -<div class="paragraph"> -<p><em>Default value</em>: <code>false</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-bootstrap-options-help" class="dlist"> -<dl> -<dt class="hdlist1"><code>--help, -h <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Show command reference information for the <code>cdk bootstrap</code> command.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-bootstrap-options-previous-parameters" class="dlist"> -<dl> -<dt class="hdlist1"><code>--previous-parameters <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Use previous values for existing parameters.</p> -<div class="paragraph"> -<p>Once a bootstrap template is deployed with a set of parameters, you must set this option to <code>false</code> to change any parameters on future deployments. When <code>false</code>, you must re-supply all previously supplied parameters.</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>true</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-bootstrap-options-public-access-block-configuration" class="dlist"> -<dl> -<dt class="hdlist1"><code>--public-access-block-configuration <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Block public access configuration on the Amazon S3 bucket that is created and used by the CDK <code class="noloc">CLI</code>.</p> -<div class="paragraph"> -<p><em>Default value</em>: <code>true</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-bootstrap-options-qualifier" class="dlist"> -<dl> -<dt class="hdlist1"><code>--qualifier <code class="replaceable">STRING</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Nine-digit string value that is unique for each bootstrap stack. This value is added to the physical ID of resources in the bootstrap stack.</p> -<div class="paragraph"> -<p>By providing a qualifier, you avoid resource name clashes when provisioning multiple bootstrap stacks in the same environment.</p> -</div> -<div class="paragraph"> -<p>When you change the qualifier, your CDK app must pass the changed value to the stack synthesizer. For more information, see <a href="#bootstrapping-custom-synth">Customize CDK stack synthesis</a>.</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>hnb659fds</code>. This value has no significance.</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-bootstrap-options-show-template" class="dlist"> -<dl> -<dt class="hdlist1"><code>--show-template <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Instead of bootstrapping, print the current bootstrap template to the standard output (<code>stdout</code>). You can then copy and customize the template as necessary.</p> -<div class="paragraph"> -<p><em>Default value</em>: <code>false</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-bootstrap-options-tags" class="dlist"> -<dl> -<dt class="hdlist1"><code>--tags, -t <code class="replaceable">ARRAY</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Tags to add to the bootstrap stack in the format of <code>KEY=VALUE</code>.</p> -<div class="paragraph"> -<p><em>Default value</em>: <code>[]</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-bootstrap-options-template" class="dlist"> -<dl> -<dt class="hdlist1"><code>--template <code class="replaceable">STRING</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Use the template from the given file instead of the built-in one.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-bootstrap-options-termination-protection" class="dlist"> -<dl> -<dt class="hdlist1"><code>--termination-protection <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Toggle AWS CloudFormation termination protection on the bootstrap stack.</p> -<div class="paragraph"> -<p>When <code>true</code>, termination protection is enabled. This prevents the bootstrap stack from being accidentally deleted.</p> -</div> -<div class="paragraph"> -<p>To learn more about termination protection, see <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-protect-stacks.html">Protecting a stack from being deleted</a> in the <em>AWS CloudFormation User Guide</em>.</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: Undefined</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-bootstrap-options-toolkit-stack-name" class="dlist"> -<dl> -<dt class="hdlist1"><code>--toolkit-stack-name <code class="replaceable">STRING</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The name of the bootstrap stack to create.</p> -<div class="paragraph"> -<p>By default, <code>cdk bootstrap</code> deploys a stack named <code class="path">CDKToolkit</code> into the specified AWS environment. Use this option to provide a different name for your bootstrap stack.</p> -</div> -<div class="paragraph"> -<p>The CDK <code class="noloc">CLI</code> uses this value to verify your bootstrap stack version.</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>CDKToolkit</code></p> -</div> -<div class="paragraph"> -<p><em>Required</em>: Yes</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-bootstrap-options-trust" class="dlist"> -<dl> -<dt class="hdlist1"><code>--trust <code class="replaceable">ARRAY</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The AWS account IDs that should be trusted to perform deployments into this environment.</p> -<div class="paragraph"> -<p>The account performing the bootstrapping will always be trusted.</p> -</div> -<div class="paragraph"> -<p>This option requires that you also provide <code>--cloudformation-execution-policies</code>.</p> -</div> -<div class="paragraph"> -<p>You can provide this option multiple times in a single command.</p> -</div> -<div class="paragraph"> -<p>This option applies to modern bootstrapping only.</p> -</div> -<div class="paragraph"> -<p>To add trusted accounts to an existing bootstrap stack, you must specify all of the accounts to trust, including those that you may have previously provided. If you only provide new accounts to trust, the previously trusted accounts will be removed.</p> -</div> -<div class="paragraph"> -<p>The following is an example that trusts two accounts:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk bootstrap aws://123456789012/us-west-2 --trust 234567890123 --trust 987654321098 --cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess - ⏳ Bootstrapping environment aws://123456789012/us-west-2... -Trusted accounts for deployment: 234567890123, 987654321098 -Trusted accounts for lookup: (none) -Execution policies: arn:aws:iam::aws:policy/AdministratorAccess -CDKToolkit: creating CloudFormation changeset... - ✅ Environment aws://123456789012/us-west-2 bootstrapped.</code></pre> -</div> -</div> -<div class="admonitionblock important"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-important" title="Important"></i> -</td> -<td class="content"> -The modern bootstrap template effectively grants the permissions implied by the <code>--cloudformation-execution-policies</code> to any AWS account in the <code>--trust</code> list. By default, this extends permissions to read and write to any resource in the bootstrapped account. Make sure to <a href="#bootstrapping-customizing">configure the bootstrapping stack</a> with policies and trusted accounts that you are comfortable with. -</td> -</tr> -</table> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>[]</code></p> -</div> -<div id="ref-cli-cmd-bootstrap-options-trust-for-lookup" class="dlist"> -<dl> -<dt class="hdlist1"><code>--trust-for-lookup <code class="replaceable">ARRAY</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The AWS account IDs that should be trusted to look up values in this environment.</p> -<div class="paragraph"> -<p>Use this option to give accounts permission to synthesize stacks that will be deployed into the environment, without actually giving them permission to deploy those stacks directly.</p> -</div> -<div class="paragraph"> -<p>You can provide this option multiple times in a single command.</p> -</div> -<div class="paragraph"> -<p>This option applies to modern bootstrapping only.</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>[]</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-bootstrap-examples">18.7.4. Examples</h4> -<div class="sect4"> -<h5 id="ref-cli-cmd-bootstrap-examples-1">Bootstrap the AWS environment specified in the prod profile</h5> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk bootstrap --profile prod</code></pre> -</div> -</div> -</div> -<div class="sect4"> -<h5 id="ref-cli-cmd-bootstrap-examples-2">Deploy the bootstrap stack to environments foo and bar</h5> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk bootstrap --app='node bin/main.js' foo bar</code></pre> -</div> -</div> -</div> -<div class="sect4"> -<h5 id="ref-cli-cmd-bootstrap-examples-3">Export the bootstrap template to customize it</h5> -<div class="paragraph"> -<p>If you have specific requirements that are not met by the bootstrap template, you can customize it to fit your needs.</p> -</div> -<div class="paragraph"> -<p>You can export the bootstrap template, modify it, and deploy it using AWS CloudFormation. The following is an example of exporting the existing template:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk bootstrap --show-template > bootstrap-template.yaml</code></pre> -</div> -</div> -<div class="paragraph"> -<p>You can also tell the CDK <code class="noloc">CLI</code> to use a custom template. The following is an example:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk bootstrap --template my-bootstrap-template.yaml</code></pre> -</div> -</div> -</div> -<div class="sect4"> -<h5 id="ref-cli-cmd-bootstrap-examples-4">Bootstrap with a permissions boundary. Then, remove that permissions boundary</h5> -<div class="paragraph"> -<p>To bootstrap with a custom permissions boundary, we run the following:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk bootstrap --custom-permissions-boundary my-permissions-boundary</code></pre> -</div> -</div> -<div class="paragraph"> -<p>To remove the permissions boundary, we run the following:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk bootstrap --no-previous-parameters</code></pre> -</div> -</div> -</div> -<div class="sect4"> -<h5 id="ref-cli-cmd-bootstrap-examples-5">Use a qualifier to distinguish resources that are created for a development environment</h5> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk bootstrap --qualifier dev2024</code></pre> -</div> -</div> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="ref-cli-cmd-context">18.8. <code class="noloc">cdk context</code></h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Manage cached context values for your AWS CDK application.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>Manage cached context values for your AWS CDK application.</p> -</div> -<div class="paragraph"> -<p><em>Context</em> represents the configuration and environment information that can influence how your stacks are synthesized and deployed. Use <code>cdk context</code> to do the following:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>View your configured context values.</p> -</li> -<li> -<p>Set and manage context values.</p> -</li> -<li> -<p>Remove context values.</p> -</li> -</ul> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-context-usage">18.8.1. Usage</h4> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk context <options></code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-context-options">18.8.2. Options</h4> -<div class="paragraph"> -<p>For a list of global options that work with all CDK <code class="noloc">CLI</code> commands, see <a href="#ref-cli-cmd-options">Global options</a>.</p> -</div> -<div id="ref-cli-cmd-context-options-clear" class="dlist"> -<dl> -<dt class="hdlist1"><code>--clear <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Clear all context.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-context-options-force" class="dlist"> -<dl> -<dt class="hdlist1"><code>--force, -f <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Ignore missing key error.</p> -<div class="paragraph"> -<p><em>Default value</em>: <code>false</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-context-options-help" class="dlist"> -<dl> -<dt class="hdlist1"><code>--help, -h <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Show command reference information for the <code>cdk context</code> command.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-context-options-reset" class="dlist"> -<dl> -<dt class="hdlist1"><code>--reset, -e <code class="replaceable">STRING</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The context key, or its index, to reset.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="ref-cli-cmd-deploy">18.9. <code class="noloc">cdk deploy</code></h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Deploy one or more AWS CDK stacks into your AWS environment.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>Deploy one or more AWS CDK stacks into your AWS environment.</p> -</div> -<div class="paragraph"> -<p>During deployment, the CDK <code class="noloc">CLI</code> will output progress indicators, similar to what can be observed from the AWS CloudFormation console.</p> -</div> -<div class="paragraph"> -<p>If the AWS environment is not bootstrapped, only stacks without assets and with synthesized templates under 51,200 bytes will successfully deploy.</p> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-deploy-usage">18.9.1. Usage</h4> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk deploy <arguments> <options></code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-deploy-args">18.9.2. Arguments</h4> -<div id="ref-cli-cmd-deploy-args-stack-name" class="dlist"> -<dl> -<dt class="hdlist1">CDK stack ID</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The construct ID of the CDK stack from your app to deploy.</p> -<div class="paragraph"> -<p><em>Type</em>: String</p> -</div> -<div class="paragraph"> -<p><em>Required</em>: No</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-deploy-options">18.9.3. Options</h4> -<div class="paragraph"> -<p>For a list of global options that work with all CDK <code class="noloc">CLI</code> commands, see <a href="#ref-cli-cmd-options">Global options</a>.</p> -</div> -<div id="ref-cli-cmd-deploy-options-all" class="dlist"> -<dl> -<dt class="hdlist1"><code>--all <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Deploy all stacks in your CDK app.</p> -<div class="paragraph"> -<p><em>Default value</em>: <code>false</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-deploy-options-asset-parallelism" class="dlist"> -<dl> -<dt class="hdlist1"><code>--asset-parallelism <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Specify whether to build and publish assets in parallel.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-deploy-options-asset-prebuild" class="dlist"> -<dl> -<dt class="hdlist1"><code>--asset-prebuild <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Specify whether to build all assets before deploying the first stack. This option is useful for failing <code class="noloc">Docker</code> builds.</p> -<div class="paragraph"> -<p><em>Default value</em>: <code>true</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-deploy-options-build-exclude" class="dlist"> -<dl> -<dt class="hdlist1"><code>--build-exclude, -E <code class="replaceable">ARRAY</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Do not rebuild asset with the given ID.</p> -<div class="paragraph"> -<p>This option can be specified multiple times in a single command.</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>[]</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-deploy-options-change-set-name" class="dlist"> -<dl> -<dt class="hdlist1"><code>--change-set-name <code class="replaceable">STRING</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The name of the AWS CloudFormation change set to create.</p> -<div class="paragraph"> -<p>This option is not compatible with <code>--method='direct'</code>.</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-deploy-options-concurrency" class="dlist"> -<dl> -<dt class="hdlist1"><code>--concurrency <code class="replaceable">NUMBER</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Deploy multiple stacks in parallel while accounting for inter-stack dependencies. Use this option to speed up deployments. You must still factor in AWS CloudFormation and other AWS account rate limiting.</p> -<div class="paragraph"> -<p>Provide a number to specify the maximum number of simultaneous deployments (dependency permitting) to perform.</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>1</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-deploy-options-exclusively" class="dlist"> -<dl> -<dt class="hdlist1"><code>--exclusively, -e <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Only deploy requested stacks and don’t include dependencies.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-deploy-options-force" class="dlist"> -<dl> -<dt class="hdlist1"><code>--force, -f <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>When you deploy to update an existing stack, the CDK <code class="noloc">CLI</code> will compare the template and tags of the deployed stack to the stack about to be deployed. If no changes are detected, the CDK <code class="noloc">CLI</code> will skip deployment.</p> -<div class="paragraph"> -<p>To override this behavior and always deploy stacks, even if no changes are detected, use this option.</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>false</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-deploy-options-help" class="dlist"> -<dl> -<dt class="hdlist1"><code>--help, -h <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Show command reference information for the <code>cdk deploy</code> command.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-deploy-options-hotswap" class="dlist"> -<dl> -<dt class="hdlist1"><code>--hotswap <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Hotswap deployments for faster development. This option attempts to perform a faster, hotswap deployment if possible. For example, if you modify the code of a Lambda function in your CDK app, the CDK <code class="noloc">CLI</code> will update the resource directly through service APIs instead of performing a CloudFormation deployment.</p> -<div class="paragraph"> -<p>If the CDK <code class="noloc">CLI</code> detects changes that don’t support hotswapping, those changes will be ignored and a message will display. If you prefer to perform a full CloudFormation deployment as a fall back, use <code>--hotswap-fallback</code> instead.</p> -</div> -<div class="paragraph"> -<p>The CDK <code class="noloc">CLI</code> uses your current AWS credentials to perform the API calls. It does not assume the roles from your bootstrap stack, even if the <code>@aws-cdk/core:newStyleStackSynthesis</code> feature flag is set to <code>true</code>. Those roles do not have the necessary permissions to update AWS resources directly, without using CloudFormation. For that reason, make sure that your credentials are for the same AWS account of the stacks that you are performing hotswap deployments against and that they have the necessary IAM permissions to update the resources.</p> -</div> -<div class="paragraph"> -<p>Hotswapping is currently supported for the following changes:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Code assets (including <code class="noloc">Docker</code> images and inline code), tag changes, and configuration changes (only description and environment variables are supported) of Lambda functions.</p> -</li> -<li> -<p>Lambda versions and alias changes.</p> -</li> -<li> -<p>Definition changes of AWS Step Functions state machines.</p> -</li> -<li> -<p>Container asset changes of Amazon ECS services.</p> -</li> -<li> -<p>Website asset changes of Amazon S3 bucket deployments.</p> -</li> -<li> -<p>Source and environment changes of AWS CodeBuild projects.</p> -</li> -<li> -<p>VTL mapping template changes for AWS AppSync resolvers and functions.</p> -</li> -<li> -<p>Schema changes for AWS AppSync <code class="noloc">GraphQL</code> APIs.</p> -<div class="paragraph"> -<p>Usage of certain CloudFormation intrinsic functions are supported as part of a hotswapped deployment. These include:</p> -</div> -</li> -<li> -<p><code>Ref</code></p> -</li> -<li> -<p><code>Fn::GetAtt</code> – Only partially supported. Refer to <a href="https://github.com/aws/aws-cdk/blob/main/packages/aws-cdk/lib/api/evaluate-cloudformation-template.ts#L477-L492">this implementation</a> for supported resources and attributes.</p> -</li> -<li> -<p><code>Fn::ImportValue</code></p> -</li> -<li> -<p><code>Fn::Join</code></p> -</li> -<li> -<p><code>Fn::Select</code></p> -</li> -<li> -<p><code>Fn::Split</code></p> -</li> -<li> -<p><code>Fn::Sub</code></p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>This option is also compatible with nested stacks.</p> -</div> -<div class="paragraph"> -<p>+ -NOTE:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>This option deliberately introduces drift in CloudFormation stacks in order to speed up deployments. For this reason, only use it for development purposes. Do not use this option for your production deployments.</p> -</li> -<li> -<p>This option is considered experimental and may have breaking changes in the future.</p> -</li> -<li> -<p>Defaults for certain parameters may be different with the hotswap parameter. For example, an Amazon ECS service’s minimum healthy percentage will currently be set at <code>0</code>. Review the source accordingly if this occurs.</p> -</li> -</ul> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>false</code></p> -</div> -<div id="ref-cli-cmd-deploy-options-hotswap-fallback" class="dlist"> -<dl> -<dt class="hdlist1"><code>--hotswap-fallback <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>This option is is similar to <code>--hotswap</code>. The difference being that <code>--hotswap-fallback</code> will fall back to perform a full CloudFormation deployment if a change is detected that requires it.</p> -<div class="paragraph"> -<p>For more information about this option, see <code>--hotswap</code>.</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>false</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-deploy-options-ignore-no-stacks" class="dlist"> -<dl> -<dt class="hdlist1"><code>--ignore-no-stacks <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Perform a deployment even if your CDK app doesn’t contain any stacks.</p> -<div class="paragraph"> -<p>This option is helpful in the following scenario: You may have an app with multiple environments, such as <code>dev</code> and <code>prod</code>. When starting development, your prod app may not have any resources, or the resources may be commented out. This will result in a deployment error with a message stating that the app has no stacks. Use <code>--ignore-no-stacks</code> to bypass this error.</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>false</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-deploy-options-import-existing-resources" class="dlist"> -<dl> -<dt class="hdlist1"><code>--import-existing-resources <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Import existing, unmanaged AWS CloudFormation resources from your AWS account.</p> -<div class="paragraph"> -<p>When you use this option, resources from your synthesized AWS CloudFormation template with the same custom name as existing unmanaged resources in the same account will be imported into your stack.</p> -</div> -<div class="paragraph"> -<p>You can use this option to import existing resources into new or existing stacks.</p> -</div> -<div class="paragraph"> -<p>You can import existing resources and deploy new resources in the same <code>cdk deploy</code> command.</p> -</div> -<div class="paragraph"> -<p>To learn more about custom names, see <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-name.html">Name type</a> in the <em>AWS CloudFormation User Guide</em>.</p> -</div> -<div class="paragraph"> -<p>To learn more about the <code>ImportExistingResources</code> CloudFormation parameter, see <a href="https://aws.amazon.com/about-aws/whats-new/2023/11/aws-cloudformation-import-parameter-changesets/">AWS CloudFormation simplifies resource import with a new parameter for ChangeSets</a>.</p> -</div> -<div class="paragraph"> -<p>For more information on using this option, see <a href="https://github.com/aws/aws-cdk-cli/tree/main/packages/aws-cdk#import-existing-resources">Import existing resources</a> in the <em>aws-cdk-cli <code class="noloc">GitHub</code> repository</em>.</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-deploy-options-logs" class="dlist"> -<dl> -<dt class="hdlist1"><code>--logs <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Show Amazon CloudWatch log in the standard output (<code>stdout</code>) for all events from all resources in the selected stacks.</p> -<div class="paragraph"> -<p>This option is only compatible with <code>--watch</code>.</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>true</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-deploy-options-method" class="dlist"> -<dl> -<dt class="hdlist1"><code>--method, -m <code class="replaceable">STRING</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Configure the method to perform a deployment.</p> -<div class="ulist"> -<ul> -<li> -<p><code>change-set</code> – Default method. The CDK <code class="noloc">CLI</code> creates a CloudFormation change set with the changes that will be deployed, then performs deployment.</p> -</li> -<li> -<p><code>direct</code> – Do not create a change set. Instead, apply the change immediately. This is typically faster than creating a change set, but you lose progress information.</p> -</li> -<li> -<p><code>prepare-change-set</code> – Create change set but don’t perform deployment. This is useful if you have external tools that will inspect the change set or if you have an approval process for change sets.</p> -</li> -</ul> -</div> -</li> -</ul> -</div> -<div class="paragraph"> -<p><em>Valid values</em>: <code>change-set</code>, <code>direct</code>, <code>prepare-change-set</code></p> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>change-set</code></p> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-deploy-options-notification-arns" class="dlist"> -<dl> -<dt class="hdlist1"><code>--notification-arns <code class="replaceable">ARRAY</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The ARNs of Amazon SNS topics that CloudFormation will notify for stack related events.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-deploy-options-outputs-file" class="dlist"> -<dl> -<dt class="hdlist1"><code>--outputs-file, -O <code class="replaceable">STRING</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The path to where stack outputs from deployments are written to.</p> -<div class="paragraph"> -<p>After deployment, stack outputs will be written to the specified output file in JSON format.</p> -</div> -<div class="paragraph"> -<p>You can configure this option in the project’s <code class="path">cdk.json</code> file or at <code class="path">~/.cdk.json</code> on your local development machine:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-json" data-lang="json">{ - "app": "npx ts-node bin/myproject.ts", - // ... - "outputsFile": "outputs.json" -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>If multiple stacks are deployed, outputs are written to the same output file, organized by keys representing the stack name.</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-deploy-options-parameters" class="dlist"> -<dl> -<dt class="hdlist1"><code>--parameters <code class="replaceable">ARRAY</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Pass additional parameters to CloudFormation during deployment.</p> -<div class="paragraph"> -<p>This option accepts an array in the following format: <code>STACK:KEY=VALUE</code>.</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><code>STACK</code> – The name of the stack to associate the parameter with.</p> -</li> -<li> -<p><code>KEY</code> – The name of the parameter from your stack.</p> -</li> -<li> -<p><code>VALUE</code> – The value to pass at deployment.</p> -</li> -</ul> -</div> -</li> -</ul> -</div> -<div class="paragraph"> -<p>If a stack name is not provided, or if <code>\*</code> is provided as the stack name, parameters will be applied to all stacks being deployed. If a stack does not make use of the parameter, deployment will fail.</p> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p>Parameters do not propagate to nested stacks. To pass parameters to nested stacks, use the <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.NestedStack.html">NestedStack</a></code> construct.</p> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>{}</code></p> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-deploy-options-previous-parameters" class="dlist"> -<dl> -<dt class="hdlist1"><code>--previous-parameters <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Use previous values for existing parameters.</p> -<div class="paragraph"> -<p>When this option is set to <code>false</code>, you must specify all parameters on every deployment.</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>true</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-deploy-options-progress" class="dlist"> -<dl> -<dt class="hdlist1"><code>--progress <code class="replaceable">STRING</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Configure how the CDK <code class="noloc">CLI</code> displays deployment progress.</p> -<div class="ulist"> -<ul> -<li> -<p><code>bar</code> – Display stack deployment events as a progress bar, with the events for the resource currently being deployed.</p> -</li> -<li> -<p><code>events</code> – Provide a complete history, including all CloudFormation events.</p> -</li> -</ul> -</div> -</li> -</ul> -</div> -<div class="paragraph"> -<p>You can also configure this option in the project’s <code class="path">cdk.json</code> file or at <code class="path">~/.cdk.json</code> on your local development machine:</p> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-json" data-lang="json">{ - "progress": "events" -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p><em>Valid values</em>: <code>bar</code>, <code>events</code></p> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>bar</code></p> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-deploy-options-require-approval" class="dlist"> -<dl> -<dt class="hdlist1"><code>--require-approval <code class="replaceable">STRING</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Specify what security-sensitive changes require manual approval.</p> -<div class="ulist"> -<ul> -<li> -<p>`any-change ` – Manual approval required for any change to the stack.</p> -</li> -<li> -<p><code>broadening</code> – Manual approval required if changes involve a broadening of permissions or security group rules.</p> -</li> -<li> -<p><code>never</code> – Approval is not required.</p> -</li> -</ul> -</div> -</li> -</ul> -</div> -<div class="paragraph"> -<p><em>Valid values</em>: <code>any-change</code>, <code>broadening</code>, <code>never</code></p> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>broadening</code></p> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-deploy-options-rollback" class="dlist"> -<dl> -<dt class="hdlist1"><code>--rollback</code> | <code>--no-rollback</code>, <code>-R</code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>During deployment, if a resource fails to be created or updated, the deployment will roll back to the latest stable state before the CDK <code class="noloc">CLI</code> returns. All changes made up to that point will be undone. Resources that were created will be deleted and updates that were made will be rolled back.</p> -<div class="paragraph"> -<p>Specify <code>--no-rollback</code> to turn off this behavior. If a resource fails to be created or updated, the CDK <code class="noloc">CLI</code> will leave changes made up to that point in place and return. This will leave your deployment in a failed, paused state. From here, you can update your code and try the deployment again. This may be helpful in development environments where you are iterating quickly.</p> -</div> -<div class="paragraph"> -<p>If a deployment performed with <code>--no-rollback</code> fails, and you decide that you want to rollback the deployment, you can use the <code>cdk rollback</code> command. For more information, see <a href="#ref-cli-cmd-rollback">cdk rollback</a>.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -With <code>--no-rollback</code>, deployments that cause resource replacements will always fail. You can only use this option value for deployments that update or create new resources. -</td> -</tr> -</table> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>--rollback</code></p> -</div> -<div id="ref-cli-cmd-deploy-options-toolkit-stack-name" class="dlist"> -<dl> -<dt class="hdlist1"><code>--toolkit-stack-name <code class="replaceable">STRING</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The name of the existing CDK Toolkit stack.</p> -<div class="paragraph"> -<p>By default, <code>cdk bootstrap</code> deploys a stack named <code class="path">CDKToolkit</code> into the specified AWS environment. Use this option to provide a different name for your bootstrap stack.</p> -</div> -<div class="paragraph"> -<p>The CDK <code class="noloc">CLI</code> uses this value to verify your bootstrap stack version.</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-deploy-options-watch" class="dlist"> -<dl> -<dt class="hdlist1"><code>--watch <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Continuously observe CDK project files, and deploy the specified stacks automatically when changes are detected.</p> -<div class="paragraph"> -<p>This option implies <code>--hotswap</code> by default.</p> -</div> -<div class="paragraph"> -<p>This option has an equivalent CDK <code class="noloc">CLI</code> command. For more information, see <a href="#ref-cli-cmd-watch">cdk watch</a>.</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-deploy-examples">18.9.4. Examples</h4> -<div class="sect4"> -<h5 id="ref-cli-cmd-deploy-examples-1">Deploy the stack named MyStackName</h5> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk deploy MyStackName --app='node bin/main.js'</code></pre> -</div> -</div> -</div> -<div class="sect4"> -<h5 id="ref-cli-cmd-deploy-examples-2">Deploy multiple stacks in an app</h5> -<div class="paragraph"> -<p>Use <code>cdk list</code> to list your stacks:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk list -CdkHelloWorldStack -CdkStack2 -CdkStack3</code></pre> -</div> -</div> -<div class="paragraph"> -<p>To deploy all stacks, use the <code>--all</code> option:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk deploy --all</code></pre> -</div> -</div> -<div class="paragraph"> -<p>To choose which stacks to deploy, provide stack names as arguments:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk deploy CdkHelloWorldStack CdkStack3</code></pre> -</div> -</div> -</div> -<div class="sect4"> -<h5 id="ref-cli-cmd-deploy-examples-3">Deploy pipeline stacks</h5> -<div class="paragraph"> -<p>Use <code>cdk list</code> to show stack names as paths, showing where they are in the pipeline hierarchy:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk list -PipelineStack -PiplelineStack/Prod -PipelineStack/Prod/MyService</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Use the <code>--all</code> option or the wildcard <code>*</code> to deploy all stacks. If you have a hierarchy of stacks as described above, <code>--all</code> and <code>\*</code> will only match stacks on the top level. To match all stacks in the hierarchy, use <code>\**</code>.</p> -</div> -<div class="paragraph"> -<p>You can combine these patterns. The following deploys all stacks in the <code>Prod</code> stage:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk deploy PipelineStack/Prod/**</code></pre> -</div> -</div> -</div> -<div class="sect4"> -<h5 id="ref-cli-cmd-deploy-examples-4">Pass parameters at deployment</h5> -<div class="paragraph"> -<p>Define parameters in your CDK stack. The following is an example that creates a parameter named <code>TopicNameParam</code> for an Amazon SNS topic:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">new sns.Topic(this, 'TopicParameter', { - topicName: new cdk.CfnParameter(this, 'TopicNameParam').value.toString() -});</code></pre> -</div> -</div> -<div class="paragraph"> -<p>To provide a parameter value of <code>parameterized</code>, run the following:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk deploy --parameters "MyStackName:TopicNameParam=parameterized"</code></pre> -</div> -</div> -<div class="paragraph"> -<p>You can override parameter values by using the <code>--force</code> option. The following is an example of overriding the topic name from a previous deployment:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk deploy --parameters "MyStackName:TopicNameParam=parameterName" --force</code></pre> -</div> -</div> -</div> -<div class="sect4"> -<h5 id="ref-cli-cmd-deploy-examples-5">Write stack outputs to a file after deployment</h5> -<div class="paragraph"> -<p>Define outputs in your CDK stack file. The following is an example that creates an output for a function ARN:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const fn = new lambda.Function(this, "fn", { - handler: "index.handler", - code: lambda.Code.fromInline(`exports.handler = \${handler.toString()}`), - runtime: lambda.Runtime.NODEJS_LATEST -}); - -new cdk.CfnOutput(this, 'FunctionArn', { - value: fn.functionArn, -});</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Deploy the stack and write outputs to <code class="path">outputs.json</code>:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk deploy --outputs-file outputs.json</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The following is an example of <code class="path">outputs.json</code> after deployment:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-json" data-lang="json">{ - "MyStack": { - "FunctionArn": "arn:aws:lambda:us-east-1:123456789012:function:MyStack-fn5FF616E3-G632ITHSP5HK" - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>From this example, the key <code>FunctionArn</code> corresponds to the logical ID of the <code>CfnOutput</code> instance.</p> -</div> -<div class="paragraph"> -<p>The following is an example of <code class="path">outputs.json</code> after deployment when multiple stacks are deployed:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-json" data-lang="json">{ - "MyStack": { - "FunctionArn": "arn:aws:lambda:us-east-1:123456789012:function:MyStack-fn5FF616E3-G632ITHSP5HK" - }, - "AnotherStack": { - "VPCId": "vpc-z0mg270fee16693f" - } -}</code></pre> -</div> -</div> -</div> -<div class="sect4"> -<h5 id="ref-cli-cmd-deploy-examples-6">Modify the deployment method</h5> -<div class="paragraph"> -<p>To deploy faster, without using change sets, use <code>--method='direct'</code>:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk deploy --method='direct'</code></pre> -</div> -</div> -<div class="paragraph"> -<p>To create a change set but don’t deploy, use <code>--method='prepare-change-set'</code>. By default, a change set named <code>cdk-deploy-change-set</code> will be created. If a previous change set with this name exists, it will be overwritten. If no changes are detected, an empty change set is still created.</p> -</div> -<div class="paragraph"> -<p>You can also name your change set. The following is an example:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk deploy --method='prepare-change-set' --change-set-name='MyChangeSetName'</code></pre> -</div> -</div> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="ref-cli-cmd-destroy">18.10. <code class="noloc">cdk destroy</code></h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Delete one or more AWS CDK stacks from your AWS environment.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>Delete one or more AWS CDK stacks from your AWS environment.</p> -</div> -<div class="paragraph"> -<p>When you delete a stack, resources in the stack will be destroyed, unless they were configured with a <code>DeletionPolicy</code> of <code>Retain</code>.</p> -</div> -<div class="paragraph"> -<p>During stack deletion, this command will output progress information similar to <code>cdk deploy</code> behavior.</p> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-destroy-usage">18.10.1. Usage</h4> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk destroy <arguments> <options></code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-destroy-args">18.10.2. Arguments</h4> -<div id="ref-cli-cmd-destroy-args-stack-name" class="dlist"> -<dl> -<dt class="hdlist1">CDK stack ID</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The construct ID of the CDK stack from your app to delete.</p> -<div class="paragraph"> -<p><em>Type</em>: String</p> -</div> -<div class="paragraph"> -<p><em>Required</em>: No</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-destroy-options">18.10.3. Options</h4> -<div class="paragraph"> -<p>For a list of global options that work with all CDK <code class="noloc">CLI</code> commands, see <a href="#ref-cli-cmd-options">Global options</a>.</p> -</div> -<div id="ref-cli-cmd-destroy-options-all" class="dlist"> -<dl> -<dt class="hdlist1"><code>--all <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Destroy all available stacks.</p> -<div class="paragraph"> -<p><em>Default value</em>: <code>false</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-destroy-options-exclusively" class="dlist"> -<dl> -<dt class="hdlist1"><code>--exclusively, -e <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Only destroy requested stacks and don’t include dependencies.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-destroy-options-force" class="dlist"> -<dl> -<dt class="hdlist1"><code>--force, -f <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Do not ask for confirmation before destroying the stacks.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-destroy-options-help" class="dlist"> -<dl> -<dt class="hdlist1"><code>--help, -h <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Show command reference information for the <code>cdk destroy</code> command.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-destroy-examples">18.10.4. Examples</h4> -<div class="sect4"> -<h5 id="ref-cli-cmd-destroy-examples-1">Delete a stack named MyStackName</h5> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk destroy --app='node bin/main.js' MyStackName</code></pre> -</div> -</div> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="ref-cli-cmd-diff">18.11. <code class="noloc">cdk diff</code></h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Perform a diff to see infrastructure changes between AWS CDK stacks.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>Perform a diff to see infrastructure changes between AWS CDK stacks.</p> -</div> -<div class="paragraph"> -<p>This command is typically used to compare differences between the current state of stacks in your local CDK app against deployed stacks. However, you can also compare a deployed stack with any local AWS CloudFormation template.</p> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-diff-usage">18.11.1. Usage</h4> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk diff <arguments> <options></code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-diff-args">18.11.2. Arguments</h4> -<div id="ref-cli-cmd-diff-args-stack-name" class="dlist"> -<dl> -<dt class="hdlist1">CDK stack ID</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The construct ID of the CDK stack from your app to perform a diff.</p> -<div class="paragraph"> -<p><em>Type</em>: String</p> -</div> -<div class="paragraph"> -<p><em>Required</em>: No</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-diff-options">18.11.3. Options</h4> -<div class="paragraph"> -<p>For a list of global options that work with all CDK <code class="noloc">CLI</code> commands, see <a href="#ref-cli-cmd-options">Global options</a>.</p> -</div> -<div id="ref-cli-cmd-diff-options-change-set" class="dlist"> -<dl> -<dt class="hdlist1"><code>--change-set <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Specify whether to create a change set to analyze resource replacements.</p> -<div class="paragraph"> -<p>When <code>true</code>, the CDK <code class="noloc">CLI</code> will create an AWS CloudFormation change set to display the exact changes that will be made to your stack. This output includes whether resources will be updated or replaced. The CDK <code class="noloc">CLI</code> uses the deploy role instead of the lookup role to perform this action.</p> -</div> -<div class="paragraph"> -<p>When <code>false</code>, a quicker, but less-accurate diff is performed by comparing CloudFormation templates. Any change detected to properties that require resource replacement will be displayed as a resource replacement, even if the change is purely cosmetic, like replacing a resource reference with a hard-coded ARN.</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>true</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-diff-options-context-lines" class="dlist"> -<dl> -<dt class="hdlist1"><code>--context-lines <code class="replaceable">NUMBER</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Number of context lines to include in arbitrary JSON diff rendering.</p> -<div class="paragraph"> -<p><em>Default value</em>: <code>3</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-diff-options-exclusively" class="dlist"> -<dl> -<dt class="hdlist1"><code>--exclusively, -e <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Only diff requested stacks and don’t include dependencies.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-diff-options-fail" class="dlist"> -<dl> -<dt class="hdlist1"><code>--fail <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Fail and exit with a code of <code>1</code> if differences are detected.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-diff-options-help" class="dlist"> -<dl> -<dt class="hdlist1"><code>--help, -h <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Show command reference information for the <code>cdk diff</code> command.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-diff-options-processed" class="dlist"> -<dl> -<dt class="hdlist1"><code>--processed <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Specify whether to compare against the template with CloudFormation transforms already processed.</p> -<div class="paragraph"> -<p><em>Default value</em>: <code>false</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-diff-options-quiet" class="dlist"> -<dl> -<dt class="hdlist1"><code>--quiet, -q <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Do not print the CDK stack name and default <code>cdk diff</code> message to <code>stdout</code> when no changes are detected.</p> -<div class="paragraph"> -<p><em>Default value</em>: <code>false</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-diff-options-security-only" class="dlist"> -<dl> -<dt class="hdlist1"><code>--security-only <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Only diff for broadened security changes.</p> -<div class="paragraph"> -<p><em>Default value</em>: <code>false</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-diff-options-strict" class="dlist"> -<dl> -<dt class="hdlist1"><code>--strict <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Modify <code>cdk diff</code> behavior to be more precise or stringent. When true, the CDK <code class="noloc">CLI</code> will not filter out <code>AWS::CDK::Metadata</code> resources or unreadable non-ASCII characters.</p> -<div class="paragraph"> -<p><em>Default value</em>: <code>false</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-diff-options-template" class="dlist"> -<dl> -<dt class="hdlist1"><code>--template <code class="replaceable">STRING</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The path to the CloudFormation template to compare a CDK stack with.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-diff-examples">18.11.4. Examples</h4> -<div class="sect4"> -<h5 id="ref-cli-cmd-diff-examples-1">Diff against the currently deployed stack named MyStackName</h5> -<div class="paragraph"> -<p>The CDK <code class="noloc">CLI</code> uses the following symbols in the diff output:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><code>[+]</code> – Identifies code or resources that will be added if you deploy your changes.</p> -</li> -<li> -<p><code>[-]</code> – Identifies code or resources that will be removed if you deploy your changes.</p> -</li> -<li> -<p><code>[~]</code> – Identifies a resource or property that will be modified if you deploy your changes.</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>The following is an example that shows a diff of local changes to a Lambda function:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk diff MyStackName -start: Building asset-hash:account-Region -success: Built asset-hash:account-Region -start: Publishing asset-hash:account-Region -success: Published asset-hash:account-Region -Hold on while we create a read-only change set to get a diff with accurate replacement information (use --no-change-set to use a less accurate but faster template-only diff) -Stack MyStackName -Resources -[~] AWS::Lambda::Function HelloWorldFunction resource-logical-ID - └─ [~] Code - └─ [~] .ZipFile: - ├─ [-] - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello World!'), - }; - }; - - └─ [+] - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello from CDK!'), - }; - }; - - - -✨ Number of stacks with differences: 1</code></pre> -</div> -</div> -<div class="paragraph"> -<p>A <code>[~]</code> indicator for resources that will be modified does not always mean a full resource replacement:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Some resource properties, like <code>Code</code>, will update the resource.</p> -</li> -<li> -<p>Some resource properties, like <code>FunctionName</code>, may cause a full resource replacement.</p> -</li> -</ul> -</div> -</div> -<div class="sect4"> -<h5 id="ref-cli-cmd-diff-examples-2">Diff against a specific CloudFormation template</h5> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk diff MyStackName --app='node bin/main.js' --template-path='./MyStackNameTemplate.yaml'</code></pre> -</div> -</div> -</div> -<div class="sect4"> -<h5 id="ref-cli-cmd-diff-examples-3">Diff a local stack with its deployed stack. Don’t print to stdout if no changes are detected</h5> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk diff MyStackName --app='node bin/main.js' --quiet</code></pre> -</div> -</div> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="ref-cli-cmd-docs">18.12. <code class="noloc">cdk docs</code></h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Open AWS CDK documentation in your browser.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>Open AWS CDK documentation in your browser.</p> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-docs-usage">18.12.1. Usage</h4> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk docs <options></code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-docs-options">18.12.2. Options</h4> -<div class="paragraph"> -<p>For a list of global options that work with all CDK <code class="noloc">CLI</code> commands, see <a href="#ref-cli-cmd-options">Global options</a>.</p> -</div> -<div id="ref-cli-cmd-docs-options-browser" class="dlist"> -<dl> -<dt class="hdlist1"><code>--browser, -b <code class="replaceable">STRING</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The command to use to open the browser, using <code>%u</code> as a placeholder for the path of the file to open.</p> -<div class="paragraph"> -<p><em>Default value</em>: <code>open %u</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-docs-options-help" class="dlist"> -<dl> -<dt class="hdlist1"><code>--help, -h <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Show command reference information for the <code>cdk docs</code> command.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-docs-examples">18.12.3. Examples</h4> -<div class="sect4"> -<h5 id="ref-cli-cmd-docs-examples-1">Open AWS CDK documentation in <code class="noloc">Google Chrome</code></h5> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk docs --browser='chrome %u'</code></pre> -</div> -</div> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="ref-cli-cmd-doctor">18.13. <code class="noloc">cdk doctor</code></h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Inspect and display useful information about your local AWS CDK project and development environment.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>Inspect and display useful information about your local AWS CDK project and development environment.</p> -</div> -<div class="paragraph"> -<p>This information can help with troubleshooting CDK issues and should be provided when submitting bug reports.</p> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-doctor-usage">18.13.1. Usage</h4> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk doctor <options></code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-doctor-options">18.13.2. Options</h4> -<div class="paragraph"> -<p>For a list of global options that work with all CDK <code class="noloc">CLI</code> commands, see <a href="#ref-cli-cmd-options">Global options</a>.</p> -</div> -<div id="ref-cli-cmd-doctor-options-help" class="dlist"> -<dl> -<dt class="hdlist1"><code>--help, -h <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Show command reference information for the <code>cdk doctor</code> command.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-doctor-examples">18.13.3. Examples</h4> -<div class="sect4"> -<h5 id="ref-cli-cmd-doctor-examples-1">Simple example of the <code>cdk doctor</code> command</h5> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk doctor -ℹ️ CDK Version: 1.0.0 (build e64993a) -ℹ️ AWS environment variables: - - AWS_EC2_METADATA_DISABLED = 1 - - AWS_SDK_LOAD_CONFIG = 1</code></pre> -</div> -</div> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="ref-cli-cmd-gc">18.14. <code class="noloc">cdk gc</code></h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Use the AWS Cloud Development Kit (AWS CDK) command line interface (<code class="noloc">CLI</code>) <code>cdk gc</code> command to perform garbage collection on unused assets stored in the resources of your bootstrap stack. Use this command to view, manage, and delete assets that you no longer need.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>Use the AWS Cloud Development Kit (AWS CDK) command line interface (<code class="noloc">CLI</code>) <code>cdk gc</code> command to perform garbage collection on unused assets stored in the resources of your bootstrap stack. Use this command to view, manage, and delete assets that you no longer need.</p> -</div> -<div class="paragraph"> -<p>For Amazon Simple Storage Service (Amazon S3) assets, the CDK <code class="noloc">CLI</code> will check existing AWS CloudFormation templates in the same environment to see if they are referenced. If not referenced, they will be considered unused and eligible for garbage collection actions.</p> -</div> -<div class="admonitionblock warning"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-warning" title="Warning"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>The <code>cdk gc</code> command is in development for the AWS CDK. The current features of this command are considered production ready and safe to use. However, the scope of this command and its features are subject to change. Therefore, you must opt in by providing the <code>unstable=gc</code> option to use this command.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-gc-usage">18.14.1. Usage</h4> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk gc <arguments> <options></code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-gc-args">18.14.2. Arguments</h4> -<div id="ref-cli-cmd-gc-args-env" class="dlist"> -<dl> -<dt class="hdlist1">AWS environment</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The target AWS environment to perform garbage collection actions on.</p> -<div class="paragraph"> -<p>When providing an environment, use the following format: <code>aws://[replaceable]</code><account-id><code>/[replaceable]</code><region><code><code>`. For example, </code>aws://<code class="replaceable">123456789012</code>/<code class="replaceable">us-east-1</code>`</code>.</p> -</div> -<div class="paragraph"> -<p>This argument can be provided multiple times in a single command to perform garbage collection actions on multiple environments.</p> -</div> -<div class="paragraph"> -<p>By default, the CDK <code class="noloc">CLI</code> will perform garbage collection actions on all environments that you reference in your CDK app or provide as arguments. If you don’t provide an environment, the CDK <code class="noloc">CLI</code> will determine the environment from default sources. These sources include environments that you specify using the <code>--profile</code> option, environment variables, or default AWS CLI sources.</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-gc-options">18.14.3. Options</h4> -<div class="paragraph"> -<p>For a list of global options that work with all CDK <code class="noloc">CLI</code> commands, see <a href="#ref-cli-cmd-options">Global options</a>.</p> -</div> -<div id="ref-cli-cmd-gc-options-action" class="dlist"> -<dl> -<dt class="hdlist1"><code>--action <code class="replaceable">STRING</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The action that <code>cdk gc</code> performs on your assets during a garbage collection.</p> -<div class="ulist"> -<ul> -<li> -<p><code>delete-tagged</code> – Deletes assets that have been tagged with a date within the range of buffer days that you provide, but does not tag newly identified unused assets.</p> -</li> -<li> -<p><code>full</code> – Perform all garbage collection actions. This includes deleting assets within the range of buffer days that you provide and tagging newly identified unused assets.</p> -</li> -<li> -<p><code>print</code> – Outputs the number of unused assets at the command prompt but doesn’t make any actual changes within your AWS environment.</p> -</li> -<li> -<p><code>tag</code> – Tags any newly identified unused assets, but doesn’t delete any assets within the range of buffer days that you provide.</p> -</li> -</ul> -</div> -</li> -</ul> -</div> -<div class="paragraph"> -<p><em>Accepted values</em>: <code>delete-tagged</code>, <code>full</code>, <code>print</code>, <code>tag</code></p> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>full</code></p> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-gc-options-bootstrap-stack-name" class="dlist"> -<dl> -<dt class="hdlist1"><code>--bootstrap-stack-name <code class="replaceable">STRING</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The name of the CDK bootstrap stack in your AWS environment. Provide this option if you customized your bootstrap stack name. If you are using the default <code>CDKToolkit</code> stack name, you don’t have to provide this option.</p> -<div class="paragraph"> -<p><em>Default value</em>: <code>CDKToolkit</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-gc-options-confirm" class="dlist"> -<dl> -<dt class="hdlist1"><code>--confirm <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Specify whether the CDK <code class="noloc">CLI</code> will request manual confirmation from you before deleting any assets.</p> -<div class="paragraph"> -<p>Specify <code>false</code> to automatically delete assets without prompting you for manual confirmation.</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>true</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-gc-options-created-buffer-days" class="dlist"> -<dl> -<dt class="hdlist1"><code>--created-buffer-days <code class="replaceable">NUMBER</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The number of days an asset must exist before it is eligible for garbage collection actions.</p> -<div class="paragraph"> -<p>When you provide a number, assets that have not existed beyond your specified number of days are filtered out from garbage collection actions.</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>1</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-gc-options-help" class="dlist"> -<dl> -<dt class="hdlist1"><code>--help, -h <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Show command reference information for the <code>cdk gc</code> command.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-gc-options-rollback-buffer-days" class="dlist"> -<dl> -<dt class="hdlist1"><code>--rollback-buffer-days <code class="replaceable">NUMBER</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The number of days an asset must be tagged as isolated before it is eligible for garbage collection actions.</p> -<div class="paragraph"> -<p>When you provide a number, the CDK <code class="noloc">CLI</code> will tag unused assets with the current date instead of deleting them. The CDK <code class="noloc">CLI</code> will also check if any assets have been tagged during previous runs of the <code>cdk gc</code> command. Previously tagged assets that fall within the range of buffer days you provide will be deleted.</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>0</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-gc-options-type" class="dlist"> -<dl> -<dt class="hdlist1"><code>--type <code class="replaceable">STRING</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The bootstrap resource type within your bootstrap stack to perform garbage collection actions on.</p> -<div class="ulist"> -<ul> -<li> -<p><code>all</code> – Perform garbage collection actions on all bootstrapped resources.</p> -</li> -<li> -<p><code>ecr</code> – Perform garbage collection actions on assets in the Amazon Elastic Container Registry (Amazon ECR) repository of your bootstrap stack.</p> -</li> -<li> -<p><code>s3</code> – Perform garbage collection actions on assets in the Amazon S3 bucket of your bootstrap stack.</p> -</li> -</ul> -</div> -</li> -</ul> -</div> -<div class="paragraph"> -<p><em>Accepted values</em>: <code>all</code>, <code>ecr</code>, <code>s3</code></p> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>all</code></p> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-gc-options-unstable" class="dlist"> -<dl> -<dt class="hdlist1"><code>--unstable <code class="replaceable">STRING</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Allow the usage of CDK <code class="noloc">CLI</code> commands that are still in development.</p> -<div class="paragraph"> -<p>This option is required to use any CDK <code class="noloc">CLI</code> command that is still in development and subject to change.</p> -</div> -<div class="paragraph"> -<p>This option can be provided multiple times in a single command.</p> -</div> -<div class="paragraph"> -<p>To use <code>cdk gc</code>, provide <code>--unstable=gc</code>.</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-gc-examples">18.14.4. Examples</h4> -<div class="sect4"> -<h5 id="ref-cli-cmd-gc-examples-basic">Basic examples</h5> -<div class="paragraph"> -<p>The following example prompts you for manual confirmation to perform default garbage collection actions on assets in the Amazon S3 bucket of your bootstrap stack:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk gc --unstable=gc --type=s3 - - ⏳ Garbage Collecting environment aws://<account-id>/<region>... -Found 99 assets to delete based off of the following criteria: -- assets have been isolated for > 0 days -- assets were created > 1 days ago - -Delete this batch (yes/no/delete-all)?</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The following example performs garbage collection actions on a range of assets in the Amazon S3 bucket of your bootstrap stack. This range includes assets that have been previously tagged by <code>cdk gc</code> for over 30 days and have been created 10 days or older. This command will prompt for manual confirmation before deleting any assets:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk gc --unstable=gc --type=s3 --rollback-buffer-days=30 --created-buffer-days=10</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The following example performs the action of deleting previously tagged assets in the Amazon S3 bucket of your bootstrap stack that have been unused for longer than 30 days:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk gc --unstable=gc --type=s3 --action=delete-tagged --rollback-buffer-days=30</code></pre> -</div> -</div> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="ref-cli-cmd-import">18.15. <code class="noloc">cdk import</code></h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Use <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resource-import.html">AWS CloudFormation resource imports</a> to import existing AWS resources into a CDK stack.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>Use <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resource-import.html">AWS CloudFormation resource imports</a> to import existing AWS resources into a CDK stack.</p> -</div> -<div class="paragraph"> -<p>With this command, you can take existing resources that were created using other methods and start managing them using the AWS CDK.</p> -</div> -<div class="paragraph"> -<p>When considering moving resources into CDK management, sometimes creating new resources is acceptable, such as with IAM roles, Lambda functions, and event rules. For other resources, such as stateful resources like Amazon S3 buckets and DynamoDB tables, creating new resources can cause impacts to your service. You can use <code>cdk import</code> to import existing resources with minimal disruption to your services. For a list of supported AWS resources, see <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resource-import-supported-resources.html">Resource type support</a> in the <em>AWS CloudFormation User Guide</em>.</p> -</div> -<div class="olist arabic"> -<ol class="arabic"> -<li> -<p>Run a <code>cdk diff</code> to make sure your CDK stack has no pending changes. When performing a <code>cdk import</code>, the only changes allowed in an import operation are the addition of new resources being imported.</p> -</li> -<li> -<p>Add constructs for the resources you want to import to your stack. For example, add the following for an Amazon S3 bucket:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">new s3.Bucket(this, 'ImportedS3Bucket', {});</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Do not add any other changes. You must also make sure to exactly model the state that the resource currently has. For the bucket example, be sure to include AWS KMS keys, lifecycle policies, and anything else that is relevant about the bucket. Otherwise, subsequent update operations may not do what you expect.</p> -</div> -</li> -<li> -<p>Run <code>cdk import</code>. If there are multiple stacks in the CDK app, pass a specific stack name as an argument.</p> -</li> -<li> -<p>The CDK <code class="noloc">CLI</code> will prompt you to pass in the actual names of the resources you are importing. After you provide this information, import will begin.</p> -</li> -<li> -<p>When <code>cdk import</code> reports success, the resource will be managed by the CDK. Any subsequent changes in the construct configuration will be reflected on the resource.</p> -</li> -</ol> -</div> -<div class="paragraph"> -<p>This feature currently has the following limitations:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Importing resources into nested stacks isn’t possible.</p> -</li> -<li> -<p>There is no check on whether the properties you specify are correct and complete for the imported resource. Try starting a drift detection operation after importing.</p> -</li> -<li> -<p>Resources that depend on other resources must all be imported together, or individually, in the right order. Otherwise, the CloudFormation deployment will fail with unresolved references.</p> -</li> -<li> -<p>This command uses the deploy role credentials, which is necessary to read the encrypted staging bucket. This requires version 12 of the bootstrap template, which includes the necessary IAM permissions for the deploy role.</p> -</li> -</ul> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-import-usage">18.15.1. Usage</h4> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk import <arguments> <options></code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-import-args">18.15.2. Arguments</h4> -<div id="ref-cli-cmd-import-args-stack-name" class="dlist"> -<dl> -<dt class="hdlist1">CDK stack ID</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The construct ID of the CDK stack from your app to import resources to. This argument can be provided multiple times in a single command.</p> -<div class="paragraph"> -<p><em>Type</em>: String</p> -</div> -<div class="paragraph"> -<p><em>Required</em>: No</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-import-options">18.15.3. Options</h4> -<div class="paragraph"> -<p>For a list of global options that work with all CDK <code class="noloc">CLI</code> commands, see <a href="#ref-cli-cmd-options">Global options</a>.</p> -</div> -<div id="ref-cli-cmd-import-options-change-set-name" class="dlist"> -<dl> -<dt class="hdlist1"><code>--change-set-name <code class="replaceable">STRING</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The name of the CloudFormation change set to create.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-import-options-execute" class="dlist"> -<dl> -<dt class="hdlist1"><code>--execute <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Specify whether to execute change set.</p> -<div class="paragraph"> -<p><em>Default value</em>: <code>true</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-import-options-force" class="dlist"> -<dl> -<dt class="hdlist1"><code>--force, -f <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>By default, the CDK <code class="noloc">CLI</code> exits the process if the template diff includes updates or deletions. Specify <code>true</code> to override this behavior and always continue with importing.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-import-options-help" class="dlist"> -<dl> -<dt class="hdlist1"><code>--help, -h <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Show command reference information for the <code>cdk import</code> command.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-import-options-record-resource-mapping" class="dlist"> -<dl> -<dt class="hdlist1"><code>--record-resource-mapping, -r <code class="replaceable">STRING</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Use this option to generate a mapping of existing physical resources to the CDK resources that will be imported. The mapping will be written to the file path that you provide. No actual import operations will be performed.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-import-options-resource-mapping" class="dlist"> -<dl> -<dt class="hdlist1"><code>--resource-mapping, -m <code class="replaceable">STRING</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Use this option to specify a file that defines your resource mapping. The CDK <code class="noloc">CLI</code> will use this file to map physical resources to resources for import instead of interactively asking you.</p> -<div class="paragraph"> -<p>This option can be run from scripts.</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-import-options-rollback" class="dlist"> -<dl> -<dt class="hdlist1"><code>--rollback <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Roll back the stack to stable state on failure.</p> -<div class="paragraph"> -<p>To specify <code>false</code>, you can use <code>--no-rollback</code> or <code>-R</code>.</p> -</div> -<div class="paragraph"> -<p>Specify <code>false</code> to iterate more rapidly. Deployments containing resource replacements will always fail.</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>true</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-import-options-toolkit-stack-name" class="dlist"> -<dl> -<dt class="hdlist1"><code>--toolkit-stack-name <code class="replaceable">STRING</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The name of the CDK Toolkit stack to create.</p> -<div class="paragraph"> -<p>By default, <code>cdk bootstrap</code> deploys a stack named <code class="path">CDKToolkit</code> into the specified AWS environment. Use this option to provide a different name for your bootstrap stack.</p> -</div> -<div class="paragraph"> -<p>The CDK <code class="noloc">CLI</code> uses this value to verify your bootstrap stack version.</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="ref-cli-cmd-init">18.16. <code class="noloc">cdk init</code></h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Create a new AWS CDK project from a template.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>Create a new AWS CDK project from a template.</p> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-init-usage">18.16.1. Usage</h4> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk init <arguments> <options></code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-init-args">18.16.2. Arguments</h4> -<div id="ref-cli-cmd-init-args-template-type" class="dlist"> -<dl> -<dt class="hdlist1">Template type</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The CDK template type to initialize a new CDK project from.</p> -<div class="ulist"> -<ul> -<li> -<p><code>app</code> – Template for a CDK application.</p> -</li> -<li> -<p><code>lib</code> – Template for an AWS Construct Library.</p> -</li> -<li> -<p><code>sample-app</code> – Example CDK application that includes some constructs.</p> -</li> -</ul> -</div> -</li> -</ul> -</div> -<div class="paragraph"> -<p><em>Valid values</em>: <code>app</code>, <code>lib</code>, <code>sample-app</code></p> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-init-options">18.16.3. Options</h4> -<div class="paragraph"> -<p>For a list of global options that work with all CDK <code class="noloc">CLI</code> commands, see <a href="#ref-cli-cmd-options">Global options</a>.</p> -</div> -<div id="ref-cli-cmd-init-options-generate-only" class="dlist"> -<dl> -<dt class="hdlist1"><code>--generate-only <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Specify this option to generate project files without initiating additional operations such as setting up a git repository, installing dependencies, or compiling the project.</p> -<div class="paragraph"> -<p><em>Default value</em>: <code>false</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-init-options-help" class="dlist"> -<dl> -<dt class="hdlist1"><code>--help, -h <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Show command reference information for the <code>cdk init command</code>.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-init-options-language" class="dlist"> -<dl> -<dt class="hdlist1"><code>--language, -l <code class="replaceable">STRING</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The language to be used for the new project. This option can be configured in the project’s <code class="path">cdk.json</code> configuration file or at <code class="path">~/.cdk.json</code> on your local development machine.</p> -<div class="paragraph"> -<p><em>Valid values</em>: <code>csharp</code>, <code>fsharp</code>, <code>go</code>, <code>java</code>, <code>javascript</code>, <code>python</code>, <code>typescript</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-init-options-list" class="dlist"> -<dl> -<dt class="hdlist1"><code>--list <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>List the available template types and languages.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-init-examples">18.16.4. Examples</h4> -<div class="sect4"> -<h5 id="ref-cli-cmd-init-examples-1">List the available template types and languages</h5> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk init --list -Available templates: -* app: Template for a CDK Application - └─ cdk init app --language=[csharp|fsharp|go|java|javascript|python|typescript] -* lib: Template for a CDK Construct Library - └─ cdk init lib --language=typescript -* sample-app: Example CDK Application with some constructs - └─ cdk init sample-app --language=[csharp|fsharp|go|java|javascript|python|typescript]</code></pre> -</div> -</div> -</div> -<div class="sect4"> -<h5 id="ref-cli-cmd-init-examples-2">Create a new CDK app in TypeScript from the library template</h5> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk init lib --language=typescript</code></pre> -</div> -</div> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="ref-cli-cmd-list">18.17. <code class="noloc">cdk list</code></h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>List all AWS CDK stacks and their dependencies from a CDK app.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>List all AWS CDK stacks and their dependencies from a CDK app.</p> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-list-usage">18.17.1. Usage</h4> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk list <arguments> <options></code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-list-args">18.17.2. Arguments</h4> -<div id="ref-cli-cmd-list-args-stack-name" class="dlist"> -<dl> -<dt class="hdlist1">CDK stack ID</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The construct ID of the CDK stack from your app to perform this command against.</p> -<div class="paragraph"> -<p><em>Type</em>: String</p> -</div> -<div class="paragraph"> -<p><em>Required</em>: No</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-list-options">18.17.3. Options</h4> -<div class="paragraph"> -<p>For a list of global options that work with all CDK <code class="noloc">CLI</code> commands, see <a href="#ref-cli-cmd-options">Global options</a>.</p> -</div> -<div id="ref-cli-cmd-list-options-help" class="dlist"> -<dl> -<dt class="hdlist1"><code>--help, -h <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Show command reference information for the <code>cdk list</code> command.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-list-options-long" class="dlist"> -<dl> -<dt class="hdlist1"><code>--long, -l <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Display AWS environment information for each stack.</p> -<div class="paragraph"> -<p><em>Default value</em>: <code>false</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-list-options-show-dependencies" class="dlist"> -<dl> -<dt class="hdlist1"><code>--show-dependencies, -d <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Display stack dependency information for each stack.</p> -<div class="paragraph"> -<p><em>Default value</em>: <code>false</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-list-examples">18.17.4. Examples</h4> -<div class="sect4"> -<h5 id="ref-cli-cmd-list-examples-1">List all stacks in the CDK app ‘node bin/main.js’</h5> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk list --app='node bin/main.js' -Foo -Bar -Baz</code></pre> -</div> -</div> -</div> -<div class="sect4"> -<h5 id="ref-cli-cmd-list-examples-">List all stacks, including AWS environment details for each stack</h5> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk list --app='node bin/main.js' --long -- - name: Foo - environment: - name: 000000000000/bermuda-triangle-1 - account: '000000000000' - region: bermuda-triangle-1 -- - name: Bar - environment: - name: 111111111111/bermuda-triangle-2 - account: '111111111111' - region: bermuda-triangle-2 -- - name: Baz - environment: - name: 333333333333/bermuda-triangle-3 - account: '333333333333' - region: bermuda-triangle-3</code></pre> -</div> -</div> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="ref-cli-cmd-metadata">18.18. <code class="noloc">cdk metadata</code></h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Display metadata associated with a CDK stack.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>Display metadata associated with a CDK stack.</p> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-metadata-usage">18.18.1. Usage</h4> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk metadata <arguments> <options></code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-metadata-args">18.18.2. Arguments</h4> -<div id="ref-cli-cmd-metadata-args-stack-name" class="dlist"> -<dl> -<dt class="hdlist1">CDK stack ID</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The construct ID of the CDK stack from your app to display metadata for.</p> -<div class="paragraph"> -<p><em>Type</em>: String</p> -</div> -<div class="paragraph"> -<p><em>Required</em>: No</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-metadata-options">18.18.3. Options</h4> -<div class="paragraph"> -<p>For a list of global options that work with all CDK <code class="noloc">CLI</code> commands, see <a href="#ref-cli-cmd-options">Global options</a>.</p> -</div> -<div id="ref-cli-cmd-metadata-options-help" class="dlist"> -<dl> -<dt class="hdlist1"><code>--help, -h <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Show command reference information for the <code>cdk metadata</code> command.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="ref-cli-cdk-migrate">18.19. <code class="noloc">cdk migrate</code></h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Migrate deployed AWS resources, AWS CloudFormation stacks, and CloudFormation templates into a new AWS CDK project.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>Migrate deployed AWS resources, AWS CloudFormation stacks, and CloudFormation templates into a new AWS CDK project.</p> -</div> -<div class="paragraph"> -<p>This command creates a new CDK app that includes a single stack that is named with the value you provide using <code>--stack-name</code>. You can configure the migration source using <code>--from-scan</code>, <code>--from-stack</code>, or <code>--from-path</code>.</p> -</div> -<div class="paragraph"> -<p>For more information on using <code>cdk migrate</code>, see <a href="#migrate">Migrate existing resources and AWS CloudFormation templates to the AWS CDK</a>.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>The <code>cdk migrate</code> command is experimental and may have breaking changes in the future.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="sect3"> -<h4 id="ref-cli-cdk-migrate-usage">18.19.1. Usage</h4> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk migrate <options></code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cdk-migrate-options">18.19.2. Options</h4> -<div class="paragraph"> -<p>For a list of global options that work with all CDK <code class="noloc">CLI</code> commands, see <a href="#ref-cli-cmd-options">Global options</a>.</p> -</div> -<div class="sect4"> -<h5 id="ref-cli-cdk-migrate-options-required">Required options</h5> -<div id="ref-cli-cdk-migrate-options-stack-name" class="dlist"> -<dl> -<dt class="hdlist1"><code>--stack-name <code class="replaceable">STRING</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The name of the AWS CloudFormation stack that will be created within the CDK app after migrating.</p> -<div class="paragraph"> -<p><em>Required</em>: Yes</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect4"> -<h5 id="ref-cli-cdk-migrate-options-conditional">Conditional options</h5> -<div id="ref-cli-cdk-migrate-options-from-path" class="dlist"> -<dl> -<dt class="hdlist1"><code>--from-path <code class="replaceable">PATH</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The path to the AWS CloudFormation template to migrate. Provide this option to specify a local template.</p> -<div class="paragraph"> -<p><em>Required</em>: Conditional. Required if migrating from a local AWS CloudFormation template.</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cdk-migrate-options-from-scan" class="dlist"> -<dl> -<dt class="hdlist1"><code>--from-scan <code class="replaceable">STRING</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>When migrating deployed resources from an AWS environment, use this option to specify whether a new scan should be started or if the AWS CDK <code class="noloc">CLI</code> should use the last successful scan.</p> -<div class="paragraph"> -<p><em>Required</em>: Conditional. Required when migrating from deployed AWS resources.</p> -</div> -<div class="paragraph"> -<p><em>Accepted values</em>: <code>most-recent</code>, <code>new</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cdk-migrate-options-from-stack" class="dlist"> -<dl> -<dt class="hdlist1"><code>--from-stack <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Provide this option to migrate from a deployed AWS CloudFormation stack. Use <code>--stack-name</code> to specify the name of the deployed AWS CloudFormation stack.</p> -<div class="paragraph"> -<p><em>Required</em>: Conditional. Required if migrating from a deployed AWS CloudFormation stack.</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect4"> -<h5 id="ref-cli-cdk-migrate-options-optional">Optional options</h5> -<div id="ref-cli-cdk-migrate-options-account" class="dlist"> -<dl> -<dt class="hdlist1"><code>--account <code class="replaceable">STRING</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The account to retrieve the AWS CloudFormation stack template from.</p> -<div class="paragraph"> -<p><em>Required</em>: No</p> -</div> -<div class="paragraph"> -<p><em>Default</em>: The AWS CDK <code class="noloc">CLI</code> obtains account information from default sources.</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cdk-migrate-options-compress" class="dlist"> -<dl> -<dt class="hdlist1"><code>--compress <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Provide this option to compress the generated CDK project into a <code class="noloc">ZIP</code> file.</p> -<div class="paragraph"> -<p><em>Required</em>: No</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cdk-migrate-options-filter" class="dlist"> -<dl> -<dt class="hdlist1"><code>--filter <code class="replaceable">ARRAY</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Use when migrating deployed resources from an AWS account and AWS Region. This option specifies a filter to determine which deployed resources to migrate.</p> -<div class="paragraph"> -<p>This option accepts an array of key-value pairs, where <strong>key</strong> represents the filter type and <strong>value</strong> represents the value to filter.</p> -</div> -<div class="paragraph"> -<p>The following are accepted keys:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><code>resource-identifier</code> – An identifier for the resource. Value can be the resource logical or physical ID. For example, <code>resource-identifier="ClusterName"</code>.</p> -</li> -<li> -<p><code>resource-type-prefix</code> – The AWS CloudFormation resource type prefix. For example, specify <code>resource-type-prefix="AWS::DynamoDB::"</code> to filter all Amazon DynamoDB resources.</p> -</li> -<li> -<p><code>tag-key</code> – The key of a resource tag. For example, <code>tag-key="myTagKey"</code>.</p> -</li> -<li> -<p><code>tag-value</code> – The value of a resource tag. For example, <code>tag-value="myTagValue"</code>.</p> -</li> -</ul> -</div> -</li> -</ul> -</div> -<div class="paragraph"> -<p>Provide multiple key-value pairs for <code>AND</code> conditional logic. The following example filters for any DynamoDB resource that is tagged with <code>myTagKey</code> as the tag key: <code>--filter resource-type-prefix="AWS::DynamoDB::", tag-key="myTagKey"</code>.</p> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p>Provide the <code>--filter</code> option multiple times in a single command for <code>OR</code> conditional logic. The following example filters for any resource that is a DynamoDB resource or is tagged with <code>myTagKey</code> as the tag key: <code>--filter resource-type-prefix="AWS::DynamoDB::" --filter tag-key="myTagKey"</code>.</p> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p><em>Required</em>: No</p> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cdk-migrate-options-help" class="dlist"> -<dl> -<dt class="hdlist1"><code>--help, -h <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Show command reference information for the <code>cdk migrate</code> command.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cdk-migrate-options-language" class="dlist"> -<dl> -<dt class="hdlist1"><code>--language <code class="replaceable">STRING</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The programming language to use for the CDK project created during migration.</p> -<div class="paragraph"> -<p><em>Required</em>: No</p> -</div> -<div class="paragraph"> -<p><em>Valid values</em>: <code>typescript</code>, <code>python</code>, <code>java</code>, <code>csharp</code>, <code>go</code>.</p> -</div> -<div class="paragraph"> -<p><em>Default</em>: <code>typescript</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cdk-migrate-options-output-path" class="dlist"> -<dl> -<dt class="hdlist1"><code>--output-path <code class="replaceable">PATH</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The output path for the migrated CDK project.</p> -<div class="paragraph"> -<p><em>Required</em>: No</p> -</div> -<div class="paragraph"> -<p><em>Default</em>: By default, the AWS CDK <code class="noloc">CLI</code> will use your current working directory.</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cdk-migrate-options-region" class="dlist"> -<dl> -<dt class="hdlist1"><code>--region <code class="replaceable">STRING</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The AWS Region to retrieve the AWS CloudFormation stack template from.</p> -<div class="paragraph"> -<p><em>Required</em>: No</p> -</div> -<div class="paragraph"> -<p><em>Default</em>: The AWS CDK <code class="noloc">CLI</code> obtains AWS Region information from default sources.</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cdk-migrate-examples">18.19.3. Examples</h4> -<div class="sect4"> -<h5 id="ref-cli-cdk-migrate-examples-1">Simple example of migrating from a CloudFormation stack</h5> -<div class="paragraph"> -<p>Migrate from a deployed CloudFormation stack in a specific AWS environment using <code>--from-stack</code>. Provide <code>--stack-name</code> to name your new CDK stack. The following is an example that migrates <code>myCloudFormationStack</code> to a new CDK app that is using <code class="noloc">TypeScript</code>:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk migrate --language typescript --from-stack --stack-name 'myCloudFormationStack'</code></pre> -</div> -</div> -</div> -<div class="sect4"> -<h5 id="ref-cli-cdk-migrate-examples-2">Simple example of migrating from a local CloudFormation template</h5> -<div class="paragraph"> -<p>Migrate from a local JSON or YAML CloudFormation template using <code>--from-path</code>. Provide <code>--stack-name</code> to name your new CDK stack. The following is an example that creates a new CDK app in <code class="noloc">TypeScript</code> that includes a <code>myCloudFormationStack</code> stack from a local <code class="path">template.json</code> file:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk migrate --stack-name "myCloudFormationStack" --language typescript --from-path "./template.json"</code></pre> -</div> -</div> -</div> -<div class="sect4"> -<h5 id="ref-cli-cdk-migrate-examples-3">Simple example of migrating from deployed AWS resources</h5> -<div class="paragraph"> -<p>Migrate deployed AWS resources from a specific AWS environment that are not associated with a CloudFormation stack using <code>--from-scan</code>. The CDK <code class="noloc">CLI</code> utilizes the <code class="noloc">IaC generator</code> service to scan for resources and generate a template. Then, the CDK <code class="noloc">CLI</code> references the template to create the new CDK app. The following is an example that creates a new CDK app in <code class="noloc">TypeScript</code> with a new <code>myCloudFormationStack</code> stack containing migrated AWS resources:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk migrate --language typescript --from-scan --stack-name "myCloudFormationStack"</code></pre> -</div> -</div> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="ref-cli-cmd-notices">18.20. <code class="noloc">cdk notices</code></h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Display notices for your CDK application.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>Display notices for your CDK application.</p> -</div> -<div class="paragraph"> -<p>Notices can include important messages regarding security vulnerabilities, regressions, and usage of unsupported versions.</p> -</div> -<div class="paragraph"> -<p>This command displays relevant notices, regardless of whether they have been acknowledged or not. Relevant notices may also appear after every command by default.</p> -</div> -<div class="paragraph"> -<p>You can suppress notices in the following ways:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Through command options. The following is an example:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk deploy --no-notices</code></pre> -</div> -</div> -</li> -<li> -<p>Suppress all notices indefinitely through context in the project’s <code class="path">cdk.json</code> file:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-json" data-lang="json">{ - "notices": false, - "context": { - // ... - } -}</code></pre> -</div> -</div> -</li> -<li> -<p>Acknowledge each notice with the <code>cdk acknowledge</code> command.</p> -</li> -</ul> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-notices-usage">18.20.1. Usage</h4> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk notices <options></code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-notices-options">18.20.2. Options</h4> -<div class="paragraph"> -<p>For a list of global options that work with all CDK <code class="noloc">CLI</code> commands, see <a href="#ref-cli-cmd-options">Global options</a>.</p> -</div> -<div id="ref-cli-cmd-notices-options-help" class="dlist"> -<dl> -<dt class="hdlist1"><code>--help, -h <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Show command reference information for the <code>cdk notices</code> command.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-notices-examples">18.20.3. Examples</h4> -<div class="sect4"> -<h5 id="ref-cli-cmd-notices-examples-1">Example of a default notice that displays after running the cdk deploy command</h5> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk deploy - -... # Normal output of the command - -NOTICES - -16603 Toggling off auto_delete_objects for Bucket empties the bucket - - Overview: If a stack is deployed with an S3 bucket with - auto_delete_objects=True, and then re-deployed with - auto_delete_objects=False, all the objects in the bucket - will be deleted. - - Affected versions: <1.126.0. - - More information at: https://github.com/aws/aws-cdk/issues/16603 - - -17061 Error when building EKS cluster with monocdk import - - Overview: When using monocdk/aws-eks to build a stack containing - an EKS cluster, error is thrown about missing - lambda-layer-node-proxy-agent/layer/package.json. - - Affected versions: >=1.126.0 <=1.130.0. - - More information at: https://github.com/aws/aws-cdk/issues/17061 - - -If you don’t want to see an notice anymore, use "cdk acknowledge ID". For example, "cdk acknowledge 16603"</code></pre> -</div> -</div> -</div> -<div class="sect4"> -<h5 id="ref-cli-cmd-notices-examples-2">Simple example of running the cdk notices command</h5> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk notices - -NOTICES - -16603 Toggling off auto_delete_objects for Bucket empties the bucket - - Overview: if a stack is deployed with an S3 bucket with - auto_delete_objects=True, and then re-deployed with - auto_delete_objects=False, all the objects in the bucket - will be deleted. - - Affected versions: framework: <=2.15.0 >=2.10.0 - - More information at: https://github.com/aws/aws-cdk/issues/16603 - - -If you don’t want to see a notice anymore, use "cdk acknowledge <id>". For example, "cdk acknowledge 16603"</code></pre> -</div> -</div> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="ref-cli-cmd-rollback">18.21. <code class="noloc">cdk rollback</code></h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Use the AWS Cloud Development Kit (AWS CDK) Command Line Interface (<code class="noloc">CLI</code>) <code>cdk rollback</code> command to rollback a failed or paused stack from an AWS CloudFormation deployment to its last stable state.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>Use the AWS Cloud Development Kit (AWS CDK) Command Line Interface (<code class="noloc">CLI</code>) <code>cdk rollback</code> command to rollback a failed or paused stack from an AWS CloudFormation deployment to its last stable state.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>To use this command, you must have v23 of the bootstrap template deployed to your environment. For more information, see <a href="#bootstrap-template-history">Bootstrap template version history</a>.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>When you deploy using <code>cdk deploy</code>, the CDK <code class="noloc">CLI</code> will rollback a failed deployment by default. If you specify <code>--no-rollback</code> with <code>cdk deploy</code>, you can then use the <code>cdk rollback</code> command to manually rollback a failed deployment. This will initiate a rollback to the last stable state of your stack.</p> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-rollback-usage">18.21.1. Usage</h4> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk rollback <arguments> <options></code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-rollback-args">18.21.2. Arguments</h4> -<div id="ref-cli-cmd-rollback-args-stack-name" class="dlist"> -<dl> -<dt class="hdlist1">CDK stack ID</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The construct ID of the CDK stack from your app to rollback.</p> -<div class="paragraph"> -<p><em>Type</em>: String</p> -</div> -<div class="paragraph"> -<p><em>Required</em>: No</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-rollback-options">18.21.3. Options</h4> -<div class="paragraph"> -<p>For a list of global options that work with all CDK <code class="noloc">CLI</code> commands, see <a href="#ref-cli-cmd-options">Global options</a>.</p> -</div> -<div id="ref-cli-cmd-rollback-options-all" class="dlist"> -<dl> -<dt class="hdlist1"><code>--all <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Rollback all stacks in your CDK app.</p> -<div class="paragraph"> -<p><em>Default value</em>: <code>false</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-rollback-options-force" class="dlist"> -<dl> -<dt class="hdlist1"><code>--force, -f <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>When you use <code>cdk rollback</code>, some resources may fail to rollback. Provide this option to force the rollback of all resources. This is the same behavior as providing the <code>--orphan</code> option for each resource in your stack.</p> -<div class="paragraph"> -<p><em>Default value</em>: <code>false</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-rollback-options-help" class="dlist"> -<dl> -<dt class="hdlist1"><code>--help, -h <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Show command reference information for the <code>cdk rollback</code> command.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-rollback-options-orphan" class="dlist"> -<dl> -<dt class="hdlist1"><code>--orphan <code class="replaceable">LogicalId</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>When you use <code>cdk rollback</code>, some resources may fail to rollback. When this happens, you can try to force the rollback of a resource by using this option and providing the logical ID of the resource that failed to rollback.</p> -<div class="paragraph"> -<p>This option can be provided multiple times in a single command The following is an example:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk rollback MyStack --orphan MyLambdaFunction --orphan MyLambdaFunction2</code></pre> -</div> -</div> -<div class="paragraph"> -<p>To force the rollback of all resources, use the <code>--force</code> option instead.</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-rollback-options-toolkit-stack-name" class="dlist"> -<dl> -<dt class="hdlist1"><code>--toolkit-stack-name <code class="replaceable">STRING</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The name of the existing CDK Toolkit stack that the environment is bootstrapped with.</p> -<div class="paragraph"> -<p>By default, <code>cdk bootstrap</code> deploys a stack named <code class="path">CDKToolkit</code> into the specified AWS environment. Use this option to provide a different name for your bootstrap stack.</p> -</div> -<div class="paragraph"> -<p>The CDK <code class="noloc">CLI</code> uses this value to verify your bootstrap stack version.</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-rollback-options-validate-bootstrap-version" class="dlist"> -<dl> -<dt class="hdlist1"><code>--validate-bootstrap-version <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Specify whether to validate the bootstrap stack version. Provide <code>--validate-bootstrap-version=false</code> or <code>--no-validate-bootsrap-version</code> to turn off this behavior.</p> -<div class="paragraph"> -<p><em>Default value</em>: <code>true</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="ref-cli-cmd-synth">18.22. <code class="noloc">cdk synthesize</code></h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Synthesize a CDK app to produce a cloud assembly, including an AWS CloudFormation template for each stack.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>Synthesize a CDK app to produce a cloud assembly, including an AWS CloudFormation template for each stack.</p> -</div> -<div class="paragraph"> -<p>Cloud assemblies are files that include everything needed to deploy your app to your AWS environment. For example, it includes a CloudFormation template for each stack in your app, and a copy of the file assets or <code class="noloc">Docker</code> images that you reference in your app.</p> -</div> -<div class="paragraph"> -<p>If your app contains a single stack or if a single stack is provided as an argument, the CloudFormation template will also be displayed in the standard output (<code>stdout</code>) in YAML format.</p> -</div> -<div class="paragraph"> -<p>If your app contains multiple stacks, <code>cdk synth</code> will synthesize the cloud assembly to <code class="path">cdk.out</code>.</p> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-synth-usage">18.22.1. Usage</h4> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk synthesize <arguments> <options></code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-synth-args">18.22.2. Arguments</h4> -<div id="ref-cli-cmd-synth-args-stack-name" class="dlist"> -<dl> -<dt class="hdlist1">CDK stack ID</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The construct ID of the CDK stack from your app to synthesize.</p> -<div class="paragraph"> -<p><em>Type</em>: String</p> -</div> -<div class="paragraph"> -<p><em>Required</em>: No</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-synth-options">18.22.3. Options</h4> -<div class="paragraph"> -<p>For a list of global options that work with all CDK <code class="noloc">CLI</code> commands, see <a href="#ref-cli-cmd-options">Global options</a>.</p> -</div> -<div id="ref-cli-cmd-synth-options-exclusively" class="dlist"> -<dl> -<dt class="hdlist1"><code>--exclusively, -e <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Only synthesize requested stacks, don’t include dependencies.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-synth-options-help" class="dlist"> -<dl> -<dt class="hdlist1"><code>--help, -h <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Show command reference information for the <code>cdk synthesize</code> command.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-synth-options-quiet" class="dlist"> -<dl> -<dt class="hdlist1"><code>--quiet, -q <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Do not output the CloudFormation template to <code>stdout</code>.</p> -<div class="paragraph"> -<p>This option can be configured in the CDK project’s <code class="path">cdk.json</code> file. The following is an example:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-json" data-lang="json">{ - "quiet": true -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>false</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-synth-options-validation" class="dlist"> -<dl> -<dt class="hdlist1"><code>--validation <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Validate the generated CloudFormation templates after synthesis by performing additional checks.</p> -<div class="paragraph"> -<p>You can also configure this option through the <code>validateOnSynth</code> attribute or <code>CDK_VALIDATION</code> environment variable.</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>true</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-synth-examples">18.22.4. Examples</h4> -<div class="sect4"> -<h5 id="ref-cli-cmd-synth-examples-1">Synthesize the cloud assembly for a CDK stack with logial ID MyStackName and output the CloudFormation template to stdout</h5> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk synth MyStackName</code></pre> -</div> -</div> -</div> -<div class="sect4"> -<h5 id="ref-cli-cmd-synth-examples-2">Synthesize the cloud assembly for all stacks in a CDK app and save them into cdk.out</h5> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk synth</code></pre> -</div> -</div> -</div> -<div class="sect4"> -<h5 id="ref-cli-cmd-synth-examples-3">Synthesize the cloud assembly for MyStackName, but don’t include dependencies</h5> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk synth MyStackName --exclusively</code></pre> -</div> -</div> -</div> -<div class="sect4"> -<h5 id="ref-cli-cmd-synth-examples-4">Synthesize the cloud assembly for MyStackName, but don’t output the CloudFormation template to stdout</h5> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk synth MyStackName --quiet</code></pre> -</div> -</div> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="ref-cli-cmd-watch">18.23. <code class="noloc">cdk watch</code></h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Continuously watch a local AWS CDK project for changes to perform deployments and hotswaps.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>Continuously watch a local AWS CDK project for changes to perform deployments and hotswaps.</p> -</div> -<div class="paragraph"> -<p>This command is similar to <code>cdk deploy</code>, except that it can perform continuous deployments and hotswaps through a single command.</p> -</div> -<div class="paragraph"> -<p>This command is a shortcut for <code>cdk deploy --watch</code>.</p> -</div> -<div class="paragraph"> -<p>To end a <code>cdk watch</code> session, interrupt the process by pressing <code>Ctrl+C</code>.</p> -</div> -<div class="paragraph"> -<p>The files that are observed is determined by the <code>"watch"</code> setting in your <code class="path">cdk.json</code> file. It has two sub-keys, <code>"include"</code> and <code>"exclude"</code>, that accepts a single string or an array of strings. Each entry is interpreted as a path relative to the location of the <code class="path">cdk.json</code> file. Both <code>*</code> and <code>\**</code> are accepted.</p> -</div> -<div class="paragraph"> -<p>If you create a project using the <code>cdk init</code> command, the following default behavior is configured for <code>cdk watch</code> in your project’s <code class="path">cdk.json</code> file:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><code>"include"</code> is set to <code>"<strong>*/</strong>"</code>, which includes all files and directories in the root of the project.</p> -</li> -<li> -<p><code>"exclude"</code> is optional, except for files and folders already ignored by default. This consists of files and directories starting with <code>.</code>, the CDK output directory, and the <code class="path">node_modules</code> directory.</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>The minimal setting to configure <code>watch</code> is <code>"watch": {}</code>.</p> -</div> -<div class="paragraph"> -<p>If either your CDK code or application code requires a build step before deployment, <code>cdk watch</code> works with the <code>"build"</code> key in the <code class="path">cdk.json</code> file.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>This command is considered experimental and may have breaking changes in the future.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>The same limitations of <code>cdk deploy --hotswap</code> applies to <code>cdk watch</code>. For more information, see <code><a href="#ref-cli-cmd-deploy-options-hotswap">cdk deploy --hotswap</a></code>.</p> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-watch-usage">18.23.1. Usage</h4> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk watch <arguments> <options></code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-watch-args">18.23.2. Arguments</h4> -<div id="ref-cli-cmd-watch-args-stack-name" class="dlist"> -<dl> -<dt class="hdlist1">CDK stack ID</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The construct ID of the CDK stack from your app to watch.</p> -<div class="paragraph"> -<p><em>Type</em>: String</p> -</div> -<div class="paragraph"> -<p><em>Required</em>: No</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-watch-options">18.23.3. Options</h4> -<div class="paragraph"> -<p>For a list of global options that work with all CDK <code class="noloc">CLI</code> commands, see <a href="#ref-cli-cmd-options">Global options</a>.</p> -</div> -<div id="ref-cli-cmd-watch-options-build-exclude" class="dlist"> -<dl> -<dt class="hdlist1"><code>--build-exclude, -E <code class="replaceable">ARRAY</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Do not rebuild asset with the given ID.</p> -<div class="paragraph"> -<p>This option can be specified multiple times in a single command.</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>[]</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-watch-options-change-set-name" class="dlist"> -<dl> -<dt class="hdlist1"><code>--change-set-name <code class="replaceable">STRING</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The name of the CloudFormation change set to create.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-watch-options-concurrency" class="dlist"> -<dl> -<dt class="hdlist1"><code>--concurrency <code class="replaceable">NUMBER</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Deploy and hotswap multiple stacks in parallel while accounting for inter-stack dependencies. Use this option to speed up deployments. You must still factor in CloudFormation and other AWS account rate limiting.</p> -<div class="paragraph"> -<p>Provide a number to specify the maximum number of simultaneous deployments (dependency permitting) to perform.</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>1</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-watch-options-exclusively" class="dlist"> -<dl> -<dt class="hdlist1"><code>--exclusively, -e <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Only deploy requested stacks and don’t include dependencies.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-watch-options-force" class="dlist"> -<dl> -<dt class="hdlist1"><code>--force, -f <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Always deploy stacks, even if templates are identical.</p> -<div class="paragraph"> -<p><em>Default value</em>: <code>false</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-watch-options-help" class="dlist"> -<dl> -<dt class="hdlist1"><code>--help, -h <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Show command reference information for the <code>cdk watch</code> command.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-watch-options-hotswap" class="dlist"> -<dl> -<dt class="hdlist1"><code>--hotswap <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>By default, <code>cdk watch</code> uses hotswap deployments when possible to update your resources. The CDK <code class="noloc">CLI</code> will attempt to perform a hotswap deployment and will not fall back to a full CloudFormation deployment if unsuccessful. Any changes detected that cannot be updated through a hotswap are ignored.</p> -<div class="paragraph"> -<p><em>Default value</em>: <code>true</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-watch-options-hotswap-fallback" class="dlist"> -<dl> -<dt class="hdlist1"><code>--hotswap-fallback <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>By default, <code>cdk watch</code> attempts to perform hotswap deployments and ignores changes that require CloudFormation deployments. Provide <code>--hotswap-fallback</code> to fall back and perform a full CloudFormation deployment if the hotswap deployment is unsuccessful.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-watch-options-logs" class="dlist"> -<dl> -<dt class="hdlist1"><code>--logs <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>By default, <code>cdk watch</code> monitors all CloudWatch log groups in your application and streams the log events locally to <code>stdout</code>.</p> -<div class="paragraph"> -<p><em>Default value</em>: <code>true</code></p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-watch-options-progress" class="dlist"> -<dl> -<dt class="hdlist1"><code>--progress <code class="replaceable">STRING</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Configure how the CDK <code class="noloc">CLI</code> displays deployment progress.</p> -<div class="ulist"> -<ul> -<li> -<p><code>bar</code> – Display stack deployment events as a progress bar, with the events for the resource currently being deployed.</p> -</li> -<li> -<p><code>events</code> – Provide a complete history, including all CloudFormation events.</p> -</li> -</ul> -</div> -</li> -</ul> -</div> -<div class="paragraph"> -<p>You can also configure this option in the project’s <code class="path">cdk.json</code> file or at <code class="path">~/.cdk.json</code> on your local development machine:</p> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-json" data-lang="json">{ - "progress": "events" -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p><em>Valid values</em>: <code>bar</code>, <code>events</code></p> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>bar</code></p> -</div> -</dd> -</dl> -</div> -<div id="ref-cli-cmd-watch-options-rollback" class="dlist"> -<dl> -<dt class="hdlist1"><code>--rollback <code class="replaceable">BOOLEAN</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>During deployment, if a resource fails to be created or updated, the deployment will roll back to the latest stable state before the CDK <code class="noloc">CLI</code> returns. All changes made up to that point will be undone. Resources that were created will be deleted and updates that were made will be rolled back.</p> -<div class="paragraph"> -<p>Use <code>--no-rollback</code> or <code>-R</code> to deactivate this behavior. If a resource fails to be created or updated, the CDK <code class="noloc">CLI</code> will leave changes made up to that point in place and return. This may be helpful in development environments where you are iterating quickly.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -When <code>false</code>, deployments that cause resource replacements will always fail. You can only use this value for deployments that update or create new resources. -</td> -</tr> -</table> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div class="paragraph"> -<p><em>Default value</em>: <code>true</code></p> -</div> -<div id="ref-cli-cmd-watch-options-toolkit-stack-name" class="dlist"> -<dl> -<dt class="hdlist1"><code>--toolkit-stack-name <code class="replaceable">STRING</code></code></dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>The name of the existing CDK Toolkit stack.</p> -<div class="paragraph"> -<p>By default, <code>cdk bootstrap</code> deploys a stack named <code class="path">CDKToolkit</code> into the specified AWS environment. Use this option to provide a different name for your bootstrap stack.</p> -</div> -<div class="paragraph"> -<p>The CDK <code class="noloc">CLI</code> uses this value to verify your bootstrap stack version.</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect3"> -<h4 id="ref-cli-cmd-watch-examples">18.23.4. Examples</h4> -<div class="sect4"> -<h5 id="ref-cli-cmd-watch-examples-1">Watch a CDK stack with logical ID DevelopmentStack for changes</h5> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk watch DevelopmentStack -Detected change to 'lambda-code/index.js' (type: change). Triggering 'cdk deploy' -DevelopmentStack: deploying... - - ✅ DevelopmentStack</code></pre> -</div> -</div> -</div> -<div class="sect4"> -<h5 id="ref-cli-cmd-watch-examples-2">Configure a cdk.json file for what to include and exclude from being watched for changes</h5> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-json" data-lang="json">{ - "app": "mvn -e -q compile exec:java", - "watch": { - "include": "src/main/**", - "exclude": "target/*" - } -}</code></pre> -</div> -</div> -</div> -<div class="sect4"> -<h5 id="ref-cli-cmd-watch-examples-3">Build a CDK project using <code class="noloc">Java</code> before deployment by configuring the cdk.json file</h5> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-json" data-lang="json">{ - "app": "mvn -e -q exec:java", - "build": "mvn package", - "watch": { - "include": "src/main/**", - "exclude": "target/*" - } -}</code></pre> -</div> -</div> -</div> -</div> -</div> -</div> -</div> -<div class="sect1"> -<h2 id="reference">19. AWS CDK reference</h2> -<div class="sectionbody"> -<div class="paragraph"> -<p>This section contains reference information for the AWS Cloud Development Kit (AWS CDK).</p> -</div> -<div class="paragraph topiclist"> -<p>[[Topic List]]</p> -</div> -<div class="sect2"> -<h3 id="reference-api">19.1. API reference</h3> -<div class="paragraph"> -<p>The <a href="https://docs.aws.amazon.com/cdk/api/v2">API Reference</a> contains information about the AWS Construct Library and other APIs provided by the AWS Cloud Development Kit (AWS CDK). Most of the AWS Construct Library is contained in a single package called by its <code class="noloc">TypeScript</code> name: <code>aws-cdk-lib</code>. The actual package name varies by language. Separate versions of the API reference are provided for each supported programming language.</p> -</div> -<div class="paragraph"> -<p>The CDK API reference is organized into sub-modules. There are one or more sub-modules for each AWS service.</p> -</div> -<div class="paragraph"> -<p>Each sub-module has an overview that includes information about how to use its APIs. For example, the <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3-readme.html">S3</a> overview demonstrates how to set default encryption on an Amazon Simple Storage Service (Amazon S3) bucket.</p> -</div> -</div> -<div class="sect2 topic"> -<h3 id="versioning">19.2. AWS CDK versioning</h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>This topic provides reference information on how the AWS Cloud Development Kit (AWS CDK) handles versioning.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>This topic provides reference information on how the AWS Cloud Development Kit (AWS CDK) handles versioning.</p> -</div> -<div class="paragraph"> -<p>Version numbers consist of three numeric version parts: <em>major</em>.<em>minor</em>.<em>patch</em>, and strictly adhere to the <a href="https://semver.org">semantic versioning</a> model. This means that breaking changes to stable APIs are limited to major releases.</p> -</div> -<div class="paragraph"> -<p>Minor and patch releases are backward compatible. The code written in a previous version with the same major version can be upgraded to a newer version within the same major version. It will also continue to build and run, producing the same output.</p> -</div> -<div class="paragraph topiclist"> -<p>[[Topic List]]</p> -</div> -<div class="sect3"> -<h4 id="cdk-toolkit-versioning">19.2.1. AWS CDK <code class="noloc">CLI</code> compatibility</h4> -<div class="paragraph"> -<p>Each version of the main AWS CDK library (<code>aws-cdk-lib</code>) is compatible with the AWS CDK <code class="noloc">CLI</code> (<code>aws-cdk-cli</code>) version that was current at the time of the CDK library’s release. It is also compatible with any newer version of the CDK <code class="noloc">CLI</code>. Each version of the CDK library maintains this compatibility until the library’s <em>End of Life</em> date. Therefore, as long as you’re using a supported CDK library version, it is always safe to upgrade your CDK <code class="noloc">CLI</code> version.</p> -</div> -<div class="paragraph"> -<p>Each version of the CDK library may also work with CDK <code class="noloc">CLI</code> versions older than the version that was current at the time of the CDK library’s release. However, this is not guaranteed. Compatibility depends on the CDK library’s cloud assembly schema version. The AWS CDK generates a cloud assembly during synthesis and the CDK <code class="noloc">CLI</code> consumes it for deployment. The schema that defines the format of the cloud assembly is strictly specified and versioned. Therefore, an older version of the CDK <code class="noloc">CLI</code> would need to support the cloud assembly schema version of the CDK library for them to be compatible.</p> -</div> -<div class="paragraph"> -<p>When the cloud assembly version required by the CDK library is not compatible with the version supported by the CDK <code class="noloc">CLI</code>, you receive an error message like the following:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre>Cloud assembly schema version mismatch: Maximum schema version supported is 3.0.0, but found 4.0.0. - Please upgrade your CLI in order to interact with this app.</pre> -</div> -</div> -<div class="paragraph"> -<p>To resolve this error, update the CDK <code class="noloc">CLI</code> to a version compatible with the required cloud assembly version, or to the latest available version. The alternative (downgrading the construct library modules your app uses) is generally not recommended.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>For more information on the exact combinations of versions that work together, see the <a href="https://github.com/aws/aws-cdk-cli/blob/main/COMPATIBILITY.md">compatibility table</a> in the <em>aws-cdk-cli <code class="noloc">GitHub</code> repository</em>.</p> -</div> -</td> -</tr> -</table> -</div> -</div> -<div class="sect3"> -<h4 id="aws-construct-lib-stability">19.2.2. AWS Construct Library versioning</h4> -<div class="paragraph"> -<p>The modules in the AWS Construct Library move through various stages as they are developed from concept to mature API. Different stages offer varying degrees of API stability in subsequent versions of the AWS CDK.</p> -</div> -<div class="paragraph"> -<p>APIs in the main AWS CDK library, <code>aws-cdk-lib</code>, are stable, and the library is fully semantically versioned. This package includes AWS CloudFormation (L1) constructs for all AWS services and all stable higher-level (L2 and L3) modules. (It also includes the core CDK classes like <code>App</code> and <code>Stack</code>). APIs will not be removed from this package (though they may be deprecated) until the next major release of the CDK. No individual API will ever have breaking changes. When a breaking change is required, an entirely new API will be added.</p> -</div> -<div class="paragraph"> -<p>New APIs under development for a service already incorporated in <code>aws-cdk-lib</code> are identified using a <code>Beta<code class="replaceable">N</code></code> suffix, where <code>N</code> starts at 1 and is incremented with each breaking change to the new API. <code>Beta<code class="replaceable">N</code></code> APIs are never removed, only deprecated, so your existing app continues to work with newer versions of <code>aws-cdk-lib</code>. When the API is deemed stable, a new API without the <code>Beta<code class="replaceable">N</code></code> suffix is added.</p> -</div> -<div class="paragraph"> -<p>When higher-level (L2 or L3) APIs begin to be developed for an AWS service that previously had only L1 APIs, those APIs are initially distributed in a separate package. The name of such a package has an "Alpha" suffix, and its version matches the first version of <code>aws-cdk-lib</code> it is compatible with, with an <code>alpha</code> sub-version. When the module supports the intended use cases, its APIs are added to <code>aws-cdk-lib</code>.</p> -</div> -</div> -<div class="sect3"> -<h4 id="aws-construct-lib-versioning-binding">19.2.3. Language binding stability</h4> -<div class="paragraph"> -<p>Over time, we might add support to the AWS CDK for additional programming languages. Although the API described in all the languages is the same, the way that API is expressed varies by language and might change as the language support evolves. For this reason, language bindings are deemed experimental for a time until they are considered ready for production use.</p> -</div> -<table class="tableblock frame-all grid-all stretch"> -<colgroup> -<col style="width: 50%;"> -<col style="width: 50%;"> -</colgroup> -<thead> -<tr> -<th class="tableblock halign-left valign-top">Language</th> -<th class="tableblock halign-left valign-top">Stability</th> -</tr> -</thead> -<tbody> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">TypeScript</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Stable</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">JavaScript</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Stable</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">Python</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Stable</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">Java</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Stable</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">C#/.NET</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Stable</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">Go</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Stable</p></td> -</tr> -</tbody> -</table> -</div> -</div> -<div class="sect2 topic"> -<h3 id="videos">19.3. AWS CDK video resources</h3> -<div class="paragraph"> -<p>Enjoy these videos presented by members of the AWS CDK team.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>Since the AWS CDK is always evolving, some of the code presented in these videos may not work quite the same way it did when the video was recorded. This is especially true for modules that were under active development at the time. It’s also possible that we’ve since added a better way to achieve the same result. Consult this Developer Guide and the <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-construct-library.html">AWS CDK API Reference</a> for up-to-date information.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="sect3"> -<h4 id="videos-infrastructure-is-code">19.3.1. Infrastructure <em>is</em> Code with the AWS CDK</h4> -<div class="videoblock"> -<div class="content"> -<iframe width="800" height="450" src="https://www.youtube.com/embed/ZWCvNFUN-sU?rel=0" frameborder="0" allowfullscreen></iframe> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="videos-deep-dive">19.3.2. Deep dive into AWS Cloud Development Kit (AWS CDK)</h4> -<div class="videoblock"> -<div class="content"> -<iframe width="800" height="450" src="https://www.youtube.com/embed/9As_ZIjUGmY?rel=0" frameborder="0" allowfullscreen></iframe> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="videos-contributing">19.3.3. Contributing to the AWS Construct Library</h4> -<div class="videoblock"> -<div class="content"> -<iframe width="800" height="450" src="https://www.youtube.com/embed/LsYlf7ggyrY?rel=0" frameborder="0" allowfullscreen></iframe> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="videos-pipeliens">19.3.4. Faster deployments with CDK Pipelines</h4> -<div class="videoblock"> -<div class="content"> -<iframe width="800" height="450" src="https://www.youtube.com/embed/1ps0Wh19MHQ?rel=0" frameborder="0" allowfullscreen></iframe> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="videos-gitpod">19.3.5. How to contribute to the AWS CDK using GitPod</h4> -<div class="videoblock"> -<div class="content"> -<iframe width="800" height="450" src="https://www.youtube.com/embed/u6XcIgs-Nok?rel=0" frameborder="0" allowfullscreen></iframe> -</div> -</div> -</div> -</div> -</div> -</div> -<div class="sect1 topic"> -<h2 id="how-tos">20. AWS CDK tutorials and examples</h2> -<div class="sectionbody"> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>This section contains tutorials and examples for the AWS Cloud Development Kit (AWS CDK).</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>This section contains tutorials and examples for the AWS Cloud Development Kit (AWS CDK).</p> -</div> -<div id="tutorials" class="dlist"> -<dl> -<dt class="hdlist1">Tutorials</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Tutorials provide you with step-by-step instructions that you can follow to implement a task using the AWS CDK.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div id="examples" class="dlist"> -<dl> -<dt class="hdlist1">Examples</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Examples show and explain how specific tasks can be implemented using the AWS CDK. They do not provide direct step-by-step instructions for you to follow.</p> -<div class="paragraph"> -<p>For more examples of AWS CDK stacks and apps in your favorite supported programming language, see the <a href="https://github.com/aws-samples/aws-cdk-examples">AWS CDK Examples</a> repository on GitHub.</p> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div class="sect2 topic"> -<h3 id="serverless-example">20.1. Tutorial: Create a serverless Hello World application</h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>In this tutorial, you use the AWS CDK to create a simple serverless <code class="noloc">Hello World</code> application that implements a basic API backend.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>In this tutorial, you use the AWS Cloud Development Kit (AWS CDK) to create a simple serverless <code class="noloc">Hello World</code> application that implements a basic API backend consisting of the following:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><strong>Amazon API Gateway <code class="noloc">REST API</code></strong> – Provides an HTTP endpoint that is used to invoke your function through an <code class="noloc">HTTP GET</code> request.</p> -</li> -<li> -<p><strong>AWS Lambda function</strong> – Function that returns a <code>Hello World!</code> message when invoked with the <code class="noloc">HTTP</code> endpoint.</p> -</li> -<li> -<p><strong>Integrations and permissions</strong> – Configuration details and permissions for your resources to interact with one another and perform actions, such as writing logs to Amazon CloudWatch.</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>The following diagram shows the components of this application:</p> -</div> -<div class="imageblock"> -<div class="content"> -<img src="images/serverless-example-01.png" alt="Diagram of a Lambda function that is invoked when you send a GET request to the API Gateway endpoint."> -</div> -</div> -<div class="paragraph"> -<p>For this tutorial, you will create and interact with your application in the following steps:</p> -</div> -<div class="olist arabic"> -<ol class="arabic"> -<li> -<p>Create an AWS CDK project.</p> -</li> -<li> -<p>Define a Lambda function and API Gateway REST API using L2 constructs from the AWS Construct Library.</p> -</li> -<li> -<p>Deploy your application to the AWS Cloud.</p> -</li> -<li> -<p>Interact with your application in the AWS Cloud.</p> -</li> -<li> -<p>Delete the sample application from the AWS Cloud.</p> -</li> -</ol> -</div> -<div class="sect3"> -<h4 id="serverless-example-pre">Prerequisites</h4> -<div class="paragraph"> -<p>Before starting this tutorial, complete the following:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Create an AWS account and have the AWS Command Line Interface (AWS CLI) installed and configured.</p> -</li> -<li> -<p>Install <code class="noloc">Node.js</code> and <code class="noloc">npm</code>.</p> -</li> -<li> -<p>Install the CDK Toolkit globally, using <code>npm install -g aws-cdk</code>.</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>For more information, see <a href="#getting-started">Getting started with the AWS CDK</a>.</p> -</div> -<div class="paragraph"> -<p>We also recommend a basic understanding of the following:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><a href="#home">What is the AWS CDK?</a> for a basic introduction to the AWS CDK.</p> -</li> -<li> -<p><a href="#core-concepts">Learn AWS CDK core concepts</a> for an overview of core concepts of the AWS CDK.</p> -</li> -</ul> -</div> -</div> -<div class="sect3"> -<h4 id="serverless-example-project">20.1.1. Step 1: Create a CDK project</h4> -<div class="paragraph"> -<p>In this step, you create a new CDK project using the AWS CDK <code class="noloc">CLI</code><code>cdk init</code> command.</p> -</div> -<div class="olist arabic"> -<ol class="arabic"> -<li> -<p>From a starting directory of your choice, create and navigate to a project directory named <code class="path">cdk-hello-world</code> on your machine:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ mkdir cdk-hello-world && cd cdk-hello-world</code></pre> -</div> -</div> -</li> -<li> -<p>Use the <code>cdk init</code> command to create a new project in your preferred programming language:</p> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>**</p> -</dd> -</dl> -</div> -</li> -</ol> -</div> -<div class="listingblock"> -<div class="content"> -<pre>$ cdk init --language typescript</pre> -</div> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p>Install AWS CDK libraries:</p> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ npm install aws-cdk-lib constructs</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>**</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk init --language javascript</code></pre> -</div> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p>Install AWS CDK libraries:</p> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ npm install aws-cdk-lib constructs</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>**</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk init --language python</code></pre> -</div> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p>Activate the virtual environment:</p> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ source .venv/bin/activate # On Windows, run '.\venv\Scripts\activate' instead</code></pre> -</div> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p>Install AWS CDK libraries and project dependencies:</p> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>(.venv)$ python3 -m pip install -r requirements.txt</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>**</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk init --language java</code></pre> -</div> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p>Install AWS CDK libraries and project dependencies:</p> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ mvn package</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>**</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk init --language csharp</code></pre> -</div> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p>Install AWS CDK libraries and project dependencies:</p> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ dotnet restore src</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>**</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk init --language go</code></pre> -</div> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p>Install project dependencies:</p> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ go get github.com/aws/aws-cdk-go/awscdk/v2 -$ go get github.com/aws/aws-cdk-go/awscdk/v2/awslambda -$ go get github.com/aws/aws-cdk-go/awscdk/v2/awsapigateway -$ go mod tidy</code></pre> -</div> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p>The CDK <code class="noloc">CLI</code> creates a project with the following structure:</p> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>**</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk-hello-world -├── .git -├── .gitignore -├── .npmignore -├── README.md -├── bin -│ └── cdk-hello-world.ts -├── cdk.json -├── jest.config.js -├── lib -│ └── cdk-hello-world-stack.ts -├── node_modules -├── package-lock.json -├── package.json -├── test -│ └── cdk-hello-world.test.ts -└── tsconfig.json</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>**</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk-hello-world -├── .git -├── .gitignore -├── .npmignore -├── README.md -├── bin -│ └── cdk-hello-world.js -├── cdk.json -├── jest.config.js -├── lib -│ └── cdk-hello-world-stack.js -├── node_modules -├── package-lock.json -├── package.json -└── test - └── cdk-hello-world.test.js</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>**</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk-hello-world -├── .git -├── .gitignore -├── .venv -├── README.md -├── app.py -├── cdk.json -├── cdk_hello_world -│ ├── __init__.py -│ └── cdk_hello_world_stack.py -├── requirements-dev.txt -├── requirements.txt -├── source.bat -└── tests</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>**</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk-hello-world -├── .git -├── .gitignore -├── README.md -├── cdk.json -├── pom.xml -├── src -│ ├── main -│ │ └── java -│ │ └── com -│ │ └── myorg -│ │ ├── CdkHelloWorldApp.java -│ │ └── CdkHelloWorldStack.java -└── target</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>**</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk-hello-world -├── .git -├── .gitignore -├── README.md -├── cdk.json -└── src - ├── CdkHelloWorld - │ ├── CdkHelloWorld.csproj - │ ├── CdkHelloWorldStack.cs - │ ├── GlobalSuppressions.cs - │ └── Program.cs - └── CdkHelloWorld.sln</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>**</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk-hello-world -├── .git -├── .gitignore -├── README.md -├── cdk-hello-world.go -├── cdk-hello-world_test.go -├── cdk.json -├── go.mod -└── go.sum</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The CDK <code class="noloc">CLI</code> automatically creates a CDK app that contains a single stack. The CDK app instance is created from the <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.App.html">App</a></code> class. The following is a portion of your CDK application file:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">bin/cdk-hello-world.ts</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">#!/usr/bin/env node -import 'source-map-support/register'; -import * as cdk from 'aws-cdk-lib'; -import { CdkHelloWorldStack } from '../lib/cdk-hello-world-stack'; - -const app = new cdk.App(); -new CdkHelloWorldStack(app, 'CdkHelloWorldStack', { -});</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">JavaScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">bin/cdk-hello-world.js</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">#!/usr/bin/env node -const cdk = require('aws-cdk-lib'); -const { CdkHelloWorldStack } = require('../lib/cdk-hello-world-stack'); -const app = new cdk.App(); -new CdkHelloWorldStack(app, 'CdkHelloWorldStack', { -});</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Python</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">app.py</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">#!/usr/bin/env python3 -import os -import aws_cdk as cdk -from cdk_hello_world.cdk_hello_world_stack import CdkHelloWorldStack - -app = cdk.App() -CdkHelloWorldStack(app, "CdkHelloWorldStack",) -app.synth()</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Java</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">src/main/java/…​/CdkHelloWorldApp.java</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">package com.myorg; - -import software.amazon.awscdk.App; -import software.amazon.awscdk.Environment; -import software.amazon.awscdk.StackProps; - -import java.util.Arrays; - -public class JavaApp { - public static void main(final String[] args) { - App app = new App(); - - new JavaStack(app, "JavaStack", StackProps.builder() - .build()); - - app.synth(); - } -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">C#</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">src/CdkHelloWorld/Program.cs</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace CdkHelloWorld -{ - sealed class Program - { - public static void Main(string[] args) - { - var app = new App(); - new CdkHelloWorldStack(app, "CdkHelloWorldStack", new StackProps - { - - }); - app.Synth(); - } - } -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Go</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">cdk-hello-world.go</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">package main -import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/constructs-go/constructs/v10" - "github.com/aws/jsii-runtime-go" -) - -// ... - -func main() { - defer jsii.Close() - app := awscdk.NewApp(nil) - NewCdkHelloWorldStack(app, "CdkHelloWorldStack", &CdkHelloWorldStackProps{ - awscdk.StackProps{ - Env: env(), - }, - }) - app.Synth(nil) -} - -func env() *awscdk.Environment { - return nil -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect3"> -<h4 id="serverless-example-function">20.1.2. Step 2: Create your Lambda function</h4> -<div class="paragraph"> -<p>Within your CDK project, create a <code class="path">lambda</code> directory that includes a new <code class="path">hello.js</code> file. The following is an example:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>From the root of your project, run the following:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ mkdir lambda && cd lambda -$ touch hello.js</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The following should now be added to your CDK project:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk-hello-world -└── lambda - └── hello.js</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">JavaScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>From the root of your project, run the following:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ mkdir lambda && cd lambda -$ touch hello.js</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The following should now be added to your CDK project:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk-hello-world -└── lambda - └── hello.js</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Python</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>From the root of your project, run the following:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ mkdir lambda && cd lambda -$ touch hello.js</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The following should now be added to your CDK project:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk-hello-world -└── lambda - └── hello.js</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Java</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>From the root of your project, run the following:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ mkdir -p src/main/resources/lambda -$ cd src/main/resources/lambda -$ touch hello.js</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The following should now be added to your CDK project:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk-hello-world -└── src - └── main - └──resources - └──lambda - └──hello.js</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">C#</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>From the root of your project, run the following:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ mkdir lambda && cd lambda -$ touch hello.js</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The following should now be added to your CDK project:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk-hello-world -└── lambda - └── hello.js</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Go</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>From the root of your project, run the following:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ mkdir lambda && cd lambda -$ touch hello.js</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The following should now be added to your CDK project:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk-hello-world -└── lambda - └── hello.js</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>To keep this tutorial simple, we use a <code class="noloc">JavaScript</code> Lambda function for all CDK programming languages.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>Define your Lambda function by adding the following to the newly created file:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">exports.handler = async (event) => { - return { - statusCode: 200, - headers: { "Content-Type": "text/plain" }, - body: JSON.stringify({ message: "Hello, World!" }), - }; -};</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="serverless-example-constructs">20.1.3. Step 3: Define your constructs</h4> -<div class="paragraph"> -<p>In this step, you will define your Lambda and API Gateway resources using AWS CDK L2 constructs.</p> -</div> -<div class="paragraph"> -<p>Open the project file that defines your CDK stack. You will modify this file to define your constructs. The following is an example of your starting stack file:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">lib/cdk-hello-world-stack.ts</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as cdk from 'aws-cdk-lib'; -import { Construct } from 'constructs'; - -export class CdkHelloWorldStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - // Your constructs will go here - - } -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">JavaScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">lib/cdk-hello-world-stack.js</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const { Stack, Duration } = require('aws-cdk-lib'); -const lambda = require('aws-cdk-lib/aws-lambda'); -const apigateway = require('aws-cdk-lib/aws-apigateway'); - -class CdkHelloWorldStack extends Stack { - - constructor(scope, id, props) { - super(scope, id, props); - - // Your constructs will go here - - } -} - -module.exports = { CdkHelloWorldStack }</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Python</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">cdk_hello_world/cdk_hello_world_stack.py</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">from aws_cdk import Stack -from constructs import Construct - -class CdkHelloWorldStack(Stack): - def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: - super().__init__(scope, construct_id, **kwargs) - - // Your constructs will go here</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Java</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">src/main/java/…​/CdkHelloWorldStack.java</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">package com.myorg; - -import software.constructs.Construct; -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.StackProps; - -public class CdkHelloWorldStack extends Stack { - public CdkHelloWorldStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public CdkHelloWorldStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - // Your constructs will go here - } -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">C#</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located in <code class="path">src/CdkHelloWorld/CdkHelloWorldStack.cs</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; -using Constructs; - -namespace CdkHelloWorld -{ - public class CdkHelloWorldStack : Stack - { - internal CdkHelloWorldStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) - { - // Your constructs will go here - } - } -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Go</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Located at <code class="path">cdk-hello-world.go</code>:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">package main - -import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/constructs-go/constructs/v10" - "github.com/aws/jsii-runtime-go" -) - -type CdkHelloWorldStackProps struct { - awscdk.StackProps -} - -func NewCdkHelloWorldStack(scope constructs.Construct, id string, props *CdkHelloWorldStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - stack := awscdk.NewStack(scope, &id, &sprops) - - // Your constructs will go here - - return stack -} - -func main() { - - // ... - -} - -func env() *awscdk.Environment { - - return nil - -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div class="paragraph"> -<p>In this file, the AWS CDK is doing the following:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Your CDK stack instance is instantiated from the <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html">Stack</a></code> class.</p> -</li> -<li> -<p>The <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/constructs-readme.html">Constructs</a></code> base class is imported and provided as the scope or parent of your stack instance.</p> -</li> -</ul> -</div> -<div class="sect4"> -<h5 id="serverless-example-constructs-lambda">Define your Lambda function resource</h5> -<div class="paragraph"> -<p>To define your Lambda function resource, you import and use the <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda-readme.html">aws-lambda</a></code> L2 construct from the AWS Construct Library.</p> -</div> -<div class="paragraph"> -<p>Modify your stack file as follows:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as cdk from 'aws-cdk-lib'; -import { Construct } from 'constructs'; -// Import Lambda L2 construct -import * as lambda from 'aws-cdk-lib/aws-lambda'; - -export class CdkHelloWorldStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - // Define the Lambda function resource - const helloWorldFunction = new lambda.Function(this, 'HelloWorldFunction', { - runtime: lambda.Runtime.NODEJS_20_X, // Choose any supported Node.js runtime - code: lambda.Code.fromAsset('lambda'), // Points to the lambda directory - handler: 'hello.handler', // Points to the 'hello' file in the lambda directory - }); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const { Stack, Duration } = require('aws-cdk-lib'); -// Import Lambda L2 construct -const lambda = require('aws-cdk-lib/aws-lambda'); - - -class CdkHelloWorldStack extends Stack { - constructor(scope, id, props) { - super(scope, id, props); - - // Define the Lambda function resource - const helloWorldFunction = new lambda.Function(this, 'HelloWorldFunction', { - runtime: lambda.Runtime.NODEJS_20_X, // Choose any supported Node.js runtime - code: lambda.Code.fromAsset('lambda'), // Points to the lambda directory - handler: 'hello.handler', // Points to the 'hello' file in the lambda directory - }); - } -} - -module.exports = { CdkHelloWorldStack }</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">from aws_cdk import ( - Stack, - # Import Lambda L2 construct - aws_lambda as _lambda, -) -# ... - -class CdkHelloWorldStack(Stack): - - def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: - super().__init__(scope, construct_id, **kwargs) - - # Define the Lambda function resource - hello_world_function = _lambda.Function( - self, - "HelloWorldFunction", - runtime = _lambda.Runtime.NODEJS_20_X, # Choose any supported Node.js runtime - code = _lambda.Code.from_asset("lambda"), # Points to the lambda directory - handler = "hello.handler", # Points to the 'hello' file in the lambda directory - )</code></pre> -</div> -</div> -<div class="paragraph"> -<p>+ -NOTE: We import the <code>aws_lambda</code> module as <code>\_lambda</code> because <code>lambda</code> is a build-in identifier in <code class="noloc">Python</code>.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">// ... -// Import Lambda L2 construct -import software.amazon.awscdk.services.lambda.Code; -import software.amazon.awscdk.services.lambda.Function; -import software.amazon.awscdk.services.lambda.Runtime; - -public class CdkHelloWorldStack extends Stack { - public CdkHelloWorldStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public CdkHelloWorldStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - // Define the Lambda function resource - Function helloWorldFunction = Function.Builder.create(this, "HelloWorldFunction") - .runtime(Runtime.NODEJS_20_X) // Choose any supported Node.js runtime - .code(Code.fromAsset("src/main/resources/lambda")) // Points to the lambda directory - .handler("hello.handler") // Points to the 'hello' file in the lambda directory - .build(); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">// ... -// Import Lambda L2 construct -using Amazon.CDK.AWS.Lambda; - -namespace CdkHelloWorld -{ - public class CdkHelloWorldStack : Stack - { - internal CdkHelloWorldStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) - { - // Define the Lambda function resource - var helloWorldFunction = new Function(this, "HelloWorldFunction", new FunctionProps - { - Runtime = Runtime.NODEJS_20_X, // Choose any supported Node.js runtime - Code = Code.FromAsset("lambda"), // Points to the lambda directory - Handler = "hello.handler" // Points to the 'hello' file in the lambda directory - }); - } - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">package main - -import ( - // ... - // Import Lambda L2 construct - "github.com/aws/aws-cdk-go/awscdk/v2/awslambda" - // Import S3 assets construct - "github.com/aws/aws-cdk-go/awscdk/v2/awss3assets" - // ... -) - -// ... - -func NewCdkHelloWorldStack(scope constructs.Construct, id string, props *CdkHelloWorldStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - stack := awscdk.NewStack(scope, &id, &sprops) - - // Define the Lambda function resource - helloWorldFunction := awslambda.NewFunction(stack, jsii.String("HelloWorldFunction"), &awslambda.FunctionProps{ - Runtime: awslambda.Runtime_NODEJS_20_X(), // Choose any supported Node.js runtime - Code: awslambda.Code_FromAsset(jsii.String("lambda"), &awss3assets.AssetOptions{}), // Points to the lambda directory - Handler: jsii.String("hello.handler"), // Points to the 'hello' file in the lambda directory - }) - - return stack -} - -// ...</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Here, you create a Lambda function resource and define the following properties:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><code>runtime</code> – The environment the function runs in. Here, we use <code class="noloc">Node.js</code> version <code class="noloc">20.x</code>.</p> -</li> -<li> -<p><code>code</code> – The path to the function code on your local machine.</p> -</li> -<li> -<p><code>handler</code> – The name of the specific file that contains your function code.</p> -</li> -</ul> -</div> -</div> -<div class="sect4"> -<h5 id="serverless-example-constructs-api">Define your API Gateway <code class="noloc">REST API</code> resource</h5> -<div class="paragraph"> -<p>To define your API Gateway <code class="noloc">REST API</code> resource, you import and use the <code><a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_apigateway-readme.html">aws-apigateway</a></code> L2 construct from the AWS Construct Library.</p> -</div> -<div class="paragraph"> -<p>Modify your stack file as follows:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">// ... -//Import API Gateway L2 construct -import * as apigateway from 'aws-cdk-lib/aws-apigateway'; - - -export class CdkHelloWorldStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - // ... - - // Define the API Gateway resource - const api = new apigateway.LambdaRestApi(this, 'HelloWorldApi', { - handler: helloWorldFunction, - proxy: false, - }); - - // Define the '/hello' resource with a GET method - const helloResource = api.root.addResource('hello'); - helloResource.addMethod('GET'); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">// ... -// Import API Gateway L2 construct -const apigateway = require('aws-cdk-lib/aws-apigateway'); - - -class CdkHelloWorldStack extends Stack { - constructor(scope, id, props) { - super(scope, id, props); - - // ... - - // Define the API Gateway resource - const api = new apigateway.LambdaRestApi(this, 'HelloWorldApi', { - handler: helloWorldFunction, - proxy: false, - }); - - // Define the '/hello' resource with a GET method - const helloResource = api.root.addResource('hello'); - helloResource.addMethod('GET'); - }; -}; - -// ...</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">from aws_cdk import ( - # ... - # Import API Gateway L2 construct - aws_apigateway as apigateway, -) -from constructs import Construct - -class CdkHelloWorldStack(Stack): - - def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: - super().__init__(scope, construct_id, **kwargs) - - # ... - - # Define the API Gateway resource - api = apigateway.LambdaRestApi( - self, - "HelloWorldApi", - handler = hello_world_function, - proxy = False, - ) - - # Define the '/hello' resource with a GET method - hello_resource = api.root.add_resource("hello") - hello_resource.add_method("GET")</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">// ... -// Import API Gateway L2 construct -import software.amazon.awscdk.services.apigateway.LambdaRestApi; -import software.amazon.awscdk.services.apigateway.Resource; - -public class CdkHelloWorldStack extends Stack { - public CdkHelloWorldStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public CdkHelloWorldStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - // ... - - // Define the API Gateway resource - LambdaRestApi api = LambdaRestApi.Builder.create(this, "HelloWorldApi") - .handler(helloWorldFunction) - .proxy(false) // Turn off default proxy integration - .build(); - - // Define the '/hello' resource and its GET method - Resource helloResource = api.getRoot().addResource("hello"); - helloResource.addMethod("GET"); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">// ... -// Import API Gateway L2 construct -using Amazon.CDK.AWS.APIGateway; - -namespace CdkHelloWorld -{ - public class CdkHelloWorldStack : Stack - { - internal CdkHelloWorldStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) - { - // ... - - // Define the API Gateway resource - var api = new LambdaRestApi(this, "HelloWorldApi", new LambdaRestApiProps - { - Handler = helloWorldFunction, - Proxy = false - }); - - // Add a '/hello' resource with a GET method - var helloResource = api.Root.AddResource("hello"); - helloResource.AddMethod("GET"); - } - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Go</dt> -<dd> -<p>*</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-go" data-lang="go">// ... - -import ( - // ... - // Import Api Gateway L2 construct - "github.com/aws/aws-cdk-go/awscdk/v2/awsapigateway" - // ... -) - -// ... - -func NewCdkHelloWorldStack(scope constructs.Construct, id string, props *CdkHelloWorldStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - stack := awscdk.NewStack(scope, &id, &sprops) - - // Define the Lambda function resource - // ... - - // Define the API Gateway resource - api := awsapigateway.NewLambdaRestApi(stack, jsii.String("HelloWorldApi"), &awsapigateway.LambdaRestApiProps{ - Handler: helloWorldFunction, - Proxy: jsii.Bool(false), - }) - - // Add a '/hello' resource with a GET method - helloResource := api.Root().AddResource(jsii.String("hello"), &awsapigateway.ResourceOptions{}) - helloResource.AddMethod(jsii.String("GET"), awsapigateway.NewLambdaIntegration(helloWorldFunction, &awsapigateway.LambdaIntegrationOptions{}), &awsapigateway.MethodOptions{}) - - return stack -} - -// ...</code></pre> -</div> -</div> -</dd> -</dl> -</div> -<div class="paragraph"> -<p>Here, you create an API Gateway <code class="noloc">REST API</code> resource, along with the following:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>An integration between the <code class="noloc">REST API</code> and your Lambda function, allowing the API to invoke your function. This includes the creation of a Lambda permission resource.</p> -</li> -<li> -<p>A new resource or path named <code>hello</code> that is added to the root of the API endpoint. This creates a new endpoint that adds <code>/hello</code> to your base <code class="noloc">URL</code>.</p> -</li> -<li> -<p>A GET method for the <code>hello</code> resource. When a GET request is sent to the <code>/hello</code> endpoint, the Lambda function is invoked and its response is returned.</p> -</li> -</ul> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="serverless-example-deploy-prepare">20.1.4. Step 4: Prepare your application for deployment</h4> -<div class="paragraph"> -<p>In this step you prepare your application for deployment by building, if necessary, and performing basic validation with the AWS CDK <code class="noloc">CLI</code><code>cdk synth</code> command.</p> -</div> -<div class="paragraph"> -<p>If necessary, build your application:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>From the root of your project, run the following:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ npm run build</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">JavaScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Building is not required.</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Python</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Building is not required.</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Java</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>From the root of your project, run the following:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ mvn package</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">C#</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>From the root of your project, run the following:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ dotnet build src</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Go</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>Building is not required.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div class="paragraph"> -<p>Run <code>cdk synth</code> to synthesize an AWS CloudFormation template from your CDK code. By using L2 constructs, many of the configuration details required by AWS CloudFormation to facilitate the interaction between your Lambda function and <code class="noloc">REST API</code> are provisioned for you by the AWS CDK.</p> -</div> -<div class="paragraph"> -<p>From the root of your project, run the following:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk synth</code></pre> -</div> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>If you receive an error like the following, verify that you are in the <code class="path">cdk-hello-world</code> directory and try again:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre>--app is required either in command-line, in cdk.json or in ~/.cdk.json</pre> -</div> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>If successful, the AWS CDK <code class="noloc">CLI</code> will output the AWS CloudFormation template in <code class="noloc">YAML</code> format at the command prompt. A <code class="noloc">JSON</code> formatted template is also saved in the <code class="path">cdk.out</code> directory.</p> -</div> -<div class="paragraph"> -<p>The following is an example output of the AWS CloudFormation template:</p> -</div> -<details id="serverless-example-deploy-cfn"> -<summary class="title">AWS CloudFormation template</summary> -<div class="content"> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-yaml" data-lang="yaml">Resources: - HelloWorldFunctionServiceRoleunique-identifier: - Type: AWS::IAM::Role - Properties: - AssumeRolePolicyDocument: - Statement: - - Action: sts:AssumeRole - Effect: Allow - Principal: - Service: lambda.amazonaws.com - Version: "2012-10-17" - ManagedPolicyArns: - - Fn::Join: - - "" - - - "arn:" - - Ref: AWS::Partition - - :iam::aws:policy/service-role/AWSLambdaBasicExecutionRole - Metadata: - aws:cdk:path: CdkHelloWorldStack/HelloWorldFunction/ServiceRole/Resource - HelloWorldFunctionunique-identifier: - Type: AWS::Lambda::Function - Properties: - Code: - S3Bucket: - Fn::Sub: cdk-unique-identifier-assets-${AWS::AccountId}-${AWS::Region} - S3Key: unique-identifier.zip - Handler: hello.handler - Role: - Fn::GetAtt: - - HelloWorldFunctionServiceRoleunique-identifier - - Arn - Runtime: nodejs20.x - DependsOn: - - HelloWorldFunctionServiceRoleunique-identifier - Metadata: - aws:cdk:path: CdkHelloWorldStack/HelloWorldFunction/Resource - aws:asset:path: asset.unique-identifier - aws:asset:is-bundled: false - aws:asset:property: Code - HelloWorldApiunique-identifier: - Type: AWS::ApiGateway::RestApi - Properties: - Name: HelloWorldApi - Metadata: - aws:cdk:path: CdkHelloWorldStack/HelloWorldApi/Resource - HelloWorldApiDeploymentunique-identifier: - Type: AWS::ApiGateway::Deployment - Properties: - Description: Automatically created by the RestApi construct - RestApiId: - Ref: HelloWorldApiunique-identifier - DependsOn: - - HelloWorldApihelloGETunique-identifier - - HelloWorldApihellounique-identifier - Metadata: - aws:cdk:path: CdkHelloWorldStack/HelloWorldApi/Deployment/Resource - HelloWorldApiDeploymentStageprod012345ABC: - Type: AWS::ApiGateway::Stage - Properties: - DeploymentId: - Ref: HelloWorldApiDeploymentunique-identifier - RestApiId: - Ref: HelloWorldApiunique-identifier - StageName: prod - Metadata: - aws:cdk:path: CdkHelloWorldStack/HelloWorldApi/DeploymentStage.prod/Resource - HelloWorldApihellounique-identifier: - Type: AWS::ApiGateway::Resource - Properties: - ParentId: - Fn::GetAtt: - - HelloWorldApiunique-identifier - - RootResourceId - PathPart: hello - RestApiId: - Ref: HelloWorldApiunique-identifier - Metadata: - aws:cdk:path: CdkHelloWorldStack/HelloWorldApi/Default/hello/Resource - HelloWorldApihelloGETApiPermissionCdkHelloWorldStackHelloWorldApiunique-identifier: - Type: AWS::Lambda::Permission - Properties: - Action: lambda:InvokeFunction - FunctionName: - Fn::GetAtt: - - HelloWorldFunctionunique-identifier - - Arn - Principal: apigateway.amazonaws.com - SourceArn: - Fn::Join: - - "" - - - "arn:" - - Ref: AWS::Partition - - ":execute-api:" - - Ref: AWS::Region - - ":" - - Ref: AWS::AccountId - - ":" - - Ref: HelloWorldApi9E278160 - - / - - Ref: HelloWorldApiDeploymentStageprodunique-identifier - - /GET/hello - Metadata: - aws:cdk:path: CdkHelloWorldStack/HelloWorldApi/Default/hello/GET/ApiPermission.CdkHelloWorldStackHelloWorldApiunique-identifier.GET..hello - HelloWorldApihelloGETApiPermissionTestCdkHelloWorldStackHelloWorldApiunique-identifier: - Type: AWS::Lambda::Permission - Properties: - Action: lambda:InvokeFunction - FunctionName: - Fn::GetAtt: - - HelloWorldFunctionunique-identifier - - Arn - Principal: apigateway.amazonaws.com - SourceArn: - Fn::Join: - - "" - - - "arn:" - - Ref: AWS::Partition - - ":execute-api:" - - Ref: AWS::Region - - ":" - - Ref: AWS::AccountId - - ":" - - Ref: HelloWorldApiunique-identifier - - /test-invoke-stage/GET/hello - Metadata: - aws:cdk:path: CdkHelloWorldStack/HelloWorldApi/Default/hello/GET/ApiPermission.Test.CdkHelloWorldStackHelloWorldApiunique-identifier.GET..hello - HelloWorldApihelloGETunique-identifier: - Type: AWS::ApiGateway::Method - Properties: - AuthorizationType: NONE - HttpMethod: GET - Integration: - IntegrationHttpMethod: POST - Type: AWS_PROXY - Uri: - Fn::Join: - - "" - - - "arn:" - - Ref: AWS::Partition - - ":apigateway:" - - Ref: AWS::Region - - :lambda:path/2015-03-31/functions/ - - Fn::GetAtt: - - HelloWorldFunctionunique-identifier - - Arn - - /invocations - ResourceId: - Ref: HelloWorldApihellounique-identifier - RestApiId: - Ref: HelloWorldApiunique-identifier - Metadata: - aws:cdk:path: CdkHelloWorldStack/HelloWorldApi/Default/hello/GET/Resource - CDKMetadata: - Type: AWS::CDK::Metadata - Properties: - Analytics: v2:deflate64:unique-identifier - Metadata: - aws:cdk:path: CdkHelloWorldStack/CDKMetadata/Default - Condition: CDKMetadataAvailable -Outputs: - HelloWorldApiEndpointunique-identifier: - Value: - Fn::Join: - - "" - - - https:// - - Ref: HelloWorldApiunique-identifier - - .execute-api. - - Ref: AWS::Region - - "." - - Ref: AWS::URLSuffix - - / - - Ref: HelloWorldApiDeploymentStageprodunique-identifier - - / -Conditions: - CDKMetadataAvailable: - Fn::Or: - - Fn::Or: - - Fn::Equals: - - Ref: AWS::Region - - af-south-1 - - Fn::Equals: - - Ref: AWS::Region - - ap-east-1 - - Fn::Equals: - - Ref: AWS::Region - - ap-northeast-1 - - Fn::Equals: - - Ref: AWS::Region - - ap-northeast-2 - - Fn::Equals: - - Ref: AWS::Region - - ap-south-1 - - Fn::Equals: - - Ref: AWS::Region - - ap-southeast-1 - - Fn::Equals: - - Ref: AWS::Region - - ap-southeast-2 - - Fn::Equals: - - Ref: AWS::Region - - ca-central-1 - - Fn::Equals: - - Ref: AWS::Region - - cn-north-1 - - Fn::Equals: - - Ref: AWS::Region - - cn-northwest-1 - - Fn::Or: - - Fn::Equals: - - Ref: AWS::Region - - eu-central-1 - - Fn::Equals: - - Ref: AWS::Region - - eu-north-1 - - Fn::Equals: - - Ref: AWS::Region - - eu-south-1 - - Fn::Equals: - - Ref: AWS::Region - - eu-west-1 - - Fn::Equals: - - Ref: AWS::Region - - eu-west-2 - - Fn::Equals: - - Ref: AWS::Region - - eu-west-3 - - Fn::Equals: - - Ref: AWS::Region - - il-central-1 - - Fn::Equals: - - Ref: AWS::Region - - me-central-1 - - Fn::Equals: - - Ref: AWS::Region - - me-south-1 - - Fn::Equals: - - Ref: AWS::Region - - sa-east-1 - - Fn::Or: - - Fn::Equals: - - Ref: AWS::Region - - us-east-1 - - Fn::Equals: - - Ref: AWS::Region - - us-east-2 - - Fn::Equals: - - Ref: AWS::Region - - us-west-1 - - Fn::Equals: - - Ref: AWS::Region - - us-west-2 -Parameters: - BootstrapVersion: - Type: AWS::SSM::Parameter::Value<String> - Default: /cdk-bootstrap/hnb659fds/version - Description: Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip] -Rules: - CheckBootstrapVersion: - Assertions: - - Assert: - Fn::Not: - - Fn::Contains: - - - "1" - - "2" - - "3" - - "4" - - "5" - - Ref: BootstrapVersion - AssertDescription: CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI.</code></pre> -</div> -</div> -</div> -</details> -<div class="paragraph"> -<p>By using L2 constructs, you define a few properties to configure your resources and use helper methods to integrate them together. The AWS CDK configures the majority of your AWS CloudFormation resources and properties required to provision your application.</p> -</div> -</div> -<div class="sect3"> -<h4 id="serverless-example-deploy">20.1.5. Step 5: Deploy your application</h4> -<div class="paragraph"> -<p>In this step, you use the AWS CDK <code class="noloc">CLI</code><code>cdk deploy</code> command to deploy your application. The AWS CDK works with the AWS CloudFormation service to provision your resources.</p> -</div> -<div class="admonitionblock important"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-important" title="Important"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>You must perform a one-time bootstrapping of your AWS environment before deployment. For instructions, see <a href="#bootstrapping-env">Bootstrap your environment for use with the AWS CDK</a>.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>From the root of your project, run the following. Confirm changes if prompted:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk deploy - -✨ Synthesis time: 2.44s - -... - -Do you wish to deploy these changes (y/n)? y</code></pre> -</div> -</div> -<div class="paragraph"> -<p>When deployment completes, the AWS CDK <code class="noloc">CLI</code> will output your endpoint URL. Copy this URL for the next step. The following is an example:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>... -✅ HelloWorldStack - -✨ Deployment time: 45.37s - -Outputs: -HelloWorldStack.HelloWorldApiEndpointunique-identifier = https://<api-id>.execute-api.<region>.amazonaws.com/prod/ -Stack ARN: -arn:aws:cloudformation:region:account-id:stack/HelloWorldStack/unique-identifier -...</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="serverless-example-interact">20.1.6. Step 6: Interact with your application</h4> -<div class="paragraph"> -<p>In this step, you initiate a GET request to your API endpoint and receive your Lambda function response.</p> -</div> -<div class="paragraph"> -<p>Locate your endpoint URL from the previous step and add the <code>/hello</code> path. Then, using your browser or command prompt, send a GET request to your endpoint. The following is an example:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ curl https://<api-id>.execute-api.<region>.amazonaws.com/prod/hello -{"message":"Hello World!"}%</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Congratulations, you have successfully created, deployed, and interacted with your application using the AWS CDK!</p> -</div> -</div> -<div class="sect3"> -<h4 id="serverless-example-delete">20.1.7. Step 7: Delete your application</h4> -<div class="paragraph"> -<p>In this step, you use the AWS CDK <code class="noloc">CLI</code> to delete your application from the AWS Cloud.</p> -</div> -<div class="paragraph"> -<p>To delete your application, run <code>cdk destroy</code>. When prompted, confirm your request to delete the application:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk destroy -Are you sure you want to delete: CdkHelloWorldStack (y/n)? y -CdkHelloWorldStack: destroying... [1/1] -... - ✅ CdkHelloWorldStack: destroyed</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="serverless-example-troubleshooting">20.1.8. Troubleshooting</h4> -<div class="sect4"> -<h5 id="w94aac85c11c55b5">Error: {“message”: “Internal server error”}%</h5> -<div class="paragraph"> -<p>When invoking the deployed Lambda function, you receive this error. This error could occur for multiple reasons.</p> -</div> -<div class="paragraph"> -<p>Use the AWS CLI to invoke your Lambda function.</p> -</div> -<div class="olist arabic"> -<ol class="arabic"> -<li> -<p>Modify your stack file to capture the output value of your deployed Lambda function name. The following is an example:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">... - -class CdkHelloWorldStack extends Stack { - constructor(scope, id, props) { - super(scope, id, props); - - // Define the Lambda function resource - // ... - - new CfnOutput(this, 'HelloWorldFunctionName', { - value: helloWorldFunction.functionName, - description: 'JavaScript Lambda function' - }); - - // Define the API Gateway resource - // ...</code></pre> -</div> -</div> -</li> -<li> -<p>Deploy your application again. The AWS CDK <code class="noloc">CLI</code> will output the value of your deployed Lambda function name:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ cdk deploy - -✨ Synthesis time: 0.29s -... - ✅ CdkHelloWorldStack - -✨ Deployment time: 20.36s - -Outputs: -... -CdkHelloWorldStack.HelloWorldFunctionName = CdkHelloWorldStack-HelloWorldFunctionunique-identifier -...</code></pre> -</div> -</div> -</li> -<li> -<p>Use the AWS CLI to invoke your Lambda function in the AWS Cloud and output the response to a text file:</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>$ aws lambda invoke --function-name CdkHelloWorldStack-HelloWorldFunctionunique-identifier output.txt</code></pre> -</div> -</div> -</li> -<li> -<p>Check <code class="path">output.txt</code> to see your results.</p> -<div class="dlist"> -<dl> -<dt class="hdlist1">Possible cause: API Gateway resource is defined incorrectly in your stack file.</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>If <code class="path">output.txt</code> shows a successful Lambda function response, the issue could be with how you defined your API Gateway REST API. The AWS CLI invokes your Lambda directly, not through your endpoint. Check your code to ensure it matches this tutorial. Then, deploy again.</p> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Possible cause: Lambda resource is defined incorrectly in your stack file.</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>If <code class="path">output.txt</code> returns an error, the issue could be with how you defined your Lambda function. Check your code to ensure it matches this tutorial. Then deploy again.</p> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</li> -</ol> -</div> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="stack-how-to-create-multiple-stacks">20.2. Example: Create a CDK app with multiple stacks</h3> -<div class="paragraph"> -<p>You can create an AWS Cloud Development Kit (AWS CDK) application containing multiple <a href="#stacks">stacks</a>. When you deploy the AWS CDK app, each stack becomes its own AWS CloudFormation template. You can also synthesize and deploy each stack individually using the AWS CDK <code class="noloc">CLI</code><code>cdk deploy</code> command.</p> -</div> -<div class="paragraph"> -<p>In this example, we cover the following:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>How to extend the <code>Stack</code> class to accept new properties or arguments.</p> -</li> -<li> -<p>How to use properties to determine which resources the stack contains and their configuration.</p> -</li> -<li> -<p>How to instantiate multiple stacks from this class.</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>The example in this topic uses a Boolean property, named <code>encryptBucket</code> (Python: <code>encrypt_bucket</code>). It indicates whether an Amazon S3 bucket should be encrypted. If so, the stack enables encryption using a key managed by AWS Key Management Service (AWS KMS). The app creates two instances of this stack, one with encryption and one without.</p> -</div> -<div class="sect3"> -<h4 id="cdk-how-to-create-multiple-stacks-prereqs">20.2.1. Prerequisites</h4> -<div class="paragraph"> -<p>This example assumes that all <a href="#getting-started">getting started</a> steps have been completed.</p> -</div> -</div> -<div class="sect3"> -<h4 id="cdk-how-to-create-multiple-stacks-create">20.2.2. Create a CDK project</h4> -<div class="paragraph"> -<p>First, we create a CDK project using the CDK <code class="noloc">CLI</code>:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">mkdir multistack -cd multistack -cdk init --language=typescript</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">mkdir multistack -cd multistack -cdk init --language=javascript</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">mkdir multistack -cd multistack -cdk init --language=python -source .venv/bin/activate # On Windows, run '.\venv\Scripts\activate' instead -pip install -r requirements.txt</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">mkdir multistack -cd multistack -cdk init --language=java</code></pre> -</div> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p>You can import the resulting Maven project into your Java IDE.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">mkdir multistack -cd multistack -cdk init --language=csharp</code></pre> -</div> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p>You can open the file <code class="path">src/Pipeline.sln</code> in Visual Studio.</p> -</div> -</div> -<div class="sect3"> -<h4 id="cdk-how-to-create-multiple-stacks-extend-stackprops">20.2.3. Add an optional parameter</h4> -<div class="paragraph"> -<p>The <code>props</code> argument of the <code>Stack</code> constructor fulfills the interface <code>StackProps</code>. In this example, we want the stack to accept an additional property to tell us whether to encrypt the Amazon S3 bucket. To do this, we create an interface or class that includes the property. This allows the compiler to make sure that the property has a Boolean value and enables auto-completion for it in your IDE.</p> -</div> -<div class="paragraph"> -<p>We open our <em>stack file</em> in our IDE or editor and add the new interface, class, or argument. New lines are highlighted in bold:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>File: <code class="path">lib/multistack-stack.ts</code></p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as cdk from 'aws-cdk-lib'; -import { Construct } from 'constructs'; - -interface MultiStackProps extends cdk.StackProps { - encryptBucket?: boolean; -} - -export class MultistackStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: MultiStackProps) { - super(scope, id, props); - - // The code that defines our stack goes here - } -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">JavaScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>File: <code class="path">lib/multistack-stack.js</code></p> -<div class="paragraph"> -<p>JavaScript doesn’t have an interface feature; we don’t need to add any code.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const cdk = require('aws-cdk-stack'); - -class MultistackStack extends cdk.Stack { - constructor(scope, id, props) { - super(scope, id, props); - - // The code that defines our stack goes here - } -} - -module.exports = { MultistackStack }</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Python</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>File: <code class="path">multistack/multistack_stack.py</code></p> -<div class="paragraph"> -<p>Python does not have an interface feature, so we’ll extend our stack to accept the new property by adding a keyword argument.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">import aws_cdk as cdk -from constructs import Construct - -class MultistackStack(cdk.Stack): - - # The Stack class doesn't know about our encrypt_bucket parameter, - # so accept it separately and pass along any other keyword arguments. - def __init__(self, scope: Construct, id: str, *, encrypt_bucket=False, - **kwargs) -> None: - super().__init__(scope, id, **kwargs) - - # The code that defines our stack goes here</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Java</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>File: <code class="path">src/main/java/com/myorg/MultistackStack.java</code></p> -<div class="paragraph"> -<p>It’s more complicated than we really want to get into to extend a props type in Java. Instead, write the stack’s constructor to accept an optional Boolean parameter. Because <code>props</code> is an optional argument, we’ll write an additional constructor that lets you skip it. It will default to <code>false</code>.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">package com.myorg; - -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.StackProps; -import software.constructs.Construct; - -import software.amazon.awscdk.services.s3.Bucket; - -public class MultistackStack extends Stack { - // additional constructors to allow props and/or encryptBucket to be omitted - public MultistackStack(final Construct scope, final String id, boolean encryptBucket) { - this(scope, id, null, encryptBucket); - } - - public MultistackStack(final Construct scope, final String id) { - this(scope, id, null, false); - } - - public MultistackStack(final Construct scope, final String id, final StackProps props, - final boolean encryptBucket) { - super(scope, id, props); - - // The code that defines our stack goes here - } -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">C#</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>File: <code class="path">src/Multistack/MultistackStack.cs</code></p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; -using constructs; - -namespace Multistack -{ - - - public class MultiStackProps : StackProps - { - public bool? EncryptBucket { get; set; } - } - - - public class MultistackStack : Stack - { - public MultistackStack(Construct scope, string id, MultiStackProps props) : base(scope, id, props) - { - // The code that defines our stack goes here - } - } -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div class="paragraph"> -<p>The new property is optional. If <code>encryptBucket</code> (Python: <code>encrypt_bucket</code>) is not present, its value is <code>undefined</code>, or the local equivalent. The bucket will be unencrypted by default.</p> -</div> -</div> -<div class="sect3"> -<h4 id="cdk-how-to-create-multiple-stacks-define-stack">20.2.4. Define the stack class</h4> -<div class="paragraph"> -<p>Next, we define our stack class, using our new property. New code is highlighted in bold:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>File: <code class="path">lib/multistack-stack.ts</code></p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as cdk from 'aws-cdk-lib'; -import { Construct } from constructs; -import * as s3 from 'aws-cdk-lib/aws-s3'; - -interface MultistackProps extends cdk.StackProps { - encryptBucket?: boolean; -} - -export class MultistackStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: MultistackProps) { - super(scope, id, props); - - // Add a Boolean property "encryptBucket" to the stack constructor. - // If true, creates an encrypted bucket. Otherwise, the bucket is unencrypted. - // Encrypted bucket uses KMS-managed keys (SSE-KMS). - if (props && props.encryptBucket) { - new s3.Bucket(this, "MyGroovyBucket", { - encryption: s3.BucketEncryption.KMS_MANAGED, - removalPolicy: cdk.RemovalPolicy.DESTROY - }); - } else { - new s3.Bucket(this, "MyGroovyBucket", { - removalPolicy: cdk.RemovalPolicy.DESTROY}); - } - } -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">JavaScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>File: <code class="path">lib/multistack-stack.js</code></p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const cdk = require('aws-cdk-lib'); -const s3 = require('aws-cdk-lib/aws-s3'); - -class MultistackStack extends cdk.Stack { - constructor(scope, id, props) { - super(scope, id, props); - - // Add a Boolean property "encryptBucket" to the stack constructor. - // If true, creates an encrypted bucket. Otherwise, the bucket is unencrypted. - // Encrypted bucket uses KMS-managed keys (SSE-KMS). - if ( props && props.encryptBucket) { - new s3.Bucket(this, "MyGroovyBucket", { - encryption: s3.BucketEncryption.KMS_MANAGED, - removalPolicy: cdk.RemovalPolicy.DESTROY - }); - } else { - new s3.Bucket(this, "MyGroovyBucket", { - removalPolicy: cdk.RemovalPolicy.DESTROY}); - } - } -} - -module.exports = { MultistackStack }</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Python</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>File: <code class="path">multistack/multistack_stack.py</code></p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">import aws_cdk as cdk -from constructs import Construct -from aws_cdk import aws_s3 as s3 - -class MultistackStack(cdk.Stack): - - # The Stack class doesn't know about our encrypt_bucket parameter, - # so accept it separately and pass along any other keyword arguments. - def __init__(self, scope: Construct, id: str, *, encrypt_bucket=False, - **kwargs) -> None: - super().__init__(scope, id, **kwargs) - - # Add a Boolean property "encryptBucket" to the stack constructor. - # If true, creates an encrypted bucket. Otherwise, the bucket is unencrypted. - # Encrypted bucket uses KMS-managed keys (SSE-KMS). - if encrypt_bucket: - s3.Bucket(self, "MyGroovyBucket", - encryption=s3.BucketEncryption.KMS_MANAGED, - removal_policy=cdk.RemovalPolicy.DESTROY) - else: - s3.Bucket(self, "MyGroovyBucket", - removal_policy=cdk.RemovalPolicy.DESTROY)</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Java</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>File: <code class="path">src/main/java/com/myorg/MultistackStack.java</code></p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">package com.myorg; - -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.StackProps; -import software.constructs.Construct; -import software.amazon.awscdk.RemovalPolicy; - -import software.amazon.awscdk.services.s3.Bucket; -import software.amazon.awscdk.services.s3.BucketEncryption; - -public class MultistackStack extends Stack { - // additional constructors to allow props and/or encryptBucket to be omitted - public MultistackStack(final Construct scope, final String id, - boolean encryptBucket) { - this(scope, id, null, encryptBucket); - } - - public MultistackStack(final Construct scope, final String id) { - this(scope, id, null, false); - } - - // main constructor - public MultistackStack(final Construct scope, final String id, - final StackProps props, final boolean encryptBucket) { - super(scope, id, props); - - // Add a Boolean property "encryptBucket" to the stack constructor. - // If true, creates an encrypted bucket. Otherwise, the bucket is - // unencrypted. Encrypted bucket uses KMS-managed keys (SSE-KMS). - if (encryptBucket) { - Bucket.Builder.create(this, "MyGroovyBucket") - .encryption(BucketEncryption.KMS_MANAGED) - .removalPolicy(RemovalPolicy.DESTROY).build(); - } else { - Bucket.Builder.create(this, "MyGroovyBucket") - .removalPolicy(RemovalPolicy.DESTROY).build(); - } - } -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">C#</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>File: <code class="path">src/Multistack/MultistackStack.cs</code></p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; -using Amazon.CDK.AWS.S3; - -namespace Multistack -{ - - public class MultiStackProps : StackProps - { - public bool? EncryptBucket { get; set; } - } - - public class MultistackStack : Stack - { - public MultistackStack(Construct scope, string id, IMultiStackProps props = null) : base(scope, id, props) - { - // Add a Boolean property "EncryptBucket" to the stack constructor. - // If true, creates an encrypted bucket. Otherwise, the bucket is unencrypted. - // Encrypted bucket uses KMS-managed keys (SSE-KMS). - if (props?.EncryptBucket ?? false) - { - new Bucket(this, "MyGroovyBucket", new BucketProps - { - Encryption = BucketEncryption.KMS_MANAGED, - RemovalPolicy = RemovalPolicy.DESTROY - }); - } - else - { - new Bucket(this, "MyGroovyBucket", new BucketProps - { - RemovalPolicy = RemovalPolicy.DESTROY - }); - } - } - } -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -</div> -<div class="sect3"> -<h4 id="stack-how-to-create-multiple-stacks-create-stacks">20.2.5. Create two stack instances</h4> -<div class="paragraph"> -<p>In our <em>application file</em>, we add the code to instantiate two separate stacks. We delete the existing <code>MultistackStack</code> definition and define our two stacks. New code is highlight in bold:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>File: <code class="path">bin/multistack.ts</code></p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">#!/usr/bin/env node -import 'source-map-support/register'; -import * as cdk from 'aws-cdk-lib'; -import { MultistackStack } from '../lib/multistack-stack'; - -const app = new cdk.App(); - -new MultistackStack(app, "MyWestCdkStack", { - env: {region: "us-west-1"}, - encryptBucket: false -}); - -new MultistackStack(app, "MyEastCdkStack", { - env: {region: "us-east-1"}, - encryptBucket: true -}); - -app.synth();</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">JavaScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>File: <code class="path">bin/multistack.js</code></p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">#!/usr/bin/env node -const cdk = require('aws-cdk-lib'); -const { MultistackStack } = require('../lib/multistack-stack'); - -const app = new cdk.App(); - -new MultistackStack(app, "MyWestCdkStack", { - env: {region: "us-west-1"}, - encryptBucket: false -}); - -new MultistackStack(app, "MyEastCdkStack", { - env: {region: "us-east-1"}, - encryptBucket: true -}); - -app.synth();</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Python</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>File: <code class="path">./app.py</code></p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">#!/usr/bin/env python3 - -import aws_cdk as cdk - -from multistack.multistack_stack import MultistackStack - -app = cdk.App() -MultistackStack(app, "MyWestCdkStack", - env=cdk.Environment(region="us-west-1"), - encrypt_bucket=False) - -MultistackStack(app, "MyEastCdkStack", - env=cdk.Environment(region="us-east-1"), - encrypt_bucket=True) - -app.synth()</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Java</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>File: <code class="path">src/main/java/com/myorg/MultistackApp.java</code></p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">package com.myorg; - -import software.amazon.awscdk.App; -import software.amazon.awscdk.Environment; -import software.amazon.awscdk.StackProps; - -public class MultistackApp { - public static void main(final String argv[]) { - App app = new App(); - - new MultistackStack(app, "MyWestCdkStack", StackProps.builder() - .env(Environment.builder() - .region("us-west-1") - .build()) - .build(), false); - - new MultistackStack(app, "MyEastCdkStack", StackProps.builder() - .env(Environment.builder() - .region("us-east-1") - .build()) - .build(), true); - - app.synth(); - } -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">C#</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>File: src/Multistack/Program.cs</p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; - -namespace Multistack -{ - class Program - { - static void Main(string[] args) - { - var app = new App(); - - new MultistackStack(app, "MyWestCdkStack", new MultiStackProps - { - Env = new Environment { Region = "us-west-1" }, - EncryptBucket = false - }); - - new MultistackStack(app, "MyEastCdkStack", new MultiStackProps - { - Env = new Environment { Region = "us-east-1" }, - EncryptBucket = true - }); - - app.Synth(); - } - } -}</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div class="paragraph"> -<p>This code uses the new <code>encryptBucket</code> (Python: <code>encrypt_bucket</code>) property on the <code>MultistackStack</code> class to instantiate the following:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>One stack with an encrypted Amazon S3 bucket in the <code>us-east-1</code> AWS Region.</p> -</li> -<li> -<p>One stack with an unencrypted Amazon S3 bucket in the <code>us-west-1</code> AWS Region.</p> -</li> -</ul> -</div> -</div> -<div class="sect3"> -<h4 id="cdk-how-to-create-multiple-stacks-synth-deploy">20.2.6. Synthesize and deploy the stack</h4> -<div class="paragraph"> -<p>Next, we can deploy stacks from the app. First, we synthesize an AWS CloudFormation template for <code>MyEastCdkStack</code>. This is the stack in <code>us-east-1</code> with the encrypted Amazon S3 bucket.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ cdk synth MyEastCdkStack</code></pre> -</div> -</div> -<div class="paragraph"> -<p>To deploy this stack to our AWS environment, we can issue one of the following commands. The first command uses our default AWS profile to obtain the credentials to deploy the stack. The second uses a profile that we specify. For <code class="replaceable">PROFILE_NAME</code>, we can substitute the name of an AWS CLI profile that contains appropriate credentials for deploying to the <code>us-east-1</code> AWS Region.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ cdk deploy MyEastCdkStack</code></pre> -</div> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">$ cdk deploy MyEastCdkStack --profile=PROFILE_NAME</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="cdk-how-to-create-multiple-stacks-destroy-stack">20.2.7. Clean up</h4> -<div class="paragraph"> -<p>To avoid charges for resources that we deployed, we destroy the stack using the following command:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk destroy MyEastCdkStack</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The destroy operation fails if there is anything stored in the stack’s bucket. There shouldn’t be, since we only created the bucket. If we did put something in the bucket, we must delete the bucket contents before destroying the stack. We can use the AWS Management Console or the AWS CLI to delete the bucket contents.</p> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="ecs-example">20.3. Example: Create an AWS Fargate service using the AWS CDK</h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Learn how to create an AWS Fargate service.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>In this example, we show you how to create an AWS Fargate service running on an Amazon Elastic Container Service (Amazon ECS) cluster that’s fronted by an internet-facing Application Load Balancer from an image on Amazon ECR.</p> -</div> -<div class="paragraph"> -<p>Amazon ECS is a highly scalable, fast, container management service that makes it easy to run, stop, and manage <code class="noloc">Docker</code> containers on a cluster. You can host your cluster on serverless infrastructure that’s managed by Amazon ECS by launching your services or tasks using the Fargate launch type. For more control, you can host your tasks on a cluster of Amazon Elastic Compute Cloud (Amazon EC2) instances that you manage by using the Amazon EC2 launch type.</p> -</div> -<div class="paragraph"> -<p>In this example, we launch some services using the Fargate launch type. If you’ve used the AWS Management Console to create a Fargate service, you know that there are many steps to follow to accomplish that task. AWS has several tutorials and documentation topics that walk you through creating a Fargate service, including:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><a href="https://aws.amazon.com/getting-started/tutorials/deploy-docker-containers">How to Deploy Docker Containers - AWS</a></p> -</li> -<li> -<p><a href="https://docs.aws.amazon.com/AmazonECS/latest/developerguide/get-set-up-for-amazon-ecs.html">Setting Up with Amazon ECS</a></p> -</li> -<li> -<p><a href="https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ECS_GetStarted.html">Getting Started with Amazon ECS Using Fargate</a></p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>This example creates a similar Fargate service using the AWS CDK.</p> -</div> -<div class="paragraph"> -<p>The Amazon ECS construct used in this example helps you use AWS services by providing the following benefits:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Automatically configures a load balancer.</p> -</li> -<li> -<p>Automatically opens a security group for load balancers. This enables load balancers to communicate with instances without having to explicitly create a security group.</p> -</li> -<li> -<p>Automatically orders dependency between the service and the load balancer attaching to a target group, where the AWS CDK enforces the correct order of creating the listener before an instance is created.</p> -</li> -<li> -<p>Automatically configures user data on automatically scaling groups. This creates the correct configuration to associate a cluster to AMIs.</p> -</li> -<li> -<p>Validates parameter combinations early. This exposes AWS CloudFormation issues earlier, thus saving deployment time. For example, depending on the task, it’s easy to improperly configure the memory settings. Previously, we would not encounter an error until we deployed our app. But now the AWS CDK can detect a misconfiguration and emit an error when we synthesize our app.</p> -</li> -<li> -<p>Automatically adds permissions for Amazon Elastic Container Registry (Amazon ECR) if we use an image from Amazon ECR.</p> -</li> -<li> -<p>Automatically scales. The AWS CDK supplies a method so we can auto scale instances when we use an Amazon EC2 cluster. This happens automatically when we use an instance in a Fargate cluster.</p> -<div class="paragraph"> -<p>In addition, the AWS CDK prevents an instance from being deleted when automatic scaling tries to stop an instance, but either a task is running or is scheduled on that instance.</p> -</div> -<div class="paragraph"> -<p>Previously, we had to create a Lambda function to have this functionality.</p> -</div> -</li> -<li> -<p>Provides asset support, so that we can deploy a source from our machine to Amazon ECS in one step. Previously, to use an application source, we had to perform several manual steps, such as uploading to Amazon ECR and creating a <code class="noloc">Docker</code> image.</p> -</li> -</ul> -</div> -<div class="admonitionblock important"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-important" title="Important"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>The <code>ApplicationLoadBalancedFargateService</code> constructs we’ll be using includes numerous AWS components, some of which have non-trivial costs if left provisioned in our AWS account, even if we don’t use them. Be sure to clean up (<strong class="command">cdk destroy</strong>) if you follow along with this example.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="sect3"> -<h4 id="ecs-example-initialize">20.3.1. Create a CDK project</h4> -<div class="paragraph"> -<p>We start by creating a CDK project. This is a directory that stores our AWS CDK code, including our CDK app.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">mkdir MyEcsConstruct -cd MyEcsConstruct -cdk init --language typescript</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">mkdir MyEcsConstruct -cd MyEcsConstruct -cdk init --language javascript</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">mkdir MyEcsConstruct -cd MyEcsConstruct -cdk init --language python -source .venv/bin/activate # On Windows, run '.\venv\Scripts\activate' instead -pip install -r requirements.txt</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">mkdir MyEcsConstruct -cd MyEcsConstruct -cdk init --language java</code></pre> -</div> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p>We may now import the Maven project into our IDE.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">mkdir MyEcsConstruct -cd MyEcsConstruct -cdk init --language csharp</code></pre> -</div> -</div> -<div class="paragraph"> -<p>+</p> -</div> -<div class="paragraph"> -<p>We may now open <code class="path">src/MyEcsConstruct.sln</code> in Visual Studio.</p> -</div> -<div class="paragraph"> -<p>Next, we run the app and confirm that it creates an empty stack.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk synth</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="ecs-example-create-fargate-service">20.3.2. Create a Fargate service</h4> -<div class="paragraph"> -<p>There are two different ways that we can run our container tasks with Amazon ECS:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Use the <code>Fargate</code> launch type, where Amazon ECS manages the physical machines that oour containers are running on for us.</p> -</li> -<li> -<p>Use the <code>EC2</code> launch type, where we do the managing, such as specifying automatic scaling.</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>For this example, we’ll create a Fargate service running on an Amazon ECS cluster, fronted by an internet-facing Application Load Balancer.</p> -</div> -<div class="paragraph"> -<p>We add the following AWS Construct Library module imports to our <em>stack file</em>:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>File: <code class="path">lib/my_ecs_construct-stack.ts</code></p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as ec2 from "aws-cdk-lib/aws-ec2"; -import * as ecs from "aws-cdk-lib/aws-ecs"; -import * as ecs_patterns from "aws-cdk-lib/aws-ecs-patterns";</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">JavaScript</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>File: <code class="path">lib/my_ecs_construct-stack.js</code></p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const ec2 = require("aws-cdk-lib/aws-ec2"); -const ecs = require("aws-cdk-lib/aws-ecs"); -const ecs_patterns = require("aws-cdk-lib/aws-ecs-patterns");</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Python</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>File: <code class="path">my_ecs_construct/my_ecs_construct_stack.py</code></p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">from aws_cdk import (aws_ec2 as ec2, aws_ecs as ecs, - aws_ecs_patterns as ecs_patterns)</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">Java</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>File: <code class="path">src/main/java/com/myorg/MyEcsConstructStack.java</code></p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">import software.amazon.awscdk.services.ec2.*; -import software.amazon.awscdk.services.ecs.*; -import software.amazon.awscdk.services.ecs.patterns.*;</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -<dt class="hdlist1">C#</dt> -<dd> -<div class="ulist"> -<ul> -<li> -<p>File: <code class="path">src/MyEcsConstruct/MyEcsConstructStack.cs</code></p> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK.AWS.EC2; -using Amazon.CDK.AWS.ECS; -using Amazon.CDK.AWS.ECS.Patterns;</code></pre> -</div> -</div> -</li> -</ul> -</div> -</dd> -</dl> -</div> -<div class="paragraph"> -<p>Within our stack, we add the following code:</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript"> const vpc = new ec2.Vpc(this, "MyVpc", { - maxAzs: 3 // Default is all AZs in region - }); - - const cluster = new ecs.Cluster(this, "MyCluster", { - vpc: vpc - }); - - // Create a load-balanced Fargate service and make it public - new ecs_patterns.ApplicationLoadBalancedFargateService(this, "MyFargateService", { - cluster: cluster, // Required - cpu: 512, // Default is 256 - desiredCount: 6, // Default is 1 - taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample") }, - memoryLimitMiB: 2048, // Default is 512 - publicLoadBalancer: true // Default is true - });</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript"> const vpc = new ec2.Vpc(this, "MyVpc", { - maxAzs: 3 // Default is all AZs in region - }); - - const cluster = new ecs.Cluster(this, "MyCluster", { - vpc: vpc - }); - - // Create a load-balanced Fargate service and make it public - new ecs_patterns.ApplicationLoadBalancedFargateService(this, "MyFargateService", { - cluster: cluster, // Required - cpu: 512, // Default is 256 - desiredCount: 6, // Default is 1 - taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample") }, - memoryLimitMiB: 2048, // Default is 512 - publicLoadBalancer: true // Default is true - });</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python"> vpc = ec2.Vpc(self, "MyVpc", max_azs=3) # default is all AZs in region - - cluster = ecs.Cluster(self, "MyCluster", vpc=vpc) - - ecs_patterns.ApplicationLoadBalancedFargateService(self, "MyFargateService", - cluster=cluster, # Required - cpu=512, # Default is 256 - desired_count=6, # Default is 1 - task_image_options=ecs_patterns.ApplicationLoadBalancedTaskImageOptions( - image=ecs.ContainerImage.from_registry("amazon/amazon-ecs-sample")), - memory_limit_mib=2048, # Default is 512 - public_load_balancer=True) # Default is True</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java"> Vpc vpc = Vpc.Builder.create(this, "MyVpc") - .maxAzs(3) // Default is all AZs in region - .build(); - - Cluster cluster = Cluster.Builder.create(this, "MyCluster") - .vpc(vpc).build(); - - // Create a load-balanced Fargate service and make it public - ApplicationLoadBalancedFargateService.Builder.create(this, "MyFargateService") - .cluster(cluster) // Required - .cpu(512) // Default is 256 - .desiredCount(6) // Default is 1 - .taskImageOptions( - ApplicationLoadBalancedTaskImageOptions.builder() - .image(ContainerImage.fromRegistry("amazon/amazon-ecs-sample")) - .build()) - .memoryLimitMiB(2048) // Default is 512 - .publicLoadBalancer(true) // Default is true - .build();</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp"> var vpc = new Vpc(this, "MyVpc", new VpcProps - { - MaxAzs = 3 // Default is all AZs in region - }); - - var cluster = new Cluster(this, "MyCluster", new ClusterProps - { - Vpc = vpc - }); - - // Create a load-balanced Fargate service and make it public - new ApplicationLoadBalancedFargateService(this, "MyFargateService", - new ApplicationLoadBalancedFargateServiceProps - { - Cluster = cluster, // Required - DesiredCount = 6, // Default is 1 - TaskImageOptions = new ApplicationLoadBalancedTaskImageOptions - { - Image = ContainerImage.FromRegistry("amazon/amazon-ecs-sample") - }, - MemoryLimitMiB = 2048, // Default is 256 - PublicLoadBalancer = true // Default is true - } - );</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Next, we validate our code by running the following to synthesize our stack:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk synth</code></pre> -</div> -</div> -<div class="paragraph"> -<p>The stack is hundreds of lines, so we won’t show it here. The stack should contain one default instance, a private subnet and a public subnet for the three Availability Zones, and a security group.</p> -</div> -<div class="paragraph"> -<p>To deploy the stack, we run the following:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk deploy</code></pre> -</div> -</div> -<div class="paragraph"> -<p>AWS CloudFormation displays information about the dozens of steps that it takes as it deploys our app.</p> -</div> -<div class="paragraph"> -<p>Once deployment completes, we have successfully created a Fargate powered Amazon ECS service to run a <code class="noloc">Docker</code> image.</p> -</div> -</div> -<div class="sect3"> -<h4 id="ecs-example-destroy">20.3.3. Clean up</h4> -<div class="paragraph"> -<p>As a general maintenance best practice, and to minimize unnecessary costs, we delete our stack when complete:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code>cdk destroy</code></pre> -</div> -</div> -</div> -</div> -</div> -</div> -<div class="sect1 topic"> -<h2 id="tools">21. Use other tools with the AWS CDK</h2> -<div class="sectionbody"> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Tools for the AWS CDK</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>You can use other tools with the AWS CDK to improve your development workflows.</p> -</div> -<div class="sect2"> -<h3 id="vscode">21.1. AWS Toolkit for Visual Studio Code</h3> -<div class="paragraph"> -<p>The <a href="https://aws.amazon.com/visualstudiocode/">AWS Toolkit for Visual Studio Code</a> is an open source plugin for Visual Studio Code that makes it easier to create, debug, and deploy applications on AWS. The toolkit provides an integrated experience for developing AWS CDK applications. It includes the AWS CDK Explorer feature to list your AWS CDK projects and browse the various components of the CDK application. <a href="https://docs.aws.amazon.com/toolkit-for-vscode/latest/userguide/setup-toolkit.html">Install the AWS Toolkit</a> and learn more about <a href="https://docs.aws.amazon.com/toolkit-for-vscode/latest/userguide/cdk-explorer.html">using the AWS CDK Explorer</a>.</p> -</div> -</div> -<div class="sect2"> -<h3 id="sam">21.2. AWS SAM integration</h3> -<div class="paragraph"> -<p>Use the AWS CDK and the AWS Serverless Application Model (AWS SAM) together to locally build and test serverless applications defined in the CDK. For complete information, see <a href="https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-cdk.html">AWS Cloud Development Kit (AWS CDK)</a> in the <em>AWS Serverless Application Model Developer Guide</em>. To install the AWS SAM <code class="noloc">CLI</code>, see <a href="https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html">Install the AWS SAM CLI</a>.</p> -</div> -</div> -</div> -</div> -<div class="sect1 topic"> -<h2 id="security">22. Security for the AWS Cloud Development Kit (AWS CDK)</h2> -<div class="sectionbody"> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Provides security-related information for the AWS CDK.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>Cloud security at Amazon Web Services (AWS) is the highest priority. As an AWS customer, you benefit from a data center and network architecture that is built to meet the requirements of the most security-sensitive organizations. Security is a shared responsibility between AWS and you. The <a href="https://aws.amazon.com/compliance/shared-responsibility-model/">Shared Responsibility Model</a> describes this as Security of the Cloud and Security in the Cloud.</p> -</div> -<div class="paragraph"> -<p><strong>Security of the Cloud</strong> – AWS is responsible for protecting the infrastructure that runs all of the services offered in the AWS Cloud and providing you with services that you can use securely. Our security responsibility is the highest priority at AWS, and the effectiveness of our security is regularly tested and verified by third-party auditors as part of the <a href="https://aws.amazon.com/compliance/programs/">AWS Compliance Programs</a>.</p> -</div> -<div class="paragraph"> -<p><strong>Security in the Cloud</strong> – Your responsibility is determined by the AWS service you are using, and other factors including the sensitivity of your data, your organization’s requirements, and applicable laws and regulations.</p> -</div> -<div class="paragraph"> -<p>The AWS CDK follows the <a href="https://aws.amazon.com/compliance/shared-responsibility-model/">shared responsibility model</a> through the specific Amazon Web Services (AWS) services it supports. For AWS service security information, see the <a href="https://docs.aws.amazon.com/security/?id=docs_gateway#aws-security">AWS service security documentation page</a> and <a href="https://aws.amazon.com/compliance/services-in-scope/">AWS services that are in scope of AWS compliance efforts by compliance program</a>.</p> -</div> -<div class="paragraph topiclist-abbrev"> -<p>[[Topic List]]</p> -</div> -<div class="sect2 topic"> -<h3 id="security-iam">22.1. Identity and access management for the AWS Cloud Development Kit (AWS CDK)</h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Provides information about identity and access management for the AWS CDK.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>AWS Identity and Access Management (IAM) is an AWS service that helps an administrator securely control access to AWS resources. IAM administrators control who can be <em>authenticated</em> (signed in) and <em>authorized</em> (have permissions) to use AWS resources. IAM is an AWS service that you can use with no additional charge.</p> -</div> -<div class="sect3"> -<h4 id="security-iam-audience">22.1.1. Audience</h4> -<div class="paragraph"> -<p>How you use AWS Identity and Access Management (IAM) differs, depending on the work that you do in AWS.</p> -</div> -<div class="paragraph"> -<p><strong>Service user</strong> – If you use AWS services to do your job, then your administrator provides you with the credentials and permissions that you need. As you use more AWS features to do your work, you might need additional permissions. Understanding how access is managed can help you request the right permissions from your administrator.</p> -</div> -<div class="paragraph"> -<p><strong>Service administrator</strong> – If you’re in charge of AWS resources at your company, you probably have full access to AWS resources. It’s your job to determine which AWS services and resources your service users should access. You must then submit requests to your IAM administrator to change the permissions of your service users. Review the information on this page to understand the basic concepts of IAM.</p> -</div> -<div class="paragraph"> -<p><strong>IAM administrator</strong> – If you’re an IAM administrator, you might want to learn details about how you can write policies to manage access to AWS services.</p> -</div> -</div> -<div class="sect3"> -<h4 id="security-iam-authentication">22.1.2. Authenticating with identities</h4> -<div class="paragraph"> -<p>Authentication is how you sign in to AWS using your identity credentials. You must be <em>authenticated</em> (signed in to AWS) as the AWS account root user, as an IAM user, or by assuming an IAM role.</p> -</div> -<div class="paragraph"> -<p>You can sign in to AWS as a federated identity by using credentials provided through an identity source. AWS IAM Identity Center (IAM Identity Center) users, your company’s single sign-on authentication, and your Google or Facebook credentials are examples of federated identities. When you sign in as a federated identity, your administrator previously set up identity federation using IAM roles. When you access AWS by using federation, you are indirectly assuming a role.</p> -</div> -<div class="paragraph"> -<p>Depending on the type of user you are, you can sign in to the AWS Management Console or the AWS access portal. For more information about signing in to AWS, see <a href="https://docs.aws.amazon.com/signin/latest/userguide/how-to-sign-in.html">How to sign in to your AWS account</a> in the <em>AWS Sign-In User Guide</em>.</p> -</div> -<div class="paragraph"> -<p>To access AWS programmatically, AWS provides the AWS CDK, software development kits (SDKs), and a command line interface (CLI) to cryptographically sign your requests using your credentials. If you don’t use AWS tools, you must sign requests yourself. For more information about using the recommended method to sign requests yourself, see <a href="https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html">Signature Version 4 signing process</a> in the <em>AWS General Reference</em>.</p> -</div> -<div class="paragraph"> -<p>Regardless of the authentication method that you use, you might be required to provide additional security information. For example, AWS recommends that you use multi-factor authentication (MFA) to increase the security of your account. To learn more, see <a href="https://docs.aws.amazon.com/singlesignon/latest/userguide/enable-mfa.html">Multi-factor authentication</a> in the <em>AWS IAM Identity Center User Guide</em> and <a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_mfa.html">Using multi-factor authentication (MFA) in AWS</a> in the <em>IAM User Guide</em>.</p> -</div> -<div class="sect4"> -<h5 id="security-iam-authentication-rootuser">AWS account root user</h5> -<div class="paragraph"> -<p>When you create an AWS account, you begin with one sign-in identity that has complete access to all AWS services and resources in the account. This identity is called the AWS account <em>root user</em> and is accessed by signing in with the email address and password that you used to create the account. We strongly recommend that you don’t use the root user for your everyday tasks. Safeguard your root user credentials and use them to perform the tasks that only the root user can perform. For the complete list of tasks that require you to sign in as the root user, see <a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_root-user.html#root-user-tasks">Tasks that require root user credentials</a> in the <em>IAM User Guide</em>.</p> -</div> -</div> -<div class="sect4"> -<h5 id="security-iam-authentication-federated">Federated identity</h5> -<div class="paragraph"> -<p>As a best practice, require human users, including users that require administrator access, to use federation with an identity provider to access AWS services by using temporary credentials.</p> -</div> -<div class="paragraph"> -<p>A <em>federated identity</em> is a user from your enterprise user directory, a web identity provider, the AWS Directory Service, the Identity Center directory, or any user that accesses AWS services by using credentials provided through an identity source. When federated identities access AWS accounts, they assume roles, and the roles provide temporary credentials.</p> -</div> -<div class="paragraph"> -<p>For centralized access management, we recommend that you use AWS IAM Identity Center. You can create users and groups in IAM Identity Center, or you can connect and synchronize to a set of users and groups in your own identity source for use across all your AWS accounts and applications. For information about IAM Identity Center, see <a href="https://docs.aws.amazon.com/singlesignon/latest/userguide/what-is.html">What is IAM Identity Center?</a> in the <em>AWS IAM Identity Center User Guide</em>.</p> -</div> -</div> -<div class="sect4"> -<h5 id="security-iam-authentication-iamuser">IAM users and groups</h5> -<div class="paragraph"> -<p>An <em><a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users.html">IAM user</a></em> is an identity within your AWS account that has specific permissions for a single person or application. Where possible, we recommend relying on temporary credentials instead of creating IAM users who have long-term credentials such as passwords and access keys. However, if you have specific use cases that require long-term credentials with IAM users, we recommend that you rotate access keys. For more information, see <a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#rotate-credentials">Rotate access keys regularly for use cases that require long-term credentials</a> in the <em>IAM User Guide</em>.</p> -</div> -<div class="paragraph"> -<p>An <a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_groups.html">IAM group</a> is an identity that specifies a collection of IAM users. You can’t sign in as a group. You can use groups to specify permissions for multiple users at a time. Groups make permissions easier to manage for large sets of users. For example, you could have a group named <em>IAMAdmins</em> and give that group permissions to administer IAM resources.</p> -</div> -<div class="paragraph"> -<p>Users are different from roles. A user is uniquely associated with one person or application, but a role is intended to be assumable by anyone who needs it. Users have permanent long-term credentials, but roles provide temporary credentials. To learn more, see <a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/gs-identities-iam-users.html">Use cases for IAM users</a> in the <em>IAM User Guide</em>.</p> -</div> -</div> -<div class="sect4"> -<h5 id="security-iam-authentication-iamrole">IAM roles</h5> -<div class="paragraph"> -<p>An <em><a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html">IAM role</a></em> is an identity within your AWS account that has specific permissions. It’s similar to an IAM user, but isn’t associated with a specific person. You can temporarily assume an IAM role in the AWS Management Console by <a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-console.html">switching roles</a>. You can assume a role by calling an AWS CLI or AWS API operation or by using a custom URL. For more information about methods for using roles, see <a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use.html">Using IAM roles</a> in the <em>IAM User Guide</em>.</p> -</div> -<div class="paragraph"> -<p>IAM roles with temporary credentials are useful in the following situations:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><strong>Federated user access</strong> – To assign permissions to a federated identity, you create a role and define permissions for the role. When a federated identity authenticates, the identity is associated with the role and is granted the permissions that are defined by the role. For information about roles for federation, see <a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-idp.html">Create a role for a third-party identity provider (federation)</a> in the <em>IAM User Guide</em>. If you use IAM Identity Center, you configure a permission set. To control what your identities can access after they authenticate, IAM Identity Center correlates the permission set to a role in IAM. For information about permissions sets, see <a href="https://docs.aws.amazon.com/singlesignon/latest/userguide/permissionsetsconcept.html">Permission sets</a> in the <em>AWS IAM Identity Center User Guide</em>.</p> -</li> -<li> -<p><strong>Temporary IAM user permissions</strong> – An IAM user or role can assume an IAM role to temporarily take on different permissions for a specific task.</p> -</li> -<li> -<p><strong>Cross-account access</strong> – You can use an IAM role to allow someone (a trusted principal) in a different account to access resources in your account. Roles are the primary way to grant cross-account access. However, with some AWS services, you can attach a policy directly to a resource (instead of using a role as a proxy). To learn the difference between roles and resource-based policies for cross-account access, see <a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_compare-resource-policies.html">How IAM roles differ from resource-based policies</a> in the <em>IAM User Guide</em>.</p> -</li> -<li> -<p><strong>Cross-service access</strong> – Some AWS services use features in other AWS services. For example, when you make a call in a service, it’s common for that service to run applications in Amazon EC2 or store objects in Amazon S3. A service might do this using the calling principal’s permissions, using a service role, or using a service-linked role.</p> -<div class="ulist"> -<ul> -<li> -<p><strong>Service role</strong> – A service role is an <a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html">IAM role</a> that a service assumes to perform actions on your behalf. An IAM administrator can create, modify, and delete a service role from within IAM. For more information, see <a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-service.html">Create a role to delegate permissions to an AWS service</a> in the <em>IAM User Guide</em>.</p> -</li> -<li> -<p><strong>Service-linked role</strong> – A service-linked role is a type of service role that is linked to an AWS service. The service can assume the role to perform an action on your behalf. Service-linked roles appear in your AWS account and are owned by the service. An IAM administrator can view, but not edit the permissions for service-linked roles.</p> -</li> -</ul> -</div> -</li> -<li> -<p><strong>Applications running on Amazon EC2</strong> – You can use an IAM role to manage temporary credentials for applications that are running on an EC2 instance and making AWS CLI or AWS API requests. This is preferable to storing access keys within the EC2 instance. To assign an AWS role to an EC2 instance and make it available to all of its applications, you create an instance profile that is attached to the instance. An instance profile contains the role and enables programs that are running on the EC2 instance to get temporary credentials. For more information, see <a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2.html">Use an IAM role to grant permissions to applications running on Amazon EC2 instances</a> in the <em>IAM User Guide</em>.</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>To learn whether to use IAM roles or IAM users, see <a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id.html#id_which-to-choose_role">When to create an IAM role (instead of a user)</a> in the <em>IAM User Guide</em>.</p> -</div> -</div> -</div> -</div> -<div class="sect2 topic"> -<h3 id="compliance-validation">22.2. Compliance validation for the AWS Cloud Development Kit (AWS CDK)</h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Provides information about compliance validation for the AWS CDK.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>The AWS CDK follows the <a href="https://aws.amazon.com/compliance/shared-responsibility-model/">shared responsibility model</a> through the specific Amazon Web Services (AWS) services it supports. For AWS service security information, see the <a href="https://docs.aws.amazon.com/security/?id=docs_gateway#aws-security">AWS service security documentation page</a> and <a href="https://aws.amazon.com/compliance/services-in-scope/">AWS services that are in scope of AWS compliance efforts by compliance program</a>.</p> -</div> -<div class="paragraph"> -<p>The security and compliance of AWS services is assessed by third-party auditors as part of multiple AWS compliance programs. These include SOC, PCI, FedRAMP, HIPAA, and others. AWS provides a frequently updated list of AWS services in scope of specific compliance programs at <a href="https://aws.amazon.com/compliance/services-in-scope/">AWS Services in Scope by Compliance Program</a>.</p> -</div> -<div class="paragraph"> -<p>Third-party audit reports are available for you to download using AWS Artifact. For more information, see <a href="https://docs.aws.amazon.com/artifact/latest/ug/downloading-documents.html">Downloading Reports in AWS Artifact</a>.</p> -</div> -<div class="paragraph"> -<p>For more information about AWS compliance programs, see <a href="https://aws.amazon.com/compliance/programs/">AWS Compliance Programs</a>.</p> -</div> -<div class="paragraph"> -<p>Your compliance responsibility when using the AWS CDK to access an AWS service is determined by the sensitivity of your data, your organization’s compliance objectives, and applicable laws and regulations. If your use of an AWS service is subject to compliance with standards such as HIPAA, PCI, or FedRAMP, AWS provides resources to help:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><a href="https://aws.amazon.com/quickstart/?quickstart-all.sort-by=item.additionalFields.updateDate&quickstart-all.sort-order=desc&awsf.quickstart-homepage-filter=categories%23security-identity-compliance">Security and Compliance Quick Start Guides</a> – Deployment guides that discuss architectural considerations and provide steps for deploying security-focused and compliance-focused baseline environments on AWS.</p> -</li> -<li> -<p><a href="https://aws.amazon.com/compliance/resources/">AWS Compliance Resources</a> – A collection of workbooks and guides that might apply to your industry and location.</p> -</li> -<li> -<p><a href="https://aws.amazon.com/config/">AWS Config</a> – A service that assesses how well your resource configurations comply with internal practices, industry guidelines, and regulations.</p> -</li> -<li> -<p><a href="https://aws.amazon.com/security-hub/">AWS Security Hub</a> – A comprehensive view of your security state within AWS that helps you check your compliance with security industry standards and best practices.</p> -</li> -</ul> -</div> -</div> -<div class="sect2 topic"> -<h3 id="disaster-recovery-resiliency">22.3. Resilience for the AWS Cloud Development Kit (AWS CDK)</h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Provides information about resilience for the AWS CDK.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>The Amazon Web Services (AWS) global infrastructure is built around AWS Regions and Availability Zones.</p> -</div> -<div class="paragraph"> -<p>AWS Regions provide multiple physically separated and isolated Availability Zones, which are connected with low-latency, high-throughput, and highly redundant networking.</p> -</div> -<div class="paragraph"> -<p>With Availability Zones, you can design and operate applications and databases that automatically fail over between Availability Zones without interruption. Availability Zones are more highly available, fault tolerant, and scalable than traditional single or multiple data center infrastructures.</p> -</div> -<div class="paragraph"> -<p>For more information about AWS Regions and Availability Zones, see <a href="https://aws.amazon.com/about-aws/global-infrastructure/">AWS Global Infrastructure</a>.</p> -</div> -<div class="paragraph"> -<p>The AWS CDK follows the <a href="https://aws.amazon.com/compliance/shared-responsibility-model/">shared responsibility model</a> through the specific Amazon Web Services (AWS) services it supports. For AWS service security information, see the <a href="https://docs.aws.amazon.com/security/?id=docs_gateway#aws-security">AWS service security documentation page</a> and <a href="https://aws.amazon.com/compliance/services-in-scope/">AWS services that are in scope of AWS compliance efforts by compliance program</a>.</p> -</div> -</div> -<div class="sect2 topic"> -<h3 id="infrastructure-security">22.4. Infrastructure security for the AWS Cloud Development Kit (AWS CDK)</h3> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Provides information about infrastructure security for the AWS CDK.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>The AWS CDK follows the <a href="https://aws.amazon.com/compliance/shared-responsibility-model/">shared responsibility model</a> through the specific Amazon Web Services (AWS) services it supports. For AWS service security information, see the <a href="https://docs.aws.amazon.com/security/?id=docs_gateway#aws-security">AWS service security documentation page</a> and <a href="https://aws.amazon.com/compliance/services-in-scope/">AWS services that are in scope of AWS compliance efforts by compliance program</a>.</p> -</div> -</div> -</div> -</div> -<div class="sect1 topic"> -<h2 id="troubleshooting">23. Troubleshooting common AWS CDK issues</h2> -<div class="sectionbody"> -<div class="paragraph"> -<p>This topic describes how to troubleshoot the following issues with the AWS CDK.</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><a href="#troubleshooting-toolkit">After updating the AWS CDK the AWS CDK Toolkit (CLI) reports a mismatch with the AWS Construct Library</a></p> -</li> -<li> -<p><a href="#troubleshooting-nobucket">When deploying my AWS CDK stack I receive a NoSuchBucket error</a></p> -</li> -<li> -<p><a href="#troubleshooting-forbidden-null">When deploying my AWS CDK stack I receive a forbidden: null message</a></p> -</li> -<li> -<p><a href="#troubleshooting-app-required">When synthesizing an AWS CDK stack I get the message --app is required either in command-line in cdk.json or in ~/.cdk.json</a></p> -</li> -<li> -<p><a href="#troubleshooting-resource-count">When synthesizing an AWS CDK stack I receive an error because the AWS CloudFormation template contains too many resources</a></p> -</li> -<li> -<p><a href="#troubleshooting-availability-zones">I specified three (or more) Availability Zones for my Auto Scaling group or VPC but it was only deployed in two</a></p> -</li> -<li> -<p><a href="#troubleshooting-resource-not-deleted">My S3 bucket DynamoDB table or other resource is not deleted when I issue cdk destroy</a></p> -</li> -</ul> -</div> -<div class="paragraph"> -<div class="title">After updating the AWS CDK, the AWS CDK Toolkit (CLI) reports a mismatch with the AWS Construct Library</div> -<p>The version of the AWS CDK Toolkit (which provides the <code>cdk</code> command) must be at least equal to the version of the main AWS Construct Library module, <code>aws-cdk-lib</code>. The Toolkit is intended to be backward compatible. The latest 2.x version of the toolkit can be used with any 1.x or 2.x release of the library. For this reason, we recommend you install this component globally and keep it up to date.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">npm update -g aws-cdk</code></pre> -</div> -</div> -<div class="paragraph"> -<p>If you need to work with multiple versions of the AWS CDK Toolkit, install a specific version of the toolkit locally in your project folder.</p> -</div> -<div class="paragraph"> -<p>If you are using TypeScript or JavaScript, your project directory already contains a versioned local copy of the CDK Toolkit.</p> -</div> -<div class="paragraph"> -<p>If you are using another language, use <code>npm</code> to install the AWS CDK Toolkit, omitting the <code>-g</code> flag and specifying the desired version. For example:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">npm install aws-cdk@2.0</code></pre> -</div> -</div> -<div class="paragraph"> -<p>To run a locally installed AWS CDK Toolkit, use the command <code>npx aws-cdk</code> instead of only <code>cdk</code>. For example:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">npx aws-cdk deploy MyStack</code></pre> -</div> -</div> -<div class="paragraph"> -<p><code>npx aws-cdk</code> runs the local version of the AWS CDK Toolkit if one exists. It falls back to the global version when a project doesn’t have a local installation. You may find it convenient to set up a shell alias to make sure <code>cdk</code> is always invoked this way.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">macOS/Linux</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">alias cdk="npx aws-cdk"</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Windows</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">doskey cdk=npx aws-cdk $*</code></pre> -</div> -</div> -<div class="paragraph"> -<p>(<a href="#troubleshooting-top">back to list</a>)<a id="troubleshooting-nobucket"></a></p> -</div> -<div class="paragraph"> -<div class="title">When deploying my AWS CDK stack, I receive a <code>NoSuchBucket</code> error</div> -<p>Your AWS environment has not been bootstrapped, and so does not have an Amazon S3 bucket to hold resources during deployment. You can create the staging bucket and other required resources with the following command:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk bootstrap aws://ACCOUNT-NUMBER/REGION</code></pre> -</div> -</div> -<div class="paragraph"> -<p>To avoid generating unexpected AWS charges, the AWS CDK does not automatically bootstrap any environment. You must explicitly bootstrap each environment into which you will deploy.</p> -</div> -<div class="paragraph"> -<p>By default, the bootstrap resources are created in the Region or Regions that are used by stacks in the current AWS CDK application. Alternatively, they are created in the Region specified in your local AWS profile (set by <code>aws configure</code>), using that profile’s account. You can specify a different account and Region on the command line as follows. (You must specify the account and Region if you are not in an app’s directory.)</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk bootstrap aws://ACCOUNT-NUMBER/REGION</code></pre> -</div> -</div> -<div class="paragraph"> -<p>For more information, see <a href="#bootstrapping">AWS CDK bootstrapping</a>.</p> -</div> -<div class="paragraph"> -<p>(<a href="#troubleshooting-top">back to list</a>)<a id="troubleshooting-forbidden-null"></a></p> -</div> -<div class="paragraph"> -<div class="title">When deploying my AWS CDK stack, I receive a <code>forbidden: null</code> message</div> -<p>You are deploying a stack that requires bootstrap resources, but are using an IAM role or account that lacks permission to write to it. (The staging bucket is used when deploying stacks that contain assets or that synthesize an AWS CloudFormation template larger than 50K.) Use an account or role that has permission to perform the action <code>s3:*</code> against the bucket mentioned in the error message.</p> -</div> -<div class="paragraph"> -<p>(<a href="#troubleshooting-top">back to list</a>)<a id="troubleshooting-app-required"></a></p> -</div> -<div class="paragraph"> -<div class="title">When synthesizing an AWS CDK stack, I get the message <code>--app is required either in command-line, in cdk.json or in ~/.cdk.json</code></div> -<p>This message usually means that you aren’t in the main directory of your AWS CDK project when you issue <code>cdk synth</code>. The file <code>cdk.json</code> in this directory, created by the <code>cdk init</code> command, contains the command line needed to run (and thereby synthesize) your AWS CDK app. For a TypeScript app, for example, the default <code>cdk.json</code> looks something like this:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-json" data-lang="json">{ - "app": "npx ts-node bin/my-cdk-app.ts" -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>We recommend issuing <code>cdk</code> commands only in your project’s main directory, so the AWS CDK toolkit can find <code class="path">cdk.json</code> there and successfully run your app.</p> -</div> -<div class="paragraph"> -<p>If this isn’t practical for some reason, the AWS CDK Toolkit looks for the app’s command line in two other locations:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>In <code class="path">cdk.json</code> in your home directory</p> -</li> -<li> -<p>On the <code>cdk synth</code> command itself using the <code>-a</code> option</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>For example, you might synthesize a stack from a TypeScript app as follows.</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">cdk synth --app "npx ts-node my-cdk-app.ts" MyStack</code></pre> -</div> -</div> -<div class="paragraph"> -<p>(<a href="#troubleshooting-top">back to list</a>)<a id="troubleshooting-resource-count"></a></p> -</div> -<div class="paragraph"> -<div class="title">When synthesizing an AWS CDK stack, I receive an error because the AWS CloudFormation template contains too many resources</div> -<p>The AWS CDK generates and deploys AWS CloudFormation templates. AWS CloudFormation has a hard limit on the number of resources a stack can contain. With the AWS CDK, you can run up against this limit more quickly than you might expect.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>The AWS CloudFormation resource limit is 500 at this writing. See <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cloudformation-limits.html">AWS CloudFormation quotas</a> for the current resource limit.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>The AWS Construct Library’s higher-level, intent-based constructs automatically provision any auxiliary resources that are needed for logging, key management, authorization, and other purposes. For example, granting one resource access to another generates any IAM objects needed for the relevant services to communicate.</p> -</div> -<div class="paragraph"> -<p>In our experience, real-world use of intent-based constructs results in 1–5 AWS CloudFormation resources per construct, though this can vary. For serverless applications, 5–8 AWS resources per API endpoint is typical.</p> -</div> -<div class="paragraph"> -<p>Patterns, which represent a higher level of abstraction, let you define even more AWS resources with even less code. The AWS CDK code in <a href="#ecs-example">Example: Create an AWS Fargate service using the AWS CDK</a>, for example, generates more than 50 AWS CloudFormation resources while defining only three constructs!</p> -</div> -<div class="paragraph"> -<p>Exceeding the AWS CloudFormation resource limit is an error during AWS CloudFormation synthesis. The AWS CDK issues a warning if your stack exceeds 80% of the limit. You can use a different limit by setting the <code>maxResources</code> property on your stack, or disable validation by setting <code>maxResources</code> to 0.</p> -</div> -<div class="admonitionblock tip"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-tip" title="Tip"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>You can get an exact count of the resources in your synthesized output using the following utility script. (Since every AWS CDK developer needs Node.js, the script is written in JavaScript.)</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">// rescount.js - count the resources defined in a stack -// invoke with: node rescount.js <path-to-stack-json> -// e.g. node rescount.js cdk.out/MyStack.template.json - -import * as fs from 'fs'; -const path = process.argv[2]; - -if (path) fs.readFile(path, 'utf8', function(err, contents) { - console.log(err ? `${err}` : - `${Object.keys(JSON.parse(contents).Resources).length} resources defined in ${path}`); -}); else console.log("Please specify the path to the stack's output .json file");</code></pre> -</div> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>As your stack’s resource count approaches the limit, consider re-architecting to reduce the number of resources your stack contains: for example, by combining some Lambda functions, or by breaking your stack into multiple stacks. The CDK supports <a href="#resource-stack">references between stacks</a>, so you can separate your app’s functionality into different stacks in whatever way makes the most sense to you.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>AWS CloudFormation experts often suggest the use of nested stacks as a solution to the resource limit. The AWS CDK supports this approach via the <a href="#stack-nesting">NestedStack</a> construct.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>(<a href="#troubleshooting-top">back to list</a>)<a id="troubleshooting-availability-zones"></a></p> -</div> -<div class="paragraph"> -<div class="title">I specified three (or more) Availability Zones for my Auto Scaling group or VPC, but it was only deployed in two</div> -<p>To get the number of Availability Zones that you request, specify the account and Region in the stack’s <code>env</code> property. If you do not specify both, the AWS CDK, by default, synthesizes the stack as environment-agnostic. You can then deploy the stack to a specific Region using AWS CloudFormation. Because some Regions have only two Availability Zones, an environment-agnostic template doesn’t use more than two.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>In the past, Regions have occasionally launched with only one Availability Zone. Environment-agnostic AWS CDK stacks cannot be deployed to such Regions. At this writing, however, all AWS Regions have at least two AZs.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>You can change this behavior by overriding your stack’s <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html#availabilityzones">availablilityZones</a> (Python: <code>availability_zones</code>) property to explicitly specify the zones that you want to use.</p> -</div> -<div class="paragraph"> -<p>For more information about specifying a stack’s account and region at synthesis time, while retaining the flexibility to deploy to any region, see <a href="#environments">Environments for the AWS CDK</a>.</p> -</div> -<div class="paragraph"> -<p>(<a href="#troubleshooting-top">back to list</a>)<a id="troubleshooting-resource-not-deleted"></a></p> -</div> -<div class="paragraph"> -<div class="title">My S3 bucket, DynamoDB table, or other resource is not deleted when I issue <code>cdk destroy</code></div> -<p>By default, resources that can contain user data have a <code>removalPolicy</code> (Python: <code>removal_policy</code>) property of <code>RETAIN</code>, and the resource is not deleted when the stack is destroyed. Instead, the resource is orphaned from the stack. You must then delete the resource manually after the stack is destroyed. Until you do, redeploying the stack fails. This is because the name of the new resource being created during deployment conflicts with the name of the orphaned resource.</p> -</div> -<div class="paragraph"> -<p>If you set a resource’s removal policy to <code>DESTROY</code>, that resource will be deleted when the stack is destroyed.</p> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">TypeScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">import * as cdk from 'aws-cdk-lib'; -import { Construct } from 'constructs'; -import * as s3 from 'aws-cdk-lib/aws-s3'; - -export class CdkTestStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - const bucket = new s3.Bucket(this, 'Bucket', { - removalPolicy: cdk.RemovalPolicy.DESTROY, - }); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">JavaScript</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-javascript" data-lang="javascript">const cdk = require('aws-cdk-lib'); -const s3 = require('aws-cdk-lib/aws-s3'); - -class CdkTestStack extends cdk.Stack { - constructor(scope, id, props) { - super(scope, id, props); - - const bucket = new s3.Bucket(this, 'Bucket', { - removalPolicy: cdk.RemovalPolicy.DESTROY - }); - } -} - -module.exports = { CdkTestStack }</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Python</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-python" data-lang="python">import aws_cdk as cdk -from constructs import Construct -import aws_cdk.aws_s3 as s3 - -class CdkTestStack(cdk.stack): - def __init__(self, scope: Construct, id: str, **kwargs): - super().__init__(scope, id, **kwargs) - - bucket = s3.Bucket(self, "Bucket", - removal_policy=cdk.RemovalPolicy.DESTROY)</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">Java</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-java" data-lang="java">software.amazon.awscdk.*; -import software.amazon.awscdk.services.s3.*; -import software.constructs; - -public class CdkTestStack extends Stack { - public CdkTestStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public CdkTestStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - Bucket.Builder.create(this, "Bucket") - .removalPolicy(RemovalPolicy.DESTROY).build(); - } -}</code></pre> -</div> -</div> -<div class="dlist"> -<dl> -<dt class="hdlist1">C#</dt> -<dd> -<p>*</p> -</dd> -</dl> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-csharp" data-lang="csharp">using Amazon.CDK; -using Amazon.CDK.AWS.S3; - -public CdkTestStack(Construct scope, string id, IStackProps props) : base(scope, id, props) -{ - new Bucket(this, "Bucket", new BucketProps { - RemovalPolicy = RemovalPolicy.DESTROY - }); -}</code></pre> -</div> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>AWS CloudFormation cannot delete a non-empty Amazon S3 bucket. If you set an Amazon S3 bucket’s removal policy to <code>DESTROY</code>, and it contains data, attempting to destroy the stack will fail because the bucket cannot be deleted. You can have the AWS CDK delete the objects in the bucket before attempting to destroy it by setting the bucket’s <code>autoDeleteObjects</code> prop to <code>true</code>.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>(<a href="#troubleshooting-top">back to list</a>)</p> -</div> -</div> -</div> -<div class="sect1"> -<h2 id="pgp-keys">24. OpenPGP keys for the AWS CDK and jsii</h2> -<div class="sectionbody"> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>Current and historical OpenPGP keys for the AWS CDK and jsii.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>This topic contains current and historical OpenPGP keys for the AWS CDK and jsii.</p> -</div> -<div class="sect2"> -<h3 id="pgp-keys-current">24.1. Current keys</h3> -<div class="paragraph"> -<p>These keys should be used to validate current releases of the AWS CDK and jsii.</p> -</div> -<div class="sect3"> -<h4 id="cdk-pgp-key">24.1.1. AWS CDK OpenPGP key</h4> -<table class="tableblock frame-all grid-all stretch"> -<colgroup> -<col style="width: 50%;"> -<col style="width: 50%;"> -</colgroup> -<tbody> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">Key ID:</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">0x42B9CF2286CD987A</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">Type:</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">RSA</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">Size:</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">4096/4096</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">Created:</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">2022-07-05</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">Expires:</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">2026-07-04</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">User ID:</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">AWS Cloud Development Kit <<a href="mailto:aws-cdk@amazon.com">aws-cdk@amazon.com</a>></p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">Key fingerprint:</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">69B5 2D5B A295 1D11 FA65 413B 42B9 CF22 86CD 987A</p></td> -</tr> -</tbody> -</table> -<div class="paragraph"> -<p>Select the "Copy" icon to copy the following OpenPGP key:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">-----BEGIN PGP PUBLIC KEY BLOCK----- - -mQINBGLEgOsBEADCoAMwvnszMLybJ+AD9cHhVyX6+rYIUEXYSgVnfkl6Z7qawIwv -wgd/a5fEs9Kiz2XJmfwS9Rxb4d+0+Y1ls1A+gnpw9FMLcZlqkC9KLnS2MqvuXWLB -t3z4kjZaL9fQ+58PoD4gy/M2hDg6gZrYqR3gtJuw8FcFpb/1KlkzRQUM8eAMFxf2 -TyfjP0V0tSHwcB+84oushX7fUXVMyc3+OHsCPOe/WBFMIlWgKA+n33JKIQlUUC8f -kCWBAsAFupil0lCveT6mZu5slNRlc1I3iBLjUZ3/MtLygfqAMKwUVXeawtDvRIZe -PrAFc2NyODEhly2JG6K0FW7eIcvBqR3rg8U49t9Y74ELTM0kKnfd+flvq35xWqQC -0zghnk3kDppRTN4zWBgTKiCMxBcsHXGOoGn57t4B9VY9Zy3vkeySigeiwl/Tw9nJ -PE0SRnwEc/HnjTTfX+GTG1aQVE0xSVyZ4m5ymRNCu6+rNH8lKwo5FujlXJ+GXPkp -qT+Lx6Ix/Ny7PaoweWxwtZUkLRS4pWUsg0yotZrGyIbS+X3yMEG8WBTFI9hf6HTq -0ryfi5/TsBrdrGKqWB99EC9xYEGgtHp4fKO5X0ynOagVOhf0jSe8t1uyuJPGb2Gc -MQagSys5xMhdG/ZnEY4Cb+JDtH/4jc3tca0+4Z5RQ7kF9IhCncFtrbjJbwARAQAB -tC5BV1MgQ2xvdWQgRGV2ZWxvcG1lbnQgS2l0IDxhd3MtY2RrQGFtYXpvbi5jb20+ -iQI/BBMBAgApBQJixIDrAhsvBQkHhM4ABwsJCAcDAgEGFQgCCQoLBBYCAwECHgEC -F4AACgkQQrnPIobNmHo2qg//Zt9p/kN1DevflzxWKouUX0AS7UmUtRYXu5k/EEbu -wkYNHpUr7+lZ+Me5YyjcIpt6UwuG9cW4SvwuxIfXucyKAWiwEbydCQauvnrYDxDa -J6Yr/ntk7Sii6An9re99qic3IsvX+xlUXh+qJ/34ooP/1PHziCMqykvW/DwAIyhx -2qvTXy+9+OlOWSUbhkCnNz5XKb4XQGq73DqalZX1nH4dG6fckZmYRX+dpw2njfTw -ZLdZ7bkrfiL84FI4A21RfSbEU4s4ngiV17lZ9ivilBKTbDv3da7+yc919M7C5N4J -yrlxvtyYNDoqKAD2WYZAnpEbG/shu3f56RyOJd56tXGwl9nKPh+F9y+379XthSwA -xZTURFtjWf7wWHaDZadU0DKi+Oeeszjg2f/VJaGmmS8PIg7q6GiSHHpqHqNvACHm -ZXMw12QFd3qt3xu0JMmE11ZC5VBgblwpkQTrO04Sq1rOpJwXI9ODMS/ZEhAIoYmT -OR7ouknlAx6mj9fwpavWDAAJHLdVUMYBZTXiQYFzDvx51ivvTRWkB1zTJcFdqShY -B37+Jz2jLDNdMrcHk2yfVp/VvfbxKcexg8wEwrrtQUslTUenl5jBZJouoz/wW81s -Y4U1nCPCdTK5/C7JCKzR2gVnCpe6uaxAWkkM2feQhjqJZkTC4cFVgBT+4M6WcT1r -yq4= -=ahbs ------END PGP PUBLIC KEY BLOCK-----</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="jsii-pgp-key">24.1.2. jsii OpenPGP key</h4> -<table class="tableblock frame-all grid-all stretch"> -<colgroup> -<col style="width: 50%;"> -<col style="width: 50%;"> -</colgroup> -<tbody> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">Key ID:</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">0x056C4E15DAE3D8D9</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">Type:</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">RSA</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">Size:</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">4096/4096</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">Created:</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">2022-07-05</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">Expires:</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">2026-07-04</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">User ID:</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">AWS JSII Team <<a href="mailto:aws-jsii@amazon.com">aws-jsii@amazon.com</a>></p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">Key fingerprint:</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">1E07 31D4 57E5 FE87 87E5 530A 056C 4E15 DAE3 D8D9</p></td> -</tr> -</tbody> -</table> -<div class="paragraph"> -<p>Select the "Copy" icon to copy the following OpenPGP key:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">-----BEGIN PGP PUBLIC KEY BLOCK----- - -mQINBGLEgOkBEAD27EPVG9g2mHQ3+M6tF6le+tfhARJ2EV7m7NKIrTdSlCZATLWn -AVLlxG1unW34NlkKZbcbR86gAxRnnAhuEhPuloU/S5wAqPGbRiFl58YjYZDNJw6U -1SSMpE4O1sfjxv9yAbiRihLYtvksyHHZmaDhYner2aK1PdeWu+BKq/tjfm3Yzsd2 -uuVEduJ72YoQk/29dEiGOHfT+2kUKxUX+0tJSJ9MGlEf4NtQE4WLzrT6Xqb2SG4+ -alIiIVxIEi0XKDn7n8ZLjFwfJwOYxVYLtEUkqFWM8e8vgoc9/nYc+vDXZVED2g3Z -FWrwSnDSXbQpnMa2cLhD4xLpDHUS3i2p7r3dkJQGLo/5JGOopLibrOAbYZ72izhu -H/TuPFogSz0mNFPglrWdnLF04UIjIq420+06V4WQZC9n55Zjcbki/OhnC3B9pAdU -tiy8zg070bWq45dPGf5STkPPn7G8A2zmKefyO51iLIi26ZzW78siB+FvcGRhdg25 -39sHJ1cmrTeC+B+k4KeV5sQ/m3UucimrZnk1xdaiVp8mWzRqWb8bB6Rs8K9RMrMV -tFBOKOBAT2QxOQtRGAantVgm193E1T1cmNpD0FKAKkDdPs64rKBEwFiHxccXHbah -eMd1weVwn3AKFD6uAm8ZRMV+dyssfcQxqpo/kfT1XpA6cQeOmGDOcKBfdwARAQAB -tCNBV1MgSlNJSSBUZWFtIDxhd3MtanNpaUBhbWF6b24uY29tPokCPwQTAQIAKQUC -YsSA6QIbLwUJB4TOAAcLCQgHAwIBBhUIAgkKCwQWAgMBAh4BAheAAAoJEAVsThXa -49jZjU4QANoyqOJUT4gRrXshE3N0mW5Ad4i8Ke09GA62HyvTtfbsA+2nkNVGJpXm -sFMzdaFO95Q65RkLS9vW4nhhjXBEc2XYNCt2AnARudA/41ykjDPwU112z9ZTB9he -y4ItIeNGpHvMWr51fihl0y2nkpODOBeiv44jscLbHyOmZfki1f5fuIu2U2IbUGK3 -5FtYyeHcgRHnpYkzLuzK4PfayOywqQPJ7M9DWrHf+v5Cu4ZCZDOIKfzF+ew7MWwc -6KaoWHCYbFpX8jxFppbGsSFOQ8Sl2quoP0TLz9Wsq70Khi6C2P8JI6lm0HRLO+1M -jFbQxNOwAcN3k4HSwunAjXBlmT/6oc1RsdBdpXBaZ2AWseIXwSYZqNXp+5L179uZ -vSiD3DSSUqLJbdQRVOsJi3/87V5QU59byq2dToHveRjtSbVnK0TkTx9ZlgkcpjvM -BwHNqWhratV6af2Upjq2YQ0fdSB42f3pgopInxNJPMvlAb+cCfr0Pfwu7ge7UooQ -WHTxbpCvwtn/HNctMGpWscO02WsWgoYVjnVFay/XphE77pQ9rRUkhMe6VKXfxj/n -OCZJKrydluIIwR8vvONNqO+QwZ1xDEhO7MaSZlOm1AuUZIXFPgaWQkPZHKiiwFA/ -QWnL/+shuRtMH2geTjkev198Jgb5HyXFm4SyYtZferQROyliEhik -=BuGv ------END PGP PUBLIC KEY BLOCK-----</code></pre> -</div> -</div> -</div> -</div> -<div class="sect2"> -<h3 id="pgp-keys-expired">24.2. Historical keys</h3> -<div class="paragraph"> -<p>These keys may be used to validate releases of the AWS CDK and jsii before 2022-07-05.</p> -</div> -<div class="admonitionblock important"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-important" title="Important"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>New keys are created before the previous ones expire. As a result, at any given moment in time, more than one key may be valid. Keys are used to sign artifacts starting the day they are created, so use the more recently-issued key where keys' validity overlaps.</p> -</div> -</td> -</tr> -</table> -</div> -<div class="sect3"> -<h4 id="cdk-pgp-key-2022-04-07-">24.2.1. AWS CDK OpenPGP key (2022-04-07)</h4> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>This key was not used to sign AWS CDK artifacts after 2022-07-05.</p> -</div> -</td> -</tr> -</table> -</div> -<table class="tableblock frame-all grid-all stretch"> -<colgroup> -<col style="width: 50%;"> -<col style="width: 50%;"> -</colgroup> -<tbody> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">Key ID:</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">0x015584281F44A3C3</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">Type:</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">RSA</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">Size:</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">4096/4096</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">Created:</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">2022-04-07</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">Expires:</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">2026-04-06</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">User ID:</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">AWS Cloud Development Kit <<a href="mailto:aws-cdk@amazon.com">aws-cdk@amazon.com</a>></p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">Key fingerprint:</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">EAE1 1A24 82B0 AA86 456E 6C67 0155 8428 1F44 A3C3</p></td> -</tr> -</tbody> -</table> -<div class="paragraph"> -<p>Select the "Copy" icon to copy the following OpenPGP key:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">-----BEGIN PGP PUBLIC KEY BLOCK----- - -mQINBGJPLgUBEADtlR5jQtxtBmROQvmWlPOViqqnJNhk0dULc3tXnq8NS/l6X81r -wHk+/CHG5kBunwvM0qaqLFRC6z9NnnNDxEHcTi47n+OAjWyDM6unxxWOPz8Dfaps -Uq/ZWa4by292ZeqRC9Ir2wdrizb69JbRjeshBwlJDAS/qtqCAqBRH/f7Zw7QSD6/ -XTxyIy+KOVjZwFPFNHMRQ/NmgUc/Rfxsa0pUjk1YAj/AkvQlwwD8DEnASoBhO0DP -QonZxouLqIpgp4LsGo8TZdQv30ocIj0C9DuYUiUXWlCPlYPgDj6IWf3rgpMQ6nB9 -wC9lx4t/L3Zg1HUD52y8aymndmbdHVn90mzlNg4XWyc58rioYrEk57YwbDnea/Kk -Hv4kVHZRfJ4/OFPyqs5ex1X3X6rb07VvA1tfLgPywO9XF2Xws8YWOWcEobaWTcnb -AzyVC6wKya8rEQzxkYJ6UkJlhDB6g6bZwIpsI2zlimG+kSBsyFvE2oRYMS0cXPqU -o+tX0+4TvxEyW3RrUQzQHIpqXrb0X1Q8Z2idPn5dwsipDEa4gsFXtrSXmbB/0Cee -eJVvKWQAsxol3+NE9L/yozq3cz5PWh0SSbmCLRcs78lMJ23MmzbMWV7BWC9DXdY+ -TywY5IkDUPjGCKlD8VlrI3TgC222bH6qaua6LYCiTtRtvpDYuJNAlUjhawARAQAB -tC5BV1MgQ2xvdWQgRGV2ZWxvcG1lbnQgS2l0IDxhd3MtY2RrQGFtYXpvbi5jb20+ -iQI/BBMBAgApBQJiTy4FAhsvBQkHhM4ABwsJCAcDAgEGFQgCCQoLBBYCAwECHgEC -F4AACgkQAVWEKB9Eo8NpbxAAiBF0kR/lVw3vuam60mk4l0iGMVsP8Xq6g/buzbEO -2MEB4Ftk04qOnoa+93S0ZiLR9PqxrwsGSp4ADDX3Vtc4uxwzUlKUi1ywEhQ1cwyL -YHQI3Hd75K1J81ozMEu6qJH+yF0TtTDZMeZHtH/XvuIYJW3Lx4o5ZFlsEegFPAgX -YCCpUS+k9qC6M8g2VjcltQJpyjGswsKm6FWaKHW+B9dfjdOHlImB9E2jaknJ8eoY -zb9zHgFANluMzpZ6rYVSiCuXiEgYmazQWCvlPcMOP7nX+1hq1z11LMqeSnfE09gX -H+OYho9cMEJkb1dzx1H9MRpylFIn9tL+2iCp4UPJjnqi6uawWyLZ2tp4G11haqQq -1yAh69u233I8GZKFUySzjHwH5qWGRgBTjrZ6FdcjSS2w/wMkVKuCPkWtdvo/TJrm -msCd1Reye8SEKYqrs0ujTwmlvWmUZmO06AdUjo1kWiBKeslTJrWEuG7Yk4pFOoA4 -dsaq83gxpOJNVCh6M3y4DLNrvl7dhF95NwTWMROPj2otw7NIjF4/cdzve2+P7YNN -pVAtyCtTJdD3eZbQPVaL3T8cf1VGqt6++pnLGnWJ0+X3TyvfmTohdJvN3TE+tq7A -7cprDX/q9c56HaXdJzVpxEzuf/YC+JuYKeHwsX3QouDhyRg3PsigdZES/02Wr8so -l6U= -=MQI4 ------END PGP PUBLIC KEY BLOCK-----</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="jsii-pgp-key-2022-04-07">24.2.2. jsii OpenPGP key (2022-04-07)</h4> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>This key was not used to sign jsii artifacts after 2022-07-05.</p> -</div> -</td> -</tr> -</table> -</div> -<table class="tableblock frame-all grid-all stretch"> -<colgroup> -<col style="width: 50%;"> -<col style="width: 50%;"> -</colgroup> -<tbody> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">Key ID:</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">0x985F5BC974B79356</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">Type:</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">RSA</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">Size:</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">4096/4096</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">Created:</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">2022-04-07</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">Expires:</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">2026-04-06</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">User ID:</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">AWS JSII Team <<a href="mailto:aws-jsii@amazon.com">aws-jsii@amazon.com</a>></p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">Key fingerprint:</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">35A7 1785 8FA6 282D C5AC CD95 985F 5BC9 74B7 9356</p></td> -</tr> -</tbody> -</table> -<div class="paragraph"> -<p>Select the "Copy" icon to copy the following OpenPGP key:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">-----BEGIN PGP PUBLIC KEY BLOCK----- - -mQINBGJPLewBEADHH4TXup/gOlHrKDZRbj8MvsMTdM6eDteA6/c32UYV/YsK9rDA -jN8Jv/xlfosOebcHrfnFpHF9VTkmjuOpN695XdwMrW/NvlEPISTGEJf21x6ZTQ2r -1xWFYzC3sl3FZmvj9XAXTmygdv+XM3TqsFgZeCaBkZVdiLbQf+FhYrovUlgotb5D -YiCQI3ofV5QTE+141jhO5Pkd3ZIoBG+P826LaT8NXhwS0o1XqVk39DCZNoFshNmR -WFZpkVCTHyv5ZhVey1NWXnD8opO375htGNV4AeSmSIH9YkURD1g5F+2t7RiosKFo -kJrfPmUjhHn8IFpReGc8qmMMZX0WaV3t+VAWfOHGGyrXDfQ4xz1VCot75C2+qypM -+qhwOAOOP0zA7CfI96ULZzSH/j8HuQk3O0DsUCybpMuKEazEMxP3tgGtRerwDaFG -jQvAlK8Rbq3v8buBI6YJuXTwSzJE8KLjleUiTFumE6WP4rsAvlP/5rBvubeMfa3n -NIMm5Rkl36Z+jt3e2Z2ZqWDPpBRta8m7QHccrZhkvqu3YC3Gl6kdnm4Vio3Xfpg2 -qtWhIQutQ6DmItewV+weQHas3hl88RPJtSrfWWIIMkpbF7Y4vbX9xcnsYCLlp2Mz -tWbbnU+EWATNSsufml/Kdnu9iEEuLmeovE11I69nwjNOq9P+GJ3r/FUb2wARAQAB -tCNBV1MgSlNJSSBUZWFtIDxhd3MtanNpaUBhbWF6b24uY29tPokCPwQTAQIAKQUC -Yk8t7AIbLwUJB4TOAAcLCQgHAwIBBhUIAgkKCwQWAgMBAh4BAheAAAoJEJhfW8l0 -t5NWo64P/2y7gcMRylLLW/wbrCjton2O4+YRocwQxKm1cBml9FVDUR5967YczNuu -EwEOfH/Pu3UAlrBfKAfxPNhKchLwYiOBNh2Wk5UUxRcldNHTLb5jn5gxCeWNAsl/ -Tc46qY+ObdBMdOf2Vu33UCOg83WLbg1bfBoA8Bm1cd0XObtLGucu606EBt1dBrKq -9UTcbJfuGivY2Xjy5r4kEiMHBoLKcFrSo2Mm7VtYlE4Mabjyj9+orqUio7qxOl60 -aa7Psa6rMvs1Ip9IOrAdG7o5Y29tQpeINH0R1/u47BrlTEAgG63Dfy49w2h/1g0G -c9KPXVuN55OWRIu0hsiySDMk/2ERsF348TU3NURZltnCOxp6pHlbPJIxRVTNa9Cn -f8tbLB3y3HfA80516g+qwNYIYiqksDdV2bz+VbvmCWcO+FellDZli831gyMGa5JJ -rq7d0lEr6nqjcnKiVwItTQXyFYmKTAXweQtVC72g1sd3oZIyqa7T8pvhWpKXxoJV -WP+OPBhGg/JEVC9sguhuv53tzVwayrNwb54JxJsD2nemfhQm1Wyvb2bPTEaJ3mrv -mhPUvXZj/I9rgsEq3L/sm2Xjy09nra4o3oe3bhEL8nOj11wkIodi17VaGP0y+H3s -I5zB5UztS6dy+cH+J7DoRaxzVzq7qtH/ZY2quClt30wwqDHUX1ef -=+iYX ------END PGP PUBLIC KEY BLOCK-----</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="cdk-pgp-key-2018-06-19-">24.2.3. AWS CDK OpenPGP key (2018-06-19)</h4> -<table class="tableblock frame-all grid-all stretch"> -<colgroup> -<col style="width: 50%;"> -<col style="width: 50%;"> -</colgroup> -<tbody> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">Key ID:</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">0x0566A784E17F3870</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">Type:</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">RSA</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">Size:</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">4096/4096</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">Created:</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">2018-06-19</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">Expires:</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">2022-06-18</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">User ID:</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">AWS CDK Team <<a href="mailto:aws-cdk@amazon.com">aws-cdk@amazon.com</a>></p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">Key fingerprint:</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">E88B E3B6 F0B1 E350 9E36 4F96 0566 A784 E17F 3870</p></td> -</tr> -</tbody> -</table> -<div class="paragraph"> -<p>Select the "Copy" icon to copy the following OpenPGP key:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">-----BEGIN PGP PUBLIC KEY BLOCK----- - -mQINBFsovE8BEADEFVCHeAVPvoQgsjVu9FPUczxy9P+2zGIT/MLI3/vPLiULQwRy -IN2oxyBNDtcDToNa/fTkW3Ev0NTP4V1h+uBoKDZD/p+dTmSDRfByECMI0sGZ3UsG -Ohhyl2Of44s0sL8gdLtDnqSRLf+ZrfT3gpgUnplW7VitkwLxr78jDpW4QD8p8dZ9 -WNm3JgB55jyPgaJKqA1Ln4Vduni/1XkrG42nxrrU71uUdZPvPZ2ELLJa6n0/raG8 -jq3le+xQh45gAIs6PGaAgy7jAsfbwkGTBHjjujITAY1DwvQH5iS31OaCM9n4JNpc -xGZeJAVYTLilznf2QtS/a50t+ZOmpq67Ssp2j6qYpiumm0Lo9q3K/R4/yF0FZ8SL -1TuNX0ecXEptiMVUfTiqrLsANg18EPtLZZOYW+ZkbcVytkDpiqj7bMwA7mI7zGCJ -1gjaTbcEmOmVdQYS1G6ZptwbTtvrgA6AfnZxX1HUxLRQ7tT/wvRtABfbQKAh85Ff -a3U9W4oC3c1MP5IyhNV1Wo8Zm0flZiZc0iZnojTtSG6UbcxNNL4Q8e08FWjhungj -yxSsIBnQO1Aeo1N4BbzlI+n9iaXVDUN7Kz1QEyS4PNpjvUyrUiQ+a9C5sRA7WP+x -IEOaBBGpoAXB3oLsdTNO6AcwcDd9+r2NlXlhWC4/uH2YHQUIegPqHmPWxwARAQAB -tCFBV1MgQ0RLIFRlYW0gPGF3cy1jZGtAYW1hem9uLmNvbT6JAj8EEwEIACkFAlso -vE8CGy8FCQeEzgAHCwkIBwMCAQYVCAIJCgsEFgIDAQIeAQIXgAAKCRAFZqeE4X84 -cLGxD/0XHnhoR2xvz38GM8HQlwlZy9W1wVhQKmNDQUavw8Zx7+iRR3m7nq3xM7Qq -BDbcbKSg1lVLSBQ6H2V6vRpysOhkPSH1nN2dO8DtvSKIPcxK48+1x7lmO+ksSs/+ -oo1UvOmTDaRzOitYh3kOGXHHXk/l11GtF2FGQzYssX5iM4PHcjBsK1unThs56IMh -OJeZezEYzBaskTu/ytRJ236bPP2kZIEXfzAvhmTytuXWUXEftxOxc6fIAcYiKTha -aofG7WyR+Fvb1j5gNLcbY552QMxa23NZd5cSZH7468WEW1SGJ3AdLA7k5xvsPPOC -2YvQFD+vUOZ1JJuu6B5rHkiEMhRTLklkvqXEShTxuXiCp7iTOo6TBCmrWAT4eQr7 -htLmqlXrgKi8qPkWmRdXXG+MQBzI/UyZq2q8KC6cx2md1PhANmeefhiM7FZZfeNM -WLonWfh8gVCsNH5h8WJ9fxsQCADd3Xxx3NelS2zDYBPRoaqZEEBbgUP6LnWFprA2 -EkSlc/RoDqZCpBGgcoy1FFWvV/ZLgNU6OTQlYH6oYOWiylSJnaTDyurrktsxJI6d -4gdsFb6tqwTGecuUPvvZaEuvhWExLxAebhu780FdAPXgVTX+YCLI2zf+dWQvkFQf -80RE7ayn7BsiaLzFBVux/zz/WgvudsZX18r8tDiVQBL51ORmqw== -=0wuQ ------END PGP PUBLIC KEY BLOCK-----</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="jsii-pgp-key-2018-08-06">24.2.4. jsii OpenPGP key (2018-08-06)</h4> -<table class="tableblock frame-all grid-all stretch"> -<colgroup> -<col style="width: 50%;"> -<col style="width: 50%;"> -</colgroup> -<tbody> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">Key ID:</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">0x1C7ACE4CB2A1B93A</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">Type:</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">RSA</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">Size:</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">4096/4096</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">Created:</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">2018-08-06</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">Expires:</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">2022-08-05</p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">User ID:</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">AWS JSII Team <<a href="mailto:aws-jsii@amazon.com">aws-jsii@amazon.com</a>></p></td> -</tr> -<tr> -<td class="tableblock halign-left valign-top"><p class="tableblock">Key fingerprint:</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">85EF 6522 4CE2 1E8C 72DB 28EC 1C7A CE4C B2A1 B93A</p></td> -</tr> -</tbody> -</table> -<div class="paragraph"> -<p>Select the "Copy" icon to copy the following OpenPGP key:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="highlight"><code class="language-none" data-lang="none">-----BEGIN PGP PUBLIC KEY BLOCK----- - -mQINBFtoSs0BEAD6WweLD0B26h0F7Jo9iR6tVQ4PgQBK1Va5H/eP+A2Iqw79UyxZ -WNzHYhzQ5MjYYI1SgcPavXy5/LV1N8HJ7QzyKszybnLYpNTLPYArWE8ZM9ZmjvIR -p1GzwnVBGQfoOlxyeutE9T5ZkAn45dTS5jlno4unji4gHjnwXKf2nP1APU2CZfdK -8vDpLOgj9LeeGlerYNbx+7xtY/I+csFIQvK09FPLSNMJQLlkBhY0r6Rt9ZQG+653 -tJn+AUjyM237w0UIX1IqyYc5IONXu8HklPGu0NYuX9AY/63Ak2Cyfj0w/PZlvueQ -noQNM3j0nkOEsTOEXCyaLQw9iBKpxvLnm5RjMSODDCkj8c9uu0LHr7J4EOtgt2S1 -pem7Y/c/N+/Z+Ksg9fP8fVTfYwRPvdI1x2sCiRDfLoQSG9tdrN5VwPFi4sGV04sI -x7Al8Vf/OBjAGZrDaJgM/gVvb9SKAQUA6t3ofeP14gDrS0eYodEXZ+lamnxFglxF -Sn8NRC4JFNmkXSUaTNGUdFf//F0D69PRNT8CnFfmniGj0CphN5037PCA2LC/Buq2 -3+K6mTPkCcCHYPC/SwItp/xIDAQsGuDc1i1SfDYXrjsK7uOuwC5jLA9X6wZ/jgXQ -4umRRJBAV1aW8b1+yfaYYCO2AfXXO6caObv8IvH7Pc4leC2DoqylD3KklQARAQAB -tCNBV1MgSlNJSSBUZWFtIDxhd3MtanNpaUBhbWF6b24uY29tPokCPwQTAQgAKQUC -W2hKzQIbLwUJB4TOAAcLCQgHAwIBBhUIAgkKCwQWAgMBAh4BAheAAAoJEBx6zkyy -obk6B34P/iNb5QjKyhT0glZiq1wK7tuDDRpR6fC/sp6Jd/GhaNjO4BzlDbUPSjW5 -950VT+qwaHXbIma/QVP7EIRztfwWy7m8eOodjpiu7JyJprhwG9nocXiNsLADcMoH -BvabkDRWXWIWSurq2wbcFMlTVwxjHPIQs6kt2oojpzP985CDS/KTzyjow6/gfMim -DLdhSSbDUM34STEgew79L2sQzL7cvM/N59k+AGyEMHZDXHkEw/Bge5Ovz50YOnsp -lisH4BzPRIw7uWqPlkVPzJKwMuo2WvMjDfgbYLbyjfvs5mqDxT2GTwAx/rd2taU6 -iSqP0QmLM54BtTVVdoVXZSmJyTmXAAGlITq8ECZ/coUW9K2pUSgVuWyu63lktFP6 -MyCQYRmXPh9aSd4+ielteXM9Y39snlyLgEJBhMxioZXVO2oszwluPuhPoAp4ekwj -/umVsBf6As6PoAchg7Qzr+lRZGmV9YTJOgDn2Z7jf/7tOes0g/mdiXTQMSGtp/Fp -ggnifTBx3iXkrQhqHlwtam8XTHGHy3MvX17ZslNuB8Pjh+07hhCxv0VUVZPUHJqJ -ZsLa398LMteQ8UMxwJ3t06jwDWAd7mbr2tatIilLHtWWBFoCwBh1XLe/03ENCpDp -njZ7OsBsBK2nVVcN0H2v5ey0T1yE93o6r7xOwCwBiVp5skTCRUob -=2Tag ------END PGP PUBLIC KEY BLOCK-----</code></pre> -</div> -</div> -</div> -</div> -</div> -</div> -<div class="sect1 topic"> -<h2 id="doc-history">25. AWS CDK Developer Guide history</h2> -<div class="sectionbody"> -<div class="quoteblock abstract"> -<blockquote> -<div class="paragraph"> -<p>AWS CDK Developer Guide history</p> -</div> -</blockquote> -</div> -<div class="sect2 updates"> -<h3 id="unknown-title">25.1. Unknown Title!</h3> -<div class="sect3 update"> -<h4 id="document-bootstrap-template-versions-v26-and-v27">25.1.1. Document bootstrap template versions v26 and v27</h4> -<div class="paragraph"> -<p>For more information, see <a href="https://docs.aws.amazon.com/cdk/v2/guide/bootstrapping-env.html#bootstrap-template-history">Bootstrap template version history</a>.</p> -</div> -</div> -<div class="sect3 update"> -<h4 id="add-documentation-for-building-and-deploying-container-image-assets">25.1.2. Add documentation for building and deploying container image assets</h4> -<div class="paragraph"> -<p>When you build container image assets with the AWS CDK, <code class="noloc">Docker</code> is utilized by default to perform these actions. If you want to use a different container management tool, you can replace <code class="noloc">Docker</code>. For more information, see <a href="https://docs.aws.amazon.com/cdk/v2/guide/build-containers.html">Build and deploy container image assets in CDK apps</a>.</p> -</div> -</div> -<div class="sect3 update"> -<h4 id="add-documentation-for-cdk-migrate-feature">25.1.3. Add documentation for CDK Migrate feature</h4> -<div class="paragraph"> -<p>Use the AWS CDK <code class="noloc">CLI</code><code>cdk migrate</code> command to migrate deployed AWS resources, deployed AWS CloudFormation stacks, and local AWS CloudFormation templates to AWS CDK. For more information, see <a href="https://docs.aws.amazon.com/cdk/v2/guide/migrate.html">Migrate to AWS CDK</a>.</p> -</div> -</div> -<div class="sect3 update"> -<h4 id="iam-best-practices-updates">25.1.4. IAM best practices updates</h4> -<div class="paragraph"> -<p>Updated guide to align with the IAM best practices. For more information, see <a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html">Security best practices in IAM</a>.</p> -</div> -</div> -<div class="sect3 update"> -<h4 id="document-cdk-json">25.1.5. Document <code class="path">cdk.json</code></h4> -<div class="paragraph"> -<p>Add documentation of <code class="path">cdk.json</code> configuration values.</p> -</div> -</div> -<div class="sect3 update"> -<h4 id="dependency-management">25.1.6. Dependency management</h4> -<div class="paragraph"> -<p>Add topic on managing dependencies with the AWS CDK.</p> -</div> -</div> -<div class="sect3 update"> -<h4 id="remove-double-braces-from-java-examples">25.1.7. Remove double-braces from Java examples</h4> -<div class="paragraph"> -<p>Replace this anti-pattern with Java 9 <code>Map.of</code> throughout.</p> -</div> -</div> -<div class="sect3 update"> -<h4 id="aws-cdk-v2-release">25.1.8. AWS CDK v2 release</h4> -<div class="paragraph"> -<p>Version 2 of the AWS CDK Developer Guide is released. <a href="../../v1/guide/doc-history.html">Document history</a> for CDK v1.</p> -</div> -<div class="paragraph"> -<p>See <a href="https://github.com/awslabs/aws-cdk/releases">Releases</a> for information about AWS CDK releases. The AWS CDK is updated approximately once a week. Maintenance versions may be released between weekly releases to address critical issues. Each release includes a matched AWS CDK Toolkit (CDK CLI), AWS Construct Library, and API Reference. Updates to this Guide generally do not synchronize with AWS CDK releases.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -<div class="paragraph"> -<p>The table below represents significant documentation milestones. We fix errors and improve content on an ongoing basis.</p> -</div> -</td> -</tr> -</table> -</div> -</div> -</div> -</div> -</div> -</div> -<div id="footer"> -<div id="footer-text"> -Last updated 2025-04-24 18:35:51 UTC -</div> -</div> -</body> -</html> \ No newline at end of file diff --git a/v2/guide/bootstrapping/bootstrapping-customizing.adoc b/v2/guide/bootstrapping/bootstrapping-customizing.adoc deleted file mode 100644 index acde1d84..00000000 --- a/v2/guide/bootstrapping/bootstrapping-customizing.adoc +++ /dev/null @@ -1,193 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[#bootstrapping-customizing] -= Customize {aws} CDK bootstrapping -:info_titleabbrev: Customize bootstrapping -:keywords: {aws} CDK, {aws} Cloud Development Kit ({aws} CDK), {aws} account, {aws} Region, Bootstrapping, Bootstrap, Environment, Customize - -[abstract] --- -You can customize {aws} Cloud Development Kit ({aws} CDK) bootstrapping by using the {aws} CDK Command Line Interface ({aws} CDK CLI) or by modifying and deploying the {aws} CloudFormation bootstrap template. --- - -// Content start - -You can customize {aws} Cloud Development Kit ({aws} CDK) bootstrapping by using the {aws} CDK Command Line Interface ({aws} CDK CLI) or by modifying and deploying the {aws} CloudFormation bootstrap template. - -For an introduction to bootstrapping, see xref:bootstrapping[{aws} CDK bootstrapping]. - -[#bootstrapping-customizing-cli] -== Use the CDK CLI to customize bootstrapping - -The following are a few examples of how you can customize bootstrapping by using the CDK CLI. For a list of all `cdk bootstrap` options, see xref:ref-cli-cmd-bootstrap[cdk bootstrap]. - -[#bootstrapping-customizing-cli-s3-name] -*Override the name of the Amazon S3 bucket*:: -Use the `--bootstrap-bucket-name` option to override the default Amazon S3 bucket name. This may require that you modify template synthesis. For more information, see xref:bootstrapping-custom-synth[Customize CDK stack synthesis]. - -[#bootstrapping-customizing-keys] -*Modify server-side encryption keys for the Amazon S3 bucket*:: -By default, the Amazon S3 bucket in the bootstrap stack is configure to use {aws} managed keys for server-side encryption. To use an existing customer managed key, use the `--bootstrap-kms-key-id` option and provide a value for the {aws} Key Management Service ({aws} KMS) key to use. If you want more control over the encryption key, provide `--bootstrap-customer-key` to use a customer managed key. - -[#bootstrapping-customizing-cli-deploy-role] -*Attach managed policies to the deployment role assumed by {aws} CloudFormation*:: -By default, stacks are deployed with full administrator permissions using the `AdministratorAccess` policy. To use your own managed policies, use the `--cloudformation-execution-policies` option and provide the ARNs of the managed policies to attach to the deployment role. -+ -To provide multiple policies, pass them a single string, separated by commas: -+ -[source,none,subs="verbatim,attributes"] ----- -$ cdk bootstrap --cloudformation-execution-policies "arn:aws:iam::aws:policy/AWSLambda_FullAccess,arn:aws:iam::aws:policy/AWSCodeDeployFullAccess" ----- -+ -To avoid deployment failures, be sure that the policies you specify are sufficient for any deployments that you will perform into the environment being bootstrapped. -+ -[#bootstrapping-customizing-cli-qualifier] -*Change the qualifier that is added to the names of resources in your bootstrap stack*:: -By default, the `hnb659fds` qualifier is added to the physical ID of resources in your bootstrap stack. To change this value, use the `--qualifier` option. -+ -This modification is useful when provisioning multiple bootstrap stacks in the same environment to avoid name clashes. -+ -Changing the qualifier is intended for name isolation between automated tests of the CDK itself. Unless you can very precisely scope down the IAM permissions given to the CloudFormation execution role, there are no permission isolation benefits to having two different bootstrap stacks in a single account. Therefore, there's usually no need to change this value. -+ -When you change the qualifier, your CDK app must pass the changed value to the stack synthesizer. For more information, see xref:bootstrapping-custom-synth[Customize CDK stack synthesis]. -+ -[#bootstrapping-customizing-cli-tags] -*Add tags to the bootstrap stack*:: -Use the `--tags` option in the format of `KEY=VALUE` to add CloudFormation tags to your bootstrap stack. -+ -[#bootstrapping-customizing-cli-accounts-deploy] -*Specify additional {aws} accounts that can deploy into the environment being bootstrapped*:: -Use the `--trust` option to provide additional {aws} accounts that are allowed to deploy into the environment being bootstrapped. By default, the account performing the bootstrapping will always be trusted. -+ -This option is useful when you are bootstrapping an environment that a CDK [.noloc]`Pipeline` from another environment will deploy into. -+ -When you use this option, you must also provide `--cloudformation-execution-policies`. -+ -To add trusted accounts to an existing bootstrap stack, you must specify all of the accounts to trust, including those that you may have previously provided. If you only provide new accounts to trust, the previously trusted accounts will be removed. -+ -The following is an example that trusts two accounts: -+ -[source,none,subs="verbatim,attributes"] ----- -$ cdk bootstrap aws://123456789012/us-west-2 --trust 234567890123 --trust 987654321098 --cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess - ⏳ Bootstrapping environment aws://123456789012/us-west-2... -Trusted accounts for deployment: 234567890123, 987654321098 -Trusted accounts for lookup: (none) -Execution policies: arn:aws:iam::aws:policy/AdministratorAccess -CDKToolkit: creating CloudFormation changeset... - ✅ Environment aws://123456789012/us-west-2 bootstrapped. ----- - -[#bootstrapping-customizing-cli-accounts-lookup] -*Specify additional {aws} accounts that can look up information in the environment being bootstrapped*:: -+ -Use the `--trust-for-lookup` option to specify {aws} accounts that are allowed to look up context information from the environment being bootstrapped. This option is useful to give accounts permission to synthesize stacks that will be deployed into the environment, without actually giving them permission to deploy those stacks directly. - -[#bootstrapping-customizing-cli-protection] -*Enable termination protection for the bootstrap stack*:: -If a bootstrap stack is deleted, the {aws} resources that were originally provisioned in the environment will also be deleted. After your environment is bootstrapped, we recommend that you don't delete and recreate the environment's bootstrap stack, unless you are intentionally doing so. Instead, try to update the bootstrap stack to a new version by running the `cdk bootstrap` command again. -+ -Use the `--termination-protection` option to manage termination protection settings for the bootstrap stack. By enabling termination protection, you prevent the bootstrap stack and its resources from being accidentally deleted. This is especially important if you use CDK [.noloc]`Pipelines` since there is no general recovery option if you accidentally delete the bootstrap stack. -+ -After enabling termination protection, you can use the {aws} CLI or {aws} CloudFormation console to verify. -+ -*To enable termination protection*::: -+ -. Run the following command to enable termination protection on a new or existing bootstrap stack: -+ -[source,none,subs="verbatim,attributes"] ----- -$ cdk bootstrap --termination-protection ----- -+ -. Use the {aws} CLI or CloudFormation console to verify. The following is an example, using the {aws} CLI. If you modified your bootstrap stack name, replace `CDKToolkit` with your stack name: -+ -[source,none,subs="verbatim,attributes"] ----- -$ aws cloudformation describe-stacks --stack-name <CDKToolkit> --query "Stacks[0].EnableTerminationProtection" -true ----- - -[#bootstrapping-customizing-template] -== Modify the default bootstrap template - -When you need more customization than the CDK CLI can provide, you can modify the bootstrap template as needed. Then, deploy the template to bootstrap your environment. - -*To modify and deploy the default bootstrap template*:: -+ -. Obtain the default bootstrap template using the `--show-template` option. By default, the CDK CLI will output the template in your terminal window. You can modify the CDK CLI command to save the template to your local machine. The following is an example: -+ -[source,none,subs="verbatim,attributes"] ----- -$ cdk bootstrap --show-template > <my-bootstrap-template.yaml> ----- -. Modify the bootstrap template as needed. Any changes that you make should adhere to the bootstrapping template contract. For more information on the bootstrapping template contract, see xref:bootstrapping-contract[Follow the bootstrap contract]. -+ -To ensure that your customizations are not accidentally overwritten later by someone running `cdk bootstrap` using the default template, change the default value of the `BootstrapVariant` template parameter. The CDK CLI will only allow overwriting the bootstrap stack with templates that have the same `BootstrapVariant` and an equal or higher version than the template that is currently deployed. -+ -. Deploy your modified template using your preferred {aws} CloudFormation deployment method. The following is an example that uses the CDK CLI: -+ -[source,none,subs="verbatim,attributes"] ----- -$ cdk bootstrap --template <my-bootstrap-template.yaml> ----- - -[#bootstrapping-contract] -== Follow the bootstrap contract - -For your CDK apps to properly deploy, the CloudFormation templates produced during synthesis must correctly specify the resources created during bootstrapping. These resources are commonly referred to as _bootstrap resources_. Bootstrapping creates resources in your {aws} environment that are used by the {aws} CDK to perform deployments and manage application assets. Synthesis produces CloudFormation templates from each CDK stack in your application. These templates don't just define the {aws} resources that will be provisioned from your application. They also specify the bootstrap resources to use during deployment. - -During synthesis, the CDK CLI doesn't know specifically how your {aws} environment has been bootstrapped. Instead, the CDK CLI produces CloudFormation templates based on the synthesizer that you configure. Therefore, when you customize bootstrapping, you may need to customize synthesis. For instructions on customizing synthesis, see xref:bootstrapping-custom-synth[Customize CDK stack synthesis]. The purpose is to ensure that your synthesized CloudFormation templates are compatible with your bootstrapped environment. This compatibility is referred to as the _bootstrap contract_. - -The simplest method to customize stack synthesis is by modifying the `DefaultStackSynthesizer` class in your `Stack` instance. If you require customization beyond what this class can offer, you can write your own synthesizer as a class that implements `link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.IStackSynthesizer.html[IStackSynthesizer]` (perhaps deriving from `DefaultStackSynthesizer`). - -When you customize bootstrapping, follow the bootstrap template contract to remain compatible with `DefaultStackSynthesizer`. If you modify bootstrapping beyond the bootstrap template contract, you will need to write your own synthesizer. - -[#bootstrapping-contract-versioning] -=== Versioning - -The bootstrap template should contain a resource to create an Amazon EC2 Systems Manager (SSM) parameter with a well-known name and an output to reflect the template's version: - -[source,yaml,subs="verbatim,attributes"] ----- -Resources: - CdkBootstrapVersion: - Type: {aws}::SSM::Parameter - Properties: - Type: String - Name: - Fn::Sub: '/cdk-bootstrap/${Qualifier}/version' - Value: 4 -Outputs: - BootstrapVersion: - Value: - Fn::GetAtt: [CdkBootstrapVersion, Value] ----- - -[#bootstrapping-contract-roles] -=== Roles - -The `DefaultStackSynthesizer` requires five IAM roles for five different purposes. If you are not using the default roles, you must specify your IAM role ARNs within your `DefaultStackSynthesizer` object. The roles are as follows: - -* The _deployment role_ is assumed by the CDK CLI and by {aws} CodePipeline to deploy into an environment. Its `AssumeRolePolicy` controls who can deploy into the environment. In the template, you can see the permissions that this role needs. -* The _lookup role_ is assumed by the CDK CLI to perform context lookups in an environment. Its `AssumeRolePolicy` controls who can deploy into the environment. The permissions this role needs can be seen in the template. -* The _file publishing role_ and the _image publishing role_ are assumed by the CDK CLI and by {aws} CodeBuild projects to publish assets into an environment. They're used to write to the Amazon S3 bucket and the Amazon ECR repository, respectively. These roles require write access to these resources. -* _The {aws} CloudFormation execution role_ is passed to {aws} CloudFormation to perform the actual deployment. Its permissions are the permissions that the deployment will execute under. The permissions are passed to the stack as a parameter that lists managed policy ARNs. - -[#bootstrapping-contract-outputs] -=== Outputs - -The CDK CLI requires that the following CloudFormation outputs exist on the bootstrap stack: - -* `BucketName` – The name of the file asset bucket. -* `BucketDomainName` – The file asset bucket in domain name format. -* `BootstrapVersion` – The current version of the bootstrap stack. - -[#bootstrapping-contract-history] -=== Template history - -The bootstrap template is versioned and evolves over time with the {aws} CDK itself. If you provide your own bootstrap template, keep it up to date with the canonical default template. You want to make sure that your template continues to work with all CDK features. For more information, see xref:bootstrap-template-history[Bootstrap template version history]. \ No newline at end of file diff --git a/v2/guide/bootstrapping/bootstrapping-env.adoc b/v2/guide/bootstrapping/bootstrapping-env.adoc deleted file mode 100644 index 85fb1fb1..00000000 --- a/v2/guide/bootstrapping/bootstrapping-env.adoc +++ /dev/null @@ -1,610 +0,0 @@ -include::../attributes.txt[] - -// Attributes -[.topic] -[#bootstrapping-env] -= Bootstrap your environment for use with the {aws} CDK -:info_titleabbrev: Bootstrap your environment -:keywords: {aws} CDK, {aws} Cloud Development Kit ({aws} CDK), {aws} account, {aws} Region, Bootstrapping, Bootstrap, Environment - -[abstract] --- -Bootstrap your {aws} environment before using the {aws} Cloud Development Kit ({aws} CDK) to deploy CDK stacks into your environment. --- - -// Content start - -Bootstrap your {aws} environment to prepare it for {aws} Cloud Development Kit ({aws} CDK) stack deployments. - -* For an introduction to environments, see xref:environments[Environments for the {aws} CDK]. -* For an introduction to bootstrapping, see xref:bootstrapping[{aws} CDK bootstrapping]. - -[#bootstrapping-howto] -== How to bootstrap your environment - -You can use the {aws} CDK Command Line Interface ({aws} CDK CLI) or your preferred {aws} CloudFormation deployment tool to bootstrap your environment. - -[#bootstrapping-howto-cli] -*Use the CDK CLI*:: -+ -You can use the CDK CLI `cdk bootstrap` command to bootstrap your environment. This is the method that we recommend if you don't require significant modifications to bootstrapping. -+ -*Bootstrap from any working directory*::: -+ -To bootstrap from any working directory, provide the environment to bootstrap as a command line argument. The following is an example: -+ -[source,bash,subs="verbatim,attributes"] ----- -$ cdk bootstrap <aws://123456789012/us-east-1> ----- -+ -[TIP] --- -If you don't have your {aws} account number, you can get it from the {aws} Management Console. You can also use the following {aws} CLI command to display your default account information, including your account number: - -[source,none,subs="verbatim,attributes"] ----- -$ aws sts get-caller-identity ----- - -If you have named profiles in your {aws} `config` and `credentials` files, use the `--profile` option to retrieve account information for a specific profile. The following is an example: - -[source,none,subs="verbatim,attributes"] ----- -$ aws sts get-caller-identity --profile <prod> ----- - -To display the default Region, use the `aws configure get` command: - -[source,none,subs="verbatim,attributes"] ----- -$ aws configure get region -$ aws configure get region --profile <prod> ----- --- -+ - -When providing an argument, the `aws://` prefix is optional. The following is valid: -+ -[source,none,subs="verbatim,attributes"] ----- -$ cdk bootstrap <123456789012/us-east-1> ----- -+ -To bootstrap multiple environments at the same time, provide multiple arguments: -+ -[source,none,subs="verbatim,attributes"] ----- -$ cdk bootstrap <aws://123456789012/us-east-1> <aws://123456789012/us-east-2> ----- - -*Bootstrap from the parent directory of a CDK project*::: -+ -You can run `cdk bootstrap` from the parent directory of a CDK project containing a `cdk.json` file. If you don`'t provide an environment as an argument, the CDK CLI will obtain environment information from default sources, such as your `config` and `credentials` files or any environment information specified for your CDK stack. -+ -When you bootstrap from the parent directory of a CDK project, environments provided from command line arguments take precedence over other sources. -+ -To bootstrap an environment that is specified in your `config` and `credentials` files, use the `--profile` option: -+ -[source,none,subs="verbatim,attributes"] ----- -$ cdk bootstrap --profile <prod> ----- -+ - -For more information on the `cdk bootstrap` command and supported options, see xref:ref-cli-cmd-bootstrap[cdk bootstrap]. - -[#bootstrapping-howto-cfn] -*Use any {aws} CloudFormation tool*:: -+ -You can copy the https://github.com/aws/aws-cdk-cli/blob/main/packages/aws-cdk/lib/api/bootstrap/bootstrap-template.yaml[bootstrap template] from the _aws-cdk-cli GitHub repository_ or obtain the template with the `cdk bootstrap --show-template` command. Then, use any {aws} CloudFormation tool to deploy the template into your environment. -+ -With this method, you can use {aws} CloudFormation StackSets or {aws} Control Tower. You can also use the {aws} CloudFormation console or the {aws} Command Line Interface ({aws} CLI). You can make modifications to your template before you deploy it. This method may be more flexible and suitable for large-scale deployments. -+ -The following is an example of using the `--show-template` option to retrieve and save the bootstrap template to your local machine: -+ -==== -[role="tablist"] -macOS/Linux:: -+ -[source,none,subs="verbatim,attributes"] ----- -$ cdk bootstrap --show-template > bootstrap-template.yaml ----- - -Windows:: -On Windows, PowerShell must be used to preserve the encoding of the template. -+ -[source,none,subs="verbatim,attributes"] ----- -powershell "cdk bootstrap --show-template | Out-File -encoding utf8 bootstrap-template.yaml" ----- -==== -+ - -[NOTE] -==== - -If CDK notices are appearing in your {aws} CloudFormation template output, provide the `--no-notices` option with your command. - -==== -+ -To deploy this template using the CDK CLI, you can run the following: -+ -[source,none,subs="verbatim,attributes"] ----- -$ cdk bootstrap --template <bootstrap-template.yaml> ----- -+ -The following is an example of using the {aws} CLI to deploy the template: -+ -==== -[role="tablist"] -macOS/Linux:: -+ -[source,none,subs="verbatim,attributes"] ----- -aws cloudformation create-stack \ - --stack-name CDKToolkit \ - --template-body file://<path/to/>bootstrap-template.yaml \ - --capabilities CAPABILITY_NAMED_IAM \ - --region <us-west-1> ----- - -Windows:: -+ -[source,none,subs="verbatim,attributes"] ----- -aws cloudformation create-stack ^ - --stack-name CDKToolkit ^ - --template-body file://<path/to/>bootstrap-template.yaml ^ - --capabilities CAPABILITY_NAMED_IAM ^ - --region <us-west-1> ----- -==== -+ - -For information on using CloudFormation StackSets to bootstrap multiple environments, see https://aws.amazon.com/blogs/mt/bootstrapping-multiple-aws-accounts-for-aws-cdk-using-cloudformation-stacksets/[Bootstrapping multiple {aws} accounts for {aws} CDK using CloudFormation StackSets] in the __{aws} Cloud Operations & Migrations Blog__. - -[#bootstrapping-env-when] -== When to bootstrap your environment - -You must bootstrap each {aws} environment before you deploy into the environment. We recommend that you proactively bootstrap each environment that you plan to use. You can do this before you plan on actually deploying CDK apps into the environment. By proactively bootstrapping your environments, you prevent potential future issues such as Amazon S3 bucket name conflicts or deploying CDK apps into environments that haven't been bootstrapped. - -It's okay to bootstrap an environment more than once. If an environment has already been bootstrapped, the bootstrap stack will be upgraded if necessary. Otherwise, nothing will happen. - -If you attempt to deploy a CDK stack into an environment that hasn`'t been bootstrapped, you will see an error like the following: - -[source,none,subs="verbatim,attributes"] ----- -$ cdk deploy - -✨ Synthesis time: 2.02s - - ❌ Deployment failed: Error: BootstrapExampleStack: SSM parameter /cdk-bootstrap/hnb659fds/version not found. Has the environment been bootstrapped? Please run 'cdk bootstrap' (see https://docs.aws.amazon.com/cdk/latest/guide/bootstrapping.html) ----- - - -[#bootstrapping-env-when-update] -*Update your bootstrap stack*:: -+ -Periodically, the CDK team will update the bootstrap template to a new version. When this happens, we recommend that you update your bootstrap stack. If you haven`'t customized the bootstrapping process, you can update your bootstrap stack by following the same steps that you took to originally bootstrap your environment. For more information, see xref:bootstrap-template-history[Bootstrap template version history]. - -[#bootstrapping-env-default] -== Default resources created during bootstrapping - -[#bootstrapping-env-roles] -*IAM roles created during bootstrapping*:: -+ -By default, bootstrapping provisions the following {aws} Identity and Access Management (IAM) roles in your environment: -+ --- -* `CloudFormationExecutionRole` -* `DeploymentActionRole` -* `FilePublishingRole` -* `ImagePublishingRole` -* `LookupRole` --- -+ -[#bootstrapping-env-roles-cfn] -`CloudFormationExecutionRole`::: -+ -This IAM role is a CloudFormation service role that grants CloudFormation permission to perform stack deployments on your behalf. This role gives CloudFormation permission to perform {aws} API calls in your account, including deploying stacks. -+ -By using a service role, the permissions provisioned for the service role determine what actions can be performed on your CloudFormation resources. Without this service role, the security credentials you provide with the CDK CLI would determine what CloudFormation is allowed to do. -+ -[#bootstrapping-env-roles-deploy] -`DeploymentActionRole`::: -+ -This IAM role grants permission to perform deployments into your environment. It is assumed by the CDK CLI during deployments. -+ -By using a role for deployments, you can perform cross-account deployments since the role can be assumed by {aws} identities in a different account. -+ -[#bootstrapping-env-roles-s3] -`FilePublishingRole`::: -+ -This IAM role grants permission to perform actions against the bootstrapped Amazon Simple Storage Service (Amazon S3) bucket, including uploading and deleting assets. It is assumed by the CDK CLI during deployments. -+ -[#bootstrapping-env-roles-ecr] -`ImagePublishingRole`::: -+ -This IAM role grants permission to perform actions against the bootstrapped Amazon Elastic Container Registry (Amazon ECR) repository. It is assumed by the CDK CLI during deployments. -+ -[#bootstrapping-env-roles-lookup] -`LookupRole`::: -+ -This IAM role grants `readOnly` permission to look up xref:context[context values] from the {aws} environment. It is assumed by the CDK CLI when performing tasks such as template synthesis and deployments. - -[#bootstrapping-env-default-id] -*Resource IDs created during bootstrapping*:: -+ -When you deploy the default bootstrap template, physical IDs for bootstrap resources are created using the following structure: `cdk-<qualifier>-<description>-<account-ID>-<Region>`. -+ --- -* *Qualifier* – A nine character unique string value of `hnb659fds`. The actual value has no significance. -* *Description* – A short description of the resource. For example, `container-assets`. -* *Account ID* – The {aws} account ID of the environment. -* *Region* – The {aws} Region of the environment. --- -+ -The following is an example physical ID of the Amazon S3 staging bucket created during bootstrapping: `cdk-hnb659fds-assets-012345678910-us-west-1`. - -[#bootstrapping-env-permissions] -== Permissions to use when bootstrapping your environment - -When bootstrapping an {aws} environment, the IAM identity performing the bootstrapping must have at least the following permissions: - -[source,json,subs="verbatim,attributes"] ----- -{ - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Action": [ - "cloudformation:*", - "ecr:*", - "ssm:*", - "s3:*", - "iam:*" - ], - "Resource": "*" - } - ] -} ----- - -Over time, the bootstrap stack, including the resources that are created and permissions they require, may change. With future changes, you may need to modify the permissions required to bootstrap an environment. - -[#bootstrapping-env-customize] -== Customize bootstrapping - -If the default bootstrap template doesn`'t suit your needs, you can customize the bootstrapping of resources into your environment in the following ways: - -* Use command line options with the `cdk bootstrap` command – This method is best for making small, specific changes that are supported through command line options. -* Modify the default bootstrap template and deploy it – This method is best for making complex changes or if you want complete control over the configuration of resources provisioned during bootstrapping. - -For more information on customizing bootstrapping, see xref:bootstrapping-customizing[Customize {aws} CDK bootstrapping]. - -[#bootstrapping-env-pipelines] -== Bootstrapping with CDK Pipelines - -If you are using CDK Pipelines to deploy into another account's environment, and you receive a message like the following: - -[source,none,subs="verbatim,attributes"] ----- -Policy contains a statement with one or more invalid principals ----- - -This error message means that the appropriate IAM roles do not exist in the other environment. The most likely cause is that the environment has not been bootstrapped. Bootstrap the environment and try again. - -[#bootstrapping-env-pipelines-protect] -*Protecting your bootstrap stack from deletion*:: -+ -If a bootstrap stack is deleted, the {aws} resources that were originally provisioned in the environment to support CDK deployments will also be deleted. This will cause the pipeline to stop working. If this happens, there is no general solution for recovery. -+ -After your environment is bootstrapped, do not delete and recreate the environment's bootstrap stack. Instead, try to update the bootstrap stack to a new version by running the `cdk bootstrap` command again. -+ -To protect against accidental deletion of your bootstrap stack, we recommend that you provide the `--termination-protection` option with the `cdk bootstrap` command to enable termination protection. You can enable termination protection on new or existing bootstrap stacks. For instructions on enabling termination protection, see xref:bootstrapping-customizing-cli-protection[Enable termination protection for the bootstrap stack]. - -[#bootstrap-template-history] -== Bootstrap template version history - -The bootstrap template is versioned and evolves over time with the {aws} CDK itself. If you provide your own bootstrap template, keep it up to date with the canonical default template. You want to make sure that your template continues to work with all CDK features. - -[NOTE] -==== - -Earlier versions of the bootstrap template created an {aws} KMS key in each bootstrapped environment by default. To avoid charges for the KMS key, re-bootstrap these environments using `--no-bootstrap-customer-key`. The current default is no KMS key, which helps avoid these charges. - -==== - -This section contains a list of the changes made in each version. - -[cols="1,1,1", options="header"] -|=== -| Template version -| {aws} CDK version -| Changes - -|**1** -|1.40.0 -|Initial version of template with Bucket, Key, Repository, and Roles. - -|**2** -|1.45.0 -|Split asset publishing role into separate file and image publishing roles. - -|**3** -|1.46.0 -|Add `FileAssetKeyArn` export to be able to add decrypt permissions to asset consumers. - -|**4** -|1.61.0 -|{aws} KMS permissions are now implicit via Amazon S3 and no longer require `FileAssetKeyArn`. Add `CdkBootstrapVersion` SSM parameter so the bootstrap stack version can be verified without knowing the stack name. - -|**5** -|1.87.0 -|Deployment role can read SSM parameter. - -|**6** -|1.108.0 -|Add lookup role separate from deployment role. - -|**6** -|1.109.0 -|Attach `aws-cdk:bootstrap-role` tag to deployment, file publishing, and image publishing roles. - -|**7** -|1.110.0 -|Deployment role can no longer read Buckets in the target account directly. (However, this role is effectively an administrator, and could always use its {aws} CloudFormation permissions to make the bucket readable anyway). - -|**8** -|1.114.0 -|The lookup role has full read-only permissions to the target environment, and has a `aws-cdk:bootstrap-role` tag as well. - -|**9** -|2.1.0 -|Fixes Amazon S3 asset uploads from being rejected by commonly referenced encryption SCP. - -|**10** -|2.4.0 -|Amazon ECR ScanOnPush is now enabled by default. - -|**11** -|2.18.0 -|Adds policy allowing Lambda to pull from Amazon ECR repos so it survives re-bootstrapping. - -|**12** -|2.20.0 -|Adds support for experimental `cdk import`. - -|**13** -|2.25.0 -|Makes container images in bootstrap-created Amazon ECR repositories immutable. - -|**14** -|2.34.0 -|Turns off Amazon ECR image scanning at the repository level by default to allow bootstrapping Regions that do not support image scanning. - -|**15** -|2.60.0 -|KMS keys cannot be tagged. - -|**16** -|2.69.0 -|Addresses Security Hub finding link:https://docs.aws.amazon.com/securityhub/latest/userguide/kms-controls.html#kms-2[KMS.2]. - -|**17** -|2.72.0 -|Addresses Security Hub finding link:https://docs.aws.amazon.com/securityhub/latest/userguide/ecr-controls.html#ecr-3[ECR.3]. - -|**18** -|2.80.0 -|Reverted changes made for version 16 as they don't work in all partitions and are are not recommended. - -|**19** -|2.106.1 -|Reverted changes made to version 18 where AccessControl property was removed from the template. (https://github.com/aws/aws-cdk/issues/27964[#27964]) - -|**20** -|2.119.0 -|Add `ssm:GetParameters` action to the {aws} CloudFormation deploy IAM role. For more information, see link:https://github.com/aws/aws-cdk/pull/28336/files#diff-4fdac38426c4747aa17d515b01af4994d3d2f12c34f7b6655f24328259beb7bf[#28336]. - -|**21** -|2.149.0 -|Add condition to the file publishing role. - -|**22** -|2.160.0 -|Add `sts:TagSession` permissions to the trust policy of bootstrap IAM roles. - -|**23** -|2.161.0 -|Add `cloudformation:RollbackStack` and `cloudformation:ContinueUpdateRollback` permissions to the trust policy of the deploy IAM role. This provides permissions for the `cdk rollback` command. - -|**24** -|2.165.0 -|Change the duration of days that noncurrent objects in the bootstrap bucket will be retained, from 365 to 30 days. Since the new `cdk gc` command introduces the ability to delete objects in the bootstrap bucket, this new behavior ensures that deleted objects remain in the bootstrap bucket for 30 days instead of 365 days. For more information on this change, see `aws-cdk` PR https://github.com/aws/aws-cdk/pull/31949[#31949]. - -|**25** -|2.165.0 -|Add support to the bootstrap bucket for the removal of incomplete multipart uploads. Incomplete multipart uploads will be deleted after 1 day. For more information on this change, see `aws-cdk` PR https://github.com/aws/aws-cdk/pull/31956[#31956]. - -|**26** -|2.1002.0 -|Add two deletion-related policies (`UpdateReplacePolicy` and `DeletionPolicy` to the `FileAssetsBucketEncryptionKey`) resource. These policies ensure that the old {aws} KMS key resource will be properly deleted when the bootstrap stack is updated or deleted. For more information on this change, see `aws-cdk-cli` PR https://github.com/aws/aws-cdk-cli/pull/100[#100]. - -|**27** -|2.1003.0 -|Add new Amazon ECR resource policy to grant Amazon EMR Serverless specific permissions for retrieving container images. For more information on this change, see `aws-cdk-cli` PR https://github.com/aws/aws-cdk-cli/pull/112[#112]. -|=== - -[#bootstrapping-template] -== Upgrade from legacy to modern bootstrap template - -The {aws} CDK v1 supported two bootstrapping templates, legacy and modern. CDK v2 supports only the modern template. For reference, here are the high-level differences between these two templates. - -[cols="1h,1,1", options="header"] -|=== -| Feature -| Legacy (v1 only) -| Modern (v1 and v2) - - -|Cross-account deployments -|Not allowed -|Allowed - -|{aws} CloudFormation Permissions -|Deploys using current user's permissions (determined by {aws} profile, environment variables, etc.) -|Deploys using the permissions specified when the bootstrap stack was provisioned (for example, by using `--trust`) - -|Versioning -|Only one version of bootstrap stack is available -|Bootstrap stack is versioned; new resources can be added in future versions, and {aws} CDK apps can require a minimum version - -|Resources* -|Amazon S3 bucket -a| - -* Amazon S3 bucket -* {aws} KMS key -* IAM roles -* Amazon ECR repository -* SSM parameter for versioning - -|{aws} KMS key -|IAM roles -|Amazon ECR repository - -//|SSM parameter for versioning - -|Resource naming -|Automatically generated -|Deterministic - -|Bucket encryption -|Default key -|{aws} managed key by default. You can customize to use a customer managed key. -|=== - -* _We will add additional resources to the bootstrap template as needed._ - -An environment that was bootstrapped using the legacy template must be upgraded to use the modern template for CDK v2 by re-bootstrapping. Re-deploy all {aws} CDK applications in the environment at least once before deleting the legacy bucket. - -[#bootstrapping-securityhub] -== Address Security Hub Findings - -If you are using {aws} Security Hub, you may see findings reported on some of the resources created by the {aws} CDK bootstrapping process. Security Hub findings help you find resource configurations you should double-check for accuracy and safety. We have reviewed these specific resource configurations with {aws} Security and are confident they do not constitute a security problem. - -[#bootstrapping-securityhub-kms2] -*[KMS.2] IAM principals should not have IAM inline policies that allow decryption actions on all KMS keys*:: -+ -The _deploy role_ (`DeploymentActionRole`) grants permission to read encrypted data, which is necessary for cross-account deployments with CDK Pipelines. Policies in this role do not grant permission to all data. It only grants permission to read encrypted data from Amazon S3 and {aws} KMS, and only when those resources allow it through their bucket or key policy. -+ -The following is a snippet of these two statements in the _deploy role_ from the bootstrap template: -+ -[source,yaml,subs="verbatim,attributes"] ----- -DeploymentActionRole: - Type: {aws}::IAM::Role - Properties: - ... - Policies: - - PolicyDocument: - Statement: - ... - - Sid: PipelineCrossAccountArtifactsBucket - Effect: Allow - Action: - - s3:GetObject* - - s3:GetBucket* - - s3:List* - - s3:Abort* - - s3:DeleteObject* - - s3:PutObject* - Resource: "*" - Condition: - StringNotEquals: - s3:ResourceAccount: - Ref: {aws}::AccountId - - Sid: PipelineCrossAccountArtifactsKey - Effect: Allow - Action: - - kms:Decrypt - - kms:DescribeKey - - kms:Encrypt - - kms:ReEncrypt* - - kms:GenerateDataKey* - Resource: "*" - Condition: - StringEquals: - kms:ViaService: - Fn::Sub: s3.${{aws}::Region}.amazonaws.com - ... ----- -+ -[#bootstrapping-securityhub-kms2-why] -*Why does Security Hub flag this?*::: -+ -The policies contain a `Resource: \*` combined with a `Condition` clause. Security Hub flags the `*` wildcard. This wildcard is used because at the time the account is bootstrapped, the {aws} KMS key created by CDK Pipelines for the CodePipeline artifact bucket does not exist yet, and therefore, can`'t be referenced on the bootstrap template by ARN. In addition, Security Hub does not consider the `Condition` clause when raising this flag. This `Condition` restricts `Resource: *` to requests made from the same {aws} account of the {aws} KMS key. These requests must come from Amazon S3 in the same {aws} Region as the {aws} KMS key. -+ -[#bootstrapping-securityhub-kms2-decide] -*Do I need to fix this finding?*::: -+ -As long as you have not modified the {aws} KMS key on your bootstrap template to be overly permissive, the _deploy role_ does not allow more access than it needs. Therefore, it is not necessary to fix this finding. -+ -[#bootstrapping-securityhub-kms2-fix] -*What if I want to fix this finding?*::: -+ -How you fix this finding depends on whether or not you will be using CDK Pipelines for cross-account deployments. -+ -*To fix the Security Hub finding and use CDK Pipelines for cross-account deployments*:::: -+ -. If you have not done so, deploy the CDK bootstrap stack using the `cdk bootstrap` command. -. If you have not done so, create and deploy your CDK [.noloc]``Pipeline``. For instructions, see xref:cdk-pipeline[Continuous integration and delivery (CI/CD) using CDK Pipelines]. -. Obtain the {aws} KMS key ARN of the CodePipeline artifact bucket. This resource is created during pipeline creation. -. Obtain a copy of the CDK bootstrap template to modify it. The following is an example, using the {aws} CDK CLI: -+ -[source,bash,subs="verbatim,attributes"] ----- -$ cdk bootstrap --show-template > bootstrap-template.yaml ----- -. Modify the template by replacing `Resource: *` of the `PipelineCrossAccountArtifactsKey` statement with your ARN value. -. Deploy the template to update your bootstrap stack. The following is an example, using the CDK CLI: -+ -[source,bash,subs="verbatim,attributes"] ----- -$ cdk bootstrap aws://<account-id>/<region> --template bootstrap-template.yaml ----- -+ - -*To fix the Security Hub finding if you’re not using CDK Pipelines for cross-account deployments*:::: -+ -. Obtain a copy of the CDK bootstrap template to modify it. The following is an example, using the CDK CLI: -+ -[source,bash,subs="verbatim,attributes"] ----- -$ cdk bootstrap --show-template > bootstrap-template.yaml ----- -. Delete the `PipelineCrossAccountArtifactsBucket` and `PipelineCrossAccountArtifactsKey` statements from the template. -. Deploy the template to update your bootstrap stack. The following is an example, using the CDK CLI: -+ -[source,bash,subs="verbatim,attributes"] ----- -$ cdk bootstrap aws://<account-id>/<region> --template bootstrap-template.yaml ----- - -[#bootstrapping-env-considerations] -== Considerations - -Since bootstrapping provisions resources in your environment, you may incur {aws} charges when those resources are used with the {aws} CDK. - -include::bootstrapping-customizing.adoc[leveloffset=+1] - - -include::customize-permissions-boundaries.adoc[leveloffset=+1] - - -include::bootstrapping-troubleshoot.adoc[leveloffset=+1] diff --git a/v2/guide/bootstrapping/bootstrapping-troubleshoot.adoc b/v2/guide/bootstrapping/bootstrapping-troubleshoot.adoc deleted file mode 100644 index 0817d898..00000000 --- a/v2/guide/bootstrapping/bootstrapping-troubleshoot.adoc +++ /dev/null @@ -1,271 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[#bootstrapping-troubleshoot] -= Troubleshoot {aws} CDK bootstrapping issues -:info_titleabbrev: Troubleshoot bootstrapping -:keywords: {aws} CDK, Bootstrapping, Troubleshoot - -[abstract] --- -Troubleshoot common issues when bootstrapping your environment with the {aws} Cloud Development Kit ({aws} CDK). --- - -// Content start - -Troubleshoot common issues when bootstrapping your environment with the {aws} Cloud Development Kit ({aws} CDK). - -* For an introduction to bootstrapping, see xref:bootstrapping[{aws} CDK bootstrapping]. -* For instructions on bootstrapping, see xref:bootstrapping-env[Bootstrap your environment for use with the {aws} CDK]. - -[#bootstrapping-troubleshoot-s3-bucket-name] -== When bootstrapping using the default template, you get a 'CREATE_FAILED' error for the Amazon S3 bucket - -When bootstrapping using the {aws} CDK Command Line Interface (CDK CLI) `cdk bootstrap` command with the default bootstrap template, you receive the following error: - -[source,none,subs="verbatim,attributes"] ----- -CREATE_FAILED | {aws}::S3::Bucket | <BucketName> already exists ----- - -Before troubleshooting, ensure that you are using the latest version of the CDK CLI. - -* To check your version, run `cdk --version`. -* To install the latest version, run `npm install -g aws-cdk`. - -After installing the latest version, try bootstrapping your environment again. If you still receive the same error, continue with troubleshooting. - -[#bootstrapping-troubleshoot-s3-bucket-name-causes] -=== Common causes - -When you bootstrap your environment, the {aws} CDK generates physical IDs for your bootstrap resources. For more information, see xref:bootstrapping-env-default-id[Resource IDs created during bootstrapping]. - -Unlike the other bootstrap resources, Amazon S3 bucket names are global. This means that each bucket name must be unique across all {aws} accounts in all {aws} Regions within a partition. For more information, see https://docs.aws.amazon.com/AmazonS3/latest/userguide/UsingBucket.html[Buckets overview] in the _Amazon S3 User Guide_. Therefore, the most common cause of this error is that the physical ID generated as your bucket name already exists somewhere within the partition. This could be within your account or another account. - -The following is an example bucket name: `cdk-hnb659fds-assets-012345678910-us-west-1`. While unlikely, due to the qualifier and account ID being a part of the name, it is possible that this name for an Amazon S3 bucket is used by another {aws} account. Since bucket names are globally scoped, it can`'t be used by you if its used by a different account in the same partition. Most likely, a bucket with the same name exists somewhere in your account. This could be in the Region you are attempting to bootstrap, or another Region. - -Generally, the resolution is to locate this bucket in your account and determine what to do with it, or customize bootstrapping to create bootstrap resources of a different name. - -[#bootstrapping-troubleshoot-s3-bucket-name-resolution] -=== Resolution - -First, determine if a bucket with the same name exists within your {aws} account. Using an {aws} identity with valid permissions to lookup Amazon S3 buckets in your account, you can do this in the following ways: - -* Use the {aws} Command Line Interface ({aws} CLI) `aws s3 ls` command to view a list of all your buckets. -* Look up bucket names for each Region in your account using the https://console.aws.amazon.com/s3[Amazon S3 console]. - -If a bucket with the same name exists, determine if it's being used. If it's not being used, consider deleting the bucket and attempting to bootstrap your environment again. - -If a bucket with the same name exists and you don't want to delete it, determine if it's already associated with a bootstrap stack in your account. You may have to check multiple Regions. The Region in the Amazon S3 bucket name doesn't necessarily mean that the bucket is in that Region. To check if it's associated with the `CDKToolkit` bootstrap stack, you can do either of the following for each Region: - -* Use the {aws} CLI `aws cloudformation describe-stack-resources --stack-name <CDKToolkit> --region <Region>` command to view the resources in your bootstrap stack and check if the bucket is listed. -* In the https://console.aws.amazon.com/cloudformation[{aws} CloudFormation console], locate the `CDKToolkit` stack. Then, on the *Resources* tab, check if the bucket exists. - -If the bucket is associated with a bootstrap stack, determine if the bootstrap stack is in the same Region that you are attempting to bootstrap. If it is, your environment is already bootstrapped and you should be able to start using the CDK to deploy applications into your environment. If the Amazon S3 bucket is associated with a bootstrap stack in a different Region, you`'ll need to determine what to do. Possible resolutions include renaming the existing Amazon S3 bucket, deleting the current Amazon S3 bucket if its not being used, or using a new name for the Amazon S3 bucket you are attempting to create. - -If you are unable to locate an Amazon S3 bucket with the same name in your account, it may exist in a different account. To resolve this, you`'ll need to customize bootstrapping to create new names for all of your bootstrap resources or for just your Amazon S3 bucket. To create new names for all bootstrap resources, you can modify the qualifier. To create a new name for only your Amazon S3 bucket, you can provide a new bucket name. - -To customize bootstrapping, you can use options with the CDK CLI `cdk bootstrap` command or by modifying the bootstrap template. For instructions, see xref:bootstrapping-customizing[Customize {aws} CDK bootstrapping]. - -If you customize bootstrapping, you will need to apply the same changes to synthesis before you can properly deploy an application. For instructions, see xref:bootstrapping-custom-synth[Customize CDK stack synthesis]. - -For example, you can provide a new qualifier with `cdk bootstrap`: - -[source,none,subs="verbatim,attributes"] ----- -$ cdk bootstrap --qualifier <abcde0123> ----- - -The following is an example Amazon S3 bucket name that will be created with this modification: `cdk-abcde0123-assets-012345678910-us-west-1`. All bootstrap resources created during bootstrapping will use this qualifier. - -When developing your CDK app, you must specify your custom qualifier in your synthesizer. This helps the CDK with identifying your bootstrap resources during synthesis and deployment. The following is an example of customizing the default synthesizer for your stack instance: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -new MyStack(this, 'MyStack', { - synthesizer: new DefaultStackSynthesizer({ - qualifier: 'abcde0123', - }), -}); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -new MyStack(this, 'MyStack', { - synthesizer: new DefaultStackSynthesizer({ - qualifier: 'abcde0123', - }), -}) ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -MyStack(self, "MyStack", - synthesizer=DefaultStackSynthesizer( - qualifier="abcde0123" -)) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -new MyStack(app, "MyStack", StackProps.builder() - .synthesizer(DefaultStackSynthesizer.Builder.create() - .qualifier("abcde0123") - .build()) - .build(); -) ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -new MyStack(app, "MyStack", new StackProps -{ - Synthesizer = new DefaultStackSynthesizer(new DefaultStackSynthesizerProps - { - Qualifier = "abcde0123" - }) -}); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -func NewMyStack(scope constructs.Construct, id string, props *MyStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - stack := awscdk.NewStack(scope, &id, &sprops) - - synth := awscdk.NewDefaultStackSynthesizer(&awscdk.DefaultStackSynthesizerProps{ - Qualifier: jsii.String("abcde0123"), - }) - - stack.SetSynthesizer(synth) - - return stack -} ----- - -You can also specify the new qualifier in the `cdk.json` file of your CDK project: - -[source,json,subs="verbatim,attributes"] ----- -{ - "app": "...", - "context": { - "@aws-cdk/core:bootstrapQualifier": "abcde0123" - } -} ----- - -To modify only the Amazon S3 bucket name, you can use the ``xref:ref-cli-cmd-bootstrap-options-bootstrap-bucket-name[--bootstrap-bucket-name]`` option. The following is an example: - -[source,none,subs="verbatim,attributes"] ----- -$ cdk bootstrap --bootstrap-bucket-name '<my-new-bucket-name>' ----- -==== - -When developing your CDK app, you must specify your new bucket name in your synthesizer. The following is an example of customizing the default synthesizer for your stack instance: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -new MyStack(this, 'MyStack', { - synthesizer: new DefaultStackSynthesizer({ - fileAssetsBucketName: 'my-new-bucket-name', - }), -}); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -new MyStack(this, 'MyStack', { - synthesizer: new DefaultStackSynthesizer({ - fileAssetsBucketName: 'my-new-bucket-name', - }), -}) ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -MyStack(self, "MyStack", - synthesizer=DefaultStackSynthesizer( - file_assets_bucket_name='my-new-bucket-name' -)) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -new MyStack(app, "MyStack", StackProps.builder() - .synthesizer(DefaultStackSynthesizer.Builder.create() - .fileAssetsBucketName("my-new-bucket-name") - .build()) - .build(); -) ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -new MyStack(app, "MyStack", new StackProps -{ - Synthesizer = new DefaultStackSynthesizer(new DefaultStackSynthesizerProps - { - FileAssetsBucketName = "my-new-bucket-name" - }) -}); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -func NewMyStack(scope constructs.Construct, id string, props *MyStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - stack := awscdk.NewStack(scope, &id, &sprops) - - synth := awscdk.NewDefaultStackSynthesizer(&awscdk.DefaultStackSynthesizerProps{ - FileAssetsBucketName: jsii.String("my-new-bucket-name"), - }) - - stack.SetSynthesizer(synth) - - return stack -} ----- -==== - -[#bootstrapping-troubleshoot-s3-bucket-name-prevention] -=== Prevention - -We recommend that you proactively bootstrap each {aws} environment that you plan to use. For more information, see xref:bootstrapping-env-when[When to bootstrap your environment]. Specifically for the Amazon S3 bucket naming issue, this will create Amazon S3 buckets in each {aws} environment and prevent others from using your Amazon S3 bucket name. \ No newline at end of file diff --git a/v2/guide/bootstrapping/customize-permissions-boundaries.adoc b/v2/guide/bootstrapping/customize-permissions-boundaries.adoc deleted file mode 100644 index 338f782d..00000000 --- a/v2/guide/bootstrapping/customize-permissions-boundaries.adoc +++ /dev/null @@ -1,54 +0,0 @@ -include::../attributes.txt[] - -// Attributes -[.topic] -[#customize-permissions-boundaries] -= Create and apply permissions boundaries for the {aws} CDK -:info_titleabbrev: Create and apply permissions boundaries -:keywords: {aws} CDK, IAM, security, permissions, Permissions boundaries - -[abstract] --- -A _permissions boundary_ is an {aws} Identity and Access Management (IAM) advanced feature that you can use to set the maximum permissions that an IAM entity, such as a user or role, can have. You can use permissions boundaries to restrict the actions that IAM entities can perform when using the {aws} Cloud Development Kit ({aws} CDK). --- - -// Content start -A _permissions boundary_ is an {aws} Identity and Access Management (IAM) advanced feature that you can use to set the maximum permissions that an IAM entity, such as a user or role, can have. You can use permissions boundaries to restrict the actions that IAM entities can perform when using the {aws} Cloud Development Kit ({aws} CDK). - -To learn more about permissions boundaries, see link:https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html[Permissions boundaries for IAM entities] in the _IAM User Guide_. - -[#customize-permissions-boundaries-when] -== When to use permissions boundaries with the {aws} CDK - -Consider applying permissions boundaries when you need to restrict developers in your organization from performing certain actions with the {aws} CDK. For example, if there are specific resources in your {aws} environment that you don't want developers to modify, you can create and apply a permissions boundary. - -[#customize-permissions-boundaries-how] -== How to apply permissions boundaries with the {aws} CDK - -[#customize-permissions-boundaries-how-create] -=== Create the permissions boundary - -First, you create the permissions boundary, using an {aws} managed policy or a customer managed policy to set the boundary for an IAM entity (user or role). This policy limits the maximum permissions for the user or role. For instructions on creating permissions boundaries, see link:https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html[Permissions boundaries for IAM entities] in the _IAM User Guide_. - -Permissions boundaries set the maximum permissions that an IAM entity can have, but don't grant permissions on their own. You must use permissions boundaries with IAM policies to effectively limit and grant the proper permissions for your organization. You must also prevent IAM entities from being able to escape the boundaries that you set. For an example, see link:https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html#access_policies_boundaries-delegate[Delegating responsibility to others using permissions boundaries] in the _IAM User Guide_. - -[#customize-permissions-boundaries-how-apply] -=== Apply the permissions boundary during bootstrapping - -After creating the permissions boundary, you can enforce it for the {aws} CDK by applying it during bootstrapping. - -Use the xref:ref-cli-cmd-bootstrap-options-custom-permissions-boundary[`--custom-permissions-boundary`] option and specify the name of the permissions boundary to apply. The following is an example that applies a permissions boundary named `cdk-permissions-boundary`: - -[source,none,subs="verbatim,attributes"] ----- -$ cdk bootstrap --custom-permissions-boundary <cdk-permissions-boundary> ----- - -By default, the CDK uses the `CloudFormationExecutionRole` IAM role, defined in the bootstrap template, to receive permissions for performing deployments. By applying the custom permissions boundary during bootstrapping, the permissions boundary gets attached to this role. The permissions boundary will then set the maximum permissions that can be performed by developers in your organization when using the {aws} CDK. To learn more about this role, see xref:bootstrapping-env-roles[IAM roles created during bootstrapping]. - -When you apply permissions boundaries in this way, they are applied to the specific environment that you bootstrap. To use the same permissions boundary across multiple environments, you must apply the permissions boundary for each environment during bootstrapping. You can also apply different permissions boundaries for different environments. - -[#customize-permissions-boundaries-learn] -== Learn more - -For more information on permissions boundaries, see https://aws.amazon.com/blogs/security/when-and-where-to-use-iam-permissions-boundaries/[When and where to use IAM permissions boundaries] in the _{aws} Security Blog_. \ No newline at end of file diff --git a/v2/guide/cli.adoc b/v2/guide/cli.adoc deleted file mode 100644 index 81cf29ff..00000000 --- a/v2/guide/cli.adoc +++ /dev/null @@ -1,785 +0,0 @@ -include::attributes.txt[] - -// Attributes - -[.topic] -[#cli] -= {aws} CDK CLI reference - -// Content start - -The {aws} Cloud Development Kit ({aws} CDK) Command Line Interface ({aws} CDK CLI), also known as the CDK Toolkit, is the primary tool for interacting with your {aws} CDK app. It executes your app, interrogates the application model you defined, and produces and deploys the {aws} CloudFormation templates generated by the {aws} CDK. It also provides other features useful for creating and working with {aws} CDK projects. This topic contains information about common use cases of the CDK CLI. - -The CDK CLI is installed with the Node Package Manager. In most cases, we recommend installing it globally. - -[source,none,subs="verbatim,attributes"] ----- -npm install -g aws-cdk # install latest version -npm install -g aws-cdk@X.YY.Z # install specific version ----- - -[TIP] -==== - -If you regularly work with multiple versions of the {aws} CDK, consider installing a matching version of the CDK CLI in individual CDK projects. To do this, omit `-g` from the `npm install` command. Then use `npx aws-cdk` to invoke it. This runs the local version if one exists, falling back to a global version if not. - -==== - -[#cli-commands] -== CDK CLI commands - -All CDK CLI commands start with `cdk`, which is followed by a subcommand (`list`, `synthesize`, `deploy`, etc.). Some subcommands have a shorter version (`ls`, `synth`, etc.) that is equivalent. Options and arguments follow the subcommand in any order. - -For a description of all subcommands, options, and arguments, see xref:ref-cli-cmd[{aws} CDK CLI command reference]. - -[#cli-options] -== Specify options and their values - -Command line options begin with two hyphens (`--`). Some frequently used options have single-letter synonyms that begin with a single hyphen (for example, `--app` has a synonym `-a`). The order of options in an CDK CLI command is not important. - -All options accept a value, which must follow the option name. The value may be separated from the name by white space or by an equals sign `=`. The following two options are equivalent. - -[source,none,subs="verbatim,attributes"] ----- ---toolkit-stack-name MyBootstrapStack ---toolkit-stack-name=MyBootstrapStack ----- - -Some options are flags (Booleans). You may specify `true` or `false` as their value. If you do not provide a value, the value is taken to be `true`. You may also prefix the option name with `no-` to imply `false`. - -[source,none,subs="verbatim,attributes"] ----- -# sets staging flag to true ---staging ---staging=true ---staging true - -# sets staging flag to false ---no-staging ---staging=false ---staging false ----- - -A few options, namely `--context`, `--parameters`, `--plugin`, `--tags`, and `--trust`, may be specified more than once to specify multiple values. These are noted as having `[array]` type in the CDK CLI help. For example: - -[source,none,subs="verbatim,attributes"] ----- -cdk bootstrap --tags costCenter=0123 --tags responsibleParty=jdoe ----- - -[#cli-help] -== Built-in help - -The CDK CLI has integrated help. You can see general help about the utility and a list of the provided subcommands by issuing: - -[source,none,subs="verbatim,attributes"] ----- -cdk --help ----- - -To see help for a particular subcommand, for example `deploy`, specify it before the `--help` flag. - -[source,none,subs="verbatim,attributes"] ----- -cdk deploy --help ----- - -Issue `cdk version` to display the version of the CDK CLI. Provide this information when requesting support. - -[#version-reporting] -== Version reporting - -To gain insight into how the {aws} CDK is used, the constructs used by {aws} CDK applications are collected and reported by using a resource identified as `{aws}::CDK::Metadata`. To learn more, see xref:usage-data[Configure {aws} CDK usage data reporting]. - -[#cli-auth] -== Authentication with {aws} - -There are different ways in which you can configure programmatic access to {aws} resources, depending on the environment and the {aws} access available to you. - -To choose your method of authentication and configure it for the CDK CLI, see xref:configure-access[Configure security credentials for the {aws} CDK CLI]. - -The recommended approach for new users developing locally, who are not given a method of authentication by their employer, is to set up {aws} IAM Identity Center. This method includes installing the {aws} CLI for ease of configuration and for regularly signing in to the {aws} access portal. If you choose this method, your environment should contain the following elements after you complete the procedure for https://docs.aws.amazon.com/sdkref/latest/guide/access-sso.html[IAM Identity Center authentication] in the _{aws} SDKs and Tools Reference Guide_: - -* The {aws} CLI, which you use to start an {aws} access portal session before you run your application. -* A https://docs.aws.amazon.com/sdkref/latest/guide/file-format.html[shared {aws} config file] having a `[default]` profile with a set of configuration values that can be referenced from the {aws} CDK. To find the location of this file, see https://docs.aws.amazon.com/sdkref/latest/guide/file-location.html[Location of the shared files] in the _{aws} SDKs and Tools Reference Guide_. -* The shared `config` file sets the https://docs.aws.amazon.com/sdkref/latest/guide/feature-region.html[region] setting. This sets the default {aws} Region the {aws} CDK and CDK CLI use for {aws} requests. -* The CDK CLI uses the profile's link:https://docs.aws.amazon.com/sdkref/latest/guide/feature-sso-credentials.html#feature-sso-credentials-profile[SSO token provider configuration] to acquire credentials before sending requests to {aws}. The `sso_role_name` value, which is an IAM role connected to an IAM Identity Center permission set, should allow access to the {aws} services used in your application. -+ -The following sample `config` file shows a default profile set up with SSO token provider configuration. The profile's `sso_session` setting refers to the named link:https://docs.aws.amazon.com/sdkref/latest/guide/file-format.html#section-session[`sso-session` section]. The `sso-session` section contains settings to initiate an {aws} access portal session. -+ -[source,none,subs="verbatim,attributes"] ----- -[default] -sso_session = <my-sso> -sso_account_id = \<111122223333> -sso_role_name = <SampleRole> -region = <us-east-1> -output = <json> - -[sso-session <my-sso>] -sso_region = <us-east-1> -sso_start_url = <https://provided-domain.awsapps.com/start> -sso_registration_scopes = sso:account:access ----- - -[#accessportal] -=== Start an {aws} access portal session - -Before accessing {aws} services, you need an active {aws} access portal session for the CDK CLI to use IAM Identity Center authentication to resolve credentials. Depending on your configured session lengths, your access will eventually expire and the CDK CLI will encounter an authentication error. Run the following command in the {aws} CLI to sign in to the {aws} access portal. - -[source,bash,subs="verbatim,attributes"] ----- -aws sso login ----- - -If your SSO token provider configuration is using a named profile instead of the default profile, the command is `aws sso login --profile <NAME>`. Also specify this profile when issuing `cdk` commands using the `--profile` option or the `AWS_PROFILE` environment variable. - -To test if you already have an active session, run the following {aws} CLI command. - -[source,bash,subs="verbatim,attributes"] ----- -aws sts get-caller-identity ----- - -The response to this command should report the IAM Identity Center account and permission set configured in the shared `config` file. - -[NOTE] -==== - -If you already have an active {aws} access portal session and run `aws sso login`, you will not be required to provide credentials. - -The sign in process may prompt you to allow the {aws} CLI access to your data. Since the {aws} CLI is built on top of the SDK for Python, permission messages may contain variations of the `botocore` name. - -==== - -[#cli-environment] -== Specify Region and other configuration - -The CDK CLI needs to know the {aws} Region that you're deploying into and how to authenticate with {aws}. This is needed for deployment operations and to retrieve context values during synthesis. Together, your account and Region make up the _environment_. - -Region may be specified using environment variables or in configuration files. These are the same variables and files used by other {aws} tools such as the {aws} CLI and the various {aws} SDKs. The CDK CLI looks for this information in the following order. - -* The `AWS_DEFAULT_REGION` environment variable. -* A named profile defined in the standard {aws} `config` file and specified using the `--profile` option on `cdk` commands. -* The `[default]` section of the standard {aws} `config` file. - -Besides specifying {aws} authentication and a Region in the `[default]` section, you can also add one or more `[profile <NAME>]` sections, where `<NAME>` is the name of the profile. For more information about named profiles, see https://docs.aws.amazon.com/sdkref/latest/guide/file-format.html[Shared config and credentials files] in the _{aws} SDKs and Tools Reference Guide_. - -The standard {aws} `config` file is located at `~/.aws/config` (macOS/Linux) or `%USERPROFILE%\.aws\config` (Windows). For details and alternate locations, see https://docs.aws.amazon.com/sdkref/latest/guide/file-location.html[Location of the shared config and credentials files] in the _{aws} SDKs and Tools Reference Guide_ - -The environment that you specify in your {aws} CDK app by using the stack's `env` property is used during synthesis. It's used to generate an environment-specific {aws} CloudFormation template, and during deployment, it overrides the account or Region specified by one of the preceding methods. For more information, see xref:environments[Environments for the {aws} CDK]. - -[NOTE] -==== - -The {aws} CDK uses credentials from the same source files as other {aws} tools and SDKs, including the https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html[{aws} Command Line Interface]. However, the {aws} CDK might behave somewhat differently from these tools. It uses the {aws} SDK for JavaScript under the hood. For complete details on setting up credentials for the {aws} SDK for JavaScript, see https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/setting-credentials.html[Setting credentials]. - -==== - -You may optionally use the `--role-arn` (or `-r`) option to specify the ARN of an IAM role that should be used for deployment. This role must be assumable by the {aws} account being used. - -[#cli-app-command] -== Specify the app command - -Many features of the CDK CLI require one or more {aws} CloudFormation templates be synthesized, which in turn requires running your application. The {aws} CDK supports programs written in a variety of languages. Therefore, it uses a configuration option to specify the exact command necessary to run your app. This option can be specified in two ways. - -First, and most commonly, it can be specified using the `app` key inside the file `cdk.json`. This is in the main directory of your {aws} CDK project. The CDK CLI provides an appropriate command when creating a new project with `cdk init`. Here is the `cdk.json` from a fresh TypeScript project, for instance. - -[source,json,subs="verbatim,attributes"] ----- -{ - "app": "npx ts-node bin/hello-cdk.ts" -} ----- - -The CDK CLI looks for `cdk.json` in the current working directory when attempting to run your app. Because of this, you might keep a shell open in your project's main directory for issuing CDK CLI commands. - -The CDK CLI also looks for the app key in `~/.cdk.json` (that is, in your home directory) if it can't find it in `./cdk.json`. Adding the app command here can be useful if you usually work with CDK code in the same language. - -If you are in some other directory, or to run your app using a command other than the one in `cdk.json`, use the `--app` (or `-a`) option to specify it. - -[source,none,subs="verbatim,attributes"] ----- -cdk --app "npx ts-node bin/hello-cdk.ts" ls ----- - -When deploying, you may also specify a directory containing synthesized cloud assemblies, such as `cdk.out`, as the value of `--app`. The specified stacks are deployed from this directory; the app is not synthesized. - -[#cli-stacks] -== Specify stacks - -Many CDK CLI commands (for example, `cdk deploy`) work on stacks defined in your app. If your app contains only one stack, the CDK CLI assumes you mean that one if you don't specify a stack explicitly. - -Otherwise, you must specify the stack or stacks you want to work with. You can do this by specifying the desired stacks by ID individually on the command line. Recall that the ID is the value specified by the second argument when you instantiate the stack. - -[source,none,subs="verbatim,attributes"] ----- -cdk synth PipelineStack LambdaStack ----- - -You may also use wildcards to specify IDs that match a pattern. - -* `?` matches any single character -* `\*` matches any number of characters (`*` alone matches all stacks) -* `**` matches everything in a hierarchy - -You may also use the `--all` option to specify all stacks. - -If your app uses xref:cdk-pipeline[CDK Pipelines], the CDK CLI understands your stacks and stages as a hierarchy. Also, the `--all` option and the `\*` wildcard only match top-level stacks. To match all the stacks, use ``\**``. Also use `**` to indicate all the stacks under a particular hierarchy. - -When using wildcards, enclose the pattern in quotes, or escape the wildcards with `\`. If you don't, your shell may try to expand the pattern to the names of files in the current directory. At best, this won't do what you expect; at worst, you could deploy stacks you didn't intend to. This isn't strictly necessary on Windows because `cmd.exe` does not expand wildcards, but is good practice nonetheless. - -[source,none,subs="verbatim,attributes"] ----- -cdk synth "*Stack" # PipelineStack, LambdaStack, etc. -cdk synth 'Stack?' # StackA, StackB, Stack1, etc. -cdk synth \* # All stacks in the app, or all top-level stacks in a CDK Pipelines app -cdk synth '**' # All stacks in a CDK Pipelines app -cdk synth 'PipelineStack/Prod/**' # All stacks in Prod stage in a CDK Pipelines app ----- - -[NOTE] -==== - -The order in which you specify the stacks is not necessarily the order in which they will be processed. The CDK CLI accounts for dependencies between stacks when deciding the order in which to process them. For example, let's say that one stack uses a value produced by another (such as the ARN of a resource defined in the second stack). In this case, the second stack is synthesized before the first one because of this dependency. You can add dependencies between stacks manually using the stack's `link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html#addwbrdependencytarget-reason[addDependency()]` method. - -==== - -[#cli-bootstrap] -== Bootstrap your {aws} environment - -Deploying stacks with the CDK requires special dedicated {aws} CDK resources to be provisioned. The `cdk bootstrap` command creates the necessary resources for you. You only need to bootstrap if you are deploying a stack that requires these dedicated resources. See xref:bootstrapping[{aws} CDK bootstrapping] for details. - -[source,none,subs="verbatim,attributes"] ----- -cdk bootstrap ----- - -If issued with no arguments, as shown here, the `cdk bootstrap` command synthesizes the current app and bootstraps the environments its stacks will be deployed to. If the app contains environment-agnostic stacks, which don't explicitly specify an environment, the default account and Region are bootstrapped, or the environment specified using `--profile`. - -Outside of an app, you must explicitly specify the environment to be bootstrapped. You may also do so to bootstrap an environment that's not specified in your app or local {aws} profile. Credentials must be configured (e.g. in `~/.aws/credentials`) for the specified account and Region. You may specify a profile that contains the required credentials. - -[source,none,subs="verbatim,attributes"] ----- -cdk bootstrap <ACCOUNT-NUMBER>/<REGION> # e.g. -cdk bootstrap 1111111111/us-east-1 -cdk bootstrap --profile test 1111111111/us-east-1 ----- - -[IMPORTANT] -==== - -Each environment (account/region combination) to which you deploy such a stack must be bootstrapped separately. - -==== - -You may incur {aws} charges for what the {aws} CDK stores in the bootstrapped resources. Additionally, if you use `--bootstrap-customer-key`, an {aws} KMS key will be created, which also incurs charges per environment. - -[NOTE] -==== - -Earlier versions of the bootstrap template created a KMS key by default. To avoid charges, re-bootstrap using `--no-bootstrap-customer-key`. - -==== - -[NOTE] -==== - -CDK CLI v2 does not support the original bootstrap template, dubbed the legacy template, used by default with CDK v1. - -==== - -[IMPORTANT] -==== - -The modern bootstrap template effectively grants the permissions implied by the `--cloudformation-execution-policies` to any {aws} account in the `--trust` list. By default, this extends permissions to read and write to any resource in the bootstrapped account. Make sure to xref:bootstrapping-customizing[configure the bootstrapping stack] with policies and trusted accounts that you are comfortable with. - -==== - -[#cli-init] -== Create a new app - -To create a new app, create a directory for it, then, inside the directory, issue `cdk init`. - -[source,none,subs="verbatim,attributes"] ----- -mkdir my-cdk-app -cd my-cdk-app -cdk init <TEMPLATE> --language <LANGUAGE> ----- - -The supported languages (<LANGUAGE>) are: - -[cols="1,1", options="header"] -|=== -| Code -| Language - -|`typescript` -|TypeScript - -|`javascript` -|JavaScript - -|`python` -|Python - -|`java` -|Java - -|`csharp` -|C# - -|`Go` -|Go -|=== - -<TEMPLATE> is an optional template. If the desired template is _app_, the default, you may omit it. The available templates are: - -[cols="1,1", options="header"] -|=== -| Template -| Description - -|`app` (default) -|Creates an empty {aws} CDK app. - -|`sample-app` -|Creates an {aws} CDK app with a stack containing an Amazon SQS queue and an Amazon SNS topic. -|=== - -The templates use the name of the project folder to generate names for files and classes inside your new app. - -[#cli-list] -== List stacks - -To see a list of the IDs of the stacks in your {aws} CDK application, enter one of the following equivalent commands: - -[source,none,subs="verbatim,attributes"] ----- -cdk list -cdk ls ----- - -If your application contains xref:cdk-pipeline[CDK Pipelines] stacks, the CDK CLI displays stack names as paths according to their location in the pipeline hierarchy. (For example, `PipelineStack`, `PipelineStack/Prod`, and `PipelineStack/Prod/MyService`.) - -If your app contains many stacks, you can specify full or partial stack IDs of the stacks to be listed. For more information, see xref:cli-stacks[Specify stacks]. - -Add the `--long` flag to see more information about the stacks, including the stack names and their environments ({aws} account and Region). - -[#cli-synth] -== Synthesize stacks - -The `cdk synthesize` command (almost always abbreviated `synth`) synthesizes a stack defined in your app into a CloudFormation template. - -[source,none,subs="verbatim,attributes"] ----- -cdk synth # if app contains only one stack -cdk synth MyStack -cdk synth Stack1 Stack2 -cdk synth "*" # all stacks in app ----- - -[NOTE] -==== - -The CDK CLI actually runs your app and synthesizes fresh templates before most operations (such as when deploying or comparing stacks). These templates are stored by default in the `cdk.out` directory. The `cdk synth` command simply prints the generated templates for one or more specified stacks. - -==== - -See `cdk synth --help` for all available options. A few of the most frequently used options are covered in the following section. - -[#cli-specify-context#] -=== Specify context values - -Use the `--context` or `-c` option to pass xref:context[runtime context] values to your CDK app. - -[source,none,subs="verbatim,attributes"] ----- -# specify a single context value -cdk synth --context key=value MyStack - -# specify multiple context values (any number) -cdk synth --context key1=value1 --context key2=value2 MyStack ----- - -When deploying multiple stacks, the specified context values are normally passed to all of them. If you want, you can specify different values for each stack by prefixing the stack name to the context value. - -[source,none,subs="verbatim,attributes"] ----- -# different context values for each stack -cdk synth --context Stack1:key=value Stack2:key=value Stack1 Stack2 ----- - -[#cli-specify-format] -=== Specify display format - -By default, the synthesized template is displayed in YAML format. Add the `--json` flag to display it in JSON format instead. - -[source,none,subs="verbatim,attributes"] ----- -cdk synth --json MyStack ----- - -[#cli-specify-output] -=== Specify the output directory - -Add the `--output` (`-o`) option to write the synthesized templates to a directory other than `cdk.out`. - -[source,none,subs="verbatim,attributes"] ----- -cdk synth --output=~/templates ----- - -[#cli-deploy] -== Deploy stacks - -The `cdk deploy` subcommand deploys one or more specified stacks to your {aws} account. - -[source,none,subs="verbatim,attributes"] ----- -cdk deploy # if app contains only one stack -cdk deploy MyStack -cdk deploy Stack1 Stack2 -cdk deploy "*" # all stacks in app ----- - -[NOTE] -==== - -The CDK CLI runs your app and synthesizes fresh {aws} CloudFormation templates before deploying anything. Therefore, most command line options you can use with `cdk synth` (for example, ``--context``) can also be used with `cdk deploy`. - -==== - -See `cdk deploy --help` for all available options. A few of the most useful options are covered in the following section. - -[#cli-deploy-nosynth] -=== Skip synthesis - -The `cdk deploy` command normally synthesizes your app's stacks before deploying to make sure that the deployment reflects the latest version of your app. If you know that you haven't changed your code since your last `cdk synth`, you can suppress the redundant synthesis step when deploying. To do so, specify your project's `cdk.out` directory in the `--app` option. - -[source,none,subs="verbatim,attributes"] ----- -cdk deploy --app cdk.out StackOne StackTwo ----- - -[#cli-deploy-norollback] -=== Disable rollback - -{aws} CloudFormation has the ability to roll back changes so that deployments are atomic. This means that they either succeed or fail as a whole. The {aws} CDK inherits this capability because it synthesizes and deploys {aws} CloudFormation templates. - -Rollback makes sure that your resources are in a consistent state at all times, which is vital for production stacks. However, while you're still developing your infrastructure, some failures are inevitable, and rolling back failed deployments can slow you down. - -For this reason, the CDK CLI lets you disable rollback by adding `--no-rollback` to your `cdk deploy` command. With this flag, failed deployments are not rolled back. Instead, resources deployed before the failed resource remain in place, and the next deployment starts with the failed resource. You'll spend a lot less time waiting for deployments and a lot more time developing your infrastructure. - -[#cli-deploy-hotswap] -=== Hot swapping - -Use the `--hotswap` flag with `cdk deploy` to attempt to update your {aws} resources directly instead of generating an {aws} CloudFormation change set and deploying it. Deployment falls back to {aws} CloudFormation deployment if hot swapping is not possible. - -Currently hot swapping supports Lambda functions, Step Functions state machines, and Amazon ECS container images. The `--hotswap` flag also disables rollback (i.e., implies `--no-rollback`). - -[IMPORTANT] -==== - -Hot-swapping is not recommended for production deployments. - -==== - -[#cli-deploy-watch] -=== Watch mode - -The CDK CLI's watch mode (`cdk deploy --watch`, or `cdk watch` for short) continuously monitors your CDK app's source files and assets for changes. It immediately performs a deployment of the specified stacks when a change is detected. - -By default, these deployments use the `--hotswap` flag, which fast-tracks deployment of changes to Lambda functions. It also falls back to deploying through {aws} CloudFormation if you have changed infrastructure configuration. To have `cdk watch` always perform full {aws} CloudFormation deployments, add the `--no-hotswap` flag to `cdk watch`. - -Any changes made while `cdk watch` is already performing a deployment are combined into a single deployment, which begins as soon as the in-progress deployment is complete. - -Watch mode uses the `"watch"` key in the project's `cdk.json` to determine which files to monitor. By default, these files are your application files and assets, but this can be changed by modifying the `"include"` and `"exclude"` entries in the `"watch"` key. The following `cdk.json` file shows an example of these entries. - -[source,json,subs="verbatim,attributes"] ----- -{ - "app": "mvn -e -q compile exec:java", - "watch": { - "include": "src/main/**", - "exclude": "target/*" - } -} ----- - -`cdk watch` executes the `"build"` command from `cdk.json` to build your app before synthesis. If your deployment requires any commands to build or package your Lambda code (or anything else that's not in your CDK app), add it here. - -Git-style wildcards, both `\*` and `\**`, can be used in the `"watch"` and `"build"` keys. Each path is interpreted relative to the parent directory of `cdk.json`. The default value of `include` is ``\**/*``, meaning all files and directories in the project root directory. `exclude` is optional. - -[IMPORTANT] -==== - -Watch mode is not recommended for production deployments. - -==== - -[#cli-specify-parameters] -=== Specify {aws} CloudFormation parameters - -The CDK CLI supports specifying {aws} CloudFormation xref:parameters[parameters] at deployment. You may provide these on the command line following the `--parameters` flag. - -[source,none,subs="verbatim,attributes"] ----- -cdk deploy MyStack --parameters uploadBucketName=UploadBucket ----- - -To define multiple parameters, use multiple `--parameters` flags. - -[source,none,subs="verbatim,attributes"] ----- -cdk deploy MyStack --parameters uploadBucketName=UpBucket --parameters downloadBucketName=DownBucket ----- - -If you are deploying multiple stacks, you can specify a different value of each parameter for each stack. To do so, prefix the name of the parameter with the stack name and a colon. Otherwise, the same value is passed to all stacks. - -[source,none,subs="verbatim,attributes"] ----- -cdk deploy MyStack YourStack --parameters MyStack:uploadBucketName=UploadBucket --parameters YourStack:uploadBucketName=UpBucket ----- - -By default, the {aws} CDK retains values of parameters from previous deployments and uses them in later deployments if they are not specified explicitly. Use the `--no-previous-parameters` flag to require all parameters to be specified. - -[#cli-specify-outputs-file] -=== Specify outputs file - -If your stack declares {aws} CloudFormation outputs, these are normally displayed on the screen at the conclusion of deployment. To write them to a file in JSON format, use the `--outputs-file` flag. - -[source,none,subs="verbatim,attributes"] ----- -cdk deploy --outputs-file outputs.json MyStack ----- - -[#cli-security] -=== Approve security-related changes - -To protect you against unintended changes that affect your security posture, the CDK CLI prompts you to approve security-related changes before deploying them. You can specify the level of change that requires approval: - -[source,none,subs="verbatim,attributes"] ----- -cdk deploy --require-approval <LEVEL> ----- - -`<LEVEL>` can be one of the following: - -[cols="1,1", options="header"] -|=== -| Term -| Meaning - -|`never` -|Approval is never required - -|`any-change` -|Requires approval on any IAM or security-group-related change - -|`broadening` (default) -|Requires approval when IAM statements or traffic rules are added; removals don't require approval -|=== - -The setting can also be configured in the `cdk.json` file. - -[source,json,subs="verbatim,attributes"] ----- -{ - "app": "...", - "requireApproval": "never" -} ----- - -[#cli-diff] -== Compare stacks - -The `cdk diff` command compares the current version of a stack (and its dependencies) defined in your app with the already-deployed versions, or with a saved {aws} CloudFormation template, and displays a list of changes. - ----- -Stack HelloCdkStack -IAM Statement Changes -┌───┬──────────────────────────────┬────────┬──────────────────────────────┬──────────────────────────────┬───────────┐ -│ │ Resource │ Effect │ Action │ Principal │ Condition │ -├───┼──────────────────────────────┼────────┼──────────────────────────────┼──────────────────────────────┼───────────┤ -│ + │ ${Custom::S3AutoDeleteObject │ Allow │ sts:AssumeRole │ Service:lambda.amazonaws.com │ │ -│ │ sCustomResourceProvider/Role │ │ │ │ │ -│ │ .Arn} │ │ │ │ │ -├───┼──────────────────────────────┼────────┼──────────────────────────────┼──────────────────────────────┼───────────┤ -│ + │ ${MyFirstBucket.Arn} │ Allow │ s3:DeleteObject* │ {aws}:${Custom::S3AutoDeleteOb │ │ -│ │ ${MyFirstBucket.Arn}/* │ │ s3:GetBucket* │ jectsCustomResourceProvider/ │ │ -│ │ │ │ s3:GetObject* │ Role.Arn} │ │ -│ │ │ │ s3:List* │ │ │ -└───┴──────────────────────────────┴────────┴──────────────────────────────┴──────────────────────────────┴───────────┘ -IAM Policy Changes -┌───┬────────────────────────────────────────────────────────┬────────────────────────────────────────────────────────┐ -│ │ Resource │ Managed Policy ARN │ -├───┼────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────┤ -│ + │ ${Custom::S3AutoDeleteObjectsCustomResourceProvider/Ro │ {"Fn::Sub":"arn:${{aws}::Partition}:iam::aws:policy/serv │ -│ │ le} │ ice-role/AWSLambdaBasicExecutionRole"} │ -└───┴────────────────────────────────────────────────────────┴────────────────────────────────────────────────────────┘ -(NOTE: There may be security-related changes not in this list. See https://github.com/aws/aws-cdk/issues/1299) - -Parameters -[+] Parameter AssetParameters/4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392/S3Bucket AssetParameters4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392S3BucketBF7A7F3F: {"Type":"String","Description":"S3 bucket for asset \"4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392\""} -[+] Parameter AssetParameters/4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392/S3VersionKey AssetParameters4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392S3VersionKeyFAF93626: {"Type":"String","Description":"S3 key for asset version \"4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392\""} -[+] Parameter AssetParameters/4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392/ArtifactHash AssetParameters4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392ArtifactHashE56CD69A: {"Type":"String","Description":"Artifact hash for asset \"4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392\""} - -Resources -[+] {aws}::S3::BucketPolicy MyFirstBucket/Policy MyFirstBucketPolicy3243DEFD -[+] Custom::S3AutoDeleteObjects MyFirstBucket/AutoDeleteObjectsCustomResource MyFirstBucketAutoDeleteObjectsCustomResourceC52FCF6E -[+] {aws}::IAM::Role Custom::S3AutoDeleteObjectsCustomResourceProvider/Role CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092 -[+] {aws}::Lambda::Function Custom::S3AutoDeleteObjectsCustomResourceProvider/Handler CustomS3AutoDeleteObjectsCustomResourceProviderHandler9D90184F -[~] {aws}::S3::Bucket MyFirstBucket MyFirstBucketB8884501 - ├─ [~] DeletionPolicy - │ ├─ [-] Retain - │ └─ [+] Delete - └─ [~] UpdateReplacePolicy - ├─ [-] Retain - └─ [+] Delete ----- - -To compare your app's stacks with the existing deployment: - -[source,none,subs="verbatim,attributes"] ----- -cdk diff MyStack ----- - -To compare your app's stacks with a saved CloudFormation template: - -[source,none,subs="verbatim,attributes"] ----- -cdk diff --template ~/stacks/MyStack.old MyStack ----- - -[#cli-import] -== Import existing resources into a stack - -You can use the `cdk import` command to bring resources under the management of CloudFormation for a particular {aws} CDK stack. This is useful if you are migrating to {aws} CDK, or are moving resources between stacks or changing their logical id. `cdk import` uses https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resource-import.html[CloudFormation resource imports]. See the https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resource-import-supported-resources.html[list of resources that can be imported here]. - -To import an existing resource into a {aws} CDK stack, follow the following steps: - -* Make sure the resource is not currently being managed by any other CloudFormation stack. If it is, first set the removal policy to `RemovalPolicy.RETAIN` in the stack the resource is currently in and perform a deployment. Then, remove the resource from the stack and perform another deployment. This process will make sure that the resource is no longer managed by CloudFormation but does not delete it. -* Run a `cdk diff` to make sure there are no pending changes to the {aws} CDK stack you want to import resources into. The only changes allowed in an "import" operation are the addition of new resources which you want to import. -* Add constructs for the resources you want to import to your stack. For example, if you want to import an Amazon S3 bucket, add something like `new s3.Bucket(this, 'ImportedS3Bucket', {});`. Do not make any modifications to any other resource. -+ -You must also make sure to exactly model the state that the resource currently has into the definition. For the example of the bucket, be sure to include {aws} KMS keys, life cycle policies, and anything else that's relevant about the bucket. If you do not, subsequent update operations may not do what you expect. -+ -You can choose whether or not to include the physical bucket name. We usually recommend to not include resource names into your {aws} CDK resource definitions so that it becomes easier to deploy your resources multiple times. -+ -* Run `cdk import <STACKNAME>`. -* If the resource names are not in your model, the CLI will prompt you to pass in the actual names of the resources you are importing. After this, the import starts. -* When `cdk import` reports success, the resource is now managed by {aws} CDK and CloudFormation. Any subsequent changes you make to the resource properties in your {aws} CDK app the construct configuration will be applied on the next deployment. -* To confirm that the resource definition in your {aws} CDK app matches the current state of the resource, you can start an https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-stack-drift.html[CloudFormation drift detection operation]. - -This feature currently does not support importing resources into nested stacks. - -[#cli-config] -== Configuration (`cdk.json`) - -Default values for many CDK CLI command line flags can be stored in a project's `cdk.json` file or in the `.cdk.json` file in your user directory. Following is an alphabetical reference to the supported configuration settings. - -[cols="1,1,1", options="header"] -|=== -| Key -| Notes -| CDK CLI option - -|`app` -|The command that executes the CDK application. -|`--app` - -|`assetMetadata` -|If `false`, CDK does not add metadata to resources that use assets. -|`--no-asset-metadata` - -|`bootstrapKmsKeyId` -|Overrides the ID of the {aws} KMS key used to encrypt the Amazon S3 deployment bucket. -|`--bootstrap-kms-key-id` - -|`build` -|The command that compiles or builds the CDK application before synthesis. Not permitted in `~/.cdk.json`. -|`--build` - -|`browser` -|The command for launching a Web browser for the `cdk docs` subcommand. -|`--browser` - -|`context` -|See xref:context[Context values and the {aws} CDK]. Context values in a configuration file will not be erased by `cdk context --clear`. (The CDK CLI places cached context values in `cdk.context.json`.) -|`--context` - -|`debug` -|If `true`, CDK CLI emits more detailed information useful for debugging. -|`--debug` - -|`language` -|The language to be used for initializing new projects. -|`--language` - -|`lookups` -|If `false`, no context lookups are permitted. Synthesis will fail if any context lookups need to be performed. -|`--no-lookups` - -|`notices` -|If `false`, suppresses the display of messages about security vulnerabilities, regressions, and unsupported versions. -|`--no-notices` - -|`output` -|The name of the directory into which the synthesized cloud assembly will be emitted (default `"cdk.out"`). -|`--output` - -|`outputsFile` -|The file to which {aws} CloudFormation outputs from deployed stacks will be written (in `JSON` format). -|`--outputs-file` - -|`pathMetadata` -|If `false`, CDK path metadata is not added to synthesized templates. -|`--no-path-metadata` - -|`plugin` -|JSON array specifying the package names or local paths of packages that extend the CDK -|`--plugin` - -|`profile` -|Name of the default {aws} profile used for specifying Region and account credentials. -|`--profile` - -|`progress` -|If set to `"events"`, the CDK CLI displays all {aws} CloudFormation events during deployment, rather than a progress bar. -|`--progress` - -|`requireApproval` -|Default approval level for security changes. See xref:cli-security[Approve security-related changes] -|`--require-approval` - -|`rollback` -|If `false`, failed deployments are not rolled back. -|`--no-rollback` - -|`staging` -|If `false`, assets are not copied to the output directory (use for local debugging of the source files with {aws} SAM). -|`--no-staging` - -|`tags` -|`JSON` object containing tags (key-value pairs) for the stack. -|`--tags` - -|`toolkitBucketName` -|The name of the Amazon S3 bucket used for deploying assets such as Lambda functions and container images (see xref:cli-bootstrap[Bootstrap your {aws} environment]). -|`--toolkit-bucket-name` - -|`toolkitStackName` -|The name of the bootstrap stack (see xref:cli-bootstrap[Bootstrap your {aws} environment]). -|`--toolkit-stack-name` - -|`versionReporting` -|If `false`, opts out of version reporting. -|`--no-version-reporting` - -|`watch` -|JSON object containing `"include"` and `"exclude"` keys that indicate which files should (or should not) trigger a rebuild of the project when changed. See xref:cli-deploy-watch[Watch mode]. -|`--watch` -|=== \ No newline at end of file diff --git a/v2/guide/concepts/apps.adoc b/v2/guide/concepts/apps.adoc deleted file mode 100644 index f7e7161a..00000000 --- a/v2/guide/concepts/apps.adoc +++ /dev/null @@ -1,128 +0,0 @@ -include::../attributes.txt[] - -// Attributes -[.topic] -:info_titleabbrev: Apps -:keywords: {aws} CDK, {aws} CDK app - -[#apps] -= {aws} CDK apps - -[abstract] --- -The {aws} Cloud Development Kit ({aws} CDK) application or _app_ is a collection of one or more CDK xref:stacks[stacks]. Stacks are a collection of one or more xref:constructs[constructs], which define {aws} resources and properties. Therefore, the overall grouping of your stacks and constructs are known as your CDK app. --- - -// Content start - -The {aws} Cloud Development Kit ({aws} CDK) application or _app_ is a collection of one or more CDK xref:stacks[stacks]. Stacks are a collection of one or more xref:constructs[constructs], which define {aws} resources and properties. Therefore, the overall grouping of your stacks and constructs are known as your CDK app. - -[#apps-define] -== How to create a CDK app - -You create an app by defining an app instance in the application file of your xref:projects[project]. To do this, you import and use the https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.App.html[App] construct from the {aws} Construct Library. The `App` construct doesn't require any initialization arguments. It is the only construct that can be used as the root. - -The `https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.App.html[App]` and `https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html[Stack]` classes from the {aws} Construct Library are unique constructs. Compared to other constructs, they don't configure {aws} resources on their own. Instead, they are used to provide context for your other constructs. All constructs that represent {aws} resources must be defined, directly or indirectly, within the scope of a `Stack` construct. `Stack` constructs are defined within the scope of an `App` construct. - -Apps are then synthesized to create {aws} CloudFormation templates for your stacks. The following is an example: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const app = new App(); -new MyFirstStack(app, 'hello-cdk'); -app.synth(); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const app = new App(); -new MyFirstStack(app, 'hello-cdk'); -app.synth(); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -app = App() -MyFirstStack(app, "hello-cdk") -app.synth() ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -App app = new App(); -new MyFirstStack(app, "hello-cdk"); -app.synth(); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -var app = new App(); -new MyFirstStack(app, "hello-cdk"); -app.Synth(); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -app := awscdk.NewApp(nil) - -MyFirstStack(app, "MyFirstStack", &MyFirstStackProps{ - awscdk.StackProps{ - Env: env(), - }, -}) - -app.Synth(nil) ----- -==== - -Stacks within a single app can easily refer to each other's resources and properties. The {aws} CDK infers dependencies between stacks so that they can be deployed in the correct order. You can deploy any or all of the stacks within an app with a single `cdk deploy` command. - -[#apps-tree] -== The construct tree - -Constructs are defined inside of other constructs using the `scope` argument that is passed to every construct, with the `App` class as the root. In this way, an {aws} CDK app defines a hierarchy of constructs known as the _construct tree_. - -The root of this tree is your app, which is an instance of the `App` class. Within the app, you instantiate one or more stacks. Within stacks, you instantiate constructs, which may themselves instantiate resources or other constructs, and so on down the tree. - -Constructs are _always_ explicitly defined within the scope of another construct, which creates relationships between constructs. Almost always, you should pass `this` (in Python, `self`) as the scope, indicating that the new construct is a child of the current construct. The intended pattern is that you derive your construct from https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html[`Construct`], then instantiate the constructs it uses in its constructor. - -Passing the scope explicitly allows each construct to add itself to the tree, with this behavior entirely contained within the https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html[`Construct` base class]. It works the same way in every language supported by the {aws} CDK and does not require additional customization. - -[IMPORTANT] -==== - -Technically, it's possible to pass some scope other than `this` when instantiating a construct. You can add constructs anywhere in the tree, or even in another stack in the same app. For example, you could write a mixin-style function that adds constructs to a scope passed in as an argument. The practical difficulty here is that you can't easily ensure that the IDs you choose for your constructs are unique within someone else's scope. The practice also makes your code more difficult to understand, maintain, and reuse. Therefore, we recommend that you use the general structure of the construct tree. - -==== - -The {aws} CDK uses the IDs of all constructs in the path from the tree's root to each child construct to generate the unique IDs required by {aws} CloudFormation. This approach means that construct IDs only need to be unique within their scope, rather than within the entire stack as in native {aws} CloudFormation. However, if you move a construct to a different scope, its generated stack-unique ID changes, and {aws} CloudFormation won't consider it the same resource. - -The construct tree is separate from the constructs that you define in your {aws} CDK code. However, it's accessible through any construct's `node` attribute, which is a reference to the node that represents that construct in the tree. Each node is a https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Node.html[`Node`] instance, the attributes of which provide access to the tree's root and to the node's parent scopes and children. - -. `node.children` – The direct children of the construct. -. `node.id` – The identifier of the construct within its scope. -. `node.path` – The full path of the construct including the IDs of all of its parents. -. `node.root` – The root of the construct tree (the app). -. `node.scope` – The scope (parent) of the construct, or undefined if the node is the root. -. `node.scopes` – All parents of the construct, up to the root. -. `node.uniqueId` – The unique alphanumeric identifier for this construct within the tree (by default, generated from `node.path` and a hash). - -The construct tree defines an implicit order in which constructs are synthesized to resources in the final {aws} CloudFormation template. Where one resource must be created before another, {aws} CloudFormation or the {aws} Construct Library generally infers the dependency. They then make sure that the resources are created in the right order. - -You can also add an explicit dependency between two nodes by using `node.addDependency()`. For more information, see https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib-readme.html#dependencies[Dependencies] in the _{aws} CDK API Reference_. - -The {aws} CDK provides a simple way to visit every node in the construct tree and perform an operation on each one. For more information, see xref:aspects[Aspects and the {aws} CDK]. \ No newline at end of file diff --git a/v2/guide/concepts/bootstrapping.adoc b/v2/guide/concepts/bootstrapping.adoc deleted file mode 100644 index dd2147fa..00000000 --- a/v2/guide/concepts/bootstrapping.adoc +++ /dev/null @@ -1,43 +0,0 @@ -include::../attributes.txt[] - -// Attributes -[.topic] -:info_titleabbrev: Bootstrapping -:keywords: {aws} CDK, {aws} Cloud Development Kit ({aws} CDK), {aws} account, {aws} Region, Bootstrapping, Bootstrap, Environment - -[#bootstrapping] -= {aws} CDK bootstrapping - -[abstract] --- -_Bootstrapping_ is the process of preparing your {aws} environment for usage with the {aws} Cloud Development Kit ({aws} CDK). Before you deploy a CDK stack into an {aws} environment, the environment must first be bootstrapped. --- - -// Content start - -_Bootstrapping_ is the process of preparing your {aws} environment for usage with the {aws} Cloud Development Kit ({aws} CDK). Before you deploy a CDK stack into an {aws} environment, the environment must first be bootstrapped. - -[#bootstrapping-what] -== What is bootstrapping? - -Bootstrapping prepares your {aws} environment by provisioning specific {aws} resources in your environment that are used by the {aws} CDK. These resources are commonly referred to as your _bootstrap resources_. They include the following: - -* *Amazon Simple Storage Service (Amazon S3) bucket* – Used to store your CDK project files, such as {aws} Lambda function code and assets. -* *Amazon Elastic Container Registry (Amazon ECR) repository* – Used primarily to store [.noloc]`Docker` images. -* *{aws} Identity and Access Management (IAM) roles* – Configured to grant permissions needed by the {aws} CDK to perform deployments. For more information about the IAM roles created during bootstrapping, see xref:bootstrapping-env-roles[IAM roles created during bootstrapping]. - -[#bootstrapping-how] -== How does bootstrapping work? - -Resources and their configuration that are used by the CDK are defined in an {aws} CloudFormation template. This template is created and managed by the CDK team. For the latest version of this template, see https://github.com/aws/aws-cdk-cli/blob/main/packages/aws-cdk/lib/api/bootstrap/bootstrap-template.yaml[`bootstrap-template.yaml`] in the _aws-cdk-cli [.noloc]`GitHub` repository_. - -To bootstrap an environment, you use the {aws} CDK Command Line Interface ({aws} CDK CLI) `cdk bootstrap` command. The CDK CLI retrieves the template and deploys it to {aws} CloudFormation as a stack, known as the _bootstrap stack_. By default, the stack name is `CDKToolkit`. By deploying this template, CloudFormation provisions the resources in your environment. After deployment, the bootstrap stack will appear in the {aws} CloudFormation console of your environment. - -You can also customize bootstrapping by modifying the template or by using CDK CLI options with the `cdk bootstrap` command. - -{aws} environments are independent. Each environment that you want to use with the {aws} CDK must first be bootstrapped. - -[#bootstrapping-learn] -== Learn more - -For instructions on bootstrapping your environment, see xref:bootstrapping-env[Bootstrap your environment for use with the {aws} CDK]. \ No newline at end of file diff --git a/v2/guide/concepts/constructs.adoc b/v2/guide/concepts/constructs.adoc deleted file mode 100644 index 716babe7..00000000 --- a/v2/guide/concepts/constructs.adoc +++ /dev/null @@ -1,1214 +0,0 @@ -include::../attributes.txt[] - -// Attributes -[.topic] -:info_titleabbrev: Constructs -:keywords: {aws} CDK, {aws} CloudFormation, IaC, Infrastructure as code, constructs - -[#constructs] -= {aws} CDK Constructs - -[abstract] --- -Constructs are the basic building blocks of {aws} Cloud Development Kit ({aws} CDK) applications. A construct is a component within your application that represents one or more {aws} CloudFormation resources and their configuration. You build your application, piece by piece, by importing and configuring constructs. --- - -// Content start - -Constructs are the basic building blocks of {aws} Cloud Development Kit ({aws} CDK) applications. A construct is a component within your application that represents one or more {aws} CloudFormation resources and their configuration. You build your application, piece by piece, by importing and configuring constructs. - -[#constructs-import] -== Import and use constructs - -Constructs are classes that you import into your CDK applications from the xref:libraries-construct[{aws} Construct Library]. You can also create and distribute your own constructs, or use constructs created by third-party developers. - -Constructs are part of the Construct Programming Model (CPM). They are available to use with other tools such as CDK for [.noloc]`Terraform` (CDKtf), CDK for [.noloc]`Kubernetes` (CDK8s), and [.noloc]`Projen`. - -Numerous third parties have also published constructs compatible with the {aws} CDK. Visit https://constructs.dev/search?q=&cdk=aws-cdk&cdkver=2&offset=0[Construct Hub] to explore the {aws} CDK construct partner ecosystem. - -[#constructs-lib-levels] -== Construct levels - -Constructs from the {aws} Construct Library are categorized into three levels. Each level offers an increasing level of abstraction. The higher the abstraction, the easier to configure, requiring less expertise. The lower the abstraction, the more customization available, requiring more expertise. - -[#constructs-lib-levels-one] -*Level 1 (L1) constructs*:: -L1 constructs, also known as _CFN resources_, are the lowest-level construct and offer no abstraction. Each L1 construct maps directly to a single {aws} CloudFormation resource. With L1 constructs, you import a construct that represents a specific {aws} CloudFormation resource. You then define the resource`'s properties within your construct instance. -+ -L1 constructs are great to use when you are familiar with {aws} CloudFormation and need complete control over defining your {aws} resource properties. -+ -In the {aws} Construct Library, L1 constructs are named starting with `Cfn`, followed by an identifier for the {aws} CloudFormation resource that it represents. For example, the https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.CfnBucket.html[`CfnBucket`] construct is an L1 construct that represents an https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html[`{aws}::S3::Bucket`] {aws} CloudFormation resource. -+ -L1 constructs are generated from the https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-resource-specification.html[{aws} CloudFormation resource specification]. If a resource exists in {aws} CloudFormation, it'll be available in the {aws} CDK as an L1 construct. New resources or properties may take up to a week to become available in the {aws} Construct Library. For more information, see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html[{aws} resource and property types reference] in the _{aws} CloudFormation User Guide_. - -[#constructs-lib-levels-two] -*Level 2 (L2) constructs*:: -L2 constructs, also known as _curated_ constructs, are thoughtfully developed by the CDK team and are usually the most widely used construct type. L2 constructs map directly to single {aws} CloudFormation resources, similar to L1 constructs. Compared to L1 constructs, L2 constructs provide a higher-level abstraction through an intuitive intent-based API. L2 constructs include sensible default property configurations, best practice security policies, and generate a lot of the boilerplate code and glue logic for you. -+ -L2 constructs also provide helper methods for most resources that make it simpler and quicker to define properties, permissions, event-based interactions between resources, and more. -+ -The https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html[`s3.Bucket`] class is an example of an L2 construct for an Amazon Simple Storage Service (Amazon S3) bucket resource. -+ -The {aws} Construct Library contains L2 constructs that are designated stable and ready for production use. For L2 constructs under development, they are designated as experimental and offered in a separate module. - -[#constructs-lib-levels-three] -*Level 3 (L3) constructs*:: -L3 constructs, also known as _patterns_, are the highest-level of abstraction. Each L3 construct can contain a collection of resources that are configured to work together to accomplish a specific task or service within your application. L3 constructs are used to create entire {aws} architectures for particular use cases in your application. -+ -To provide complete system designs, or substantial parts of a larger system, L3 constructs offer opinionated default property configurations. They are built around a particular approach toward solving a problem and providing a solution. With L3 constructs, you can create and configure multiple resources quickly, with the fewest amount of input and code. -+ -The https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs_patterns.ApplicationLoadBalancedFargateService.html[`ecsPatterns.ApplicationLoadBalancedFargateService`] class is an example of an L3 construct that represents an {aws} Fargate service running on an Amazon Elastic Container Service (Amazon ECS) cluster and fronted by an application load balancer. -+ -Similar to L2 constructs, L3 constructs that are ready for production use are included in the {aws} Construct Library. Those under development are offered in separate modules. - -[#constructs-define,constructs-define.title] -== Defining constructs - -[#constructs-composition] -=== Composition - -_Composition_ is the key pattern for defining higher-level abstractions through constructs. A high-level construct can be composed from any number of lower-level constructs. From a bottom-up perspective, you use constructs to organize the individual {aws} resources that you want to deploy. You use whatever abstractions are convenient for your purpose, with as many levels as you need. - -With composition, you define reusable components and share them like any other code. For example, a team can define a construct that implements the company`'s best practice for an Amazon DynamoDB table, including backup, global replication, automatic scaling, and monitoring. The team can share the construct internally with other teams, or publicly. - -Teams can use constructs like any other library package. When the library is updated, developers get access to the new version's improvements and bug fixes, similar to any other code library. - -[#constructs-init] -=== Initialization - -Constructs are implemented in classes that extend the https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html[`Construct`] base class. You define a construct by instantiating the class. All constructs take three parameters when they are initialized: - -* *scope* – The construct's parent or owner. This can either be a stack or another construct. Scope determines the construct's place in the xref:apps-tree[construct tree]. You should usually pass `this` (`self` in Python), which represents the current object, for the scope. -* *id* – An xref:identifiers[identifier] that must be unique within the scope. The identifier serves as a namespace for everything that's defined within the construct. It's used to generate unique identifiers, such as xref:resources-physical-names[resource names] and {aws} CloudFormation logical IDs. -+ -Identifiers need only be unique within a scope. This lets you instantiate and reuse constructs without concern for the constructs and identifiers they might contain, and enables composing constructs into higher-level abstractions. In addition, scopes make it possible to refer to groups of constructs all at once. Examples include for https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Tag.html[tagging], or specifying where the constructs will be deployed. - -* *props* – A set of properties or keyword arguments, depending on the language, that define the construct`'s initial configuration. Higher-level constructs provide more defaults, and if all prop elements are optional, you can omit the props parameter completely. - -[#constructs-config] -=== Configuration - -Most constructs accept `props` as their third argument (or in Python, keyword arguments), a name/value collection that defines the construct's configuration. The following example defines a bucket with {aws} Key Management Service ({aws} KMS) encryption and static website hosting enabled. Since it does not explicitly specify an encryption key, the `Bucket` construct defines a new `kms.Key` and associates it with the bucket. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -new s3.Bucket(this, 'MyEncryptedBucket', { - encryption: s3.BucketEncryption.KMS, - websiteIndexDocument: 'index.html' -}); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -new s3.Bucket(this, 'MyEncryptedBucket', { - encryption: s3.BucketEncryption.KMS, - websiteIndexDocument: 'index.html' -}); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -s3.Bucket(self, "MyEncryptedBucket", encryption=s3.BucketEncryption.KMS, - website_index_document="index.html") ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -Bucket.Builder.create(this, "MyEncryptedBucket") - .encryption(BucketEncryption.KMS_MANAGED) - .websiteIndexDocument("index.html").build(); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -new Bucket(this, "MyEncryptedBucket", new BucketProps -{ - Encryption = BucketEncryption.KMS_MANAGED, - WebsiteIndexDocument = "index.html" -}); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- - awss3.NewBucket(stack, jsii.String("MyEncryptedBucket"), &awss3.BucketProps{ - Encryption: awss3.BucketEncryption_KMS, - WebsiteIndexDocument: jsii.String("index.html"), - }) ----- -==== - -[#constructs-interact] -=== Interacting with constructs - -Constructs are classes that extend the base https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html[Construct] class. After you instantiate a construct, the construct object exposes a set of methods and properties that let you interact with the construct and pass it around as a reference to other parts of the system. - -The {aws} CDK framework doesn't put any restrictions on the APIs of constructs. Authors can define any API they want. However, the {aws} constructs that are included with the {aws} Construct Library, such as `s3.Bucket`, follow guidelines and common patterns. This provides a consistent experience across all {aws} resources. - -Most {aws} constructs have a set of xref:permissions-grants[grant] methods that you can use to grant {aws} Identity and Access Management (IAM) permissions on that construct to a principal. The following example grants the IAM group `data-science` permission to read from the Amazon S3 bucket `raw-data`. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const rawData = new s3.Bucket(this, 'raw-data'); -const dataScience = new iam.Group(this, 'data-science'); -rawData.grantRead(dataScience); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const rawData = new s3.Bucket(this, 'raw-data'); -const dataScience = new iam.Group(this, 'data-science'); -rawData.grantRead(dataScience); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -raw_data = s3.Bucket(self, 'raw-data') -data_science = iam.Group(self, 'data-science') -raw_data.grant_read(data_science) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -Bucket rawData = new Bucket(this, "raw-data"); -Group dataScience = new Group(this, "data-science"); -rawData.grantRead(dataScience); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -var rawData = new Bucket(this, "raw-data"); -var dataScience = new Group(this, "data-science"); -rawData.GrantRead(dataScience); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- - rawData := awss3.NewBucket(stack, jsii.String("raw-data"), nil) - dataScience := awsiam.NewGroup(stack, jsii.String("data-science"), nil) - rawData.GrantRead(dataScience, nil) ----- -==== - -Another common pattern is for {aws} constructs to set one of the resource's attributes from data supplied elsewhere. Attributes can include Amazon Resource Names (ARNs), names, or URLs. - -The following code defines an {aws} Lambda function and associates it with an Amazon Simple Queue Service (Amazon SQS) queue through the queue's URL in an environment variable. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const jobsQueue = new sqs.Queue(this, 'jobs'); -const createJobLambda = new lambda.Function(this, 'create-job', { - runtime: lambda.Runtime.NODEJS_18_X, - handler: 'index.handler', - code: lambda.Code.fromAsset('./create-job-lambda-code'), - environment: { - QUEUE_URL: jobsQueue.queueUrl - } -}); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const jobsQueue = new sqs.Queue(this, 'jobs'); -const createJobLambda = new lambda.Function(this, 'create-job', { - runtime: lambda.Runtime.NODEJS_18_X, - handler: 'index.handler', - code: lambda.Code.fromAsset('./create-job-lambda-code'), - environment: { - QUEUE_URL: jobsQueue.queueUrl - } -}); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -jobs_queue = sqs.Queue(self, "jobs") -create_job_lambda = lambda_.Function(self, "create-job", - runtime=lambda_.Runtime.NODEJS_18_X, - handler="index.handler", - code=lambda_.Code.from_asset("./create-job-lambda-code"), - environment=dict( - QUEUE_URL=jobs_queue.queue_url - ) -) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -final Queue jobsQueue = new Queue(this, "jobs"); -Function createJobLambda = Function.Builder.create(this, "create-job") - .handler("index.handler") - .code(Code.fromAsset("./create-job-lambda-code")) - .environment(java.util.Map.of( // Map.of is Java 9 or later - "QUEUE_URL", jobsQueue.getQueueUrl())) - .build(); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -var jobsQueue = new Queue(this, "jobs"); -var createJobLambda = new Function(this, "create-job", new FunctionProps -{ - Runtime = Runtime.NODEJS_18_X, - Handler = "index.handler", - Code = Code.FromAsset(@".\create-job-lambda-code"), - Environment = new Dictionary<string, string> - { - ["QUEUE_URL"] = jobsQueue.QueueUrl - } -}); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- - createJobLambda := awslambda.NewFunction(stack, jsii.String("create-job"), &awslambda.FunctionProps{ - Runtime: awslambda.Runtime_NODEJS_18_X(), - Handler: jsii.String("index.handler"), - Code: awslambda.Code_FromAsset(jsii.String(".\\create-job-lambda-code"), nil), - Environment: &map[string]*string{ - "QUEUE_URL": jsii.String(*jobsQueue.QueueUrl()), - }, - }) ----- -==== - -For information about the most common API patterns in the {aws} Construct Library, see xref:resources[Resources and the {aws} CDK]. - -[#constructs-apps-stacks] -=== The app and stack construct - -The https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.App.html[`App`] and https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html[`Stack`] classes from the {aws} Construct Library are unique constructs. Compared to other constructs, they don't configure {aws} resources on their own. Instead, they are used to provide context for your other constructs. All constructs that represent {aws} resources must be defined, directly or indirectly, within the scope of a `Stack` construct. `Stack` constructs are defined within the scope of an `App` construct. - -To learn more about CDK apps, see xref:apps[{aws} CDK apps]. To learn more about CDK stacks, see xref:stacks[Introduction to {aws} CDK stacks]. - -The following example defines an app with a single stack. Within the stack, an L2 construct is used to configure an Amazon S3 bucket resource. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -import { App, Stack, StackProps } from 'aws-cdk-lib'; -import * as s3 from 'aws-cdk-lib/aws-s3'; - -class HelloCdkStack extends Stack { - constructor(scope: App, id: string, props?: StackProps) { - super(scope, id, props); - - new s3.Bucket(this, 'MyFirstBucket', { - versioned: true - }); - } -} - -const app = new App(); -new HelloCdkStack(app, "HelloCdkStack"); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const { App , Stack } = require('aws-cdk-lib'); -const s3 = require('aws-cdk-lib/aws-s3'); - -class HelloCdkStack extends Stack { - constructor(scope, id, props) { - super(scope, id, props); - - new s3.Bucket(this, 'MyFirstBucket', { - versioned: true - }); - } -} - -const app = new App(); -new HelloCdkStack(app, "HelloCdkStack"); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -from aws_cdk import App, Stack -import aws_cdk.aws_s3 as s3 -from constructs import Construct - -class HelloCdkStack(Stack): - - def __init__(self, scope: Construct, id: str, **kwargs) -> None: - super().__init__(scope, id, **kwargs) - - s3.Bucket(self, "MyFirstBucket", versioned=True) - -app = App() -HelloCdkStack(app, "HelloCdkStack") ----- - -Java:: -Stack defined in `HelloCdkStack.java` file: -+ -[source,java,subs="verbatim,attributes"] ----- -import software.constructs.Construct; -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.StackProps; -import software.amazon.awscdk.services.s3.*; - -public class HelloCdkStack extends Stack { - public HelloCdkStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public HelloCdkStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - Bucket.Builder.create(this, "MyFirstBucket") - .versioned(true).build(); - } -} ----- -+ - -App defined in `HelloCdkApp.java` file: -+ -[source,java,subs="verbatim,attributes"] ----- -import software.amazon.awscdk.App; -import software.amazon.awscdk.StackProps; - -public class HelloCdkApp { - public static void main(final String[] args) { - App app = new App(); - - new HelloCdkStack(app, "HelloCdkStack", StackProps.builder() - .build()); - - app.synth(); - } -} ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -using Amazon.CDK; -using Amazon.CDK.{aws}.S3; - -namespace HelloCdkApp -{ - internal static class Program - { - public static void Main(string[] args) - { - var app = new App(); - new HelloCdkStack(app, "HelloCdkStack"); - app.Synth(); - } - } - - public class HelloCdkStack : Stack - { - public HelloCdkStack(Construct scope, string id, IStackProps props=null) : base(scope, id, props) - { - new Bucket(this, "MyFirstBucket", new BucketProps { Versioned = true }); - } - } -} ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -func NewHelloCdkStack(scope constructs.Construct, id string, props *HelloCdkStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - stack := awscdk.NewStack(scope, &id, &sprops) - - awss3.NewBucket(stack, jsii.String("MyFirstBucket"), &awss3.BucketProps{ - Versioned: jsii.Bool(true), - }) - - return stack -} ----- -==== - - -[#constructs-work] -== Working with constructs - -[#constructs-l1-using] -=== Working with L1 constructs - -L1 constructs map directly to individual {aws} CloudFormation resources. You must provide the resource's required configuration. - -In this example, we create a `bucket` object using the `CfnBucket` L1 construct: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const bucket = new s3.CfnBucket(this, "amzn-s3-demo-bucket", { - bucketName: "amzn-s3-demo-bucket" -}); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const bucket = new s3.CfnBucket(this, "amzn-s3-demo-bucket", { - bucketName: "amzn-s3-demo-bucket" -}); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -bucket = s3.CfnBucket(self, "amzn-s3-demo-bucket", bucket_name="amzn-s3-demo-bucket") ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -CfnBucket bucket = new CfnBucket.Builder().bucketName("amzn-s3-demo-bucket").build(); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -var bucket = new CfnBucket(this, "amzn-s3-demo-bucket", new CfnBucketProps -{ - BucketName= "amzn-s3-demo-bucket" -}); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- - awss3.NewCfnBucket(stack, jsii.String("amzn-s3-demo-bucket"), &awss3.CfnBucketProps{ - BucketName: jsii.String("amzn-s3-demo-bucket"), - }) ----- -==== - -Construct properties that aren't simple Booleans, strings, numbers, or containers are handled differently in the supported languages. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const bucket = new s3.CfnBucket(this, "amzn-s3-demo-bucket", { - bucketName: "amzn-s3-demo-bucket", - corsConfiguration: { - corsRules: [{ - allowedOrigins: ["*"], - allowedMethods: ["GET"] - }] - } -}); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const bucket = new s3.CfnBucket(this, "amzn-s3-demo-bucket", { - bucketName: "amzn-s3-demo-bucket", - corsConfiguration: { - corsRules: [{ - allowedOrigins: ["*"], - allowedMethods: ["GET"] - }] - } -}); ----- - -Python:: -In Python, these properties are represented by types defined as inner classes of the L1 construct. For example, the optional property `cors_configuration` of a `CfnBucket` requires a wrapper of type `CfnBucket.CorsConfigurationProperty`. Here we are defining `cors_configuration` on a `CfnBucket` instance. -+ -[source,python,subs="verbatim,attributes"] ----- -bucket = CfnBucket(self, "amzn-s3-demo-bucket", bucket_name="amzn-s3-demo-bucket", - cors_configuration=CfnBucket.CorsConfigurationProperty( - cors_rules=[CfnBucket.CorsRuleProperty( - allowed_origins=["*"], - allowed_methods=["GET"] - )] - ) -) ----- - -Java:: -In Java, these properties are represented by types defined as inner classes of the L1 construct. For example, the optional property `corsConfiguration` of a `CfnBucket` requires a wrapper of type `CfnBucket.CorsConfigurationProperty`. Here we are defining `corsConfiguration` on a `CfnBucket` instance. -+ -[source,java,subs="verbatim,attributes"] ----- -CfnBucket bucket = CfnBucket.Builder.create(this, "amzn-s3-demo-bucket") - .bucketName("amzn-s3-demo-bucket") - .corsConfiguration(new CfnBucket.CorsConfigurationProperty.Builder() - .corsRules(Arrays.asList(new CfnBucket.CorsRuleProperty.Builder() - .allowedOrigins(Arrays.asList("*")) - .allowedMethods(Arrays.asList("GET")) - .build())) - .build()) - .build(); ----- - -C#:: -In C#, these properties are represented by types defined as inner classes of the L1 construct. For example, the optional property `CorsConfiguration` of a `CfnBucket` requires a wrapper of type `CfnBucket.CorsConfigurationProperty`. Here we are defining `CorsConfiguration` on a `CfnBucket` instance. -+ -[source,csharp,subs="verbatim,attributes"] ----- -var bucket = new CfnBucket(this, "amzn-s3-demo-bucket", new CfnBucketProps -{ - BucketName = "amzn-s3-demo-bucket", - CorsConfiguration = new CfnBucket.CorsConfigurationProperty - { - CorsRules = new object[] { - new CfnBucket.CorsRuleProperty - { - AllowedOrigins = new string[] { "*" }, - AllowedMethods = new string[] { "GET" }, - } - } - } -}); ----- - -Go:: -In Go, these types are named using the name of the L1 construct, an underscore, and the property name. For example, the optional property `CorsConfiguration` of a `CfnBucket` requires a wrapper of type `CfnBucket_CorsConfigurationProperty`. Here we are defining `CorsConfiguration` on a `CfnBucket` instance. -+ -[source,go,subs="verbatim,attributes"] ----- - awss3.NewCfnBucket(stack, jsii.String("amzn-s3-demo-bucket"), &awss3.CfnBucketProps{ - BucketName: jsii.String("amzn-s3-demo-bucket"), - CorsConfiguration: &awss3.CfnBucket_CorsConfigurationProperty{ - CorsRules: []awss3.CorsRule{ - awss3.CorsRule{ - AllowedOrigins: jsii.Strings("*"), - AllowedMethods: &[]awss3.HttpMethods{"GET"}, - }, - }, - }, - }) ----- -==== - - -[IMPORTANT] -==== - -You can't use L2 property types with L1 constructs, or vice versa. When working with L1 constructs, always use the types defined for the L1 construct you're using. Do not use types from other L1 constructs (some may have the same name, but they are not the same type). - -Some of our language-specific API references currently have errors in the paths to L1 property types, or don't document these classes at all. We hope to fix this soon. In the meantime, remember that such types are always inner classes of the L1 construct they are used with. - -==== - -[#constructs-using] -=== Working with L2 constructs - -In the following example, we define an Amazon S3 bucket by creating an object from the link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html[`Bucket`] L2 construct: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -import * as s3 from 'aws-cdk-lib/aws-s3'; - -// "this" is HelloCdkStack -new s3.Bucket(this, 'MyFirstBucket', { - versioned: true -}); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const s3 = require('aws-cdk-lib/aws-s3'); - -// "this" is HelloCdkStack -new s3.Bucket(this, 'MyFirstBucket', { - versioned: true -}); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -import aws_cdk.aws_s3 as s3 - -# "self" is HelloCdkStack -s3.Bucket(self, "MyFirstBucket", versioned=True) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -import software.amazon.awscdk.services.s3.*; - -public class HelloCdkStack extends Stack { - public HelloCdkStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public HelloCdkStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - Bucket.Builder.create(this, "MyFirstBucket") - .versioned(true).build(); - } -} ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -using Amazon.CDK.{aws}.S3; - -// "this" is HelloCdkStack -new Bucket(this, "MyFirstBucket", new BucketProps -{ - Versioned = true -}); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -import ( - "github.com/aws/aws-cdk-go/awscdk/v2/awss3" - "github.com/aws/jsii-runtime-go" -) - -// stack is HelloCdkStack -awss3.NewBucket(stack, jsii.String("MyFirstBucket"), &awss3.BucketProps{ - Versioned: jsii.Bool(true), - }) ----- -==== - -`MyFirstBucket` is not the name of the bucket that {aws} CloudFormation creates. It is a logical identifier given to the new construct within the context of your CDK app. The https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Resource.html#physicalname[physicalName] value will be used to name the {aws} CloudFormation resource. - -[#constructs-work-third] -== Working with third-party constructs - -https://constructs.dev/search?q=&cdk=aws-cdk&cdkver=2&sort=downloadsDesc&offset=0[Construct Hub] is a resource to help you discover additional constructs from {aws}, third parties, and the open-source CDK community. - -[#constructs-author] -=== Writing your own constructs - -In addition to using existing constructs, you can also write your own constructs and let anyone use them in their apps. All constructs are equal in the {aws} CDK. Constructs from the {aws} Construct Library are treated the same as a construct from a third-party library published via [.noloc]`NPM`, [.noloc]`Maven`, or [.noloc]`PyPI`. Constructs published to your company's internal package repository are also treated in the same way. - -To declare a new construct, create a class that extends the https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html[Construct] base class, in the `constructs` package, then follow the pattern for initializer arguments. - -The following example shows how to declare a construct that represents an Amazon S3 bucket. The S3 bucket sends an Amazon Simple Notification Service (Amazon SNS) notification every time someone uploads a file into it. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -export interface NotifyingBucketProps { - prefix?: string; -} - -export class NotifyingBucket extends Construct { - constructor(scope: Construct, id: string, props: NotifyingBucketProps = {}) { - super(scope, id); - const bucket = new s3.Bucket(this, 'bucket'); - const topic = new sns.Topic(this, 'topic'); - bucket.addObjectCreatedNotification(new s3notify.SnsDestination(topic), - { prefix: props.prefix }); - } -} ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -class NotifyingBucket extends Construct { - constructor(scope, id, props = {}) { - super(scope, id); - const bucket = new s3.Bucket(this, 'bucket'); - const topic = new sns.Topic(this, 'topic'); - bucket.addObjectCreatedNotification(new s3notify.SnsDestination(topic), - { prefix: props.prefix }); - } -} - -module.exports = { NotifyingBucket } ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -class NotifyingBucket(Construct): - - def __init__(self, scope: Construct, id: str, *, prefix=None): - super().__init__(scope, id) - bucket = s3.Bucket(self, "bucket") - topic = sns.Topic(self, "topic") - bucket.add_object_created_notification(s3notify.SnsDestination(topic), - s3.NotificationKeyFilter(prefix=prefix)) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -public class NotifyingBucket extends Construct { - - public NotifyingBucket(final Construct scope, final String id) { - this(scope, id, null, null); - } - - public NotifyingBucket(final Construct scope, final String id, final BucketProps props) { - this(scope, id, props, null); - } - - public NotifyingBucket(final Construct scope, final String id, final String prefix) { - this(scope, id, null, prefix); - } - - public NotifyingBucket(final Construct scope, final String id, final BucketProps props, final String prefix) { - super(scope, id); - - Bucket bucket = new Bucket(this, "bucket"); - Topic topic = new Topic(this, "topic"); - if (prefix != null) - bucket.addObjectCreatedNotification(new SnsDestination(topic), - NotificationKeyFilter.builder().prefix(prefix).build()); - } -} ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -public class NotifyingBucketProps : BucketProps -{ - public string Prefix { get; set; } -} - -public class NotifyingBucket : Construct -{ - public NotifyingBucket(Construct scope, string id, NotifyingBucketProps props = null) : base(scope, id) - { - var bucket = new Bucket(this, "bucket"); - var topic = new Topic(this, "topic"); - bucket.AddObjectCreatedNotification(new SnsDestination(topic), new NotificationKeyFilter - { - Prefix = props?.Prefix - }); - } -} ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -type NotifyingBucketProps struct { - awss3.BucketProps - Prefix *string -} - -func NewNotifyingBucket(scope constructs.Construct, id *string, props *NotifyingBucketProps) awss3.Bucket { - var bucket awss3.Bucket - if props == nil { - bucket = awss3.NewBucket(scope, jsii.String(*id+"Bucket"), nil) - } else { - bucket = awss3.NewBucket(scope, jsii.String(*id+"Bucket"), &props.BucketProps) - } - topic := awssns.NewTopic(scope, jsii.String(*id+"Topic"), nil) - if props == nil { - bucket.AddObjectCreatedNotification(awss3notifications.NewSnsDestination(topic)) - } else { - bucket.AddObjectCreatedNotification(awss3notifications.NewSnsDestination(topic), &awss3.NotificationKeyFilter{ - Prefix: props.Prefix, - }) - } - return bucket -} ----- -==== - - -[NOTE] -==== - -Our `NotifyingBucket` construct inherits not from `Bucket` but rather from `Construct`. We are using composition, not inheritance, to bundle an Amazon S3 bucket and an Amazon SNS topic together. In general, composition is preferred over inheritance when developing {aws} CDK constructs. - -==== - -The `NotifyingBucket` constructor has a typical construct signature: `scope`, `id`, and `props`. The last argument, `props`, is optional (gets the default value `{}`) because all props are optional. (The base `Construct` class does not take a `props` argument.) You could define an instance of this construct in your app without `props`, for example: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -new NotifyingBucket(this, 'MyNotifyingBucket'); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -new NotifyingBucket(this, 'MyNotifyingBucket'); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -NotifyingBucket(self, "MyNotifyingBucket") ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -new NotifyingBucket(this, "MyNotifyingBucket"); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -new NotifyingBucket(this, "MyNotifyingBucket"); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -NewNotifyingBucket(stack, jsii.String("MyNotifyingBucket"), nil) ----- -==== - -Or you could use `props` (in Java, an additional parameter) to specify the path prefix to filter on, for example: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -new NotifyingBucket(this, 'MyNotifyingBucket', { prefix: 'images/' }); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -new NotifyingBucket(this, 'MyNotifyingBucket', { prefix: 'images/' }); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -NotifyingBucket(self, "MyNotifyingBucket", prefix="images/") ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -new NotifyingBucket(this, "MyNotifyingBucket", "/images"); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -new NotifyingBucket(this, "MyNotifyingBucket", new NotifyingBucketProps -{ - Prefix = "/images" -}); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -NewNotifyingBucket(stack, jsii.String("MyNotifyingBucket"), &NotifyingBucketProps{ - Prefix: jsii.String("images/"), -}) ----- -==== - -Typically, you would also want to expose some properties or methods on your constructs. It's not very useful to have a topic hidden behind your construct, because users of your construct aren't able to subscribe to it. Adding a `topic` property lets consumers access the inner topic, as shown in the following example: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -export class NotifyingBucket extends Construct { - public readonly topic: sns.Topic; - - constructor(scope: Construct, id: string, props: NotifyingBucketProps) { - super(scope, id); - const bucket = new s3.Bucket(this, 'bucket'); - this.topic = new sns.Topic(this, 'topic'); - bucket.addObjectCreatedNotification(new s3notify.SnsDestination(this.topic), { prefix: props.prefix }); - } -} ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -class NotifyingBucket extends Construct { - - constructor(scope, id, props) { - super(scope, id); - const bucket = new s3.Bucket(this, 'bucket'); - this.topic = new sns.Topic(this, 'topic'); - bucket.addObjectCreatedNotification(new s3notify.SnsDestination(this.topic), { prefix: props.prefix }); - } -} - -module.exports = { NotifyingBucket }; ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -class NotifyingBucket(Construct): - - def __init__(self, scope: Construct, id: str, *, prefix=None, **kwargs): - super().__init__(scope, id) - bucket = s3.Bucket(self, "bucket") - self.topic = sns.Topic(self, "topic") - bucket.add_object_created_notification(s3notify.SnsDestination(self.topic), - s3.NotificationKeyFilter(prefix=prefix)) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -public class NotifyingBucket extends Construct { - - public Topic topic = null; - - public NotifyingBucket(final Construct scope, final String id) { - this(scope, id, null, null); - } - - public NotifyingBucket(final Construct scope, final String id, final BucketProps props) { - this(scope, id, props, null); - } - - public NotifyingBucket(final Construct scope, final String id, final String prefix) { - this(scope, id, null, prefix); - } - - public NotifyingBucket(final Construct scope, final String id, final BucketProps props, final String prefix) { - super(scope, id); - - Bucket bucket = new Bucket(this, "bucket"); - topic = new Topic(this, "topic"); - if (prefix != null) - bucket.addObjectCreatedNotification(new SnsDestination(topic), - NotificationKeyFilter.builder().prefix(prefix).build()); - } -} ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -public class NotifyingBucket : Construct -{ - public readonly Topic topic; - - public NotifyingBucket(Construct scope, string id, NotifyingBucketProps props = null) : base(scope, id) - { - var bucket = new Bucket(this, "bucket"); - topic = new Topic(this, "topic"); - bucket.AddObjectCreatedNotification(new SnsDestination(topic), new NotificationKeyFilter - { - Prefix = props?.Prefix - }); - } -} ----- - -Go:: -To do this in Go, we'll need a little extra plumbing. Our original `NewNotifyingBucket` function returned an `awss3.Bucket`. We'll need to extend `Bucket` to include a `topic` member by creating a `NotifyingBucket` struct. Our function will then return this type. -+ -[source,go,subs="verbatim,attributes"] ----- -type NotifyingBucket struct { - awss3.Bucket - topic awssns.Topic -} - -func NewNotifyingBucket(scope constructs.Construct, id *string, props *NotifyingBucketProps) NotifyingBucket { - var bucket awss3.Bucket - if props == nil { - bucket = awss3.NewBucket(scope, jsii.String(*id+"Bucket"), nil) - } else { - bucket = awss3.NewBucket(scope, jsii.String(*id+"Bucket"), &props.BucketProps) - } - topic := awssns.NewTopic(scope, jsii.String(*id+"Topic"), nil) - if props == nil { - bucket.AddObjectCreatedNotification(awss3notifications.NewSnsDestination(topic)) - } else { - bucket.AddObjectCreatedNotification(awss3notifications.NewSnsDestination(topic), &awss3.NotificationKeyFilter{ - Prefix: props.Prefix, - }) - } - var nbucket NotifyingBucket - nbucket.Bucket = bucket - nbucket.topic = topic - return nbucket -} ----- -==== - -Now, consumers can subscribe to the topic, for example: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const queue = new sqs.Queue(this, 'NewImagesQueue'); -const images = new NotifyingBucket(this, '/images'); -images.topic.addSubscription(new sns_sub.SqsSubscription(queue)); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const queue = new sqs.Queue(this, 'NewImagesQueue'); -const images = new NotifyingBucket(this, '/images'); -images.topic.addSubscription(new sns_sub.SqsSubscription(queue)); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -queue = sqs.Queue(self, "NewImagesQueue") -images = NotifyingBucket(self, prefix="Images") -images.topic.add_subscription(sns_sub.SqsSubscription(queue)) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -NotifyingBucket images = new NotifyingBucket(this, "MyNotifyingBucket", "/images"); -images.topic.addSubscription(new SqsSubscription(queue)); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -var queue = new Queue(this, "NewImagesQueue"); -var images = new NotifyingBucket(this, "MyNotifyingBucket", new NotifyingBucketProps -{ - Prefix = "/images" -}); -images.topic.AddSubscription(new SqsSubscription(queue)); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- - queue := awssqs.NewQueue(stack, jsii.String("NewImagesQueue"), nil) - images := NewNotifyingBucket(stack, jsii.String("MyNotifyingBucket"), &NotifyingBucketProps{ - Prefix: jsii.String("/images"), - }) - images.topic.AddSubscription(awssnssubscriptions.NewSqsSubscription(queue, nil)) ----- -==== - -[#constructs-learn] -== Learn more - -The following video provides a comprehensive overview of CDK constructs, and explains how you can use them in your CDK apps. - -video::PzU-i0rJPGw[youtube,align = center,height = 390,fileref = https://www.youtube.com/embed/PzU-i0rJPGw,width = 480] diff --git a/v2/guide/concepts/context.adoc b/v2/guide/concepts/context.adoc deleted file mode 100644 index 932b696f..00000000 --- a/v2/guide/concepts/context.adoc +++ /dev/null @@ -1,392 +0,0 @@ -include::../attributes.txt[] - -// Attributes -[.topic] -:info_titleabbrev: Context values -:keywords: {aws} CDK, Context values - -[#context] -= Context values and the {aws} CDK - -[abstract] --- -Context values are key-value pairs that can be associated with an app, stack, or construct. They may be supplied to your app from a file (usually either `cdk.json` or `cdk.context.json` in your project directory) or on the command line. --- - -// Context start - -Context values are key-value pairs that can be associated with an app, stack, or construct. They may be supplied to your app from a file (usually either `cdk.json` or `cdk.context.json` in your project directory) or on the command line. - -The CDK Toolkit uses context to cache values retrieved from your {aws} account during synthesis. Values include the Availability Zones in your account or the Amazon Machine Image (AMI) IDs currently available for Amazon EC2 instances. Because these values are provided by your {aws} account, they can change between runs of your CDK application. This makes them a potential source of unintended change. The CDK Toolkit's caching behavior "freezes" these values for your CDK app until you decide to accept the new values. - -Imagine the following scenario without context caching. Let's say you specified "latest Amazon Linux" as the AMI for your Amazon EC2 instances, and a new version of this AMI was released. Then, the next time you deployed your CDK stack, your already-deployed instances would be using the outdated ("wrong") AMI and would need to be upgraded. Upgrading would result in replacing all your existing instances with new ones, which would probably be unexpected and undesired. - -Instead, the CDK records your account's available AMIs in your project's `cdk.context.json` file, and uses the stored value for future synthesis operations. This way, the list of AMIs is no longer a potential source of change. You can also be sure that your stacks will always synthesize to the same {aws} CloudFormation templates. - -Not all context values are cached values from your {aws} environment. xref:featureflags[{aws} CDK feature flags] are also context values. You can also create your own context values for use by your apps or constructs. - -Context keys are strings. Values may be any type supported by JSON: numbers, strings, arrays, or objects. - -[TIP] -==== - -If your constructs create their own context values, incorporate your library's package name in its keys so they won't conflict with other packages' context values. - -==== - -Many context values are associated with a particular {aws} environment, and a given CDK app can be deployed in more than one environment. The key for such values includes the {aws} account and Region so that values from different environments do not conflict. - -The following context key illustrates the format used by the {aws} CDK, including the account and Region. - -[source,none,subs="verbatim,attributes"] ----- -availability-zones:account=123456789012:region=eu-central-1 ----- - -[IMPORTANT] -==== - -Cached context values are managed by the {aws} CDK and its constructs, including constructs you may write. Do not add or change cached context values by manually editing files. It can be useful, however, to review `cdk.context.json` occasionally to see what values are being cached. Context values that don't represent cached values should be stored under the `context` key of `cdk.json`. This way, they won't be cleared when cached values are cleared. - -==== - -[#context-construct] -== Sources of context values - -Context values can be provided to your {aws} CDK app in six different ways: - -* Automatically from the current {aws} account. -* Through the `--context` option to the `cdk` command. (These values are always strings.) -* In the project's `cdk.context.json` file. -* In the `context` key of the project's `cdk.json` file. -* In the `context` key of your `~/.cdk.json` file. -* In your {aws} CDK app using the `construct.node.setContext()` method. - -The project file `cdk.context.json` is where the {aws} CDK caches context values retrieved from your {aws} account. This practice avoids unexpected changes to your deployments when, for example, a new Availability Zone is introduced. The {aws} CDK does not write context data to any of the other files listed. - -[IMPORTANT] -==== - -Because they're part of your application's state, `cdk.json` and `cdk.context.json` must be committed to source control along with the rest of your app's source code. Otherwise, deployments in other environments (for example, a CI pipeline) might produce inconsistent results. - -==== - -Context values are scoped to the construct that created them; they are visible to child constructs, but not to parents or siblings. Context values that are set by the {aws} CDK Toolkit (the `cdk` command) can be set automatically, from a file, or from the `--context` option. Context values from these sources are implicitly set on the `App` construct. Therefore, they're visible to every construct in every stack in the app. - -Your app can read a context value using the `construct.node.tryGetContext` method. If the requested entry isn't found on the current construct or any of its parents, the result is `undefined`. (Alternatively, the result could be your language's equivalent, such as `None` in Python.) - -[#context-methods] -== Context methods - -The {aws} CDK supports several context methods that enable {aws} CDK apps to obtain contextual information from the {aws} environment. For example, you can get a list of Availability Zones that are available in a given {aws} account and Region, using the link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html#availabilityzones[`stack.availabilityZones`] method. - -The following are the context methods: - -link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_route53.HostedZone.html#static-fromwbrlookupscope-id-query[`HostedZone.fromLookup`]:: -+ -Gets the hosted zones in your account. - -link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html#availabilityzones[`stack.availabilityZones`]:: -+ -Gets the supported Availability Zones. - -link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ssm.StringParameter.html#static-valuewbrfromwbrlookupscope-parametername[`StringParameter.valueFromLookup`]:: -+ -Gets a value from the current Region's Amazon EC2 Systems Manager Parameter Store. - -link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.Vpc.html#static-fromwbrlookupscope-id-options[`Vpc.fromLookup`]:: -+ -Gets the existing Amazon Virtual Private Clouds in your accounts. - -link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.LookupMachineImage.html[`LookupMachineImage`]:: -+ -Looks up a machine image for use with a NAT instance in an Amazon Virtual Private Cloud. - -If a required context value isn't available, the {aws} CDK app notifies the CDK Toolkit that the context information is missing. Next, the CLI queries the current {aws} account for the information and stores the resulting context information in the `cdk.context.json` file. Then, it executes the {aws} CDK app again with the context values. - -[#context-viewing] -== Viewing and managing context - -Use the `cdk context` command to view and manage the information in your `cdk.context.json` file. To see this information, use the `cdk context` command without any options. The output should be something like the following. - -[source,none,subs="verbatim,attributes"] ----- -Context found in cdk.json: - -┌───┬─────────────────────────────────────────────────────────────┬─────────────────────────────────────────────────────────┐ -│ # │ Key │ Value │ -├───┼─────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────┤ -│ 1 │ availability-zones:account=123456789012:region=eu-central-1 │ [ "eu-central-1a", "eu-central-1b", "eu-central-1c" ] │ -├───┼─────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────┤ -│ 2 │ availability-zones:account=123456789012:region=eu-west-1 │ [ "eu-west-1a", "eu-west-1b", "eu-west-1c" ] │ -└───┴─────────────────────────────────────────────────────────────┴─────────────────────────────────────────────────────────┘ - -Run - - cdk context --reset KEY_OR_NUMBER - - to remove a context key. If it is a cached value, it will be refreshed on the next - - cdk synth - -. ----- - -To remove a context value, run `cdk context --reset`, specifying the value's corresponding key or number. The following example removes the value that corresponds to the second key in the preceding example. This value represents the list of Availability Zones in the Europe (Ireland) Region. - -[source,none,subs="verbatim,attributes"] ----- -cdk context --reset 2 ----- - -[source,none,subs="verbatim,attributes"] ----- -Context value -availability-zones:account=123456789012:region=eu-west-1 -reset. It will be refreshed on the next SDK synthesis run. ----- - -Therefore, if you want to update to the latest version of the Amazon Linux AMI, use the preceding example to do a controlled update of the context value and reset it. Then, synthesize and deploy your app again. - -[source,bash,subs="verbatim,attributes"] ----- -$ cdk synth ----- - -To clear all of the stored context values for your app, run `cdk context --clear`, as follows. - -[source,bash,subs="verbatim,attributes"] ----- -$ cdk context --clear ----- - -Only context values stored in `cdk.context.json` can be reset or cleared. The {aws} CDK does not touch other context values. Therefore, to protect a context value from being reset using these commands, you might copy the value to `cdk.json`. - -[#context-cli] -== {aws} CDK Toolkit `--context` flag - -Use the `--context` (`-c` for short) option to pass runtime context values to your CDK app during synthesis or deployment. - -[source,bash,subs="verbatim,attributes"] ----- -$ cdk synth --context key=value MyStack ----- - -To specify multiple context values, repeat the `--context` option any number of times, providing one key-value pair each time. - -[source,bash,subs="verbatim,attributes"] ----- -$ cdk synth --context key1=value1 --context key2=value2 MyStack ----- - -When synthesizing multiple stacks, the specified context values are passed to all stacks. To provide different context values to individual stacks, either use different keys for the values, or use multiple `cdk synth` or `cdk deploy` commands. - -Context values passed from the command line are always strings. If a value is usually of some other type, your code must be prepared to convert or parse the value. You might have non-string context values provided in other ways (for example, in `cdk.context.json`). To make sure this kind of value works as expected, confirm that the value is a string before converting it. - -[#context-example] -== Example - -Following is an example of using an existing Amazon VPC using {aws} CDK context. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -import * as cdk from 'aws-cdk-lib'; -import * as ec2 from 'aws-cdk-lib/aws-ec2'; -import { Construct } from 'constructs'; - -export class ExistsVpcStack extends cdk.Stack { - - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - - super(scope, id, props); - - const vpcid = this.node.tryGetContext('vpcid'); - const vpc = ec2.Vpc.fromLookup(this, 'VPC', { - vpcId: vpcid, - }); - - const pubsubnets = vpc.selectSubnets({subnetType: ec2.SubnetType.PUBLIC}); - - new cdk.CfnOutput(this, 'publicsubnets', { - value: pubsubnets.subnetIds.toString(), - }); - } -} ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const cdk = require('aws-cdk-lib'); -const ec2 = require('aws-cdk-lib/aws-ec2'); - -class ExistsVpcStack extends cdk.Stack { - - constructor(scope, id, props) { - - super(scope, id, props); - - const vpcid = this.node.tryGetContext('vpcid'); - const vpc = ec2.Vpc.fromLookup(this, 'VPC', { - vpcId: vpcid - }); - - const pubsubnets = vpc.selectSubnets({subnetType: ec2.SubnetType.PUBLIC}); - - new cdk.CfnOutput(this, 'publicsubnets', { - value: pubsubnets.subnetIds.toString() - }); - } -} - -module.exports = { ExistsVpcStack } ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -import aws_cdk as cdk -import aws_cdk.aws_ec2 as ec2 -from constructs import Construct - -class ExistsVpcStack(cdk.Stack): - - def __init__(scope: Construct, id: str, **kwargs): - - super().__init__(scope, id, **kwargs) - - vpcid = self.node.try_get_context("vpcid") - vpc = ec2.Vpc.from_lookup(self, "VPC", vpc_id=vpcid) - - pubsubnets = vpc.select_subnets(subnetType=ec2.SubnetType.PUBLIC) - - cdk.CfnOutput(self, "publicsubnets", - value=pubsubnets.subnet_ids.to_string()) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -import software.amazon.awscdk.CfnOutput; - -import software.amazon.awscdk.services.ec2.Vpc; -import software.amazon.awscdk.services.ec2.VpcLookupOptions; -import software.amazon.awscdk.services.ec2.SelectedSubnets; -import software.amazon.awscdk.services.ec2.SubnetSelection; -import software.amazon.awscdk.services.ec2.SubnetType; -import software.constructs.Construct; - -public class ExistsVpcStack extends Stack { - public ExistsVpcStack(Construct context, String id) { - this(context, id, null); - } - - public ExistsVpcStack(Construct context, String id, StackProps props) { - super(context, id, props); - - String vpcId = (String)this.getNode().tryGetContext("vpcid"); - Vpc vpc = (Vpc)Vpc.fromLookup(this, "VPC", VpcLookupOptions.builder() - .vpcId(vpcId).build()); - - SelectedSubnets pubSubNets = vpc.selectSubnets(SubnetSelection.builder() - .subnetType(SubnetType.PUBLIC).build()); - - CfnOutput.Builder.create(this, "publicsubnets") - .value(pubSubNets.getSubnetIds().toString()).build(); - } -} ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -using Amazon.CDK; -using Amazon.CDK.{aws}.EC2; -using Constructs; - -class ExistsVpcStack : Stack -{ - public ExistsVpcStack(Construct scope, string id, StackProps props) : base(scope, id, props) - { - var vpcId = (string)this.Node.TryGetContext("vpcid"); - var vpc = Vpc.FromLookup(this, "VPC", new VpcLookupOptions - { - VpcId = vpcId - }); - - SelectedSubnets pubSubNets = vpc.SelectSubnets([new SubnetSelection - { - SubnetType = SubnetType.PUBLIC - }]); - - new CfnOutput(this, "publicsubnets", new CfnOutputProps { - Value = pubSubNets.SubnetIds.ToString() - }); - } -} ----- -==== - -You can use `cdk diff` to see the effects of passing in a context value on the command line: - -[source,bash,subs="verbatim,attributes"] ----- -$ cdk diff -c vpcid=vpc-0cb9c31031d0d3e22 ----- - -[source,none,subs="verbatim,attributes"] ----- -Stack ExistsvpcStack -Outputs -[+] Output publicsubnets publicsubnets: {"Value":"subnet-06e0ea7dd302d3e8f,subnet-01fc0acfb58f3128f"} ----- - -The resulting context values can be viewed as shown here. - -[source,bash,subs="verbatim,attributes"] ----- -$ cdk context -j ----- - -[source,none,subs="verbatim,attributes"] ----- -{ - "vpc-provider:account=123456789012:filter.vpc-id=vpc-0cb9c31031d0d3e22:region=us-east-1": { - "vpcId": "vpc-0cb9c31031d0d3e22", - "availabilityZones": [ - "us-east-1a", - "us-east-1b" - ], - "privateSubnetIds": [ - "subnet-03ecfc033225be285", - "subnet-0cded5da53180ebfa" - ], - "privateSubnetNames": [ - "Private" - ], - "privateSubnetRouteTableIds": [ - "rtb-0e955393ced0ada04", - "rtb-05602e7b9f310e5b0" - ], - "publicSubnetIds": [ - "subnet-06e0ea7dd302d3e8f", - "subnet-01fc0acfb58f3128f" - ], - "publicSubnetNames": [ - "Public" - ], - "publicSubnetRouteTableIds": [ - "rtb-00d1fdfd823c82289", - "rtb-04bb1969b42969bcb" - ] - } -} ----- \ No newline at end of file diff --git a/v2/guide/concepts/core-concepts.adoc b/v2/guide/concepts/core-concepts.adoc deleted file mode 100644 index 04c522ab..00000000 --- a/v2/guide/concepts/core-concepts.adoc +++ /dev/null @@ -1,103 +0,0 @@ -include::../attributes.txt[] - -// Attributes -[.topic] -[#core-concepts] -= Learn {aws} CDK core concepts -:info_titleabbrev: CDK core concepts -:keywords: {aws} Cloud Development Kit ({aws} CDK), {aws} CDK, IaC, Infrastructure as code, {aws} CloudFormation, Serverless applications, Modern applications, {aws} - -[abstract] --- -Learn core concepts behind the {aws} Cloud Development Kit ({aws} CDK). --- - -// Content start - -Learn core concepts behind the {aws} Cloud Development Kit ({aws} CDK). - -[#concepts-iac] -== {aws} CDK and [.noloc]`IaC` - -The {aws} CDK is an open-source framework that you can use to manage your {aws} infrastructure using code. This approach is known as __infrastructure as code ([.noloc]`IaC`)__. By managing and provisioning your infrastructure as code, you treat your infrastructure in the same way that developers treat code. This provides many benefits, such as version control and scalability. To learn more about IaC, see https://aws.amazon.com/what-is/iac/[What is Infrastructure as Code?] - -[#concepts-cfn] -== {aws} CDK and {aws} CloudFormation - -The {aws} CDK is tightly integrated with {aws} CloudFormation. {aws} CloudFormation is a fully managed service that you can use to manage and provision your infrastructure on {aws}. With {aws} CloudFormation, you define your infrastructure in templates and deploy them to {aws} CloudFormation. The {aws} CloudFormation service then provisions your infrastructure according to the configuration defined on your templates. - -{aws} CloudFormation templates are __declarative__, meaning they declare the desired state or outcome of your infrastructure. Using JSON or YAML, you declare your {aws} infrastructure by defining {aws} _resources_ and __properties__. Resources represent the many services on {aws} and properties represent your desired configuration of those services. When you deploy your template to {aws} CloudFormation, your resources and their configured properties are provisioned as described on your template. - -With the {aws} CDK, you can manage your infrastructure __imperatively__, using general-purpose programming languages. Instead of just defining a desired state declaratively, you can define the logic or sequence necessary to reach the desired state. For example, you can use `if` statements or conditional loops that determine how to reach a desired end state for your infrastructure. - -Infrastructure created with the {aws} CDK is eventually translated, or _synthesized_ into {aws} CloudFormation templates and deployed using the {aws} CloudFormation service. So while the {aws} CDK offers a different approach to creating your infrastructure, you still receive the benefits of {aws} CloudFormation, such as extensive {aws} resource configuration support and robust deployment processes. - -To learn more about {aws} CloudFormation, see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/Welcome.html[What is {aws} CloudFormation?] in the __{aws} CloudFormation User Guide__. - -[#concepts-abstractions] -== {aws} CDK and abstractions - -With {aws} CloudFormation, you must define every detail of how your resources are configured. This provides the benefit of having complete control over your infrastructure. However, this requires you to learn, understand, and create robust templates that contain resource configuration details and relationships between resources, such as permissions and event-driven interactions. - -With the {aws} CDK, you can have the same control over your resource configurations. However, the {aws} CDK also offers powerful abstractions, which can speed up and simplify the infrastructure development process. For example, the {aws} CDK includes constructs that provide sensible default configurations and helper methods that generate boilerplate code for you. The {aws} CDK also offers tools, such as the {aws} CDK Command Line Interface ({aws} CDK CLI), that perform infrastructure management actions for you. - -[#concepts-learn] -== Learn more about core {aws} CDK concepts - -[#concepts-learn-interact] -*Interacting with the {aws} CDK*:: -+ -When using with the {aws} CDK, you will primarily interact with the {aws} Construct Library and the {aws} CDK CLI. - -[#concepts-learn-develop] -*Developing with the {aws} CDK*:: -+ -The {aws} CDK can be written in any xref:languages[supported programming language]. You start with a xref:projects[CDK project], which contains a structure of folders and files, including xref:assets[assets]. Within the project, you create a xref:apps[CDK application]. Within the app, you define a xref:stacks[stack], which directly represents a CloudFormation stack. Within the stack, you define your {aws} resources and properties using xref:constructs[constructs]. - -[#concepts-learn-deploy] -*Deploying with the {aws} CDK*:: -+ -You deploy CDK apps into an {aws} xref:environments[environment]. Before deploying, you must perform a one-time xref:bootstrapping[bootstrapping] to prepare your environment. - -[#concepts-learn-more] -*Learn more*:: -+ -To learn more about {aws} CDK core concepts, see the topics in this section. - -include::languages.adoc[leveloffset=+1] - -include::libraries.adoc[leveloffset=+1] - -include::projects.adoc[leveloffset=+1] - -include::apps.adoc[leveloffset=+1] - -include::stacks.adoc[leveloffset=+1] - -include::stages.adoc[leveloffset=+1] - -include::constructs.adoc[leveloffset=+1] - -include::environments.adoc[leveloffset=+1] - -include::bootstrapping.adoc[leveloffset=+1] - -include::resources.adoc[leveloffset=+1] - -include::identifiers.adoc[leveloffset=+1] - -include::tokens.adoc[leveloffset=+1] - -include::parameters.adoc[leveloffset=+1] - -include::tagging.adoc[leveloffset=+1] - -include::assets.adoc[leveloffset=+1] - -include::permissions.adoc[leveloffset=+1] - -include::context.adoc[leveloffset=+1] - -include::feature-flags.adoc[leveloffset=+1] - -include::aspects.adoc[leveloffset=+1] \ No newline at end of file diff --git a/v2/guide/concepts/environments.adoc b/v2/guide/concepts/environments.adoc deleted file mode 100644 index cfe6ac20..00000000 --- a/v2/guide/concepts/environments.adoc +++ /dev/null @@ -1,93 +0,0 @@ -include::../attributes.txt[] - -// Attributes -:https---docs-aws-amazon-com-general-latest-gr-rande-html-regional-endpoints: https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints -:https---aws-amazon-com-about-aws-global-infrastructure-regions-az-: https://aws.amazon.com/about-aws/global-infrastructure/regions_az/ - -[.topic] -:info_titleabbrev: Environments -:keywords: {aws} CDK, {aws} Cloud Development Kit ({aws} CDK), environment, env, {aws} account, {aws} Region - -[#environments] -= Environments for the {aws} CDK - -[abstract] --- -An environment consists of the {aws} account and {aws} Region that you deploy an {aws} Cloud Development Kit ({aws} CDK) stack to. --- - -// Content start - -An environment consists of the {aws} account and {aws} Region that you deploy an {aws} Cloud Development Kit ({aws} CDK) stack to. - -*{aws} account*:: -When you create an {aws} account, you receive an account ID. This ID is a 12-digit number, such as **012345678901**, that uniquely identifies your account. To learn more, see https://docs.aws.amazon.com/accounts/latest/reference/manage-acct-identifiers.html[View {aws} account identifiers] in the _{aws} Account Management Reference Guide_. - -*{aws} Region*:: -{aws} Regions are named by using a combination of geographical location and a number that represents an Availability Zone in the Region. For example, *[.noloc]`us-east-1`* represents an Availability Zone in the US East (N. Virginia) Region. To learn more about {aws} Regions, see https://aws.amazon.com/about-aws/global-infrastructure/regions_az/[Regions and Availability Zones]. For a list of Region codes, see https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints[Regional endpoints] in the _{aws} General Reference_ Reference Guide. - -The {aws} CDK can determine environments from your credentials and configuration files. These files can be created and managed with the {aws} Command Line Interface ({aws} CLI). The following is a basic example of these files: - -*Credentials file*:: -+ -[source,toml,subs="verbatim,attributes"] ----- -[default] -aws_access_key_id=ASIAIOSFODNN7EXAMPLE -aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY -aws_session_token = IQoJb3JpZ2luX2IQoJb3JpZ2luX2IQoJb3JpZ2luX2IQoJb3JpZ2luX2IQoJb3JpZVERYLONGSTRINGEXAMPLE - -[user1] -aws_access_key_id=ASIAI44QH8DHBEXAMPLE -aws_secret_access_key=je7MtGbClwBF/2Zp9Utk/h3yCo8nvbEXAMPLEKEY -aws_session_token = fcZib3JpZ2luX2IQoJb3JpZ2luX2IQoJb3JpZ2luX2IQoJb3JpZ2luX2IQoJb3JpZVERYLONGSTRINGEXAMPLE ----- - -*Configuration file*:: -+ -[source,toml,subs="verbatim,attributes"] ----- -[default] -region=us-west-2 -output=json - -[profile user1] -region=us-east-1 -output=text ----- - -You can pass environment information from these files in your CDK code through environment variables that are provided by the CDK. When you run a CDK CLI command, such as `cdk deploy`, you then provide the profile from your credentials and configuration files to gather environment information from. - -The following is an example of specifying these environment variables in your CDK code: - -[source,javascript,subs="verbatim,attributes"] ----- -new MyDevStack(app, 'dev', { - env: { - account: process.env.CDK_DEFAULT_ACCOUNT, - region: process.env.CDK_DEFAULT_REGION -}}); ----- - -The following is an example of passing values associated with the `user1` profile from your credentials and configuration files to the CDK CLI using the `--profile` option. Values from these files will be passed to your environment variables: - -[source,bash,subs="verbatim,attributes"] ----- -$ cdk deploy <myStack> --profile <user1> ----- - -Instead of using values from the credentials and configuration files, you can also hard-code environment values in your CDK code. The following is an example: - -[source,javascript,subs="verbatim,attributes"] ----- -const envEU = { account: '238383838383', region: 'eu-west-1' }; -const envUSA = { account: '837873873873', region: 'us-west-2' }; - -new MyFirstStack(app, 'first-stack-us', { env: envUSA }); -new MyFirstStack(app, 'first-stack-eu', { env: envEU }); ----- - -[#environments-learn] -== Learn more - -To get started with using environments with the {aws} CDK, see xref:configure-env[Configure environments to use with the {aws} CDK]. \ No newline at end of file diff --git a/v2/guide/concepts/feature-flags.adoc b/v2/guide/concepts/feature-flags.adoc deleted file mode 100644 index 382d9c0a..00000000 --- a/v2/guide/concepts/feature-flags.adoc +++ /dev/null @@ -1,70 +0,0 @@ -include::../attributes.txt[] - -// Attributes -:https---github-com-aws-aws-cdk-blob-main-packages-aws-cdk-lib-cx-api-FEATURE-FLAGS-md: https://github.com/aws/aws-cdk/blob/main/packages/aws-cdk-lib/cx-api/FEATURE_FLAGS.md - -[.topic] -:info_titleabbrev: Feature flags -:keywords: {aws} CDK, Feature flags - -[#featureflags] -= {aws} CDK feature flags - -[abstract] --- -The {aws} CDK uses _feature flags_ to enable potentially breaking behaviors in a release. Flags are stored as xref:context[Context values and the {aws} CDK] values in `cdk.json` (or `~/.cdk.json`). They are not removed by the `cdk context --reset` or `cdk context --clear` commands. --- - -// Content start - -The {aws} CDK uses _feature flags_ to enable potentially breaking behaviors in a release. Flags are stored as xref:context[Context values and the {aws} CDK] values in `cdk.json` (or `~/.cdk.json`). They are not removed by the `cdk context --reset` or `cdk context --clear` commands. - -Feature flags are disabled by default. Existing projects that do not specify the flag will continue to work as before with later {aws} CDK releases. New projects created using `cdk init` include flags enabling all features available in the release that created the project. Edit `cdk.json` to disable any flags for which you prefer the earlier behavior. You can also add flags to enable new behaviors after upgrading the {aws} CDK. - -A list of all current feature flags can be found on the {aws} CDK GitHub repository in {https---github-com-aws-aws-cdk-blob-main-packages-aws-cdk-lib-cx-api-FEATURE-FLAGS-md}[FEATURE_FLAGS.md]. See the `CHANGELOG` in a given release for a description of any new feature flags added in that release. - -[[featureflags-disabling,featureflags-disabling.title]] -== Reverting to v1 behavior - -In CDK v2, the defaults for some feature flags have been changed with respect to v1. You can set these back to `false` to revert to specific {aws} CDK v1 behavior. Use the `cdk diff` command to inspect the changes to your synthesized template to see if any of these flags are needed. - - - -`@aws-cdk/core:newStyleStackSynthesis`:: -Use the new stack synthesis method, which assumes bootstrap resources with well-known names. Requires xref:bootstrapping[modern bootstrapping], but in turn allows CI/CD via xref:cdk-pipeline[CDK Pipelines] and cross-account deployments out of the box. - - -`@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId`:: -If your application uses multiple Amazon API Gateway API keys and associates them to usage plans. - - -`@aws-cdk/aws-rds:lowercaseDbIdentifier`:: -If your application uses Amazon RDS database instance or database clusters, and explicitly specifies the identifier for these. - - -`@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021`:: -If your application uses the TLS_V1_2_2019 security policy with Amazon CloudFront distributions. CDK v2 uses security policy TLSv1.2_2021 by default. - - -`@aws-cdk/core:stackRelativeExports`:: -If your application uses multiple stacks and you refer to resources from one stack in another, this determines whether absolute or relative path is used to construct {aws} CloudFormation exports. - - -`@aws-cdk/aws-lambda:recognizeVersionProps`:: -If set to ``false``, the CDK includes metadata when detecting whether a Lambda function has changed. This can cause deployment failures when only the metadata has changed, since duplicate versions are not allowed. There is no need to revert this flag if you've made at least one change to all Lambda Functions in your application. - -The syntax for reverting these flags in `cdk.json` is shown here. - -[source,json,subs="verbatim,attributes"] ----- -{ - "context": { - "@aws-cdk/core:newStyleStackSynthesis": false, - "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": false, - "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": false, - "@aws-cdk/aws-rds:lowercaseDbIdentifier": false, - "@aws-cdk/core:stackRelativeExports": false, - "@aws-cdk/aws-lambda:recognizeVersionProps": false - } -} ----- \ No newline at end of file diff --git a/v2/guide/concepts/identifiers.adoc b/v2/guide/concepts/identifiers.adoc deleted file mode 100644 index f835bbc2..00000000 --- a/v2/guide/concepts/identifiers.adoc +++ /dev/null @@ -1,309 +0,0 @@ -include::../attributes.txt[] - -// Attributes -[.topic] -:info_titleabbrev: Identifiers -:keywords: {aws} CDK, Identifiers - -[#identifiers] -= Identifiers and the {aws} CDK - -[abstract] --- -When building {aws} Cloud Development Kit ({aws} CDK) apps, you will use many types of identifiers and names. To use the {aws} CDK effectively and avoid errors, it is important to understand the types of identifiers. --- - -// Content start - -When building {aws} Cloud Development Kit ({aws} CDK) apps, you will use many types of identifiers and names. To use the {aws} CDK effectively and avoid errors, it is important to understand the types of identifiers. - -Identifiers must be unique within the scope in which they are created; they do not need to be globally unique in your {aws} CDK application. - -If you attempt to create an identifier with the same value within the same scope, the {aws} CDK throws an exception. - -[#identifiers-construct-ids] -== Construct IDs - -The most common identifier, `id`, is the identifier passed as the second argument when instantiating a construct object. This identifier, like all identifiers, only needs to be unique within the scope in which it is created, which is the first argument when instantiating a construct object. - -[NOTE] -==== - -The `id` of a stack is also the identifier that you use to refer to it in the xref:cli[{aws} CDK CLI reference]. - -==== - -Let's look at an example where we have two constructs with the identifier `MyBucket` in our app. The first is defined in the scope of the stack with the identifier `Stack1`. The second is defined in the scope of a stack with the identifier `Stack2`. Because they're defined in different scopes, this doesn't cause any conflict, and they can coexist in the same app without issues. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -import { App, Stack, StackProps } from 'aws-cdk-lib'; -import { Construct } from 'constructs'; -import * as s3 from 'aws-cdk-lib/aws-s3'; - -class MyStack extends Stack { - constructor(scope: Construct, id: string, props: StackProps = {}) { - super(scope, id, props); - - new s3.Bucket(this, 'MyBucket'); - } -} - -const app = new App(); -new MyStack(app, 'Stack1'); -new MyStack(app, 'Stack2'); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const { App , Stack } = require('aws-cdk-lib'); -const s3 = require('aws-cdk-lib/aws-s3'); - -class MyStack extends Stack { - constructor(scope, id, props = {}) { - super(scope, id, props); - - new s3.Bucket(this, 'MyBucket'); - } -} - -const app = new App(); -new MyStack(app, 'Stack1'); -new MyStack(app, 'Stack2'); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -from aws_cdk import App, Construct, Stack, StackProps -from constructs import Construct -from aws_cdk import aws_s3 as s3 - -class MyStack(Stack): - - def __init__(self, scope: Construct, id: str, **kwargs): - - super().__init__(scope, id, **kwargs) - s3.Bucket(self, "MyBucket") - -app = App() -MyStack(app, 'Stack1') -MyStack(app, 'Stack2') ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -// MyStack.java -package com.myorg; - -import software.amazon.awscdk.App; -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.StackProps; -import software.constructs.Construct; -import software.amazon.awscdk.services.s3.Bucket; - -public class MyStack extends Stack { - public MyStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public MyStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - new Bucket(this, "MyBucket"); - } -} - -// Main.java -package com.myorg; - -import software.amazon.awscdk.App; - -public class Main { - public static void main(String[] args) { - App app = new App(); - new MyStack(app, "Stack1"); - new MyStack(app, "Stack2"); - } -} ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -using Amazon.CDK; -using constructs; -using Amazon.CDK.{aws}.S3; - -public class MyStack : Stack -{ - public MyStack(Construct scope, string id, IStackProps props) : base(scope, id, props) - { - new Bucket(this, "MyBucket"); - } -} - -class Program -{ - static void Main(string[] args) - { - var app = new App(); - new MyStack(app, "Stack1"); - new MyStack(app, "Stack2"); - } -} ----- -==== - -[#identifiers-paths] -== Paths - -The constructs in an {aws} CDK application form a hierarchy rooted in the `App` class. We refer to the collection of IDs from a given construct, its parent construct, its grandparent, and so on to the root of the construct tree, as a _path_. - -The {aws} CDK typically displays paths in your templates as a string. The IDs from the levels are separated by slashes, starting at the node immediately under the root `App` instance, which is usually a stack. For example, the paths of the two Amazon S3 bucket resources in the previous code example are `Stack1/MyBucket` and `Stack2/MyBucket`. - -You can access the path of any construct programmatically, as shown in the following example. This gets the path of `myConstruct` (or `my_construct`, as Python developers would write it). Since IDs must be unique within the scope they are created, their paths are always unique within an {aws} CDK application. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const path: string = myConstruct.node.path; ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const path = myConstruct.node.path; ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -path = my_construct.node.path ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -String path = myConstruct.getNode().getPath(); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -string path = myConstruct.Node.Path; ----- -==== - -[#identifiers-unique-ids] -== Unique IDs - -{aws} CloudFormation requires that all logical IDs in a template be unique. Because of this, the {aws} CDK must be able to generate a unique identifier for each construct in an application. Resources have paths that are globally unique (the names of all scopes from the stack to a specific resource). Therefore, the {aws} CDK generates the necessary unique identifiers by concatenating the elements of the path and adding an 8-digit hash. (The hash is necessary to distinguish distinct paths, such as `A/B/C` and `A/BC`, that would result in the same {aws} CloudFormation identifier. {aws} CloudFormation identifiers are alphanumeric and cannot contain slashes or other separator characters.) The {aws} CDK calls this string the _unique ID_ of the construct. - -In general, your {aws} CDK app should not need to know about unique IDs. You can, however, access the unique ID of any construct programmatically, as shown in the following example. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const uid: string = Names.uniqueId(myConstruct); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const uid = Names.uniqueId(myConstruct); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -uid = Names.unique_id(my_construct) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -String uid = Names.uniqueId(myConstruct); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -string uid = Names.Uniqueid(myConstruct); ----- -==== - -The _address_ is another kind of unique identifier that uniquely distinguishes CDK resources. Derived from the SHA-1 hash of the path, it is not human-readable. However, its constant, relatively short length (always 42 hexadecimal characters) makes it useful in situations where the "traditional" unique ID might be too long. Some constructs may use the address in the synthesized {aws} CloudFormation template instead of the unique ID. Again, your app generally should not need to know about its constructs' addresses, but you can retrieve a construct's address as follows. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const addr: string = myConstruct.node.addr; ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const addr = myConstruct.node.addr; ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -addr = my_construct.node.addr ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -String addr = myConstruct.getNode().getAddr(); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -string addr = myConstruct.Node.Addr; ----- -==== - -[#identifiers-logical-ids] -== Logical IDs - -Unique IDs serve as the _logical identifiers_ (or __logical names__) of resources in the generated {aws} CloudFormation templates for constructs that represent {aws} resources. - -For example, the Amazon S3 bucket in the previous example that is created within `Stack2` results in an `{aws}::S3::Bucket` resource. The resource's logical ID is `Stack2MyBucket4DD88B4F` in the resulting {aws} CloudFormation template. (For details on how this identifier is generated, see xref:identifiers-unique-ids[Unique IDs].) - -[#identifiers-logical-id-stability] -=== Logical ID stability - -Avoid changing the logical ID of a resource after it has been created. {aws} CloudFormation identifies resources by their logical ID. Therefore, if you change the logical ID of a resource, {aws} CloudFormation creates a new resource with the new logical ID, then deletes the existing one. Depending on the type of resource, this might cause service interruption, data loss, or both. \ No newline at end of file diff --git a/v2/guide/concepts/languages.adoc b/v2/guide/concepts/languages.adoc deleted file mode 100644 index b830a8fc..00000000 --- a/v2/guide/concepts/languages.adoc +++ /dev/null @@ -1,121 +0,0 @@ -include::../attributes.txt[] - -// Attributes -[.topic] -:info_titleabbrev: Programming languages -:keywords: {aws} CDK, TypeScript, JavaScript, Python, Java, C#, Go - -[#languages] -= Supported programming languages for the {aws} CDK - -[abstract] --- -The {aws} Cloud Development Kit ({aws} CDK) has first-class support for the TypeScript, JavaScript, Python, Java, C#, and [.noloc]``Go`` general-purpose programming languages. --- - -// Content start - -The {aws} Cloud Development Kit ({aws} CDK) has first-class support for the following general-purpose programming languages: - -* TypeScript -* JavaScript -* Python -* Java -* C# -* [.noloc]`Go` - -Other [.noloc]`JVM` and [.noloc]`.NET` [.noloc]`CLR` languages may also be used in theory, but we do not offer official support at this time. - -The {aws} CDK is developed in one language, TypeScript. To support the other languages, the {aws} CDK utilizes a tool called https://github.com/aws/jsii[JSII] to generate language bindings. - -We attempt to offer each language's usual conventions to make development with the {aws} CDK as natural and intuitive as possible. For example, we distribute {aws} Construct Library modules using your preferred language's standard repository, and you install them using the language's standard package manager. Methods and properties are also named using your language's recommended naming patterns. - -The following are a few code examples: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const bucket = new s3.Bucket(this, 'amzn-s3-demo-bucket', { - bucketName: 'amzn-s3-demo-bucket', - versioned: true, - websiteRedirect: {hostName: 'aws.amazon.com'}}); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const bucket = new s3.Bucket(this, 'amzn-s3-demo-bucket', { - bucketName: 'amzn-s3-demo-bucket', - versioned: true, - websiteRedirect: {hostName: 'aws.amazon.com'}}); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -bucket = s3.Bucket("amzn-s3-demo-bucket", bucket_name="amzn-s3-demo-bucket", versioned=True, - website_redirect=s3.RedirectTarget(host_name="aws.amazon.com")) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -Bucket bucket = Bucket.Builder.create(self, "amzn-s3-demo-bucket") - .bucketName("amzn-s3-demo-bucket") - .versioned(true) - .websiteRedirect(new RedirectTarget.Builder() - .hostName("aws.amazon.com").build()) - .build(); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -var bucket = new Bucket(this, "amzn-s3-demo-bucket", new BucketProps { - BucketName = "amzn-s3-demo-bucket", - Versioned = true, - WebsiteRedirect = new RedirectTarget { - HostName = "aws.amazon.com" - }}); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -bucket := awss3.NewBucket(scope, jsii.String("amzn-s3-demo-bucket"), &awss3.BucketProps { - BucketName: jsii.String("amzn-s3-demo-bucket"), - Versioned: jsii.Bool(true), - WebsiteRedirect: &awss3.RedirectTarget { - HostName: jsii.String("aws.amazon.com"), - }, -}) ----- -==== - -[NOTE] -==== - -These code snippets are intended for illustration only. They are incomplete and won't run as they are. - -==== - -The {aws} Construct Library is distributed using each language's standard package management tools, including [.noloc]`NPM`, [.noloc]`PyPi`, [.noloc]`Maven`, and [.noloc]`NuGet`. We also provide a version of the https://docs.aws.amazon.com/cdk/api/v2/docs/aws-construct-library.html[{aws} CDK API Reference] for each language. - -To help you use the {aws} CDK in your preferred language, this guide includes the following topics for supported languages: - -* xref:work-with-cdk-typescript[Working with the {aws} CDK in TypeScript] -* xref:work-with-cdk-javascript[Working with the {aws} CDK in JavaScript] -* xref:work-with-cdk-python[Working with the {aws} CDK in Python] -* xref:work-with-cdk-java[Working with the {aws} CDK in Java] -* xref:work-with-cdk-csharp[Working with the {aws} CDK in C#] -* xref:work-with-cdk-go[Working with the {aws} CDK in Go] - -TypeScript was the first language supported by the {aws} CDK, and much of the {aws} CDK example code is written in TypeScript. This guide includes a topic specifically to show how to adapt TypeScript {aws} CDK code for use with the other supported languages. For more information, see xref:work-with-cdk-compare[Comparing {aws} CDK in TypeScript with other languages]. \ No newline at end of file diff --git a/v2/guide/concepts/libraries.adoc b/v2/guide/concepts/libraries.adoc deleted file mode 100644 index 023cf17b..00000000 --- a/v2/guide/concepts/libraries.adoc +++ /dev/null @@ -1,50 +0,0 @@ -include::../attributes.txt[] - -[.topic] -[#libraries] -= The {aws} CDK libraries -:info_titleabbrev: Libraries -:keywords: {aws} CDK, {aws} CDK libraries, constructs, {aws} Construct Library - -[abstract] --- -Learn about the core libraries that you will use with the {aws} Cloud Development Kit ({aws} CDK). --- - -// Content start - -Learn about the core libraries that you will use with the {aws} Cloud Development Kit ({aws} CDK). - -[#libraries-cdk] -== The {aws} CDK Library - -The {aws} CDK Library, also referred to as `aws-cdk-lib`, is the main library that you will use to develop applications with the {aws} CDK. It is developed and maintained by {aws}. This library contains base classes, such as https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.App.html[`App`] and https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html[`Stack`]. It also contains the libraries you will use to define your infrastructure through constructs. - -[#libraries-construct] -== The {aws} Construct Library - -The {aws} Construct Library is a part of the {aws} CDK Library. It contains a collection of xref:constructs[constructs] that are developed and maintained by {aws}. It is organized into various modules for each {aws} service. Each module includes constructs that you can use to define your {aws} resources and properties. - -[#libraries-constructs] -== The Constructs library - -The Constructs library, commonly referred to as `constructs`, is a library for defining and composing cloud infrastructure components. It contains the core https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html[`Construct`] class, which represents the construct building block. This class is the foundational base class of all constructs from the {aws} Construct Library. The Constructs library is a separate general-purpose library that is used by other construct-based tools such as _CDK for Terraform_ and _CDK for Kubernetes_. - -[#libraries-reference] -== The {aws} CDK API reference - -The https://docs.aws.amazon.com/cdk/api/v2/docs/aws-construct-library.html[{aws} CDK API reference] contains official reference documentation for the {aws} CDK Library, including the {aws} Construct Library and Constructs library. A version of the API reference is provided for each supported programming language. - -* For {aws} CDK Library (`aws-cdk-lib`) documentation, see https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib-readme.html[aws-cdk-lib module]. -* Documentation for constructs in the {aws} Construct Library are organized by {aws} service in the following format: `aws-cdk-lib.<service>`. For example, construct documentation for Amazon Simple Storage Service (Amazon S3), can be found at https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3-readme.html[aws-cdk-lib.aws_s3 module]. -* For Constructs library (constructs) documentation, see https://docs.aws.amazon.com/cdk/api/v2/docs/constructs-readme.html[constructs module]. - -[#libraries-reference-contribute] -=== Contribute to the {aws} CDK API reference - -The {aws} CDK is open-source and we welcome you to contribute. Community contributions positively impact and improve the {aws} CDK. For instructions on contributing specifically to {aws} CDK API reference documentation, see https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md#documentation[Documentation] in the __aws-cdk [.noloc]`GitHub` repository__. - -[#libraries-learn,libraries-learn.title] -== Learn more - -For instructions on importing and using the CDK Library, see xref:work-with[Work with the CDK library]. \ No newline at end of file diff --git a/v2/guide/concepts/parameters.adoc b/v2/guide/concepts/parameters.adoc deleted file mode 100644 index c006911c..00000000 --- a/v2/guide/concepts/parameters.adoc +++ /dev/null @@ -1,45 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -:info_titleabbrev: Parameters -:keywords: {aws} CDK, {aws} CloudFormation, Parameters - -[#parameters] -= Parameters and the {aws} CDK - -[abstract] --- -_Parameters_ are custom values that are supplied at deployment time. --- - -// Content start -_Parameters_ are custom values that are supplied at deployment time. https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html[Parameters] are a feature of {aws} CloudFormation. Since the {aws} Cloud Development Kit ({aws} CDK) synthesizes {aws} CloudFormation templates, it also offers support for deployment-time parameters. - -[#parameters-about] -== About parameters - -Using the {aws} CDK, you can define parameters, which can then be used in the properties of constructs you create. You can also deploy stacks that contain parameters. - -When deploying the {aws} CloudFormation template using the {aws} CDK CLI, you provide the parameter values on the command line. If you deploy the template through the {aws} CloudFormation console, you are prompted for the parameter values. - -In general, we recommend against using {aws} CloudFormation parameters with the {aws} CDK. The usual ways to pass values into {aws} CDK apps are xref:context[context values] and environment variables. Because they are not available at synthesis time, parameter values cannot be easily used for flow control and other purposes in your CDK app. - -[NOTE] -==== - -To do control flow with parameters, you can use https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.CfnCondition.html[`CfnCondition`] constructs, although this is awkward compared to native `if` statements. - -==== - -Using parameters requires you to be mindful of how the code you're writing behaves at deployment time, and also at synthesis time. This makes it harder to understand and reason about your {aws} CDK application, in many cases for little benefit. - -Generally, it's better to have your CDK app accept necessary information in a well-defined way and use it directly to declare constructs in your CDK app. An ideal {aws} CDK–generated {aws} CloudFormation template is concrete, with no values remaining to be specified at deployment time. - -There are, however, use cases to which {aws} CloudFormation parameters are uniquely suited. If you have separate teams defining and deploying infrastructure, for example, you can use parameters to make the generated templates more widely useful. Also, because the {aws} CDK supports {aws} CloudFormation parameters, you can use the {aws} CDK with {aws} services that use {aws} CloudFormation templates (such as Service Catalog). These {aws} services use parameters to configure the template that's being deployed. - -[#parameters-learn] -== Learn more - -For instructions on developing CDK apps with parameters, see xref:get-cfn-param[Use CloudFormation parameters to get a CloudFormation value]. \ No newline at end of file diff --git a/v2/guide/concepts/permissions.adoc b/v2/guide/concepts/permissions.adoc deleted file mode 100644 index 239d85a7..00000000 --- a/v2/guide/concepts/permissions.adoc +++ /dev/null @@ -1,555 +0,0 @@ -include::../attributes.txt[] - -// Attributes -[.topic] -:info_titleabbrev: Permissions -:keywords: {aws} CDK, Permissions, IAM - -[#permissions] -= Permissions and the {aws} CDK - -[abstract] --- -The {aws} Construct Library uses a few common, widely implemented idioms to manage access and permissions. The IAM module provides you with the tools you need to use these idioms. --- - -// Content start - -The {aws} Construct Library uses a few common, widely implemented idioms to manage access and permissions. The IAM module provides you with the tools you need to use these idioms. - -{aws} CDK uses {aws} CloudFormation to deploy changes. Every deployment involves an actor (either a developer, or an automated system) that starts a {aws} CloudFormation deployment. In the course of doing this, the actor will assume one or more IAM Identities (user or roles) and optionally pass a role to {aws} CloudFormation. - -If you use {aws} IAM Identity Center to authenticate as a user, then the single sign-on provider supplies short-lived session credentials that authorize you to act as a pre-defined IAM role. To learn how the {aws} CDK obtains {aws} credentials from IAM Identity Center authentication, see https://docs.aws.amazon.com/sdkref/latest/guide/understanding-sso.html[Understand IAM Identity Center authentication] in the _{aws} SDKs and Tools Reference Guide_. - -[#permissions-principals] -== Principals - -An IAM principal is an authenticated {aws} entity representing a user, service, or application that can call {aws} APIs. The {aws} Construct Library supports specifying principals in several flexible ways to grant them access your {aws} resources. - -In security contexts, the term "principal" refers specifically to authenticated entities such as users. Objects like groups and roles do not _represent_ users (and other authenticated entities) but rather _identify_ them indirectly for the purpose of granting permissions. - -For example, if you create an IAM group, you can grant the group (and thus its members) write access to an Amazon RDS table. However, the group itself is not a principal because it doesn't represent a single entity (also, you cannot log in to a group). - -In the CDK's IAM library, classes that directly or indirectly identify principals implement the https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.IPrincipal.html[`IPrincipal`] interface, allowing these objects to be used interchangeably in access policies. However, not all of them are principals in the security sense. These objects include: - -. IAM resources such as https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html[`Role`], https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.User.html[`User`], and https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Group.html[`Group`] -. Service principals (`new iam.link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.ServicePrincipal.html[ServicePrincipal]('service.amazonaws.com')`) -. Federated principals (`new iam.link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.FederatedPrincipal.html[FederatedPrincipal]('cognito-identity.amazonaws.com')`) -. Account principals (`new iam.link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.AccountPrincipal.html[AccountPrincipal]('0123456789012')`) -. Canonical user principals (`new iam.link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.CanonicalUserPrincipal.html[CanonicalUserPrincipal]('79a59d[...]7ef2be')`) -. {aws} Organizations principals (`new iam.link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.OrganizationPrincipal.html[OrganizationPrincipal]('org-id')`) -. Arbitrary ARN principals (`new iam.link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.ArnPrincipal.html[ArnPrincipal](res.arn)`) -. An `iam.link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.CompositePrincipal.html[CompositePrincipal](principal1, principal2, ...)` to trust multiple principals - -[#permissions-grants] -== Grants - -Every construct that represents a resource that can be accessed, such as an Amazon S3 bucket or Amazon DynamoDB table, has methods that grant access to another entity. All such methods have names starting with *grant*. - -For example, Amazon S3 buckets have the methods link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html#grantwbrreadidentity-objectskeypattern[`grantRead`] and link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html#grantwbrreadwbrwriteidentity-objectskeypattern[`grantReadWrite`] (Python: `grant_read`, `grant_read_write`) to enable read and read/write access, respectively, from an entity to the bucket. The entity doesn't have to know exactly which Amazon S3 IAM permissions are required to perform these operations. - -The first argument of a *grant* method is always of type link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.IGrantable.html[`IGrantable`]. This interface represents entities that can be granted permissions. That is, it represents resources with roles, such as the IAM objects link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html[`Role`], link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.User.html[`User`], and link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Group.html[`Group`]. - -Other entities can also be granted permissions. For example, later in this topic, we show how to grant a CodeBuild project access to an Amazon S3 bucket. Generally, the associated role is obtained via a `role` property on the entity being granted access. - -Resources that use execution roles, such as link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.Function.html[`lambda.Function`], also implement `IGrantable`, so you can grant them access directly instead of granting access to their role. For example, if `bucket` is an Amazon S3 bucket, and `function` is a Lambda function, the following code grants the function read access to the bucket. - -==== -[role="tablist"] -TypeScript:: -+ -[source,none,subs="verbatim,attributes"] ----- -bucket.grantRead(function); ----- - -JavaScript:: -+ -[source,none,subs="verbatim,attributes"] ----- -bucket.grantRead(function); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -bucket.grant_read(function) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -bucket.grantRead(function); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -bucket.GrantRead(function); ----- -==== - -Sometimes permissions must be applied while your stack is being deployed. One such case is when you grant an {aws} CloudFormation custom resource access to some other resource. The custom resource will be invoked during deployment, so it must have the specified permissions at deployment time. - -Another case is when a service verifies that the role you pass to it has the right policies applied. (A number of {aws} services do this to make sure that you didn't forget to set the policies.) In those cases, the deployment might fail if the permissions are applied too late. - -To force the grant's permissions to be applied before another resource is created, you can add a dependency on the grant itself, as shown here. Though the return value of grant methods is commonly discarded, every grant method in fact returns an `iam.Grant` object. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const grant = bucket.grantRead(lambda); -const custom = new CustomResource(...); -custom.node.addDependency(grant); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const grant = bucket.grantRead(lambda); -const custom = new CustomResource(...); -custom.node.addDependency(grant); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -grant = bucket.grant_read(function) -custom = CustomResource(...) -custom.node.add_dependency(grant) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -Grant grant = bucket.grantRead(function); -CustomResource custom = new CustomResource(...); -custom.node.addDependency(grant); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -var grant = bucket.GrantRead(function); -var custom = new CustomResource(...); -custom.node.AddDependency(grant); ----- -==== - -[#permissions-roles] -== Roles - -The IAM package contains a link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html[`Role`] construct that represents IAM roles. The following code creates a new role, trusting the Amazon EC2 service. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -import * as iam from 'aws-cdk-lib/aws-iam'; - -const role = new iam.Role(this, 'Role', { - assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com'), // required -}); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const iam = require('aws-cdk-lib/aws-iam'); - -const role = new iam.Role(this, 'Role', { - assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com') // required -}); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -import aws_cdk.aws_iam as iam - -role = iam.Role(self, "Role", - assumed_by=iam.ServicePrincipal("ec2.amazonaws.com")) # required ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -import software.amazon.awscdk.services.iam.Role; -import software.amazon.awscdk.services.iam.ServicePrincipal; - -Role role = Role.Builder.create(this, "Role") - .assumedBy(new ServicePrincipal("ec2.amazonaws.com")).build(); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -using Amazon.CDK.{aws}.IAM; - -var role = new Role(this, "Role", new RoleProps -{ - AssumedBy = new ServicePrincipal("ec2.amazonaws.com"), // required -}); ----- -==== - -You can add permissions to a role by calling the role's link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html#addwbrtowbrpolicystatement[`addToPolicy`] method (Python: `add_to_policy`), passing in a link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.PolicyStatement.html[`PolicyStatement`] that defines the rule to be added. The statement is added to the role's default policy; if it has none, one is created. - -The following example adds a `Deny` policy statement to the role for the actions `ec2:SomeAction` and `s3:AnotherAction` on the resources `bucket` and `otherRole` (Python: `other_role`), under the condition that the authorized service is {aws} CodeBuild. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -role.addToPolicy(new iam.PolicyStatement({ - effect: iam.Effect.DENY, - resources: [bucket.bucketArn, otherRole.roleArn], - actions: ['ec2:SomeAction', 's3:AnotherAction'], - conditions: {StringEquals: { - 'ec2:AuthorizedService': 'codebuild.amazonaws.com', -}}})); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -role.addToPolicy(new iam.PolicyStatement({ - effect: iam.Effect.DENY, - resources: [bucket.bucketArn, otherRole.roleArn], - actions: ['ec2:SomeAction', 's3:AnotherAction'], - conditions: {StringEquals: { - 'ec2:AuthorizedService': 'codebuild.amazonaws.com' -}}})); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -role.add_to_policy(iam.PolicyStatement( - effect=iam.Effect.DENY, - resources=[bucket.bucket_arn, other_role.role_arn], - actions=["ec2:SomeAction", "s3:AnotherAction"], - conditions={"StringEquals": { - "ec2:AuthorizedService": "codebuild.amazonaws.com"}} -)) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -role.addToPolicy(PolicyStatement.Builder.create() - .effect(Effect.DENY) - .resources(Arrays.asList(bucket.getBucketArn(), otherRole.getRoleArn())) - .actions(Arrays.asList("ec2:SomeAction", "s3:AnotherAction")) - .conditions(java.util.Map.of( // Map.of requires Java 9 or later - "StringEquals", java.util.Map.of( - "ec2:AuthorizedService", "codebuild.amazonaws.com"))) - .build()); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -role.AddToPolicy(new PolicyStatement(new PolicyStatementProps -{ - Effect = Effect.DENY, - Resources = new string[] { bucket.BucketArn, otherRole.RoleArn }, - Actions = new string[] { "ec2:SomeAction", "s3:AnotherAction" }, - Conditions = new Dictionary<string, object> - { - ["StringEquals"] = new Dictionary<string, string> - { - ["ec2:AuthorizedService"] = "codebuild.amazonaws.com" - } - } -})); ----- -==== - -In the preceding example, we've created a new link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.PolicyStatement.html[`PolicyStatement`] inline with the link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html#addwbrtowbrpolicystatement[`addToPolicy`] (Python: `add_to_policy`) call. You can also pass in an existing policy statement or one you've modified. The link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.PolicyStatement.html[`PolicyStatement`] object has link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.PolicyStatement.html#methods[numerous methods] for adding principals, resources, conditions, and actions. - -If you're using a construct that requires a role to function correctly, you can do one of the following: - -* Pass in an existing role when instantiating the construct object. -* Let the construct create a new role for you, trusting the appropriate service principal. The following example uses such a construct: a CodeBuild project. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -import * as codebuild from 'aws-cdk-lib/aws-codebuild'; - -// imagine roleOrUndefined is a function that might return a Role object -// under some conditions, and undefined under other conditions -const someRole: iam.IRole | undefined = roleOrUndefined(); - -const project = new codebuild.Project(this, 'Project', { - // if someRole is undefined, the Project creates a new default role, - // trusting the codebuild.amazonaws.com service principal - role: someRole, -}); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const codebuild = require('aws-cdk-lib/aws-codebuild'); - -// imagine roleOrUndefined is a function that might return a Role object -// under some conditions, and undefined under other conditions -const someRole = roleOrUndefined(); - -const project = new codebuild.Project(this, 'Project', { - // if someRole is undefined, the Project creates a new default role, - // trusting the codebuild.amazonaws.com service principal - role: someRole -}); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -import aws_cdk.aws_codebuild as codebuild - -# imagine role_or_none is a function that might return a Role object -# under some conditions, and None under other conditions -some_role = role_or_none(); - -project = codebuild.Project(self, "Project", -# if role is None, the Project creates a new default role, -# trusting the codebuild.amazonaws.com service principal -role=some_role) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -import software.amazon.awscdk.services.iam.Role; -import software.amazon.awscdk.services.codebuild.Project; - -// imagine roleOrNull is a function that might return a Role object -// under some conditions, and null under other conditions -Role someRole = roleOrNull(); - -// if someRole is null, the Project creates a new default role, -// trusting the codebuild.amazonaws.com service principal -Project project = Project.Builder.create(this, "Project") - .role(someRole).build(); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -using Amazon.CDK.{aws}.CodeBuild; - -// imagine roleOrNull is a function that might return a Role object -// under some conditions, and null under other conditions -var someRole = roleOrNull(); - -// if someRole is null, the Project creates a new default role, -// trusting the codebuild.amazonaws.com service principal -var project = new Project(this, "Project", new ProjectProps -{ - Role = someRole -}); ----- -==== - -Once the object is created, the role (whether the role passed in or the default one created by the construct) is available as the property `role`. However, this property is not available on external resources. Therefore, these constructs have an `addToRolePolicy` (Python: `add_to_role_policy`) method. - -The method does nothing if the construct is an external resource, and it calls the `addToPolicy` (Python: `add_to_policy`) method of the `role` property otherwise. This saves you the trouble of handling the undefined case explicitly. - -The following example demonstrates: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -// project is imported into the CDK application -const project = codebuild.Project.fromProjectName(this, 'Project', 'ProjectName'); - -// project is imported, so project.role is undefined, and this call has no effect -project.addToRolePolicy(new iam.PolicyStatement({ - effect: iam.Effect.ALLOW, // ... and so on defining the policy -})); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -// project is imported into the CDK application -const project = codebuild.Project.fromProjectName(this, 'Project', 'ProjectName'); - -// project is imported, so project.role is undefined, and this call has no effect -project.addToRolePolicy(new iam.PolicyStatement({ - effect: iam.Effect.ALLOW // ... and so on defining the policy -})); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -# project is imported into the CDK application -project = codebuild.Project.from_project_name(self, 'Project', 'ProjectName') - -# project is imported, so project.role is undefined, and this call has no effect -project.add_to_role_policy(iam.PolicyStatement( - effect=iam.Effect.ALLOW, # ... and so on defining the policy - ) -) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -// project is imported into the CDK application -Project project = Project.fromProjectName(this, "Project", "ProjectName"); - -// project is imported, so project.getRole() is null, and this call has no effect -project.addToRolePolicy(PolicyStatement.Builder.create() - .effect(Effect.ALLOW) // .. and so on defining the policy - .build(); -) ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -// project is imported into the CDK application -var project = Project.FromProjectName(this, "Project", "ProjectName"); - -// project is imported, so project.role is null, and this call has no effect -project.AddToRolePolicy(new PolicyStatement(new PolicyStatementProps -{ - Effect = Effect.ALLOW, // ... and so on defining the policy -})); ----- -==== - -[#permissions-resource-policies] -== Resource policies - -A few resources in {aws}, such as Amazon S3 buckets and IAM roles, also have a resource policy. These constructs have an `addToResourcePolicy` method (Python: `add_to_resource_policy`), which takes a link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.PolicyStatement.html[`PolicyStatement`] as its argument. Every policy statement added to a resource policy must specify at least one principal. - -In the following example, the link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html[Amazon S3 bucket] `bucket` grants a role with the `s3:SomeAction` permission to itself. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -bucket.addToResourcePolicy(new iam.PolicyStatement({ - effect: iam.Effect.ALLOW, - actions: ['s3:SomeAction'], - resources: [bucket.bucketArn], - principals: [role] -})); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -bucket.addToResourcePolicy(new iam.PolicyStatement({ - effect: iam.Effect.ALLOW, - actions: ['s3:SomeAction'], - resources: [bucket.bucketArn], - principals: [role] -})); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -bucket.add_to_resource_policy(iam.PolicyStatement( - effect=iam.Effect.ALLOW, - actions=["s3:SomeAction"], - resources=[bucket.bucket_arn], - principals=role)) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -bucket.addToResourcePolicy(PolicyStatement.Builder.create() - .effect(Effect.ALLOW) - .actions(Arrays.asList("s3:SomeAction")) - .resources(Arrays.asList(bucket.getBucketArn())) - .principals(Arrays.asList(role)) - .build()); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -bucket.AddToResourcePolicy(new PolicyStatement(new PolicyStatementProps -{ - Effect = Effect.ALLOW, - Actions = new string[] { "s3:SomeAction" }, - Resources = new string[] { bucket.BucketArn }, - Principals = new IPrincipal[] { role } -})); ----- -==== - -[#permissions-existing] -== Using external IAM objects - -If you have defined an IAM user, principal, group, or role outside your {aws} CDK app, you can use that IAM object in your {aws} CDK app. To do so, create a reference to it using its ARN or its name. (Use the name for users, groups, and roles.) The returned reference can then be used to grant permissions or to construct policy statements as explained previously. - -* For users, call link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.User.html#static-fromwbruserwbrarnscope-id-userarn[`User.fromUserArn()`] or link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.User.html#static-fromwbruserwbrnamescope-id-username[`User.fromUserName()`]. `User.fromUserAttributes()` is also available, but currently provides the same functionality as `User.fromUserArn()`. -* For principals, instantiate an link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.ArnPrincipal.html[`ArnPrincipal`] object. -* For groups, call link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Group.html#static-fromwbrgroupwbrarnscope-id-grouparn[`Group.fromGroupArn()`] or link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Group.html#static-fromwbrgroupwbrnamescope-id-groupname[`Group.fromGroupName()`]. -* For roles, call link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html#static-fromwbrrolewbrarnscope-id-rolearn-options[`Role.fromRoleArn()`] or link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html#static-fromwbrrolewbrnamescope-id-rolename[`Role.fromRoleName()`]. - -Policies (including managed policies) can be used in similar fashion using the following methods. You can use references to these objects anywhere an IAM policy is required. - -* link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Policy.html#static-fromwbrpolicywbrnamescope-id-policyname[`Policy.fromPolicyName`] -* link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.ManagedPolicy.html#static-fromwbrmanagedwbrpolicywbrarnscope-id-managedpolicyarn[`ManagedPolicy.fromManagedPolicyArn`] -* link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.ManagedPolicy.html#static-fromwbrmanagedwbrpolicywbrnamescope-id-managedpolicyname[`ManagedPolicy.fromManagedPolicyName`] -* link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.ManagedPolicy.html#static-fromwbrawswbrmanagedwbrpolicywbrnamemanagedpolicyname[`ManagedPolicy.fromAwsManagedPolicyName`] - -[NOTE] -==== - -As with all references to external {aws} resources, you cannot modify external IAM objects in your CDK app. - -==== \ No newline at end of file diff --git a/v2/guide/concepts/projects.adoc b/v2/guide/concepts/projects.adoc deleted file mode 100644 index ca96ee4d..00000000 --- a/v2/guide/concepts/projects.adoc +++ /dev/null @@ -1,554 +0,0 @@ -include::../attributes.txt[] - -// Attributes -[.topic] -:info_titleabbrev: Projects -:keywords: {aws} CDK, {aws} CloudFormation, IaC, Infrastructure as code, CDK projects, {aws} CDK concepts - -[[projects,projects.title]] -= {aws} CDK projects - -[abstract] --- -An {aws} Cloud Development Kit ({aws} CDK) project represents the files and folders that contain your CDK code. Contents will vary based on your programming language. --- - -// Content start - -An {aws} Cloud Development Kit ({aws} CDK) project represents the files and folders that contain your CDK code. Contents will vary based on your programming language. - -You can create your {aws} CDK project manually or with the {aws} CDK Command Line Interface ({aws} CDK CLI) `cdk init` command. In this topic, we will refer to the project structure and naming conventions of files and folders created by the {aws} CDK CLI. You can customize and organize your CDK projects to fit your needs. - -[NOTE] -==== - -Project structure created by the {aws} CDK CLI may vary across versions over time. - -==== - -[#projects-universal] -== Universal files and folders - -[[projects-universal-git]] -`.git`:: If you have `git` installed, the {aws} CDK CLI automatically initializes a [.noloc]`Git` repository for your project. The `.git` directory contains information about the repository. - -[[projects-universal-gitignore]] -`.gitignore`:: Text file used by [.noloc]``Git`` to specify files and folders to ignore. - -[[projects-universal-readme]] -`README.md`:: Text file that provides you with basic guidance and important information for managing your {aws} CDK project. Modify this file as necessary to document important information regarding your CDK project. - -[[projects-universal-cdk]] -`cdk.json`:: Configuration file for the {aws} CDK. This file provides instruction to the {aws} CDK CLI regarding how to run your app. - -[#projects-specific] -== Language-specific files and folders - -The following files and folders are unique to each supported programming language. - -==== -[role="tablist"] -TypeScript:: -The following is an example project created in the `my-cdk-ts-project` directory using the `cdk init --language typescript` command: -+ -[source,none,subs="verbatim,attributes"] ----- -my-cdk-ts-project -├── .git -├── .gitignore -├── .npmignore -├── README.md -├── bin -│ └── my-cdk-ts-project.ts -├── cdk.json -├── jest.config.js -├── lib -│ └── my-cdk-ts-project-stack.ts -├── node_modules -├── package-lock.json -├── package.json -├── test -│ └── my-cdk-ts-project.test.ts -└── tsconfig.json ----- - -`.npmignore`::: File that specifies which files and folders to ignore when publishing a package to the `npm` registry. This file is similar to `.gitignore`, but is specific to `npm` packages. - -`bin/my-cdk-ts-project.ts`::: The _application file_ defines your CDK app. CDK projects can contain one or more application files. Application files are stored in the `bin` folder. -+ -The following is an example of a basic application file that defines a CDK app: -+ -[source,javascript,subs="verbatim,attributes"] ----- -#!/usr/bin/env node -import 'source-map-support/register'; -import * as cdk from 'aws-cdk-lib'; -import { MyCdkTsProjectStack } from '../lib/my-cdk-ts-project-stack'; - -const app = new cdk.App(); -new MyCdkTsProjectStack(app, 'MyCdkTsProjectStack'); ----- - -`jest.config.js`::: Configuration file for [.noloc]`Jest`. [.noloc]_Jest_ is a popular JavaScript testing framework. - -`lib/my-cdk-ts-project-stack.ts`::: The _stack file_ defines your CDK stack. Within your stack, you define {aws} resources and properties using constructs. -+ -The following is an example of a basic stack file that defines a CDK stack: -+ -[source,javascript,subs="verbatim,attributes"] ----- -import * as cdk from 'aws-cdk-lib'; -import { Construct } from 'constructs'; - -export class MyCdkTsProjectStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - // code that defines your resources and properties go here - } -} ----- - -`node_modules`::: Common folder in [.noloc]`Node.js` projects that contain dependencies for your project. - -`package-lock.json`::: Metadata file that works with the `package.json` file to manage versions of dependencies. - -`package.json`::: Metadata file that is commonly used in [.noloc]`Node.js` projects. This file contains information about your CDK project such as the project name, script definitions, dependencies, and other import project-level information. - -`test/my-cdk-ts-project.test.ts`::: A test folder is created to organize tests for your CDK project. A sample test file is also created. -+ -You can write tests in TypeScript and use [.noloc]`Jest` to compile your TypeScript code before running tests. - -`tsconfig.json`::: Configuration file used in TypeScript projects that specifies compiler options and project settings. - -JavaScript:: -The following is an example project created in the `my-cdk-js-project` directory using the `cdk init --language javascript` command: -+ -[source,none,subs="verbatim,attributes"] ----- -my-cdk-js-project -├── .git -├── .gitignore -├── .npmignore -├── README.md -├── bin -│ └── my-cdk-js-project.js -├── cdk.json -├── jest.config.js -├── lib -│ └── my-cdk-js-project-stack.js -├── node_modules -├── package-lock.json -├── package.json -└── test - └── my-cdk-js-project.test.js ----- - -`.npmignore`::: File that specifies which files and folders to ignore when publishing a package to the `npm` registry. This file is similar to `.gitignore`, but is specific to `npm` packages. - -`bin/my-cdk-js-project.js`::: The _application file_ defines your CDK app. CDK projects can contain one or more application files. Application files are stored in the `bin` folder. -+ -The following is an example of a basic application file that defines a CDK app: -+ -[source,javascript,subs="verbatim,attributes"] ----- -#!/usr/bin/env node - -const cdk = require('aws-cdk-lib'); -const { MyCdkJsProjectStack } = require('../lib/my-cdk-js-project-stack'); - -const app = new cdk.App(); -new MyCdkJsProjectStack(app, 'MyCdkJsProjectStack'); ----- - -`jest.config.js`::: Configuration file for [.noloc]`Jest`. [.noloc]_Jest_ is a popular JavaScript testing framework. - -`lib/my-cdk-js-project-stack.js`::: The _stack file_ defines your CDK stack. Within your stack, you define {aws} resources and properties using constructs. -+ -The following is an example of a basic stack file that defines a CDK stack: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const { Stack, Duration } = require('aws-cdk-lib'); - -class MyCdkJsProjectStack extends Stack { - constructor(scope, id, props) { - super(scope, id, props); - - // code that defines your resources and properties go here - } -} - -module.exports = { MyCdkJsProjectStack } ----- - -`node_modules`::: Common folder in [.noloc]`Node.js` projects that contain dependencies for your project. - -`package-lock.json`::: Metadata file that works with the `package.json` file to manage versions of dependencies. - -`package.json`::: Metadata file that is commonly used in [.noloc]`Node.js` projects. This file contains information about your CDK project such as the project name, script definitions, dependencies, and other import project-level information. - -`test/my-cdk-js-project.test.js`::: A test folder is created to organize tests for your CDK project. A sample test file is also created. -+ -You can write tests in JavaScript and use [.noloc]`Jest` to compile your JavaScript code before running tests. - -Python:: The following is an example project created in the `my-cdk-py-project` directory using the `cdk init --language python` command: -+ -[source,none,subs="verbatim,attributes"] ----- -my-cdk-py-project -├── .git -├── .gitignore -├── .venv -├── README.md -├── app.py -├── cdk.json -├── my_cdk_py_project -│ ├── __init__.py -│ └── my_cdk_py_project_stack.py -├── requirements-dev.txt -├── requirements.txt -├── source.bat -└── tests - ├── __init__.py - └── unit ----- - -`.venv`::: The CDK CLI automatically creates a virtual environment for your project. The `.venv` directory refers to this virtual environment. - -`app.py`::: The _application file_ defines your CDK app. CDK projects can contain one or more application files. -+ -The following is an example of a basic application file that defines a CDK app: -+ -[source,python,subs="verbatim,attributes"] ----- -#!/usr/bin/env python3 -import os - -import aws_cdk as cdk - -from my_cdk_py_project.my_cdk_py_project_stack import MyCdkPyProjectStack - -app = cdk.App() -MyCdkPyProjectStack(app, "MyCdkPyProjectStack") - -app.synth() ----- - -`my_cdk_py_project`::: -Directory that contains your __stack files__. The CDK CLI creates the following here: -+ --- -* +__init__.py+ – An empty Python package definition file. -* `my_cdk_py_project` – File that defines your CDK stack. You then define {aws} resources and properties within the stack using constructs. --- -+ -The following is an example of a stack file: -+ -[source,python,subs="verbatim,attributes"] ----- -from aws_cdk import Stack - -from constructs import Construct - -class MyCdkPyProjectStack(Stack): - def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: - super().__init__(scope, construct_id, **kwargs) - - # code that defines your resources and properties go here ----- - -`requirements-dev.txt`::: File similar to `requirements.txt`, but used to manage dependencies specifically for development purposes rather than production. - -`requirements.txt`::: Common file used in Python projects to specify and manage project dependencies. - -`source.bat`::: Batch file for [.noloc]`Windows` that is used to set up the Python virtual environment. - -`tests`::: Directory that contains tests for your CDK project. -+ -The following is an example of a unit test: -+ -[source,python,subs="verbatim,attributes"] ----- -import aws_cdk as core -import aws_cdk.assertions as assertions - -from my_cdk_py_project.my_cdk_py_project_stack import MyCdkPyProjectStack - -def test_sqs_queue_created(): - app = core.App() - stack = MyCdkPyProjectStack(app, "my-cdk-py-project") - template = assertions.Template.from_stack(stack) - - template.has_resource_properties("{aws}::SQS::Queue", { - "VisibilityTimeout": 300 - }) ----- - -Java:: -The following is an example project created in the `my-cdk-java-project` directory using the `cdk init --language java` command: -+ -[source,none,subs="verbatim,attributes"] ----- -my-cdk-java-project -├── .git -├── .gitignore -├── README.md -├── cdk.json -├── pom.xml -└── src - ├── main - └── test ----- - -`pom.xml`::: -File that contains configuration information and metadata about your CDK project. This file is a part of [.noloc]`Maven`. - -`src/main`::: -Directory containing your _application_ and _stack_ files. -+ -The following is an example application file: -+ -[source,java,subs="verbatim,attributes"] ----- -package com.myorg; - -import software.amazon.awscdk.App; -import software.amazon.awscdk.Environment; -import software.amazon.awscdk.StackProps; - -import java.util.Arrays; - -public class MyCdkJavaProjectApp { - public static void main(final String[] args) { - App app = new App(); - - new MyCdkJavaProjectStack(app, "MyCdkJavaProjectStack", StackProps.builder() - .build()); - - app.synth(); - } -} ----- -+ -The following is an example stack file: -+ -[source,java,subs="verbatim,attributes"] ----- -package com.myorg; - -import software.constructs.Construct; -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.StackProps; - -public class MyCdkJavaProjectStack extends Stack { - public MyCdkJavaProjectStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public MyCdkJavaProjectStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - // code that defines your resources and properties go here - } -} ----- - -`src/test`::: -Directory containing your test files. The following is an example: -+ -[source,java,subs="verbatim,attributes"] ----- -package com.myorg; - -import software.amazon.awscdk.App; -import software.amazon.awscdk.assertions.Template; -import java.io.IOException; - -import java.util.HashMap; - -import org.junit.jupiter.api.Test; - -public class MyCdkJavaProjectTest { - - @Test - public void testStack() throws IOException { - App app = new App(); - MyCdkJavaProjectStack stack = new MyCdkJavaProjectStack(app, "test"); - - Template template = Template.fromStack(stack); - - template.hasResourceProperties("{aws}::SQS::Queue", new HashMap<String, Number>() {{ - put("VisibilityTimeout", 300); - }}); - } -} ----- - -C#:: -The following is an example project created in the `my-cdk-csharp-project` directory using the `cdk init --language csharp` command: -+ -[source,none,subs="verbatim,attributes"] ----- -my-cdk-csharp-project -├── .git -├── .gitignore -├── README.md -├── cdk.json -└── src - ├── MyCdkCsharpProject - └── MyCdkCsharpProject.sln ----- - -`src/MyCdkCsharpProject`::: -Directory containing your _application_ and _stack_ files. -+ -The following is an example application file: -+ -[source,csharp,subs="verbatim,attributes"] ----- -using Amazon.CDK; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace MyCdkCsharpProject -{ - sealed class Program - { - public static void Main(string[] args) - { - var app = new App(); - new MyCdkCsharpProjectStack(app, "MyCdkCsharpProjectStack", new StackProps{}); - app.Synth(); - } - } -} ----- -+ -The following is an example stack file: -+ -[source,csharp,subs="verbatim,attributes"] ----- -using Amazon.CDK; -using Constructs; - -namespace MyCdkCsharpProject -{ - public class MyCdkCsharpProjectStack : Stack - { - internal MyCdkCsharpProjectStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) - { - // code that defines your resources and properties go here - } - } -} ----- -+ -This directory also contains the following: -+ ---- -* `GlobalSuppressions.cs` – File used to suppress specific compiler warnings or errors across your project. -* `.csproj` – XML-based file used to define project settings, dependencies, and build configurations. ---- - -`src/MyCdkCsharpProject.sln`::: -[.noloc]``Microsoft Visual Studio Solution File`` used to organize and manage related projects. - -[.noloc]``Go``:: -The following is an example project created in the `my-cdk-go-project` directory using the `cdk init --language go` command: -+ -[source,none,subs="verbatim,attributes"] ----- -my-cdk-go-project -├── .git -├── .gitignore -├── README.md -├── cdk.json -├── go.mod -├── my-cdk-go-project.go -└── my-cdk-go-project_test.go ----- - -`go.mod`::: -File that contains module information and is used to manage dependencies and versioning for your [.noloc]`Go` project. - -`my-cdk-go-project.go`::: -File that defines your CDK application and stacks. -+ -The following is an example: -+ -[source,go,subs="verbatim,attributes"] ----- -package main -import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/constructs-go/constructs/v10" - "github.com/aws/jsii-runtime-go" -) - -type MyCdkGoProjectStackProps struct { - awscdk.StackProps -} - -func NewMyCdkGoProjectStack(scope constructs.Construct, id string, props *MyCdkGoProjectStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - stack := awscdk.NewStack(scope, &id, &sprops) - // The code that defines your resources and properties go here - - return stack -} - -func main() { - defer jsii.Close() - app := awscdk.NewApp(nil) - NewMyCdkGoProjectStack(app, "MyCdkGoProjectStack", &MyCdkGoProjectStackProps{ - awscdk.StackProps{ - Env: env(), - }, - }) - app.Synth(nil) -} - -func env() *awscdk.Environment { - - return nil -} ----- - -`my-cdk-go-project_test.go`::: -File that defines a sample test. -+ -The following is an example: -+ -[source,go,subs="verbatim,attributes"] ----- -package main - -import ( - "testing" - - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/aws-cdk-go/awscdk/v2/assertions" - "github.com/aws/jsii-runtime-go" -) - -func TestMyCdkGoProjectStack(t *testing.T) { - - // GIVEN - app := awscdk.NewApp(nil) - - // WHEN - stack := NewMyCdkGoProjectStack(app, "MyStack", nil) - - // THEN - template := assertions.Template_FromStack(stack, nil) - template.HasResourceProperties(jsii.String("{aws}::SQS::Queue"), map[string]interface{}{ - "VisibilityTimeout": 300, - }) -} ----- -==== \ No newline at end of file diff --git a/v2/guide/concepts/resources.adoc b/v2/guide/concepts/resources.adoc deleted file mode 100644 index 85fad348..00000000 --- a/v2/guide/concepts/resources.adoc +++ /dev/null @@ -1,1583 +0,0 @@ -include::../attributes.txt[] - -// Attributes -[.topic] -:info_titleabbrev: Resources -:keywords: {aws} CDK, {aws} Cloud Development Kit ({aws} CDK), {aws} CloudFormation, IaC, Infrastructure as code, {aws}, {aws} resources - -[#resources] -= Resources and the {aws} CDK - -[abstract] --- -_Resources_ are what you configure to use {aws} services in your applications. Resources are a feature of {aws} CloudFormation. By configuring resources and their properties in a CloudFormation template, you can deploy to CloudFormation to provision your resources. With the {aws} Cloud Development Kit ({aws} CDK), you can configure resources through constructs. You then deploy your CDK app, which involves synthesizing a {aws} CloudFormation template and deploying to {aws} CloudFormation to provision your resources. --- - -// Content start - -_Resources_ are what you configure to use {aws} services in your applications. Resources are a feature of {aws} CloudFormation. By configuring resources and their properties in a {aws} CloudFormation template, you can deploy to {aws} CloudFormation to provision your resources. With the {aws} Cloud Development Kit ({aws} CDK), you can configure resources through constructs. You then deploy your CDK app, which involves synthesizing a {aws} CloudFormation template and deploying to {aws} CloudFormation to provision your resources. - -[#resources-configure] -== Configuring resources using constructs - -As described in xref:constructs[{aws} CDK Constructs], the {aws} CDK provides a rich class library of constructs, called _constructs_, that represent all {aws} resources. - -To create an instance of a resource using its corresponding construct, pass in the scope as the first argument, the logical ID of the construct, and a set of configuration properties (props). For example, here's how to create an Amazon SQS queue with {aws} KMS encryption using the https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_sqs.Queue.html[`sqs.Queue`] construct from the {aws} Construct Library. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -import * as sqs from '@aws-cdk/aws-sqs'; - -new sqs.Queue(this, 'MyQueue', { - encryption: sqs.QueueEncryption.KMS_MANAGED -}); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const sqs = require('@aws-cdk/aws-sqs'); - -new sqs.Queue(this, 'MyQueue', { - encryption: sqs.QueueEncryption.KMS_MANAGED -}); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -import aws_cdk.aws_sqs as sqs - -sqs.Queue(self, "MyQueue", encryption=sqs.QueueEncryption.KMS_MANAGED) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -import software.amazon.awscdk.services.sqs.*; - -Queue.Builder.create(this, "MyQueue").encryption( - QueueEncryption.KMS_MANAGED).build(); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -using Amazon.CDK.{aws}.SQS; - -new Queue(this, "MyQueue", new QueueProps -{ - Encryption = QueueEncryption.KMS_MANAGED -}); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/jsii-runtime-go" - sqs "github.com/aws/aws-cdk-go/awscdk/v2/awssqs" -) - -sqs.NewQueue(stack, jsii.String("MyQueue"), &sqs.QueueProps{ - Encryption: sqs.QueueEncryption_KMS_MANAGED, -}) ----- -==== - -Some configuration props are optional, and in many cases have default values. In some cases, all props are optional, and the last argument can be omitted entirely. - -[#resources-attributes] -=== Resource attributes - -Most resources in the {aws} Construct Library expose attributes, which are resolved at deployment time by {aws} CloudFormation. Attributes are exposed in the form of properties on the resource classes with the type name as a prefix. The following example shows how to get the URL of an Amazon SQS queue using the `queueUrl` (Python: `queue_url`) property. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -import * as sqs from '@aws-cdk/aws-sqs'; - -const queue = new sqs.Queue(this, 'MyQueue'); -const url = queue.queueUrl; // => A string representing a deploy-time value ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const sqs = require('@aws-cdk/aws-sqs'); - -const queue = new sqs.Queue(this, 'MyQueue'); -const url = queue.queueUrl; // => A string representing a deploy-time value ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -import aws_cdk.aws_sqs as sqs - -queue = sqs.Queue(self, "MyQueue") -url = queue.queue_url # => A string representing a deploy-time value ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -Queue queue = new Queue(this, "MyQueue"); -String url = queue.getQueueUrl(); // => A string representing a deploy-time value ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -var queue = new Queue(this, "MyQueue"); -var url = queue.QueueUrl; // => A string representing a deploy-time value ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/jsii-runtime-go" - sqs "github.com/aws/aws-cdk-go/awscdk/v2/awssqs" -) - -queue := sqs.NewQueue(stack, jsii.String("MyQueue"), &sqs.QueueProps{}) -url := queue.QueueUrl() // => A string representing a deploy-time value ----- -==== - -See xref:tokens[Tokens and the {aws} CDK] for information about how the {aws} CDK encodes deploy-time attributes as strings. - -[#resources-referencing] -== Referencing resources - -When configuring resources, you will often have to reference properties of another resource. The following are examples: - -* An Amazon Elastic Container Service (Amazon ECS) resource requires a reference to the cluster on which it runs. -* An Amazon CloudFront distribution requires a reference to the Amazon Simple Storage Service (Amazon S3) bucket containing the source code. - -You can reference resources in any of the following ways: - -* By passing a resource defined in your CDK app, either in the same stack or in a different one -* By passing a proxy object referencing a resource defined in your {aws} account, created from a unique identifier of the resource (such as an ARN) - -If the property of a construct represents a construct for another resource, its type is that of the interface type of the construct. For example, the Amazon ECS construct takes a property `cluster` of type `ecs.ICluster`. Another example, is the CloudFront distribution construct that takes a property `sourceBucket` (Python: `source_bucket`) of type `s3.IBucket`. - -You can directly pass any resource object of the proper type defined in the same {aws} CDK app. The following example defines an Amazon ECS cluster and then uses it to define an Amazon ECS service. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const cluster = new ecs.Cluster(this, 'Cluster', { /*...*/ }); - -const service = new ecs.Ec2Service(this, 'Service', { cluster: cluster }); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const cluster = new ecs.Cluster(this, 'Cluster', { /*...*/ }); - -const service = new ecs.Ec2Service(this, 'Service', { cluster: cluster }); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -cluster = ecs.Cluster(self, "Cluster") - -service = ecs.Ec2Service(self, "Service", cluster=cluster) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -Cluster cluster = new Cluster(this, "Cluster"); -Ec2Service service = new Ec2Service(this, "Service", - new Ec2ServiceProps.Builder().cluster(cluster).build()); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -var cluster = new Cluster(this, "Cluster"); -var service = new Ec2Service(this, "Service", new Ec2ServiceProps { Cluster = cluster }); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/jsii-runtime-go" - ecs "github.com/aws/aws-cdk-go/awscdk/v2/awsecs" -) - -cluster := ecs.NewCluster(stack, jsii.String("MyCluster"), &ecs.ClusterProps{}) -service := ecs.NewEc2Service(stack, jsii.String("MyService"), &ecs.Ec2ServiceProps{ - Cluster: cluster, -}) ----- -==== - -[#resource-stack] -=== Referencing resources in a different stack - -You can refer to resources in a different stack as long as they are defined in the same app and are in the same {aws} environment. The following pattern is generally used: - -* Store a reference to the construct as an attribute of the stack that produces the resource. (To get a reference to the current construct's stack, use `Stack.of(this)`.) -* Pass this reference to the constructor of the stack that consumes the resource as a parameter or a property. The consuming stack then passes it as a property to any construct that needs it. - -The following example defines a stack `stack1`. This stack defines an Amazon S3 bucket and stores a reference to the bucket construct as an attribute of the stack. Then the app defines a second stack, `stack2`, which accepts a bucket at instantiation. `stack2` might, for example, define an {aws} Glue Table that uses the bucket for data storage. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const prod = { account: '123456789012', region: 'us-east-1' }; - -const stack1 = new StackThatProvidesABucket(app, 'Stack1', { env: prod }); - -// stack2 will take a property { bucket: IBucket } -const stack2 = new StackThatExpectsABucket(app, 'Stack2', { - bucket: stack1.bucket, - env: prod -}); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const prod = { account: '123456789012', region: 'us-east-1' }; - -const stack1 = new StackThatProvidesABucket(app, 'Stack1', { env: prod }); - -// stack2 will take a property { bucket: IBucket } -const stack2 = new StackThatExpectsABucket(app, 'Stack2', { - bucket: stack1.bucket, - env: prod -}); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -prod = core.Environment(account="123456789012", region="us-east-1") - -stack1 = StackThatProvidesABucket(app, "Stack1", env=prod) - -# stack2 will take a property "bucket" -stack2 = StackThatExpectsABucket(app, "Stack2", bucket=stack1.bucket, env=prod) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -// Helper method to build an environment -static Environment makeEnv(String account, String region) { - return Environment.builder().account(account).region(region) - .build(); -} - -App app = new App(); - -Environment prod = makeEnv("123456789012", "us-east-1"); - -StackThatProvidesABucket stack1 = new StackThatProvidesABucket(app, "Stack1", - StackProps.builder().env(prod).build()); - -// stack2 will take an argument "bucket" -StackThatExpectsABucket stack2 = new StackThatExpectsABucket(app, "Stack,", - StackProps.builder().env(prod).build(), stack1.bucket); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -Amazon.CDK.Environment makeEnv(string account, string region) -{ - return new Amazon.CDK.Environment { Account = account, Region = region }; -} - -var prod = makeEnv(account: "123456789012", region: "us-east-1"); - -var stack1 = new StackThatProvidesABucket(app, "Stack1", new StackProps { Env = prod }); - -// stack2 will take a property "bucket" -var stack2 = new StackThatExpectsABucket(app, "Stack2", new StackProps { Env = prod, - bucket = stack1.Bucket}); ----- -==== - -If the {aws} CDK determines that the resource is in the same environment, but in a different stack, it automatically synthesizes {aws} CloudFormation https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-stack-exports.html[exports] in the producing stack and an https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-importvalue.html[`Fn::ImportValue`] in the consuming stack to transfer that information from one stack to the other. - -[#resources-deadlock] -==== Resolving dependency deadlocks - -Referencing a resource from one stack in a different stack creates a dependency between the two stacks. This makes sure that they're deployed in the right order. After the stacks are deployed, this dependency is concrete. After that, removing the use of the shared resource from the consuming stack can cause an unexpected deployment failure. This happens if there is another dependency between the two stacks that force them to be deployed in the same order. It can also happen without a dependency if the producing stack is simply chosen by the CDK Toolkit to be deployed first. The {aws} CloudFormation export is removed from the producing stack because it's no longer needed, but the exported resource is still being used in the consuming stack because its update is not yet deployed. Therefore, deploying the producer stack fails. - -To break this deadlock, remove the use of the shared resource from the consuming stack. (This removes the automatic export from the producing stack.) Next, manually add the same export to the producing stack using exactly the same logical ID as the automatically generated export. Remove the use of the shared resource in the consuming stack and deploy both stacks. Then, remove the manual export (and the shared resource if it's no longer needed) and deploy both stacks again. The stack's https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html#exportwbrvalueexportedvalue-options[`exportValue()`] method is a convenient way to create the manual export for this purpose. (See the example in the linked method reference.) - -[#resources-external] -=== Referencing resources in your {aws} account - -Suppose you want to use a resource already available in your {aws} account in your {aws} CDK app. This might be a resource that was defined through the console, an {aws} SDK, directly with {aws} CloudFormation, or in a different {aws} CDK application. You can turn the resource's ARN (or another identifying attribute, or group of attributes) into a proxy object. The proxy object serves as a reference to the resource by calling a static factory method on the resource's class. - -When you create such a proxy, the external resource *does not* become a part of your {aws} CDK app. Therefore, changes you make to the proxy in your {aws} CDK app do not affect the deployed resource. The proxy can, however, be passed to any {aws} CDK method that requires a resource of that type. - -The following example shows how to reference a bucket based on an existing bucket with the ARN `arn:aws:s3:::amzn-s3-demo-bucket1`, and an Amazon Virtual Private Cloud based on an existing VPC having a specific ID. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -// Construct a proxy for a bucket by its name (must be same account) -s3.Bucket.fromBucketName(this, 'MyBucket', 'amzn-s3-demo-bucket1'); - -// Construct a proxy for a bucket by its full ARN (can be another account) -s3.Bucket.fromBucketArn(this, 'MyBucket', 'arn:aws:s3:::amzn-s3-demo-bucket1'); - -// Construct a proxy for an existing VPC from its attribute(s) -ec2.Vpc.fromVpcAttributes(this, 'MyVpc', { - vpcId: 'vpc-1234567890abcde', -}); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -// Construct a proxy for a bucket by its name (must be same account) -s3.Bucket.fromBucketName(this, 'MyBucket', 'amzn-s3-demo-bucket1'); - -// Construct a proxy for a bucket by its full ARN (can be another account) -s3.Bucket.fromBucketArn(this, 'MyBucket', 'arn:aws:s3:::amzn-s3-demo-bucket1'); - -// Construct a proxy for an existing VPC from its attribute(s) -ec2.Vpc.fromVpcAttributes(this, 'MyVpc', { - vpcId: 'vpc-1234567890abcde' -}); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -# Construct a proxy for a bucket by its name (must be same account) -s3.Bucket.from_bucket_name(self, "MyBucket", "amzn-s3-demo-bucket1") - -# Construct a proxy for a bucket by its full ARN (can be another account) -s3.Bucket.from_bucket_arn(self, "MyBucket", "arn:aws:s3:::amzn-s3-demo-bucket1") - -# Construct a proxy for an existing VPC from its attribute(s) -ec2.Vpc.from_vpc_attributes(self, "MyVpc", vpc_id="vpc-1234567890abcdef") ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -// Construct a proxy for a bucket by its name (must be same account) -Bucket.fromBucketName(this, "MyBucket", "amzn-s3-demo-bucket1"); - -// Construct a proxy for a bucket by its full ARN (can be another account) -Bucket.fromBucketArn(this, "MyBucket", - "arn:aws:s3:::amzn-s3-demo-bucket1"); - -// Construct a proxy for an existing VPC from its attribute(s) -Vpc.fromVpcAttributes(this, "MyVpc", VpcAttributes.builder() - .vpcId("vpc-1234567890abcdef").build()); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -// Construct a proxy for a bucket by its name (must be same account) -Bucket.FromBucketName(this, "MyBucket", "amzn-s3-demo-bucket1"); - -// Construct a proxy for a bucket by its full ARN (can be another account) -Bucket.FromBucketArn(this, "MyBucket", "arn:aws:s3:::amzn-s3-demo-bucket1"); - -// Construct a proxy for an existing VPC from its attribute(s) -Vpc.FromVpcAttributes(this, "MyVpc", new VpcAttributes -{ - VpcId = "vpc-1234567890abcdef" -}); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -// Define a proxy for a bucket by its name (must be same account) -s3.Bucket_FromBucketName(stack, jsii.String("MyBucket"), jsii.String("amzn-s3-demo-bucket1")) - -// Define a proxy for a bucket by its full ARN (can be another account) -s3.Bucket_FromBucketArn(stack, jsii.String("MyBucket"), jsii.String("arn:aws:s3:::amzn-s3-demo-bucket1")) - -// Define a proxy for an existing VPC from its attributes -ec2.Vpc_FromVpcAttributes(stack, jsii.String("MyVpc"), &ec2.VpcAttributes{ - VpcId: jsii.String("vpc-1234567890abcde"), -}) ----- -==== - -Let's take a closer look at the https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-ec2.Vpc.html#static-fromwbrlookupscope-id-options[`Vpc.fromLookup()`] method. Because the `ec2.Vpc` construct is complex, there are many ways you might want to select the VPC to be used with your CDK app. To address this, the VPC construct has a `fromLookup` static method (Python: `from_lookup`) that lets you look up the desired Amazon VPC by querying your {aws} account at synthesis time. - -To use `Vpc.fromLookup()`, the system that synthesizes the stack must have access to the account that owns the Amazon VPC. This is because the CDK Toolkit queries the account to find the right Amazon VPC at synthesis time. - -Furthermore, `Vpc.fromLookup()` works only in stacks that are defined with an explicit *account* and *region* (see xref:environments[Environments for the {aws} CDK]). If the {aws} CDK tries to look up an Amazon VPC from an xref:stack-api[environment-agnostic stack], the CDK Toolkit doesn't know which environment to query to find the VPC. - -You must provide `Vpc.fromLookup()` attributes sufficient to uniquely identify a VPC in your {aws} account. For example, there can only ever be one default VPC, so it's sufficient to specify the VPC as the default. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -ec2.Vpc.fromLookup(this, 'DefaultVpc', { - isDefault: true -}); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -ec2.Vpc.fromLookup(this, 'DefaultVpc', { - isDefault: true -}); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -ec2.Vpc.from_lookup(self, "DefaultVpc", is_default=True) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -Vpc.fromLookup(this, "DefaultVpc", VpcLookupOptions.builder() - .isDefault(true).build()); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -Vpc.FromLookup(this, id = "DefaultVpc", new VpcLookupOptions { IsDefault = true }); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -ec2.Vpc_FromLookup(this, jsii.String("DefaultVpc"), &ec2.VpcLookupOptions{ - IsDefault: jsii.Bool(true), -}) ----- -==== - -You can also use the `tags` property to query for VPCs by tag. You can add tags to the Amazon VPC at the time of its creation by using {aws} CloudFormation or the {aws} CDK. You can edit tags at any time after creation by using the {aws} Management Console, the {aws} CLI, or an {aws} SDK. In addition to any tags you add yourself, the {aws} CDK automatically adds the following tags to all VPCs it creates. - -* *Name* – The name of the VPC. -* *aws-cdk:subnet-name* – The name of the subnet. -* *aws-cdk:subnet-type* – The type of the subnet: Public, Private, or Isolated. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -ec2.Vpc.fromLookup(this, 'PublicVpc', - {tags: {'aws-cdk:subnet-type': "Public"}}); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -ec2.Vpc.fromLookup(this, 'PublicVpc', - {tags: {'aws-cdk:subnet-type': "Public"}}); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -ec2.Vpc.from_lookup(self, "PublicVpc", - tags={"aws-cdk:subnet-type": "Public"}) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -Vpc.fromLookup(this, "PublicVpc", VpcLookupOptions.builder() - .tags(java.util.Map.of("aws-cdk:subnet-type", "Public")) // Java 9 or later - .build()); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -Vpc.FromLookup(this, id: "PublicVpc", new VpcLookupOptions -{ - Tags = new Dictionary<string, string> { ["aws-cdk:subnet-type"] = "Public" } -}); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -ec2.Vpc_FromLookup(this, jsii.String("DefaultVpc"), &ec2.VpcLookupOptions{ - Tags: &map[string]*string{"aws-cdk:subnet-type": jsii.String("Public")}, -}) ----- -==== - -Results of `Vpc.fromLookup()` are cached in the project's `cdk.context.json` file. (See xref:context[Context values and the {aws} CDK].) Commit this file to version control so that your app will continue to refer to the same Amazon VPC. This works even if you later change the attributes of your VPCs in a way that would result in a different VPC being selected. This is particularly important if you're deploying the stack in an environment that doesn't have access to the {aws} account that defines the VPC, such as xref:cdk-pipeline[CDK Pipelines]. - -Although you can use an external resource anywhere you'd use a similar resource defined in your {aws} CDK app, you cannot modify it. For example, calling `addToResourcePolicy` (Python: `add_to_resource_policy`) on an external `s3.Bucket` does nothing. - -[#resources-physical-names] -== Resource physical names - -The logical names of resources in {aws} CloudFormation are different from the names of resources that are shown in the {aws} Management Console after they're deployed by {aws} CloudFormation. The {aws} CDK calls these final names _physical names_. - -For example, {aws} CloudFormation might create the Amazon S3 bucket with the logical ID `Stack2MyBucket4DD88B4F` and the physical name `stack2MyBucket4dd88b4f-iuv1rbv9z3to`. - -You can specify a physical name when creating constructs that represent resources by using the property `<resourceType>Name`. The following example creates an Amazon S3 bucket with the physical name `amzn-s3-demo-bucket`. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const bucket = new s3.Bucket(this, 'MyBucket', { - bucketName: 'amzn-s3-demo-bucket', -}); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const bucket = new s3.Bucket(this, 'MyBucket', { - bucketName: 'amzn-s3-demo-bucket' -}); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -bucket = s3.Bucket(self, "MyBucket", bucket_name="amzn-s3-demo-bucket") ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -Bucket bucket = Bucket.Builder.create(this, "MyBucket") - .bucketName("amzn-s3-demo-bucket").build(); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -var bucket = new Bucket(this, "MyBucket", new BucketProps { BucketName = "amzn-s3-demo-bucket" }); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -bucket := s3.NewBucket(this, jsii.String("MyBucket"), &s3.BucketProps{ - BucketName: jsii.String("amzn-s3-demo-bucket"), -}) ----- -==== - -Assigning physical names to resources has some disadvantages in {aws} CloudFormation. Most importantly, any changes to deployed resources that require a resource replacement, such as changes to a resource's properties that are immutable after creation, will fail if a resource has a physical name assigned. If you end up in that state, the only solution is to delete the {aws} CloudFormation stack, then deploy the {aws} CDK app again. See the https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-name.html[{aws} CloudFormation documentation] for details. - -In some cases, such as when creating an {aws} CDK app with cross-environment references, physical names are required for the {aws} CDK to function correctly. In those cases, if you don't want to bother with coming up with a physical name yourself, you can let the {aws} CDK name it for you. To do so, use the special value `PhysicalName.GENERATE_IF_NEEDED`, as follows. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const bucket = new s3.Bucket(this, 'MyBucket', { - bucketName: core.PhysicalName.GENERATE_IF_NEEDED, -}); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const bucket = new s3.Bucket(this, 'MyBucket', { - bucketName: core.PhysicalName.GENERATE_IF_NEEDED -}); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -bucket = s3.Bucket(self, "MyBucket", - bucket_name=core.PhysicalName.GENERATE_IF_NEEDED) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -Bucket bucket = Bucket.Builder.create(this, "MyBucket") - .bucketName(PhysicalName.GENERATE_IF_NEEDED).build(); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -var bucket = new Bucket(this, "MyBucket", new BucketProps - { BucketName = PhysicalName.GENERATE_IF_NEEDED }); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -bucket := s3.NewBucket(this, jsii.String("MyBucket"), &s3.BucketProps{ - BucketName: awscdk.PhysicalName_GENERATE_IF_NEEDED(), -}) ----- -==== - -[#resources-identifiers] -== Passing unique resource identifiers - -Whenever possible, you should pass resources by reference, as described in the previous section. However, there are cases where you have no other choice but to refer to a resource by one of its attributes. Example use cases include the following: - -* When you are using low-level {aws} CloudFormation resources. -* When you need to expose resources to the runtime components of an {aws} CDK application, such as when referring to Lambda functions through environment variables. - -These identifiers are available as attributes on the resources, such as the following. - -==== -[role="tablist"] -TypeScript:: -+ -[source,none,subs="verbatim,attributes"] ----- -bucket.bucketName -lambdaFunc.functionArn -securityGroup.groupArn ----- - -JavaScript:: -+ -[source,none,subs="verbatim,attributes"] ----- -bucket.bucketName -lambdaFunc.functionArn -securityGroup.groupArn ----- - -Python:: -+ -[source,none,subs="verbatim,attributes"] ----- -bucket.bucket_name -lambda_func.function_arn -security_group_arn ----- - -Java:: -The Java {aws} CDK binding uses getter methods for attributes. -+ -[source,java,subs="verbatim,attributes"] ----- -bucket.getBucketName() -lambdaFunc.getFunctionArn() -securityGroup.getGroupArn() ----- - -C#:: -+ -[source,none,subs="verbatim,attributes"] ----- -bucket.BucketName -lambdaFunc.FunctionArn -securityGroup.GroupArn ----- - -Go:: -+ -[source,none,subs="verbatim,attributes"] ----- -bucket.BucketName() -fn.FunctionArn() ----- -==== - -The following example shows how to pass a generated bucket name to an {aws} Lambda function. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const bucket = new s3.Bucket(this, 'Bucket'); - -new lambda.Function(this, 'MyLambda', { - // ... - environment: { - BUCKET_NAME: bucket.bucketName, - }, -}); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const bucket = new s3.Bucket(this, 'Bucket'); - -new lambda.Function(this, 'MyLambda', { - // ... - environment: { - BUCKET_NAME: bucket.bucketName - } -}); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -bucket = s3.Bucket(self, "Bucket") - -lambda.Function(self, "MyLambda", environment=dict(BUCKET_NAME=bucket.bucket_name)) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -final Bucket bucket = new Bucket(this, "Bucket"); - -Function.Builder.create(this, "MyLambda") - .environment(java.util.Map.of( // Java 9 or later - "BUCKET_NAME", bucket.getBucketName())) - .build(); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -var bucket = new Bucket(this, "Bucket"); - -new Function(this, "MyLambda", new FunctionProps -{ - Environment = new Dictionary<string, string> - { - ["BUCKET_NAME"] = bucket.BucketName - } -}); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -bucket := s3.NewBucket(this, jsii.String("Bucket"), &s3.BucketProps{}) -lambda.NewFunction(this, jsii.String("MyLambda"), &lambda.FunctionProps{ - Environment: &map[string]*string{"BUCKET_NAME": bucket.BucketName()}, -}) ----- -==== - -[#resources-grants] -== Granting permissions between resources - -Higher-level constructs make least-privilege permissions achievable by offering simple, intent-based APIs to express permission requirements. For example, many L2 constructs offer grant methods that you can use to grant an entity (such as an IAM role or user) permission to work with the resource, without having to manually create IAM permission statements. - -The following example creates the permissions to allow a Lambda function's execution role to read and write objects to a particular Amazon S3 bucket. If the Amazon S3 bucket is encrypted with an {aws} KMS key, this method also grants permissions to the Lambda function's execution role to decrypt with the key. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -if (bucket.grantReadWrite(func).success) { - // ... -} ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -if ( bucket.grantReadWrite(func).success) { - // ... -} ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -if bucket.grant_read_write(func).success: - # ... ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -if (bucket.grantReadWrite(func).getSuccess()) { - // ... -} ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -if (bucket.GrantReadWrite(func).Success) -{ - // ... -} ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -if *bucket.GrantReadWrite(function, nil).Success() { - // ... -} ----- -==== - -The grant methods return an `iam.Grant` object. Use the `success` attribute of the `Grant` object to determine whether the grant was effectively applied (for example, it may not have been applied on xref:resources-referencing[external resources]). You can also use the `assertSuccess` (Python: `assert_success`) method of the `Grant` object to enforce that the grant was successfully applied. - -If a specific grant method isn't available for the particular use case, you can use a generic grant method to define a new grant with a specified list of actions. - -The following example shows how to grant a Lambda function access to the Amazon DynamoDB `CreateBackup` action. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -table.grant(func, 'dynamodb:CreateBackup'); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -table.grant(func, 'dynamodb:CreateBackup'); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -table.grant(func, "dynamodb:CreateBackup") ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -table.grant(func, "dynamodb:CreateBackup"); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -table.Grant(func, "dynamodb:CreateBackup"); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -table := dynamodb.NewTable(this, jsii.String("MyTable"), &dynamodb.TableProps{}) -table.Grant(function, jsii.String("dynamodb:CreateBackup")) ----- -==== - -Many resources, such as Lambda functions, require a role to be assumed when executing code. A configuration property enables you to specify an `iam.IRole`. If no role is specified, the function automatically creates a role specifically for this use. You can then use grant methods on the resources to add statements to the role. - -The grant methods are built using lower-level APIs for handling with IAM policies. Policies are modeled as https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.PolicyDocument.html[PolicyDocument] objects. Add statements directly to roles (or a construct's attached role) using the `addToRolePolicy` method (Python: `add_to_role_policy`), or to a resource's policy (such as a `Bucket` policy) using the `addToResourcePolicy` (Python: `add_to_resource_policy`) method. - -[#resources-metrics] -== Resource metrics and alarms - -Many resources emit CloudWatch metrics that can be used to set up monitoring dashboards and alarms. Higher-level constructs have metric methods that let you access the metrics without looking up the correct name to use. - -The following example shows how to define an alarm when the `ApproximateNumberOfMessagesNotVisible` of an Amazon SQS queue exceeds 100. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -import * as cw from '@aws-cdk/aws-cloudwatch'; -import * as sqs from '@aws-cdk/aws-sqs'; -import { Duration } from '@aws-cdk/core'; - -const queue = new sqs.Queue(this, 'MyQueue'); - -const metric = queue.metricApproximateNumberOfMessagesNotVisible({ - label: 'Messages Visible (Approx)', - period: Duration.minutes(5), - // ... -}); -metric.createAlarm(this, 'TooManyMessagesAlarm', { - comparisonOperator: cw.ComparisonOperator.GREATER_THAN_THRESHOLD, - threshold: 100, - // ... -}); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const cw = require('@aws-cdk/aws-cloudwatch'); -const sqs = require('@aws-cdk/aws-sqs'); -const { Duration } = require('@aws-cdk/core'); - -const queue = new sqs.Queue(this, 'MyQueue'); - -const metric = queue.metricApproximateNumberOfMessagesNotVisible({ - label: 'Messages Visible (Approx)', - period: Duration.minutes(5) - // ... -}); -metric.createAlarm(this, 'TooManyMessagesAlarm', { - comparisonOperator: cw.ComparisonOperator.GREATER_THAN_THRESHOLD, - threshold: 100 - // ... -}); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -import aws_cdk.aws_cloudwatch as cw -import aws_cdk.aws_sqs as sqs -from aws_cdk.core import Duration - -queue = sqs.Queue(self, "MyQueue") -metric = queue.metric_approximate_number_of_messages_not_visible( - label="Messages Visible (Approx)", - period=Duration.minutes(5), - # ... -) -metric.create_alarm(self, "TooManyMessagesAlarm", - comparison_operator=cw.ComparisonOperator.GREATER_THAN_THRESHOLD, - threshold=100, - # ... -) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -import software.amazon.awscdk.core.Duration; -import software.amazon.awscdk.services.sqs.Queue; -import software.amazon.awscdk.services.cloudwatch.Metric; -import software.amazon.awscdk.services.cloudwatch.MetricOptions; -import software.amazon.awscdk.services.cloudwatch.CreateAlarmOptions; -import software.amazon.awscdk.services.cloudwatch.ComparisonOperator; - -Queue queue = new Queue(this, "MyQueue"); - -Metric metric = queue - .metricApproximateNumberOfMessagesNotVisible(MetricOptions.builder() - .label("Messages Visible (Approx)") - .period(Duration.minutes(5)).build()); - -metric.createAlarm(this, "TooManyMessagesAlarm", CreateAlarmOptions.builder() - .comparisonOperator(ComparisonOperator.GREATER_THAN_THRESHOLD) - .threshold(100) - // ... - .build()); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -using cdk = Amazon.CDK; -using cw = Amazon.CDK.{aws}.CloudWatch; -using sqs = Amazon.CDK.{aws}.SQS; - -var queue = new sqs.Queue(this, "MyQueue"); -var metric = queue.MetricApproximateNumberOfMessagesNotVisible(new cw.MetricOptions -{ - Label = "Messages Visible (Approx)", - Period = cdk.Duration.Minutes(5), - // ... -}); -metric.CreateAlarm(this, "TooManyMessagesAlarm", new cw.CreateAlarmOptions -{ - ComparisonOperator = cw.ComparisonOperator.GREATER_THAN_THRESHOLD, - Threshold = 100, - // .. -}); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/jsii-runtime-go" - cw "github.com/aws/aws-cdk-go/awscdk/v2/awscloudwatch" - sqs "github.com/aws/aws-cdk-go/awscdk/v2/awssqs" -) - -queue := sqs.NewQueue(this, jsii.String("MyQueue"), &sqs.QueueProps{}) -metric := queue.MetricApproximateNumberOfMessagesNotVisible(&cw.MetricOptions{ - Label: jsii.String("Messages Visible (Approx)"), - Period: awscdk.Duration_Minutes(jsii.Number(5)), -}) - -metric.CreateAlarm(this, jsii.String("TooManyMessagesAlarm"), &cw.CreateAlarmOptions{ - ComparisonOperator: cw.ComparisonOperator_GREATER_THAN_THRESHOLD, - Threshold: jsii.Number(100), -}) ----- -==== - -If there is no method for a particular metric, you can use the general metric method to specify the metric name manually. - -Metrics can also be added to CloudWatch dashboards. See https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_cloudwatch-readme.html[CloudWatch]. - -[#resources-traffic] -== Network traffic - -In many cases, you must enable permissions on a network for an application to work, such as when the compute infrastructure needs to access the persistence layer. Resources that establish or listen for connections expose methods that enable traffic flows, including setting security group rules or network ACLs. - -https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.IConnectable.html[IConnectable] resources have a `connections` property that is the gateway to network traffic rules configuration. - -You enable data to flow on a given network path by using `allow` methods. The following example enables HTTPS connections to the web and incoming connections from the Amazon EC2 Auto Scaling group `fleet2`. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -import * as asg from '@aws-cdk/aws-autoscaling'; -import * as ec2 from '@aws-cdk/aws-ec2'; - -const fleet1: asg.AutoScalingGroup = asg.AutoScalingGroup(/*...*/); - -// Allow surfing the (secure) web -fleet1.connections.allowTo(new ec2.Peer.anyIpv4(), new ec2.Port({ fromPort: 443, toPort: 443 })); - -const fleet2: asg.AutoScalingGroup = asg.AutoScalingGroup(/*...*/); -fleet1.connections.allowFrom(fleet2, ec2.Port.AllTraffic()); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const asg = require('@aws-cdk/aws-autoscaling'); -const ec2 = require('@aws-cdk/aws-ec2'); - -const fleet1 = asg.AutoScalingGroup(); - -// Allow surfing the (secure) web -fleet1.connections.allowTo(new ec2.Peer.anyIpv4(), new ec2.Port({ fromPort: 443, toPort: 443 })); - -const fleet2 = asg.AutoScalingGroup(); -fleet1.connections.allowFrom(fleet2, ec2.Port.AllTraffic()); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -import aws_cdk.aws_autoscaling as asg -import aws_cdk.aws_ec2 as ec2 - -fleet1 = asg.AutoScalingGroup( ... ) - -# Allow surfing the (secure) web -fleet1.connections.allow_to(ec2.Peer.any_ipv4(), - ec2.Port(PortProps(from_port=443, to_port=443))) - -fleet2 = asg.AutoScalingGroup( ... ) -fleet1.connections.allow_from(fleet2, ec2.Port.all_traffic()) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -import software.amazon.awscdk.services.autoscaling.AutoScalingGroup; -import software.amazon.awscdk.services.ec2.Peer; -import software.amazon.awscdk.services.ec2.Port; - -AutoScalingGroup fleet1 = AutoScalingGroup.Builder.create(this, "MyFleet") - /* ... */.build(); - -// Allow surfing the (secure) Web -fleet1.getConnections().allowTo(Peer.anyIpv4(), - Port.Builder.create().fromPort(443).toPort(443).build()); - -AutoScalingGroup fleet2 = AutoScalingGroup.Builder.create(this, "MyFleet2") - /* ... */.build(); -fleet1.getConnections().allowFrom(fleet2, Port.allTraffic()); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -using cdk = Amazon.CDK; -using asg = Amazon.CDK.AWS.AutoScaling; -using ec2 = Amazon.CDK.AWS.EC2; - -// Allow surfing the (secure) Web -var fleet1 = new asg.AutoScalingGroup(this, "MyFleet", new asg.AutoScalingGroupProps { /* ... */ }); -fleet1.Connections.AllowTo(ec2.Peer.AnyIpv4(), new ec2.Port(new ec2.PortProps - { FromPort = 443, ToPort = 443 })); - -var fleet2 = new asg.AutoScalingGroup(this, "MyFleet2", new asg.AutoScalingGroupProps { /* ... */ }); -fleet1.Connections.AllowFrom(fleet2, ec2.Port.AllTraffic()); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/jsii-runtime-go" - autoscaling "github.com/aws/aws-cdk-go/awscdk/v2/awsautoscaling" - ec2 "github.com/aws/aws-cdk-go/awscdk/v2/awsec2" -) - -fleet1 := autoscaling.NewAutoScalingGroup(this, jsii.String("MyFleet1"), &autoscaling.AutoScalingGroupProps{}) -fleet1.Connections().AllowTo(ec2.Peer_AnyIpv4(),ec2.NewPort(&ec2.PortProps{ FromPort: jsii.Number(443), ToPort: jsii.Number(443) }),jsii.String("secure web")) - -fleet2 := autoscaling.NewAutoScalingGroup(this, jsii.String("MyFleet2"), &autoscaling.AutoScalingGroupProps{}) -fleet1.Connections().AllowFrom(fleet2, ec2.Port_AllTraffic(),jsii.String("all traffic")) ----- -==== - -Certain resources have default ports associated with them. Examples include the listener of a load balancer on the public port, and the ports on which the database engine accepts connections for instances of an Amazon RDS database. In such cases, you can enforce tight network control without having to manually specify the port. To do so, use the `allowDefaultPortFrom` and `allowToDefaultPort` methods (Python: `allow_default_port_from`, `allow_to_default_port`). - -The following example shows how to enable connections from any IPV4 address, and a connection from an Auto Scaling group to access a database. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -listener.connections.allowDefaultPortFromAnyIpv4('Allow public access'); - -fleet.connections.allowToDefaultPort(rdsDatabase, 'Fleet can access database'); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -listener.connections.allowDefaultPortFromAnyIpv4('Allow public access'); - -fleet.connections.allowToDefaultPort(rdsDatabase, 'Fleet can access database'); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -listener.connections.allow_default_port_from_any_ipv4("Allow public access") - -fleet.connections.allow_to_default_port(rds_database, "Fleet can access database") ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -listener.getConnections().allowDefaultPortFromAnyIpv4("Allow public access"); - -fleet.getConnections().AllowToDefaultPort(rdsDatabase, "Fleet can access database"); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -listener.Connections.AllowDefaultPortFromAnyIpv4("Allow public access"); - -fleet.Connections.AllowToDefaultPort(rdsDatabase, "Fleet can access database"); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -listener.Connections().AllowDefaultPortFromAnyIpv4(jsii.String("Allow public Access")) -fleet.Connections().AllowToDefaultPort(rdsDatabase, jsii.String("Fleet can access database")) ----- -==== - - -[#resources-events] -== Event handling - -Some resources can act as event sources. Use the `addEventNotification` method (Python: `add_event_notification`) to register an event target to a particular event type emitted by the resource. In addition to this, `addXxxNotification` methods offer a simple way to register a handler for common event types. - -The following example shows how to trigger a Lambda function when an object is added to an Amazon S3 bucket. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -import * as s3nots from '@aws-cdk/aws-s3-notifications'; - -const handler = new lambda.Function(this, 'Handler', { /*…*/ }); -const bucket = new s3.Bucket(this, 'Bucket'); -bucket.addObjectCreatedNotification(new s3nots.LambdaDestination(handler)); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const s3nots = require('@aws-cdk/aws-s3-notifications'); - -const handler = new lambda.Function(this, 'Handler', { /*…*/ }); -const bucket = new s3.Bucket(this, 'Bucket'); -bucket.addObjectCreatedNotification(new s3nots.LambdaDestination(handler)); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -import aws_cdk.aws_s3_notifications as s3_nots - -handler = lambda_.Function(self, "Handler", ...) -bucket = s3.Bucket(self, "Bucket") -bucket.add_object_created_notification(s3_nots.LambdaDestination(handler)) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -import software.amazon.awscdk.services.s3.Bucket; -import software.amazon.awscdk.services.lambda.Function; -import software.amazon.awscdk.services.s3.notifications.LambdaDestination; - -Function handler = Function.Builder.create(this, "Handler")/* ... */.build(); -Bucket bucket = new Bucket(this, "Bucket"); -bucket.addObjectCreatedNotification(new LambdaDestination(handler)); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -using lambda = Amazon.CDK.{aws}.Lambda; -using s3 = Amazon.CDK.{aws}.S3; -using s3Nots = Amazon.CDK.{aws}.S3.Notifications; - -var handler = new lambda.Function(this, "Handler", new lambda.FunctionProps { .. }); -var bucket = new s3.Bucket(this, "Bucket"); -bucket.AddObjectCreatedNotification(new s3Nots.LambdaDestination(handler)); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/jsii-runtime-go" - s3 "github.com/aws/aws-cdk-go/awscdk/v2/awss3" - s3nots "github.com/aws/aws-cdk-go/awscdk/v2/awss3notifications" -) - -handler := lambda.NewFunction(this, jsii.String("MyFunction"), &lambda.FunctionProps{}) -bucket := s3.NewBucket(this, jsii.String("Bucket"), &s3.BucketProps{}) -bucket.AddObjectCreatedNotification(s3nots.NewLambdaDestination(handler), nil) ----- -==== - -[#resources-removal] -== Removal policies - -Resources that maintain persistent data, such as databases, Amazon S3 buckets, and Amazon ECR registries, have a _removal policy_. The removal policy indicates whether to delete persistent objects when the {aws} CDK stack that contains them is destroyed. The values specifying the removal policy are available through the `RemovalPolicy` enumeration in the {aws} CDK `core` module. - -[NOTE] -==== - -Resources besides those that store data persistently might also have a `removalPolicy` that is used for a different purpose. For example, a Lambda function version uses a `removalPolicy` attribute to determine whether a given version is retained when a new version is deployed. These have different meanings and defaults compared to the removal policy on an Amazon S3 bucket or DynamoDB table. - -==== - -[cols="1,1", options="header"] -|=== -|Value -|Meaning - -|`RemovalPolicy.RETAIN` -|Keep the contents of the resource when destroying the stack (default). The resource is orphaned from the stack and must be deleted manually. If you attempt to re-deploy the stack while the resource still exists, you will receive an error message due to a name conflict. - -|`RemovalPolicy.DESTROY` -|The resource will be destroyed along with the stack. -|=== - -{aws} CloudFormation does not remove Amazon S3 buckets that contain files even if their removal policy is set to `DESTROY`. Attempting to do so is an {aws} CloudFormation error. To have the {aws} CDK delete all files from the bucket before destroying it, set the bucket's `autoDeleteObjects` property to `true`. - -Following is an example of creating an Amazon S3 bucket with `RemovalPolicy` of `DESTROY` and `autoDeleteOjbects` set to `true`. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -import * as cdk from '@aws-cdk/core'; -import * as s3 from '@aws-cdk/aws-s3'; - -export class CdkTestStack extends cdk.Stack { - constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - const bucket = new s3.Bucket(this, 'Bucket', { - removalPolicy: cdk.RemovalPolicy.DESTROY, - autoDeleteObjects: true - }); - } -} ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const cdk = require('@aws-cdk/core'); -const s3 = require('@aws-cdk/aws-s3'); - -class CdkTestStack extends cdk.Stack { - constructor(scope, id, props) { - super(scope, id, props); - - const bucket = new s3.Bucket(this, 'Bucket', { - removalPolicy: cdk.RemovalPolicy.DESTROY, - autoDeleteObjects: true - }); - } -} - -module.exports = { CdkTestStack } ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -import aws_cdk.core as cdk -import aws_cdk.aws_s3 as s3 - -class CdkTestStack(cdk.stack): - def __init__(self, scope: cdk.Construct, id: str, **kwargs): - super().__init__(scope, id, **kwargs) - - bucket = s3.Bucket(self, "Bucket", - removal_policy=cdk.RemovalPolicy.DESTROY, - auto_delete_objects=True) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -software.amazon.awscdk.core.*; -import software.amazon.awscdk.services.s3.*; - -public class CdkTestStack extends Stack { - public CdkTestStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public CdkTestStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - Bucket.Builder.create(this, "Bucket") - .removalPolicy(RemovalPolicy.DESTROY) - .autoDeleteObjects(true).build(); - } -} ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -using Amazon.CDK; -using Amazon.CDK.{aws}.S3; - -public CdkTestStack(Construct scope, string id, IStackProps props) : base(scope, id, props) -{ - new Bucket(this, "Bucket", new BucketProps { - RemovalPolicy = RemovalPolicy.DESTROY, - AutoDeleteObjects = true - }); -} ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/jsii-runtime-go" - s3 "github.com/aws/aws-cdk-go/awscdk/v2/awss3" -) - -s3.NewBucket(this, jsii.String("Bucket"), &s3.BucketProps{ - RemovalPolicy: awscdk.RemovalPolicy_DESTROY, - AutoDeleteObjects: jsii.Bool(true), -}) ----- -==== - -You can also apply a removal policy directly to the underlying {aws} CloudFormation resource via the `applyRemovalPolicy()` method. This method is available on some stateful resources that do not have a `removalPolicy` property in their L2 resource's props. Examples include the following: - -* {aws} CloudFormation stacks -* Amazon Cognito user pools -* Amazon DocumentDB database instances -* Amazon EC2 volumes -* Amazon OpenSearch Service domains -* Amazon FSx file systems -* Amazon SQS queues - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const resource = bucket.node.findChild('Resource') as cdk.CfnResource; -resource.applyRemovalPolicy(cdk.RemovalPolicy.DESTROY); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const resource = bucket.node.findChild('Resource'); -resource.applyRemovalPolicy(cdk.RemovalPolicy.DESTROY); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -resource = bucket.node.find_child('Resource') -resource.apply_removal_policy(cdk.RemovalPolicy.DESTROY); ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -CfnResource resource = (CfnResource)bucket.node.findChild("Resource"); -resource.applyRemovalPolicy(cdk.RemovalPolicy.DESTROY); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- - -var resource = (CfnResource)bucket.node.findChild('Resource'); -resource.ApplyRemovalPolicy(cdk.RemovalPolicy.DESTROY); ----- -==== - -[NOTE] -==== - -The {aws} CDK's `RemovalPolicy` translates to {aws} CloudFormation's `DeletionPolicy`. However, the default in {aws} CDK is to retain the data, which is the opposite of the {aws} CloudFormation default. - -==== \ No newline at end of file diff --git a/v2/guide/concepts/stacks.adoc b/v2/guide/concepts/stacks.adoc deleted file mode 100644 index 3db9730c..00000000 --- a/v2/guide/concepts/stacks.adoc +++ /dev/null @@ -1,875 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -:info_titleabbrev: CDK stacks -:info_abstract: An {aws} CDK stack is a single unit of deployment. It represents a collection of {aws} resources. When you develop \ - CDK applications, you define {aws} resources using CDK constructs and organize them within CDK \ - stacks. When you deploy, the resources within a CDK stack are deployed together as an {aws} CloudFormation stack. -:keywords: {aws} CDK, {aws} CDK concepts, {aws} CDK stacks, stacks, stack, {aws} CloudFormation, {aws} CloudFormation stacks - -[#stacks] -= Introduction to {aws} CDK stacks - -[abstract] --- -An {aws} CDK stack is a single unit of deployment. It represents a collection of {aws} resources. When you develop CDK applications, you define {aws} resources using CDK constructs and organize them within CDK stacks. When you deploy, the resources within a CDK stack are deployed together as an {aws} CloudFormation stack. --- - -// Content start - -An {aws} CDK stack is the smallest single unit of deployment. It represents a collection of {aws} resources that you define using CDK constructs. When you deploy CDK apps, the resources within a CDK stack are deployed together as an {aws} CloudFormation stack. To learn more about {aws} CloudFormation stacks, see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacks.html[Managing {aws} resources as a single unit with {aws} CloudFormation stacks] in the _{aws} CloudFormation User Guide_. - -You define a stack by extending or inheriting from the https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html[`Stack`] construct. The following example is a common pattern for defining a CDK stack on a separate file, known as a _stack file_. Here, we extend or inherit the `Stack` class and define a constructor that accepts `scope`, `id`, and `props`. Then, we invoke the base `Stack` class constructor using `super` with the received `scope`, `id`, and `props`: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -import * as cdk from 'aws-cdk-lib'; -import { Construct } from 'constructs'; - -export class MyCdkStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - // Define your constructs here - - } -} ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const { Stack } = require('aws-cdk-lib'); - -class MyCdkStack extends Stack { - constructor(scope, id, props) { - super(scope, id, props); - - // Define your constructs here - - } -} - -module.exports = { MyCdkStack } ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -from aws_cdk import ( - Stack, -) -from constructs import Construct - -class MyCdkStack(Stack): - - def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: - super().__init__(scope, construct_id, **kwargs) - - # Define your constructs here ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -package com.myorg; - -import software.constructs.Construct; -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.StackProps; - -public class MyCdkStack extends Stack { - public MyCdkStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public MyCdkStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - // Define your constructs here - } -} ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -using Amazon.CDK; -using Constructs; - -namespace MyCdk -{ - public class MyCdkStack : Stack - { - internal MyCdkStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) - { - // Define your constructs here - } - } -} ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -package main - -import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/constructs-go/constructs/v10" - "github.com/aws/jsii-runtime-go" -) - -type CdkDemoAppStackProps struct { - awscdk.StackProps -} - -func NewCdkDemoAppStack(scope constructs.Construct, id string, props *CdkDemoAppStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - stack := awscdk.NewStack(scope, &id, &sprops) - - // The code that defines your stack goes here - - return stack -} - -func main() { - defer jsii.Close() - - app := awscdk.NewApp(nil) - - NewCdkDemoAppStack(app, "CdkDemoAppStack", &CdkDemoAppStackProps{ - awscdk.StackProps{ - Env: env(), - }, - }) - - app.Synth(nil) -} - -//... ----- -==== - -The previous example has only defined a stack. To create the stack, it must be instantiated within the context of your CDK app. A common pattern is to define your CDK app and initialize your stack on a separate file, known as an _application file_. - -The following is an example that creates a CDK stack named `MyCdkStack`. Here, the CDK app is created and `MyCdkStack` is instantiated in the context of the app: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -#!/usr/bin/env node -import 'source-map-support/register'; -import * as cdk from 'aws-cdk-lib'; -import { MyCdkStack } from '../lib/my-cdk-stack'; - -const app = new cdk.App(); -new MyCdkStack(app, 'MyCdkStack', { -}); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -#!/usr/bin/env node - -const cdk = require('aws-cdk-lib'); -const { MyCdkStack } = require('../lib/my-cdk-stack'); - -const app = new cdk.App(); -new MyCdkStack(app, 'MyCdkStack', { -}); ----- - -Python:: -Located in `app.py`: -+ -[source,python,subs="verbatim,attributes"] ----- -#!/usr/bin/env python3 -import os - -import aws_cdk as cdk - -from my_cdk.my_cdk_stack import MyCdkStack - - -app = cdk.App() -MyCdkStack(app, "MyCdkStack",) - -app.synth() ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -package com.myorg; - -import software.amazon.awscdk.App; -import software.amazon.awscdk.Environment; -import software.amazon.awscdk.StackProps; - -import java.util.Arrays; - -public class MyCdkApp { - public static void main(final String[] args) { - App app = new App(); - - new MyCdkStack(app, "MyCdkStack", StackProps.builder() - .build()); - - app.synth(); - } -} ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -using Amazon.CDK; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace MyCdk -{ - sealed class Program - { - public static void Main(string[] args) - { - var app = new App(); - new MyCdkStack(app, "MyCdkStack", new StackProps - {}); - app.Synth(); - } - } -} ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -package main - -import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/constructs-go/constructs/v10" - "github.com/aws/jsii-runtime-go" -) - -// ... - -func main() { - defer jsii.Close() - - app := awscdk.NewApp(nil) - - NewMyCdkStack(app, "MyCdkStack", &MyCdkStackProps{ - awscdk.StackProps{ - Env: env(), - }, - }) - - app.Synth(nil) -} - -// ... ----- -==== - -The following example creates a CDK app that contains two stacks: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const app = new App(); - -new MyFirstStack(app, 'stack1'); -new MySecondStack(app, 'stack2'); - -app.synth(); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const app = new App(); - -new MyFirstStack(app, 'stack1'); -new MySecondStack(app, 'stack2'); - -app.synth(); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -app = App() - -MyFirstStack(app, 'stack1') -MySecondStack(app, 'stack2') - -app.synth() ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -App app = new App(); - -new MyFirstStack(app, "stack1"); -new MySecondStack(app, "stack2"); - -app.synth(); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -var app = new App(); - -new MyFirstStack(app, "stack1"); -new MySecondStack(app, "stack2"); - -app.Synth(); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -package main - -import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/constructs-go/constructs/v10" - "github.com/aws/jsii-runtime-go" -) - -type MyFirstStackProps struct { - awscdk.StackProps -} - -func NewMyFirstStack(scope constructs.Construct, id string, props *MyFirstStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - myFirstStack := awscdk.NewStack(scope, &id, &sprops) - - // The code that defines your stack goes here - - return myFirstStack -} - -type MySecondStackProps struct { - awscdk.StackProps -} - -func NewMySecondStack(scope constructs.Construct, id string, props *MySecondStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - mySecondStack := awscdk.NewStack(scope, &id, &sprops) - - // The code that defines your stack goes here - - return mySecondStack -} - -func main() { - defer jsii.Close() - - app := awscdk.NewApp(nil) - - NewMyFirstStack(app, "MyFirstStack", &MyFirstStackProps{ - awscdk.StackProps{ - Env: env(), - }, - }) - - NewMySecondStack(app, "MySecondStack", &MySecondStackProps{ - awscdk.StackProps{ - Env: env(), - }, - }) - - app.Synth(nil) -} - -// ... ----- -==== - -[#stack-api] -== About the stack API - -The https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html[`Stack`] object provides a rich API, including the following: - -* `Stack.of(construct)` – A static method that returns the *Stack* in which a construct is defined. This is useful if you need to interact with a stack from within a reusable construct. The call fails if a stack cannot be found in scope. -* `stack.stackName` (Python: `stack_name`) – Returns the physical name of the stack. As mentioned previously, all {aws} CDK stacks have a physical name that the {aws} CDK can resolve during synthesis. -* `stack.region` and `stack.account` – Return the {aws} Region and account, respectively, into which this stack will be deployed. These properties return one of the following: -** The account or Region explicitly specified when the stack was defined -** A string-encoded token that resolves to the {aws} CloudFormation pseudo parameters for account and Region to indicate that this stack is environment agnostic -+ - -For information about how environments are determined for stacks, see xref:environments[Environments for the {aws} CDK]. -+ - -* `stack.addDependency(stack)` (Python: `stack.add_dependency(stack)`) – Can be used to explicitly define dependency order between two stacks. This order is respected by the `cdk deploy` command when deploying multiple stacks at once. -* `stack.tags` – Returns a https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.TagManager.html[TagManager] that you can use to add or remove stack-level tags. This tag manager tags all resources within the stack, and also tags the stack itself when it's created through {aws} CloudFormation. -* `stack.partition`, `stack.urlSuffix` (Python: `url_suffix`), `stack.stackId` (Python: `stack_id`), and `stack.notificationArn` (Python: `notification_arn`) – Return tokens that resolve to the respective {aws} CloudFormation pseudo parameters, such as `{ "Ref": "{aws}::Partition" }`. These tokens are associated with the specific stack object so that the {aws} CDK framework can identify cross-stack references. -* `stack.availabilityZones` (Python: `availability_zones`) – Returns the set of Availability Zones available in the environment in which this stack is deployed. For environment-agnostic stacks, this always returns an array with two Availability Zones. For environment-specific stacks, the {aws} CDK queries the environment and returns the exact set of Availability Zones available in the Region that you specified. -* `stack.parseArn(arn)` and `stack.formatArn(comps)` (Python: `parse_arn`, `format_arn`) – Can be used to work with Amazon Resource Names (ARNs). -* `stack.toJsonString(obj)` (Python: `to_json_string`) – Can be used to format an arbitrary object as a JSON string that can be embedded in an {aws} CloudFormation template. The object can include tokens, attributes, and references, which are only resolved during deployment. -* `stack.templateOptions` (Python: `template_options`) – Use to specify {aws} CloudFormation template options, such as Transform, Description, and Metadata, for your stack. - -[#stacks-work] -== Working with stacks - -Stacks are deployed as an {aws} CloudFormation stack into an {aws} xref:environments[environment]. The environment covers a specific {aws} account and {aws} Region. - -When you run the `cdk synth` command for an app with multiple stacks, the cloud assembly includes a separate template for each stack instance. Even if the two stacks are instances of the same class, the {aws} CDK emits them as two individual templates. - -You can synthesize each template by specifying the stack name in the `cdk synth` command. The following example synthesizes the template for `stack1`: - -[source,bash,subs="verbatim,attributes"] ----- -$ cdk synth <stack1> ----- - -This approach is conceptually different from how {aws} CloudFormation templates are normally used, where a template can be deployed multiple times and parameterized through https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html[{aws} CloudFormation parameters]. Although {aws} CloudFormation parameters can be defined in the {aws} CDK, they are generally discouraged because {aws} CloudFormation parameters are resolved only during deployment. This means that you cannot determine their value in your code. - -For example, to conditionally include a resource in your app based on a parameter value, you must set up an https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/conditions-section-structure.html[{aws} CloudFormation condition] and tag the resource with it. The {aws} CDK takes an approach where concrete templates are resolved at synthesis time. Therefore, you can use an `if` statement to check the value to determine whether a resource should be defined or some behavior should be applied. - -[NOTE] -==== - -The {aws} CDK provides as much resolution as possible during synthesis time to enable idiomatic and natural usage of your programming language. - -==== - -Like any other construct, stacks can be composed together into groups. The following code shows an example of a service that consists of three stacks: a control plane, a data plane, and monitoring stacks. The service construct is defined twice: once for the beta environment and once for the production environment. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -import { App, Stack } from 'aws-cdk-lib'; -import { Construct } from 'constructs'; - -interface EnvProps { - prod: boolean; -} - -// imagine these stacks declare a bunch of related resources -class ControlPlane extends Stack {} -class DataPlane extends Stack {} -class Monitoring extends Stack {} - -class MyService extends Construct { - - constructor(scope: Construct, id: string, props?: EnvProps) { - - super(scope, id); - - // we might use the prod argument to change how the service is configured - new ControlPlane(this, "cp"); - new DataPlane(this, "data"); - new Monitoring(this, "mon"); } -} - -const app = new App(); -new MyService(app, "beta"); -new MyService(app, "prod", { prod: true }); - -app.synth(); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const { App, Stack } = require('aws-cdk-lib'); -const { Construct } = require('constructs'); - -// imagine these stacks declare a bunch of related resources -class ControlPlane extends Stack {} -class DataPlane extends Stack {} -class Monitoring extends Stack {} - -class MyService extends Construct { - - constructor(scope, id, props) { - - super(scope, id); - - // we might use the prod argument to change how the service is configured - new ControlPlane(this, "cp"); - new DataPlane(this, "data"); - new Monitoring(this, "mon"); - } -} - -const app = new App(); -new MyService(app, "beta"); -new MyService(app, "prod", { prod: true }); - -app.synth(); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -from aws_cdk import App, Stack -from constructs import Construct - -# imagine these stacks declare a bunch of related resources -class ControlPlane(Stack): pass -class DataPlane(Stack): pass -class Monitoring(Stack): pass - -class MyService(Construct): - - def __init__(self, scope: Construct, id: str, *, prod=False): - - super().__init__(scope, id) - - # we might use the prod argument to change how the service is configured - ControlPlane(self, "cp") - DataPlane(self, "data") - Monitoring(self, "mon") - -app = App(); -MyService(app, "beta") -MyService(app, "prod", prod=True) - -app.synth() ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -package com.myorg; - -import software.amazon.awscdk.App; -import software.amazon.awscdk.Stack; -import software.constructs.Construct; - -public class MyApp { - - // imagine these stacks declare a bunch of related resources - static class ControlPlane extends Stack { - ControlPlane(Construct scope, String id) { - super(scope, id); - } - } - - static class DataPlane extends Stack { - DataPlane(Construct scope, String id) { - super(scope, id); - } - } - - static class Monitoring extends Stack { - Monitoring(Construct scope, String id) { - super(scope, id); - } - } - - static class MyService extends Construct { - MyService(Construct scope, String id) { - this(scope, id, false); - } - - MyService(Construct scope, String id, boolean prod) { - super(scope, id); - - // we might use the prod argument to change how the service is configured - new ControlPlane(this, "cp"); - new DataPlane(this, "data"); - new Monitoring(this, "mon"); - } - } - - public static void main(final String argv[]) { - App app = new App(); - - new MyService(app, "beta"); - new MyService(app, "prod", true); - - app.synth(); - } -} ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -using Amazon.CDK; -using Constructs; - -// imagine these stacks declare a bunch of related resources -public class ControlPlane : Stack { - public ControlPlane(Construct scope, string id=null) : base(scope, id) { } -} - -public class DataPlane : Stack { - public DataPlane(Construct scope, string id=null) : base(scope, id) { } -} - -public class Monitoring : Stack -{ - public Monitoring(Construct scope, string id=null) : base(scope, id) { } -} - -public class MyService : Construct -{ - public MyService(Construct scope, string id, Boolean prod=false) : base(scope, id) - { - // we might use the prod argument to change how the service is configured - new ControlPlane(this, "cp"); - new DataPlane(this, "data"); - new Monitoring(this, "mon"); - } -} - -class Program -{ - static void Main(string[] args) - { - - var app = new App(); - new MyService(app, "beta"); - new MyService(app, "prod", prod: true); - app.Synth(); - } -} ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -package main - -import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/constructs-go/constructs/v10" - "github.com/aws/jsii-runtime-go" -) - -type ControlPlaneStackProps struct { - awscdk.StackProps -} - -func NewControlPlaneStack(scope constructs.Construct, id string, props *ControlPlaneStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - ControlPlaneStack := awscdk.NewStack(scope, jsii.String(id), &sprops) - - // The code that defines your stack goes here - - return ControlPlaneStack -} - -type DataPlaneStackProps struct { - awscdk.StackProps -} - -func NewDataPlaneStack(scope constructs.Construct, id string, props *DataPlaneStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - DataPlaneStack := awscdk.NewStack(scope, jsii.String(id), &sprops) - - // The code that defines your stack goes here - - return DataPlaneStack -} - -type MonitoringStackProps struct { - awscdk.StackProps -} - -func NewMonitoringStack(scope constructs.Construct, id string, props *MonitoringStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - MonitoringStack := awscdk.NewStack(scope, jsii.String(id), &sprops) - - // The code that defines your stack goes here - - return MonitoringStack -} - -type MyServiceStackProps struct { - awscdk.StackProps - Prod bool -} - -func NewMyServiceStack(scope constructs.Construct, id string, props *MyServiceStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - MyServiceStack := awscdk.NewStack(scope, jsii.String(id), &sprops) - - NewControlPlaneStack(MyServiceStack, "cp", &ControlPlaneStackProps{ - StackProps: sprops, - }) - NewDataPlaneStack(MyServiceStack, "data", &DataPlaneStackProps{ - StackProps: sprops, - }) - NewMonitoringStack(MyServiceStack, "mon", &MonitoringStackProps{ - StackProps: sprops, - }) - - return MyServiceStack -} - -func main() { - defer jsii.Close() - - app := awscdk.NewApp(nil) - - betaProps := MyServiceStackProps{ - StackProps: awscdk.StackProps{ - Env: env(), - }, - Prod: false, - } - - NewMyServiceStack(app, "beta", &betaProps) - - prodProps := MyServiceStackProps{ - StackProps: awscdk.StackProps{ - Env: env(), - }, - Prod: true, - } - - NewMyServiceStack(app, "prod", &prodProps) - - app.Synth(nil) -} - -// ... ----- - -This {aws} CDK app eventually consists of six stacks, three for each environment: - -[source,bash,subs="verbatim,attributes"] ----- -$ cdk ls - -betacpDA8372D3 -betadataE23DB2BA -betamon632BD457 -prodcp187264CE -proddataF7378CE5 -prodmon631A1083 ----- -==== - -The physical names of the {aws} CloudFormation stacks are automatically determined by the {aws} CDK based on the stack's construct path in the tree. By default, a stack's name is derived from the construct ID of the `Stack` object. However, you can specify an explicit name by using the `stackName` prop (in Python, `stack_name`), as follows. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -new MyStack(this, 'not:a:stack:name', { stackName: 'this-is-stack-name' }); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -new MyStack(this, 'not:a:stack:name', { stackName: 'this-is-stack-name' }); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -MyStack(self, "not:a:stack:name", stack_name="this-is-stack-name") ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -new MyStack(this, "not:a:stack:name", StackProps.builder() - .StackName("this-is-stack-name").build()); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -new MyStack(this, "not:a:stack:name", new StackProps -{ - StackName = "this-is-stack-name" -}); ----- -==== - -[#stack-nesting] -=== Working with nested stacks - -A _nested stack_ is a CDK stack that you create inside another stack, known as the parent stack. You create nested stacks using the https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.NestedStack.html[`NestedStack`] construct. - -By using nested stacks, you can organize resources across multiple stacks. Nested stacks also offer a way around the {aws} CloudFormation 500-resource limit for stacks. A nested stack counts as only one resource in the stack that contains it. However, it can contain up to 500 resources, including additional nested stacks. - -The scope of a nested stack must be a `Stack` or `NestedStack` construct. The nested stack doesn't need to be declared lexically inside its parent stack. It is necessary only to pass the parent stack as the first parameter (`scope`) when instantiating the nested stack. Aside from this restriction, defining constructs in a nested stack works exactly the same as in an ordinary stack. - -At synthesis time, the nested stack is synthesized to its own {aws} CloudFormation template, which is uploaded to the {aws} CDK staging bucket at deployment. Nested stacks are bound to their parent stack and are not treated as independent deployment artifacts. They aren't listed by `cdk list`, and they can't be deployed by `cdk deploy`. - -References between parent stacks and nested stacks are automatically translated to stack parameters and outputs in the generated {aws} CloudFormation templates, as with any xref:resource-stack[cross-stack reference]. - -[WARNING] -==== - -Changes in security posture are not displayed before deployment for nested stacks. This information is displayed only for top-level stacks. - -==== \ No newline at end of file diff --git a/v2/guide/concepts/stages.adoc b/v2/guide/concepts/stages.adoc deleted file mode 100644 index fae0416e..00000000 --- a/v2/guide/concepts/stages.adoc +++ /dev/null @@ -1,817 +0,0 @@ -include::../attributes.txt[] - -// Attributes -[.topic] -:info_titleabbrev: CDK stages -:info_abstract: An {aws} Cloud Development Kit ({aws} CDK) stage represents a group of one or more CDK stacks that are configured to \ - deploy together. Use stages to deploy the same grouping of stacks to multiple environments, such as development, testing, \ - and production. -:keywords: {aws} CDK, CDK stages, Deployment, CDK stacks - -[#stages] -= Introduction to {aws} CDK stages - -[abstract] --- -An {aws} Cloud Development Kit ({aws} CDK) _stage_ represents a group of one or more CDK stacks that are configured to deploy together. Use stages to deploy the same grouping of stacks to multiple environments, such as development, testing, and production. --- - -// Content start - -An {aws} Cloud Development Kit ({aws} CDK) _stage_ represents a group of one or more CDK stacks that are configured to deploy together. Use stages to deploy the same grouping of stacks to multiple environments, such as development, testing, and production. - -To configure a CDK stage, import and use the https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stage.html[`Stage`] construct. - -The following is a basic example that defines a CDK stage named `MyAppStage`. We add two CDK stacks, named `AppStack` and `DatabaseStack` to our stage. For this example, `AppStack` contains application resources and `DatabaseStack` contains database resources. We then create two instances of `MyAppStage`, for development and production environments: - -==== -[role="tablist"] -TypeScript:: -In `cdk-demo-app/lib/app-stack.ts`: -+ -[source,javascript,subs="verbatim,attributes"] ----- -import * as cdk from 'aws-cdk-lib'; -import { Construct } from 'constructs'; - -// Define the app stack -export class AppStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - // The code that defines your application goes here - } -} ----- -+ - -In `cdk-demo-app/lib/database-stack.ts`: -+ -[source,javascript,subs="verbatim,attributes"] ----- -import * as cdk from 'aws-cdk-lib'; -import { Construct } from 'constructs'; - -// Define the database stack -export class DatabaseStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - // The code that defines your database goes here - } -} ----- -+ - -In `cdk-demo-app/lib/my-stage.ts`: -+ -[source,javascript,subs="verbatim,attributes"] ----- -import * as cdk from 'aws-cdk-lib'; -import { Construct } from 'constructs'; -import { Stage } from 'aws-cdk-lib'; -import { AppStack } from './app-stack'; -import { DatabaseStack } from './database-stack'; - -// Define the stage -export class MyAppStage extends Stage { - constructor(scope: Construct, id: string, props?: cdk.StageProps) { - super(scope, id, props); - - // Add both stacks to the stage - new AppStack(this, 'AppStack'); - new DatabaseStack(this, 'DatabaseStack'); - } -} ----- -+ - -In `cdk-demo-app/bin/cdk-demo-app.ts`: -+ -[source,javascript,subs="verbatim,attributes"] ----- -#!/usr/bin/env node -import 'source-map-support/register'; -import * as cdk from 'aws-cdk-lib'; -import { MyAppStage } from '../lib/my-stage'; - -// Create a CDK app -const app = new cdk.App(); - -// Create the development stage -new MyAppStage(app, 'Dev', { - env: { - account: '123456789012', - region: 'us-east-1' - } -}); - -// Create the production stage -new MyAppStage(app, 'Prod', { - env: { - account: '098765432109', - region: 'us-east-1' - } -}); ----- - -JavaScript:: -In `cdk-demo-app/lib/app-stack.js`: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const { Stack } = require('aws-cdk-lib'); - -class AppStack extends Stack { - constructor(scope, id, props) { - super(scope, id, props); - - // The code that defines your application goes here - } -} - -module.exports = { AppStack } ----- -+ - -In `cdk-demo-app/lib/database-stack.js`: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const { Stack } = require('aws-cdk-lib'); - -class DatabaseStack extends Stack { - constructor(scope, id, props) { - super(scope, id, props); - - // The code that defines your database goes here - } -} - -module.exports = { DatabaseStack } ----- -+ - -In `cdk-demo-app/lib/my-stage.js`: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const { Stage } = require('aws-cdk-lib'); -const { AppStack } = require('./app-stack'); -const { DatabaseStack } = require('./database-stack'); - -// Define the stage -class MyAppStage extends Stage { - constructor(scope, id, props) { - super(scope, id, props); - - // Add both stacks to the stage - new AppStack(this, 'AppStack'); - new DatabaseStack(this, 'DatabaseStack'); - } -} - -module.exports = { MyAppStage }; ----- -+ - -In `cdk-demo-app/bin/cdk-demo-app.js`: -+ -[source,javascript,subs="verbatim,attributes"] ----- -#!/usr/bin/env node - -const cdk = require('aws-cdk-lib'); -const { MyAppStage } = require('../lib/my-stage'); - -// Create the CDK app -const app = new cdk.App(); - -// Create the development stage -new MyAppStage(app, 'Dev', { - env: { - account: '123456789012', - region: 'us-east-1', - }, -}); - -// Create the production stage -new MyAppStage(app, 'Prod', { - env: { - account: '098765432109', - region: 'us-east-1', - }, -}); ----- - -Python:: -In `cdk-demo-app/cdk_demo_app/app_stack.py`: -+ -[source,python,subs="verbatim,attributes"] ----- -from aws_cdk import Stack -from constructs import Construct - -# Define the app stack -class AppStack(Stack): - def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: - super().__init__(scope, construct_id, **kwargs) - - # The code that defines your application goes here ----- -+ - -In `cdk-demo-app/cdk_demo_app/database_stack.py`: -+ -[source,python,subs="verbatim,attributes"] ----- -from aws_cdk import Stack -from constructs import Construct - -# Define the database stack -class DatabaseStack(Stack): - def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: - super().__init__(scope, construct_id, **kwargs) - - # The code that defines your database goes here ----- -+ - -In `cdk-demo-app/cdk_demo_app/my_stage.py`: -+ -[source,python,subs="verbatim,attributes"] ----- -from aws_cdk import Stage -from constructs import Construct -from .app_stack import AppStack -from .database_stack import DatabaseStack - -# Define the stage -class MyAppStage(Stage): - def __init__(self, scope: Construct, id: str, **kwargs) -> None: - super().__init__(scope, id, **kwargs) - - # Add both stacks to the stage - AppStack(self, "AppStack") - DatabaseStack(self, "DatabaseStack") ----- -+ - -In `cdk-demo-app/app.py`: -+ -[source,python,subs="verbatim,attributes"] ----- -#!/usr/bin/env python3 -import os - -import aws_cdk as cdk - -from cdk_demo_app.my_stage import MyAppStage - -# Create a CDK app -app = cdk.App() - -# Create the development stage -MyAppStage(app, 'Dev', - env=cdk.Environment(account='123456789012', region='us-east-1'), - ) - -# Create the production stage -MyAppStage(app, 'Prod', - env=cdk.Environment(account='098765432109', region='us-east-1'), - ) - -app.synth() ----- - -Java:: -In `cdk-demo-app/src/main/java/com/myorg/AppStack.java`: -+ -[source,java,subs="verbatim,attributes"] ----- -package com.myorg; - -import software.constructs.Construct; -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.StackProps; - -public class AppStack extends Stack { - public AppStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public AppStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - // The code that defines your application goes here - } -} ----- -+ - -In `cdk-demo-app/src/main/java/com/myorg/DatabaseStack.java`: -+ -[source,java,subs="verbatim,attributes"] ----- -package com.myorg; - -import software.constructs.Construct; -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.StackProps; - -public class DatabaseStack extends Stack { - public DatabaseStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public DatabaseStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - // The code that defines your database goes here - } -} ----- -+ - -In `cdk-demo-app/src/main/java/com/myorg/MyAppStage.java`: -+ -[source,java,subs="verbatim,attributes"] ----- -package com.myorg; - -import software.amazon.awscdk.Stage; -import software.amazon.awscdk.StageProps; -import software.constructs.Construct; - -// Define the stage -public class MyAppStage extends Stage { - public MyAppStage(final Construct scope, final String id, final software.amazon.awscdk.Environment env) { - super(scope, id, StageProps.builder().env(env).build()); - - // Add both stacks to the stage - new AppStack(this, "AppStack"); - new DatabaseStack(this, "DatabaseStack"); - } -} ----- -+ - -In `cdk-demo-app/src/main/java/com/myorg/CdkDemoAppApp.java`: -+ -[source,java,subs="verbatim,attributes"] ----- -package com.myorg; - -import software.amazon.awscdk.App; -import software.amazon.awscdk.Environment; -import software.amazon.awscdk.StackProps; - -import java.util.Arrays; - -public class CdkDemoAppApp { - public static void main(final String[] args) { - - // Create a CDK app - App app = new App(); - - // Create the development stage - new MyAppStage(app, "Dev", Environment.builder() - .account("123456789012") - .region("us-east-1") - .build()); - - // Create the production stage - new MyAppStage(app, "Prod", Environment.builder() - .account("098765432109") - .region("us-east-1") - .build()); - - app.synth(); - } -} ----- - -C#:: -In `cdk-demo-app/src/CdkDemoApp/AppStack.cs`: -+ -[source,csharp,subs="verbatim,attributes"] ----- -using Amazon.CDK; -using Constructs; - -namespace CdkDemoApp -{ - public class AppStack : Stack - { - internal AppStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) - { - // The code that defines your application goes here - } - } -} ----- -+ - -In `cdk-demo-app/src/CdkDemoApp/DatabaseStack.cs`: -+ -[source,csharp,subs="verbatim,attributes"] ----- -using Amazon.CDK; -using Constructs; - -namespace CdkDemoApp -{ - public class DatabaseStack : Stack - { - internal DatabaseStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) - { - // The code that defines your database goes here - } - } -} ----- -+ - -In `cdk-demo-app/src/CdkDemoApp/MyAppStage.cs`: -+ -[source,csharp,subs="verbatim,attributes"] ----- -using Amazon.CDK; -using Constructs; - -namespace CdkDemoApp -{ - // Define the stage - public class MyAppStage : Stage - { - internal MyAppStage(Construct scope, string id, Environment env) : base(scope, id, new StageProps { Env = env }) - { - // Add both stacks to the stage - new AppStack(this, "AppStack"); - new DatabaseStack(this, "DatabaseStack"); - } - } -} ----- -+ - -In `cdk-demo-app/src/CdkDemoApp/program.cs`: -+ -[source,csharp,subs="verbatim,attributes"] ----- -using Amazon.CDK; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace CdkDemoApp -{ - sealed class Program - { - public static void Main(string[] args) - { - // Create a CDK app - var app = new App(); - - // Create the development stage - new MyAppStage(app, "Dev", new Amazon.CDK.Environment - { - Account = "123456789012", - Region = "us-east-1" - }); - - // Create the production stage - new MyAppStage(app, "Prod", new Amazon.CDK.Environment - { - Account = "098765432109", - Region = "us-east-1" - }); - - app.Synth(); - } - } -} ----- - -Go:: -In `cdk-demo-app/cdk-demo-app.go`: -+ -[source,go,subs="verbatim,attributes"] ----- -package main - -import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/constructs-go/constructs/v10" - "github.com/aws/jsii-runtime-go" -) - -// Define the app stack -type AppStackProps struct { - awscdk.StackProps -} - -func NewAppStack(scope constructs.Construct, id string, props *AppStackProps) awscdk.Stack { - stack := awscdk.NewStack(scope, &id, &props.StackProps) - - // The code that defines your application goes here - - return stack -} - -// Define the database stack -type DatabaseStackProps struct { - awscdk.StackProps -} - -func NewDatabaseStack(scope constructs.Construct, id string, props *DatabaseStackProps) awscdk.Stack { - stack := awscdk.NewStack(scope, &id, &props.StackProps) - - // The code that defines your database goes here - - return stack -} - -// Define the stage -type MyAppStageProps struct { - awscdk.StageProps -} - -func NewMyAppStage(scope constructs.Construct, id string, props *MyAppStageProps) awscdk.Stage { - stage := awscdk.NewStage(scope, &id, &props.StageProps) - - // Add both stacks to the stage - NewAppStack(stage, "AppStack", &AppStackProps{ - StackProps: awscdk.StackProps{ - Env: props.Env, - }, - }) - - NewDatabaseStack(stage, "DatabaseStack", &DatabaseStackProps{ - StackProps: awscdk.StackProps{ - Env: props.Env, - }, - }) - - return stage -} - -func main() { - defer jsii.Close() - - // Create a CDK app - app := awscdk.NewApp(nil) - - // Create the development stage - NewMyAppStage(app, "Dev", &MyAppStageProps{ - StageProps: awscdk.StageProps{ - Env: &awscdk.Environment{ - Account: jsii.String("123456789012"), - Region: jsii.String("us-east-1"), - }, - }, - }) - - // Create the production stage - NewMyAppStage(app, "Prod", &MyAppStageProps{ - StageProps: awscdk.StageProps{ - Env: &awscdk.Environment{ - Account: jsii.String("098765432109"), - Region: jsii.String("us-east-1"), - }, - }, - }) - - app.Synth(nil) -} - -func env() *awscdk.Environment { - return nil -} ----- -==== - -When we run `cdk synth`, two cloud assemblies are created in `cdk.out`. These two cloud assemblies contain the synthesized {aws} CloudFormation template and assets for each stage. The following is snippet of our project directory: - -==== -[role="tablist"] -TypeScript:: -+ -[source,none,subs="verbatim,attributes"] ----- -cdk-demo-app -├── bin -│ └── cdk-demo-app.ts -├── cdk.out -│ ├── assembly-Dev -│ │ ├── DevAppStack<unique-hash>.assets.json -│ │ ├── DevAppStack<unique-hash>.template.json -│ │ ├── DevDatabaseStack<unique-hash>.assets.json -│ │ ├── DevDatabaseStack<unique-hash>.template.json -│ │ ├── cdk.out -│ │ └── manifest.json -│ ├── assembly-Prod -│ │ ├── ProdAppStack<unique-hash>.assets.json -│ │ ├── ProdAppStack<unique-hash>.template.json -│ │ ├── ProdDatabaseStack<unique-hash>.assets.json -│ │ ├── ProdDatabaseStack<unique-hash>.template.json -│ │ ├── cdk.out -│ │ └── manifest.json -└── lib - ├── app-stack.ts - ├── database-stack.ts - └── my-stage.ts ----- - -JavaScript:: -+ -[source,none,subs="verbatim,attributes"] ----- -cdk-demo-app -├── bin -│ └── cdk-demo-app.js -├── cdk.out -│ ├── assembly-Dev -│ │ ├── DevAppStack<unique-hash>.assets.json -│ │ ├── DevAppStack<unique-hash>.template.json -│ │ ├── DevDatabaseStack<unique-hash>.assets.json -│ │ ├── DevDatabaseStack<unique-hash>.template.json -│ │ ├── cdk.out -│ │ └── manifest.json -│ ├── assembly-Prod -│ │ ├── ProdAppStack<unique-hash>.assets.json -│ │ ├── ProdAppStack<unique-hash>.template.json -│ │ ├── ProdDatabaseStack<unique-hash>.assets.json -│ │ ├── ProdDatabaseStack<unique-hash>.template.json -│ │ ├── cdk.out -│ │ └── manifest.json -└── lib - ├── app-stack.js - ├── database-stack.js - └── my-stage.js ----- - -Python:: -+ -[source,none,subs="verbatim,attributes"] ----- -cdk-demo-app -├── app.py -├── cdk.out -│ ├── assembly-Dev -│ │ ├── DevAppStack<unique-hash>.assets.json -│ │ ├── DevAppStack<unique-hash>.template.json -│ │ ├── DevDatabaseStack<unique-hash>.assets.json -│ │ ├── DevDatabaseStack<unique-hash>.template.json -│ │ ├── cdk.out -│ │ └── manifest.json -│ ├── assembly-Prod -│ │ ├── ProdAppStack<unique-hash>.assets.json -│ │ ├── ProdAppStack<unique-hash>.template.json -│ │ ├── ProdDatabaseStack<unique-hash>.assets.json -│ │ ├── ProdDatabaseStack<unique-hash>.template.json -│ │ ├── cdk.out -│ │ └── manifest.json -│ ├── cdk.out -│ ├── manifest.json -│ └── tree.json -└── cdk_demo_app - ├── __init__.py - ├── app_stack.py - ├── database_stack.py - └── my_stage.py ----- - -Java:: -+ -[source,none,subs="verbatim,attributes"] ----- -cdk-demo-app -├── cdk.out -│ ├── assembly-Dev -│ │ ├── DevAppStack<unique-hash>.assets.json -│ │ ├── DevAppStack<unique-hash>.template.json -│ │ ├── DevDatabaseStack<unique-hash>.assets.json -│ │ ├── DevDatabaseStack<unique-hash>.template.json -│ │ ├── cdk.out -│ │ └── manifest.json -│ ├── assembly-Prod -│ │ ├── ProdAppStack<unique-hash>.assets.json -│ │ ├── ProdAppStack<unique-hash>.template.json -│ │ ├── ProdDatabaseStack<unique-hash>.assets.json -│ │ ├── ProdDatabaseStack<unique-hash>.template.json -│ │ ├── cdk.out -│ │ └── manifest.json -│ ├── cdk.out -│ ├── manifest.json -│ └── tree.json -└── src - └── main - └── java - └── com - └── myorg - ├── AppStack.java - ├── CdkDemoAppApp.java - ├── DatabaseStack.java - └── MyAppStage.java ----- - -C#:: -+ -[source,none,subs="verbatim,attributes"] ----- -cdk-demo-app -├── cdk.out -│ ├── assembly-Dev -│ │ ├── DevAppStack<unique-hash>.assets.json -│ │ ├── DevAppStack<unique-hash>.template.json -│ │ ├── DevDatabaseStack<unique-hash>.assets.json -│ │ ├── DevDatabaseStack<unique-hash>.template.json -│ │ ├── cdk.out -│ │ └── manifest.json -│ ├── assembly-Prod -│ │ ├── ProdAppStack<unique-hash>.assets.json -│ │ ├── ProdAppStack<unique-hash>.template.json -│ │ ├── ProdDatabaseStack<unique-hash>.assets.json -│ │ ├── ProdDatabaseStack<unique-hash>.template.json -│ │ ├── cdk.out -│ │ └── manifest.json -│ ├── cdk.out -│ ├── manifest.json -│ └── tree.json -└── src - └── CdkDemoApp - ├── AppStack.cs - ├── DatabaseStack.cs - ├── MyAppStage.cs - └── Program.cs ----- - -Go:: -+ -[source,none,subs="verbatim,attributes"] ----- -cdk-demo-app -├── cdk-demo-app.go -└── cdk.out - ├── assembly-Dev - │ ├── DevAppStack<unique-hash>.assets.json - │ ├── DevAppStack<unique-hash>.template.json - │ ├── DevDatabaseStack<unique-hash>.assets.json - │ ├── DevDatabaseStack<unique-hash>.template.json - │ ├── cdk.out - │ └── manifest.json - ├── assembly-Prod - │ ├── ProdAppStack<unique-hash>.assets.json - │ ├── ProdAppStack<unique-hash>.template.json - │ ├── ProdDatabaseStack<unique-hash>.assets.json - │ ├── ProdDatabaseStack<unique-hash>.template.json - │ ├── cdk.out - │ └── manifest.json - ├── cdk.out - ├── manifest.json - └── tree.json ----- - -When we list our stacks with `cdk list`, we see a total of four stacks: - -[source,none,subs="verbatim,attributes"] ----- -$ cdk list -Dev/AppStack (Dev-AppStack) -Dev/DatabaseStack (Dev-DatabaseStack) -Prod/AppStack (Prod-AppStack) -Prod/DatabaseStack (Prod-DatabaseStack) ----- - -To deploy a specific stage, we run `cdk deploy` and provide the stacks to deploy. The following is an example that uses the `/*` wildcard to deploy both stacks in our `Dev` stage: - -[source,none,subs="verbatim,attributes"] ----- -$ cdk deploy <"Dev/*"> - -✨ Synthesis time: 3.18s - -Dev/AppStack (Dev-AppStack) -Dev/AppStack (Dev-AppStack): deploying... [1/2] - - ✅ Dev/AppStack (Dev-AppStack) - -✨ Deployment time: 1.11s - -Stack ARN: -... - -✨ Total time: 4.29s - -Dev/DatabaseStack (Dev-DatabaseStack) -Dev/DatabaseStack (Dev-DatabaseStack): deploying... [2/2] - - ✅ Dev/DatabaseStack (Dev-DatabaseStack) - -✨ Deployment time: 1.09s - -Stack ARN: -... - -✨ Total time: 4.27s ----- -==== \ No newline at end of file diff --git a/v2/guide/concepts/tagging.adoc b/v2/guide/concepts/tagging.adoc deleted file mode 100644 index 066b8e02..00000000 --- a/v2/guide/concepts/tagging.adoc +++ /dev/null @@ -1,675 +0,0 @@ -include::../attributes.txt[] - -// Attributes -:https---docs-aws-amazon-com-cdk-api-v2-docs-aws-cdk-lib-Tags-html-removekey-props: https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Tags.html#removekey-props -:https---docs-aws-amazon-com-cdk-api-v2-docs-aws-cdk-lib-Tags-html-addkey-value-props: https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Tags.html#addkey-value-props - -[.topic] -:info_titleabbrev: Tags -:keywords: {aws} CDK, Tags - -[#tagging] -= Tags and the {aws} CDK - -[abstract] --- -Tags are informational key-value elements that you can add to constructs in your {aws} CDK app. A tag applied to a given construct also applies to all of its taggable children. Tags are included in the {aws} CloudFormation template synthesized from your app and are applied to the {aws} resources it deploys. You can use tags to identify and categorize resources for the following purposes: --- - -// Content start - -Tags are informational key-value elements that you can add to constructs in your {aws} CDK app. A tag applied to a given construct also applies to all of its taggable children. Tags are included in the {aws} CloudFormation template synthesized from your app and are applied to the {aws} resources it deploys. You can use tags to identify and categorize resources for the following purposes: - -* Simplifying management -* Cost allocation -* Access control -* Any other purposes that you devise - -[TIP] -==== - -For more information about how you can use tags with your {aws} resources, see https://docs.aws.amazon.com/whitepapers/latest/tagging-best-practices/tagging-best-practices.html[Best Practices for Tagging {aws} Resources] in the _{aws} Whitepaper_. - -==== - -[#tagging-use] -== Using tags - -The https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Tags.html[Tags] class includes the static method `of()`, through which you can add tags to, or remove tags from, the specified construct. - -* https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Tags.html#addkey-value-props[`Tags.of(<SCOPE>).add()`] applies a new tag to the given construct and all of its children. -* https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Tags.html#removekey-props[`Tags.of(<SCOPE>).remove()`] removes a tag from the given construct and any of its children, including tags a child construct may have applied to itself. - -[NOTE] -==== - -Tagging is implemented using xref:aspects[Aspects and the {aws} CDK]. Aspects are a way to apply an operation (such as tagging) to all constructs in a given scope. - -==== - -The following example applies the tag *key* with the value *value* to a construct. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -Tags.of(myConstruct).add('key', 'value'); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -Tags.of(myConstruct).add('key', 'value'); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -Tags.of(my_construct).add("key", "value") ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -Tags.of(myConstruct).add("key", "value"); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -Tags.Of(myConstruct).Add("key", "value"); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -awscdk.Tags_Of(myConstruct).Add(jsii.String("key"), jsii.String("value"), &awscdk.TagProps{}) ----- -==== - -The following example deletes the tag *key* from a construct. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -Tags.of(myConstruct).remove('key'); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -Tags.of(myConstruct).remove('key'); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -Tags.of(my_construct).remove("key") ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -Tags.of(myConstruct).remove("key"); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -Tags.Of(myConstruct).Remove("key"); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -awscdk.Tags_Of(myConstruct).Remove(jsii.String("key"), &awscdk.TagProps{}) ----- -==== - -If you are using `Stage` constructs, apply the tag at the `Stage` level or below. Tags are not applied across `Stage` boundaries. - -[#tagging-priorities] -== Tag priorities - -The {aws} CDK applies and removes tags recursively. If there are conflicts, the tagging operation with the highest priority wins. (Priorities are set using the optional `priority` property.) If the priorities of two operations are the same, the tagging operation closest to the bottom of the construct tree wins. By default, applying a tag has a priority of 100 (except for tags added directly to an {aws} CloudFormation resource, which has a priority of 50). The default priority for removing a tag is 200. - -The following applies a tag with a priority of 300 to a construct. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -Tags.of(myConstruct).add('key', 'value', { - priority: 300 -}); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -Tags.of(myConstruct).add('key', 'value', { - priority: 300 -}); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -Tags.of(my_construct).add("key", "value", priority=300) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -Tags.of(myConstruct).add("key", "value", TagProps.builder() - .priority(300).build()); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -Tags.Of(myConstruct).Add("key", "value", new TagProps { Priority = 300 }); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -awscdk.Tags_Of(myConstruct).Add(jsii.String("key"), jsii.String("value"), &awscdk.TagProps{ - Priority: jsii.Number(300), -}) ----- -==== - -[#tagging-props] -== Optional properties - -Tags support https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.TagProps.html[`properties`] that fine-tune how tags are applied to, or removed from, resources. All properties are optional. - -`applyToLaunchedInstances` (Python: `apply_to_launched_instances`):: -+ -Available for add() only. By default, tags are applied to instances launched in an Auto Scaling group. Set this property to *false* to ignore instances launched in an Auto Scaling group. - -`includeResourceTypes`/`excludeResourceTypes` (Python: `include_resource_types`/`exclude_resource_types`):: -+ -Use these to manipulate tags only on a subset of resources, based on {aws} CloudFormation resource types. By default, the operation is applied to all resources in the construct subtree, but this can be changed by including or excluding certain resource types. Exclude takes precedence over include, if both are specified. - -`priority`:: -+ -Use this to set the priority of this operation with respect to other `Tags.add()` and `Tags.remove()` operations. Higher values take precedence over lower values. The default is 100 for add operations (50 for tags applied directly to {aws} CloudFormation resources) and 200 for remove operations. - -The following example applies the tag *tagname* with the value *value* and priority *100* to resources of type *{aws}::Xxx::Yyy* in the construct. It doesn't apply the tag to instances launched in an Amazon EC2 Auto Scaling group or to resources of type **{aws}::Xxx::Zzz**. (These are placeholders for two arbitrary but different {aws} CloudFormation resource types.) - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -Tags.of(myConstruct).add('tagname', 'value', { - applyToLaunchedInstances: false, - includeResourceTypes: ['{aws}::Xxx::Yyy'], - excludeResourceTypes: ['{aws}::Xxx::Zzz'], - priority: 100, -}); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -Tags.of(myConstruct).add('tagname', 'value', { - applyToLaunchedInstances: false, - includeResourceTypes: ['{aws}::Xxx::Yyy'], - excludeResourceTypes: ['{aws}::Xxx::Zzz'], - priority: 100 -}); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -Tags.of(my_construct).add("tagname", "value", - apply_to_launched_instances=False, - include_resource_types=["{aws}::Xxx::Yyy"], - exclude_resource_types=["{aws}::Xxx::Zzz"], - priority=100) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -Tags.of(myConstruct).add("tagname", "value", TagProps.builder() - .applyToLaunchedInstances(false) - .includeResourceTypes(Arrays.asList("{aws}::Xxx::Yyy")) - .excludeResourceTypes(Arrays.asList("{aws}::Xxx::Zzz")) - .priority(100).build()); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -Tags.Of(myConstruct).Add("tagname", "value", new TagProps -{ - ApplyToLaunchedInstances = false, - IncludeResourceTypes = ["{aws}::Xxx::Yyy"], - ExcludeResourceTypes = ["{aws}::Xxx::Zzz"], - Priority = 100 -}); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -awscdk.Tags_Of(myConstruct).Add(jsii.String("tagname"), jsii.String("value"), &awscdk.TagProps{ - ApplyToLaunchedInstances: jsii.Bool(false), - IncludeResourceTypes: &[]*string{jsii.String("{aws}::Xxx:Yyy")}, - ExcludeResourceTypes: &[]*string{jsii.String("{aws}::Xxx:Zzz")}, - Priority: jsii.Number(100), -}) ----- -==== - -The following example removes the tag *tagname* with priority *200* from resources of type *{aws}::Xxx::Yyy* in the construct, but not from resources of type **{aws}::Xxx::Zzz**. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -Tags.of(myConstruct).remove('tagname', { - includeResourceTypes: ['{aws}::Xxx::Yyy'], - excludeResourceTypes: ['{aws}::Xxx::Zzz'], - priority: 200, -}); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -Tags.of(myConstruct).remove('tagname', { - includeResourceTypes: ['{aws}::Xxx::Yyy'], - excludeResourceTypes: ['{aws}::Xxx::Zzz'], - priority: 200 -}); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -Tags.of(my_construct).remove("tagname", - include_resource_types=["{aws}::Xxx::Yyy"], - exclude_resource_types=["{aws}::Xxx::Zzz"], - priority=200,) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -Tags.of((myConstruct).remove("tagname", TagProps.builder() - .includeResourceTypes(Arrays.asList("{aws}::Xxx::Yyy")) - .excludeResourceTypes(Arrays.asList("{aws}::Xxx::Zzz")) - .priority(100).build()); - ) ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -Tags.Of(myConstruct).Remove("tagname", new TagProps -{ - IncludeResourceTypes = ["{aws}::Xxx::Yyy"], - ExcludeResourceTypes = ["{aws}::Xxx::Zzz"], - Priority = 100 -}); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -awscdk.Tags_Of(myConstruct).Remove(jsii.String("tagname"), &awscdk.TagProps{ - IncludeResourceTypes: &[]*string{jsii.String("{aws}::Xxx:Yyy")}, - ExcludeResourceTypes: &[]*string{jsii.String("{aws}::Xxx:Zzz")}, - Priority: jsii.Number(200), -}) ----- -==== - -[#tagging-example] -== Example - -The following example adds the tag key *StackType* with value *TheBest* to any resource created within the `Stack` named `MarketingSystem`. Then it removes it again from all resources except Amazon EC2 VPC subnets. The result is that only the subnets have the tag applied. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -import { App, Stack, Tags } from 'aws-cdk-lib'; - -const app = new App(); -const theBestStack = new Stack(app, 'MarketingSystem'); - -// Add a tag to all constructs in the stack -Tags.of(theBestStack).add('StackType', 'TheBest'); - -// Remove the tag from all resources except subnet resources -Tags.of(theBestStack).remove('StackType', { - excludeResourceTypes: ['{aws}::EC2::Subnet'] -}); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const { App, Stack, Tags } = require('aws-cdk-lib'); - -const app = new App(); -const theBestStack = new Stack(app, 'MarketingSystem'); - -// Add a tag to all constructs in the stack -Tags.of(theBestStack).add('StackType', 'TheBest'); - -// Remove the tag from all resources except subnet resources -Tags.of(theBestStack).remove('StackType', { - excludeResourceTypes: ['{aws}::EC2::Subnet'] -}); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -from aws_cdk import App, Stack, Tags - -app = App(); -the_best_stack = Stack(app, 'MarketingSystem') - -# Add a tag to all constructs in the stack -Tags.of(the_best_stack).add("StackType", "TheBest") - -# Remove the tag from all resources except subnet resources -Tags.of(the_best_stack).remove("StackType", - exclude_resource_types=["{aws}::EC2::Subnet"]) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -import software.amazon.awscdk.App; -import software.amazon.awscdk.Tags; - -// Add a tag to all constructs in the stack -Tags.of(theBestStack).add("StackType", "TheBest"); - -// Remove the tag from all resources except subnet resources -Tags.of(theBestStack).remove("StackType", TagProps.builder() - .excludeResourceTypes(Arrays.asList("{aws}::EC2::Subnet")) - .build()); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -using Amazon.CDK; - -var app = new App(); -var theBestStack = new Stack(app, 'MarketingSystem'); - -// Add a tag to all constructs in the stack -Tags.Of(theBestStack).Add("StackType", "TheBest"); - -// Remove the tag from all resources except subnet resources -Tags.Of(theBestStack).Remove("StackType", new TagProps -{ - ExcludeResourceTypes = ["{aws}::EC2::Subnet"] -}); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -import "github.com/aws/aws-cdk-go/awscdk/v2" -app := awscdk.NewApp(nil) -theBestStack := awscdk.NewStack(app, jsii.String("MarketingSystem"), &awscdk.StackProps{}) - -// Add a tag to all constructs in the stack -awscdk.Tags_Of(theBestStack).Add(jsii.String("StackType"), jsii.String("TheBest"), &awscdk.TagProps{}) - -// Remove the tag from all resources except subnet resources -awscdk.Tags_Of(theBestStack).Add(jsii.String("StackType"), jsii.String("TheBest"), &awscdk.TagProps{ - ExcludeResourceTypes: &[]*string{jsii.String("{aws}::EC2::Subnet")}, -}) ----- -==== - -The following code achieves the same result. Consider which approach (inclusion or exclusion) makes your intent clearer. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -Tags.of(theBestStack).add('StackType', 'TheBest', - { includeResourceTypes: ['{aws}::EC2::Subnet']}); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -Tags.of(theBestStack).add('StackType', 'TheBest', - { includeResourceTypes: ['{aws}::EC2::Subnet']}); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -Tags.of(the_best_stack).add("StackType", "TheBest", - include_resource_types=["{aws}::EC2::Subnet"]) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -Tags.of(theBestStack).add("StackType", "TheBest", TagProps.builder() - .includeResourceTypes(Arrays.asList("{aws}::EC2::Subnet")) - .build()); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -Tags.Of(theBestStack).Add("StackType", "TheBest", new TagProps { - IncludeResourceTypes = ["{aws}::EC2::Subnet"] -}); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -awscdk.Tags_Of(theBestStack).Add(jsii.String("StackType"), jsii.String("TheBest"), &awscdk.TagProps{ - IncludeResourceTypes: &[]*string{jsii.String("{aws}::EC2::Subnet")}, -}) ----- -==== - -[#tagging-single] -== Tagging single constructs - -`Tags.of(scope).add(key, value)` is the standard way to add tags to constructs in the {aws} CDK. Its tree-walking behavior, which recursively tags all taggable resources under the given scope, is almost always what you want. Sometimes, however, you need to tag a specific, arbitrary construct (or constructs). - -One such case involves applying tags whose value is derived from some property of the construct being tagged. The standard tagging approach recursively applies the same key and value to all matching resources in the scope. However, here the value could be different for each tagged construct. - -Tags are implemented using xref:aspects[aspects], and the CDK calls the tag's `visit()` method for each construct under the scope you specified using `Tags.of(scope)`. We can call `Tag.visit()` directly to apply a tag to a single construct. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -new cdk.Tag(key, value).visit(scope); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -new cdk.Tag(key, value).visit(scope); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -cdk.Tag(key, value).visit(scope) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -Tag.Builder.create(key, value).build().visit(scope); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -new Tag(key, value).Visit(scope); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -awscdk.NewTag(key, value, &awscdk.TagProps{}).Visit(scope) ----- -==== - -You can tag all constructs under a scope but let the values of the tags derive from properties of each construct. To do so, write an aspect and apply the tag in the aspect's `visit()` method as shown in the preceding example. Then, add the aspect to the desired scope using `Aspects.of(scope).add(aspect)`. - -The following example applies a tag to each resource in a stack containing the resource's path. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -class PathTagger implements cdk.IAspect { - visit(node: IConstruct) { - new cdk.Tag("aws-cdk-path", node.node.path).visit(node); - } -} - -stack = new MyStack(app); -cdk.Aspects.of(stack).add(new PathTagger()) ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -class PathTagger { - visit(node) { - new cdk.Tag("aws-cdk-path", node.node.path).visit(node); - } -} - -stack = new MyStack(app); -cdk.Aspects.of(stack).add(new PathTagger()) ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -@jsii.implements(cdk.IAspect) -class PathTagger: - def visit(self, node: IConstruct): - cdk.Tag("aws-cdk-path", node.node.path).visit(node) - -stack = MyStack(app) -cdk.Aspects.of(stack).add(PathTagger()) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -final class PathTagger implements IAspect { - public void visit(IConstruct node) { - Tag.Builder.create("aws-cdk-path", node.getNode().getPath()).build().visit(node); - } -} - -stack stack = new MyStack(app); -Aspects.of(stack).add(new PathTagger()); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -public class PathTagger : IAspect -{ - public void Visit(IConstruct node) - { - new Tag("aws-cdk-path", node.Node.Path).Visit(node); - } -} - -var stack = new MyStack(app); -Aspects.Of(stack).Add(new PathTagger); ----- -==== - -[TIP] -==== - -The logic of conditional tagging, including priorities, resource types, and so on, is built into the `Tag` class. You can use these features when applying tags to arbitrary resources; the tag is not applied if the conditions aren't met. Also, the `Tag` class only tags taggable resources, so you don't need to test whether a construct is taggable before applying a tag. - -==== \ No newline at end of file diff --git a/v2/guide/concepts/tokens.adoc b/v2/guide/concepts/tokens.adoc deleted file mode 100644 index 7b5db2e8..00000000 --- a/v2/guide/concepts/tokens.adoc +++ /dev/null @@ -1,2032 +0,0 @@ -include::../attributes.txt[] - -// Attributes -[.topic] -:info_titleabbrev: Tokens -:info_abstract: In the {aws} Cloud Development Kit ({aws} CDK), tokens are placeholders for values that aren’t known when defining constructs or synthesizing stacks. These values will be fully resolved at deployment, when your actual infrastructure is created. When developing {aws} CDK applications, you will work with tokens to manage these values across your application. -:keywords: {aws} CDK, Tokens, {aws} CloudFormation, concepts - -[#tokens] -= Tokens and the {aws} CDK - -[abstract] --- -In the {aws} Cloud Development Kit ({aws} CDK), _tokens_ are placeholders for values that aren't known when defining constructs or synthesizing stacks. These values will be fully resolved at deployment, when your actual infrastructure is created. When developing {aws} CDK applications, you will work with tokens to manage these values across your application. --- - -// Content start - -In the {aws} Cloud Development Kit ({aws} CDK), _tokens_ are placeholders for values that aren't known when defining constructs or synthesizing stacks. These values will be fully resolved at deployment, when your actual infrastructure is created. When developing {aws} CDK applications, you will work with tokens to manage these values across your application. - -[#tokens-example] -== Token example - -The following is an example of a CDK stack that defines a construct for an Amazon Simple Storage Service (Amazon S3) bucket. Since the name of our bucket is not yet known, the value for `bucketName` is stored as a token: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -import * as cdk from 'aws-cdk-lib'; -import { Construct } from 'constructs'; -import * as s3 from 'aws-cdk-lib/aws-s3'; - -export class CdkDemoAppStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - // Define an S3 bucket - const myBucket = new s3.Bucket(this, 'myBucket'); - - // Store value of the S3 bucket name - const myBucketName = myBucket.bucketName; - - // Print the current value for the S3 bucket name at synthesis - console.log("myBucketName: " + bucketName); - } -} ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const { Stack, Duration } = require('aws-cdk-lib'); -const s3 = require('aws-cdk-lib/aws-s3'); - -class CdkDemoAppStack extends Stack { - constructor(scope, id, props) { - super(scope, id, props); - - // Define an S3 bucket - const myBucket = new s3.Bucket(this, 'myBucket'); - - // Store value of the S3 bucket name - const myBucketName = myBucket.bucketName; - - // Print the current value for the S3 bucket name at synthesis - console.log("myBucketName: " + myBucketName); - } -} - -module.exports = { CdkDemoAppStack } ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -from aws_cdk import ( - Stack -) -from constructs import Construct -from aws_cdk import aws_s3 as s3 - -class CdkDemoAppStack(Stack): - - def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: - super().__init__(scope, construct_id, **kwargs) - - # Define an S3 bucket - my_bucket = s3.Bucket(self, "myBucket") - - # Store the value of the S3 bucket name - my_bucket_name = my_bucket.bucket_name - - # Print the current value for the S3 bucket name at synthesis - print(f"myBucketName: {my_bucket_name}") ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -package com.myorg; - -import software.constructs.Construct; -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.StackProps; -import software.amazon.awscdk.services.s3.Bucket; - -import java.util.Map; - -public class CdkDemoAppStack extends Stack { - public CdkDemoAppStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public CdkDemoAppStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - // Define an S3 bucket - Bucket myBucket = Bucket.Builder.create(this, "myBucket") - .build(); - - // Store the token for the bucket name - String myBucketName = myBucket.getBucketName(); - - // Print the token at synthesis - System.out.println("myBucketName: " + myBucketName); - } -} ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -using Amazon.CDK; -using Constructs; -using Amazon.CDK.{aws}.S3; - -namespace CdkDemoApp -{ - public class CdkDemoAppStack : Stack - { - internal CdkDemoAppStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) - { - // Define an S3 bucket - var myBucket = new Bucket(this, "myBucket"); - - // Store the token for the bucket name - var myBucketName = myBucket.BucketName; - - // Print the token at synthesis - System.Console.WriteLine($"myBucketName: {myBucketName}"); - } - } -} ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -package main - -import ( - "fmt" - - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/aws-cdk-go/awscdk/v2/awss3" - "github.com/aws/constructs-go/constructs/v10" - "github.com/aws/jsii-runtime-go" -) - -type CdkDemoAppStackProps struct { - awscdk.StackProps -} - -func NewCdkDemoAppStack(scope constructs.Construct, id string, props *CdkDemoAppStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - stack := awscdk.NewStack(scope, &id, &sprops) - - // Define an S3 bucket - myBucket := awss3.NewBucket(stack, jsii.String("myBucket"), &awss3.BucketProps{}) - - // Store the token for the bucket name - myBucketName := myBucket.BucketName() - - // Print the token at synthesis - fmt.Println("myBucketName: ", *myBucketName) - - return stack -} - -// ... ----- - -When we run `cdk synth` to synthesize our stack, the value for `myBucketName` will be displayed in the token format of `${Token[TOKEN.<1234>]}`. This token format is a result of how the {aws} CDK encodes tokens. In this example, the token is encoded as a string: - -[source,bash,subs="verbatim,attributes"] ----- -$ cdk synth --quiet -myBucketName: ${Token[TOKEN.21]} ----- - -Since the value for our bucket name is not known at synthesis, the token is rendered as `myBucket<unique-hash>`. Our {aws} CloudFormation template uses the `Ref` intrinsic function to reference its value, which will be known at deployment: - -[source,yaml,subs="verbatim,attributes"] ----- -Resources: - myBucket<5AF9C99B>: - # ... -Outputs: - bucketNameOutput: - Description: The name of the S3 bucket - Value: - Ref: myBucket<5AF9C99B> ----- -==== - -For more information on how the unique hash is generated, see xref:how-synth-default-logical-ids[Generated logical IDs in your {aws} CloudFormation template]. - -[#tokens-passing] -== Passing tokens - -Tokens can be passed around as if they were the actual value they represent. The following is an example that passes the token for our bucket name to a construct for an {aws} Lambda function: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -import * as cdk from 'aws-cdk-lib'; -import { Construct } from 'constructs'; -import * as s3 from 'aws-cdk-lib/aws-s3'; -import * as lambda from 'aws-cdk-lib/aws-lambda'; - -export class CdkDemoAppStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - // Define an S3 bucket - const myBucket = new s3.Bucket(this, 'myBucket'); - - // ... - - // Define a Lambda function - const myFunction = new lambda.Function(this, "myFunction", { - runtime: lambda.Runtime.NODEJS_20_X, - handler: "index.handler", - code: lambda.Code.fromInline(` - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello World!'), - }; - }; - `), - functionName: myBucketName + "Function", // Pass token for the S3 bucket name - environment: { - BUCKET_NAME: myBucketName, // Pass token for the S3 bucket name - } - }); - } -} ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const { Stack, Duration } = require('aws-cdk-lib'); -const s3 = require('aws-cdk-lib/aws-s3'); -const lambda = require('aws-cdk-lib/aws-lambda'); - -class CdkDemoAppStack extends Stack { - constructor(scope, id, props) { - super(scope, id, props); - - // Define an S3 bucket - const myBucket = new s3.Bucket(this, 'myBucket'); - - // ... - - // Define a Lambda function - const myFunction = new lambda.Function(this, 'myFunction', { - runtime: lambda.Runtime.NODEJS_20_X, - handler: 'index.handler', - code: lambda.Code.fromInline(` - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello World!'), - }; - }; - `), - functionName: myBucketName + 'Function', // Pass token for the S3 bucket name - environment: { - BUCKET_NAME: myBucketName, // Pass token for the S3 bucket name - } - }); - } -} - -module.exports = { CdkDemoAppStack } ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -from aws_cdk import ( - Stack -) -from constructs import Construct -from aws_cdk import aws_s3 as s3 -from aws_cdk import aws_lambda as _lambda - -class CdkDemoAppStack(Stack): - - def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: - super().__init__(scope, construct_id, **kwargs) - - # Define an S3 bucket - my_bucket = s3.Bucket(self, "myBucket") - - # ... - - # Define a Lambda function - my_function = _lambda.Function(self, "myFunction", - runtime=_lambda.Runtime.NODEJS_20_X, - handler="index.handler", - code=_lambda.Code.from_inline(""" - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello World!'), - }; - }; - """), - function_name=f"{my_bucket_name}Function", # Pass token for the S3 bucket name - environment={ - "BUCKET_NAME": my_bucket_name # Pass token for the S3 bucket name - } - ) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -package com.myorg; - -import software.constructs.Construct; -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.StackProps; -import software.amazon.awscdk.services.s3.Bucket; -import software.amazon.awscdk.services.lambda.Code; -import software.amazon.awscdk.services.lambda.Function; -import software.amazon.awscdk.services.lambda.Runtime; - -import java.util.Map; - -public class CdkDemoAppStack extends Stack { - public CdkDemoAppStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public CdkDemoAppStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - // Define an S3 bucket - Bucket myBucket = Bucket.Builder.create(this, "myBucket") - .build(); - - // ... - - // Define a Lambda function - Function myFunction = Function.Builder.create(this, "myFunction") - .runtime(Runtime.NODEJS_20_X) - .handler("index.handler") - .code(Code.fromInline( - "exports.handler = async function(event) {" + - "return {" + - "statusCode: 200," + - "body: JSON.stringify('Hello World!')," + - "};" + - "};" - )) - .functionName(myBucketName + "Function") // Pass the token for the s3 bucket to the function construct - .environment(Map.of("BUCKET_NAME", myBucketName)) // Pass the bucket name as environment variable - .build(); - } -} ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -using Amazon.CDK; -using Constructs; -using Amazon.CDK.{aws}.S3; -using Amazon.CDK.{aws}.Lambda; -using System; -using System.Collections.Generic; - -namespace CdkDemoApp -{ - public class CdkDemoAppStack : Stack - { - internal CdkDemoAppStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) - { - // Define an S3 bucket - var myBucket = new Bucket(this, "myBucket"); - - // ... - - // Define a Lambda function - var myFunction = new Function(this, "myFunction", new FunctionProps - { - Runtime = Runtime.NODEJS_20_X, - Handler = "index.handler", - Code = Code.FromInline(@" - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello World!'), - }; - }; - "), - // Pass the token for the S3 bucket name - Environment = new Dictionary<string, string> - { - { "BUCKET_NAME", myBucketName } - }, - FunctionName = $"{myBucketName}Function" // Pass the token for the s3 bucket to the function construct - }); - } - } -} ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -package main - -import ( - "fmt" - - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/aws-cdk-go/awscdk/v2/awslambda" - "github.com/aws/aws-cdk-go/awscdk/v2/awss3" - "github.com/aws/constructs-go/constructs/v10" - "github.com/aws/jsii-runtime-go" -) - -type CdkDemoAppStackProps struct { - awscdk.StackProps -} - -func NewCdkDemoAppStack(scope constructs.Construct, id string, props *CdkDemoAppStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - stack := awscdk.NewStack(scope, &id, &sprops) - - // Define an S3 bucket - myBucket := awss3.NewBucket(stack, jsii.String("myBucket"), &awss3.BucketProps{}) - - // ... - - // Define a Lambda function - myFunction := awslambda.NewFunction(stack, jsii.String("myFunction"), &awslambda.FunctionProps{ - Runtime: awslambda.Runtime_NODEJS_20_X(), - Handler: jsii.String("index.handler"), - Code: awslambda.Code_FromInline(jsii.String(` - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello World!'), - }; - }; - `)), - FunctionName: jsii.String(fmt.Sprintf("%sFunction", *myBucketName)), // Pass the token for the S3 bucket to the function name - Environment: &map[string]*string{ - "BUCKET_NAME": myBucketName, - }, - }) - - return stack -} -// ... ----- - -When we synthesize our template, the `Ref` and `Fn::Join` intrinsic functions are used to specify the values, which will be known at deployment: - -[source,yaml,subs="verbatim,attributes"] ----- -Resources: - myBucket<5AF9C99B>: - Type: {aws}::S3::Bucket - # ... - myFunction<884E1557>: - Type: {aws}::Lambda::Function - Properties: - # ... - Environment: - Variables: - BUCKET_NAME: - Ref: myBucket<5AF9C99B> - FunctionName: - Fn::Join: - - "" - - - Ref: myBucket<5AF9C99B> - - Function - # ... ----- -==== - -[#tokens-work] -== How token encodings work - -Tokens are objects that implement the https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.IResolvable.html[`IResolvable`] interface, which contains a single `resolve` method. During synthesis, the {aws} CDK calls this method to produce the final value for tokens in your CloudFormation template. - -[NOTE] -==== - -You'll rarely work directly with the `IResolvable` interface. You will most likely only see string-encoded versions of tokens. - -==== - -[#tokens-work-types] -=== Token encoding types - -Tokens participate in the synthesis process to produce arbitrary values of any type. Other functions typically only accept arguments of basic types, such as `string` or `number`. To use tokens in these cases, you can encode them into one of three types by using static methods on the https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Token.html[`cdk.Token`] class. - -* https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Token.html#static-aswbrstringvalue-options[`Token.asString`] to generate a string encoding (or call `.toString()` on the token object). -* https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Token.html#static-aswbrlistvalue-options[`Token.asList`] to generate a list encoding. -* https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Token.html#static-aswbrnumbervalue[`Token.asNumber`] to generate a numeric encoding. - -These take an arbitrary value, which can be an `IResolvable`, and encode them into a primitive value of the indicated type. - -[IMPORTANT] -==== - -Because any one of the previous types can potentially be an encoded token, be careful when you parse or try to read their contents. For example, if you attempt to parse a string to extract a value from it, and the string is an encoded token, your parsing fails. Similarly, if you try to query the length of an array or perform math operations with a number, you must first verify that they aren't encoded tokens. - -==== - -[#tokens-check] -== How to check for tokens in your app - -To check whether a value has an unresolved token in it, call the https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Token.html#static-iswbrunresolvedobj[`Token.isUnresolved`] (Python: `is_unresolved`) method. The following is an example that checks if the value for our Amazon S3 bucket name is a token. If its not a token, we then validate the length of the bucket name: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -// ... - -export class CdkDemoAppStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - // Define an S3 bucket - const myBucket = new s3.Bucket(this, 'myBucket'); - // ... - - // Check if bucket name is a token. If not, check if length is less than 10 characters - if (cdk.Token.isUnresolved(myBucketName)) { - console.log("Token identified."); - } else if (!cdk.Token.isUnresolved(myBucketName) && myBucketName.length > 10) { - throw new Error('Maximum length for name is 10 characters.'); - }; - - // ... - } -} ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const { Stack, Duration, Token, CfnOutput } = require('aws-cdk-lib'); -// ... - -class CdkDemoAppStack extends Stack { - constructor(scope, id, props) { - super(scope, id, props); - - // Define an S3 bucket - const myBucket = new s3.Bucket(this, 'myBucket'); - - // ... - - // Check if bucket name is a token. If not, check if length is less than 10 characters - if (Token.isUnresolved(myBucketName)) { - console.log("Token identified."); - } else if (!Token.isUnresolved(myBucketName) && myBucketName.length > 10) { - throw new Error('Maximum length for name is 10 characters.'); - }; - - // ... - } -} ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -from aws_cdk import ( - Stack, - Token -) -# ... - -class CdkDemoAppStack(Stack): - - def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: - super().__init__(scope, construct_id, **kwargs) - - # Define an S3 bucket - my_bucket = s3.Bucket(self, "myBucket") - - # ... - - # Check if bucket name is a token. If not, check if length is less than 10 characters - if Token.is_unresolved(my_bucket_name): - print("Token identified.") - elif not Token.is_unresolved(my_bucket_name) and len(my_bucket_name) < 10: - raise ValueError("Maximum length for name is 10 characters.") - - # ... ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -// ... -import software.amazon.awscdk.Token; -import software.amazon.awscdk.services.s3.Bucket; -// ... - -public class CdkDemoAppStack extends Stack { - public CdkDemoAppStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public CdkDemoAppStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - // Define an S3 bucket - Bucket myBucket = Bucket.Builder.create(this, "myBucket") - .build(); - - // ... - - // Get the bucket name - String myBucketName = myBucket.getBucketName(); - - // Check if the bucket name is a token. If not, check if length is less than 10 characters - if (Token.isUnresolved(myBucketName)) { - System.out.println("Token identified."); - } else if (!Token.isUnresolved(myBucketName) && myBucketName.length() > 10) { - throw new IllegalArgumentException("Maximum length for name is 10 characters."); - } - - // ... - } - } - } ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -using Amazon.CDK; -using Constructs; -using Amazon.CDK.AWS.S3; -using Amazon.CDK.AWS.Lambda; -using System; -using System.Collections.Generic; - -namespace CdkDemoApp -{ - public class CdkDemoAppStack : Stack - { - internal CdkDemoAppStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) - { - // Define an S3 bucket - var myBucket = new Bucket(this, "myBucket"); - - // ... - - // Get the bucket name - var myBucketName = myBucket.BucketName; - - // Check if bucket name is a token. If not, check if length is less than 10 characters - if (Token.IsUnresolved(myBucketName)) - { - System.Console.WriteLine("Token identified."); - } - else if (!Token.IsUnresolved(myBucketName) && myBucketName.Length > 10) - { - throw new System.Exception("Maximum length for name is 10 characters."); - } - - // ... - } - } -} ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -// ... - -func NewCdkDemoAppStack(scope constructs.Construct, id string, props *CdkDemoAppStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - stack := awscdk.NewStack(scope, &id, &sprops) - - // Define an S3 bucket - myBucket := awss3.NewBucket(stack, jsii.String("myBucket"), &awss3.BucketProps{}) - - // ... - - // Check if the bucket name is unresolved (a token) - if tokenUnresolved := awscdk.Token_IsUnresolved(myBucketName); tokenUnresolved != nil && *tokenUnresolved { - fmt.Println("Token identified.") - } else if tokenUnresolved != nil && !*tokenUnresolved && len(*myBucketName) > 10 { - panic("Maximum length for name is 10 characters.") - } - - // ... -} ----- -==== - -When we run `cdk synth`, `myBucketName` is identified as a token: - -[source,bash,subs="verbatim,attributes"] ----- -$ cdk synth --quiet -Token identified. ----- - -[NOTE] -==== - -You can use token encodings to escape the type system. For example, you could string-encode a token that produces a number value at synthesis time. If you use these functions, it's your responsibility to make sure that your template resolves to a usable state after synthesis. - -==== - -[#tokens-string] -== Working with string-encoded tokens - -String-encoded tokens look like the following. - -[source,none,subs="verbatim,attributes"] ----- -${TOKEN[Bucket.Name.1234]} ----- - -They can be passed around like regular strings, and can be concatenated, as shown in the following example. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const functionName = bucket.bucketName + 'Function'; ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const functionName = bucket.bucketName + 'Function'; ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -function_name = bucket.bucket_name + "Function" ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -String functionName = bucket.getBucketName().concat("Function"); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -string functionName = bucket.BucketName + "Function"; ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -functionName := *bucket.BucketName() + "Function" ----- -==== - -You can also use string interpolation, if your language supports it, as shown in the following example. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const functionName = `${bucket.bucketName}Function`; ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const functionName = `${bucket.bucketName}Function`; ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -function_name = f"{bucket.bucket_name}Function" ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -String functionName = String.format("%sFunction". bucket.getBucketName()); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -string functionName = $"${bucket.bucketName}Function"; ----- - -Go:: -Use `fmt.Sprintf` for similar functionality: -+ -[source,go,subs="verbatim,attributes"] ----- -functionName := fmt.Sprintf("%sFunction", *bucket.BucketName()) ----- -==== - -Avoid manipulating the string in other ways. For example, taking a substring of a string is likely to break the string token. - -[#tokens-list] -== Working with list-encoded tokens - -List-encoded tokens look like the following: - -[source,none,subs="verbatim,attributes"] ----- -["#{TOKEN[Stack.NotificationArns.1234]}"] ----- - -The only safe thing to do with these lists is pass them directly to other constructs. Tokens in string list form cannot be concatenated, nor can an element be taken from the token. The only safe way to manipulate them is by using {aws} CloudFormation intrinsic functions like https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-select.html[`Fn.select`]. - -[#tokens-number] -== Working with number-encoded tokens - -Number-encoded tokens are a set of tiny negative floating-point numbers that look like the following. - -[source,none,subs="verbatim,attributes"] ----- --1.8881545897087626e+289 ----- - -As with list tokens, you cannot modify the number value, as doing so is likely to break the number token. - -The following is an example of a construct that contains a token encoded as a number: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -import { Stack, Duration, StackProps } from 'aws-cdk-lib'; -import { Construct } from 'constructs'; -import * as rds from 'aws-cdk-lib/aws-rds'; -import * as ec2 from 'aws-cdk-lib/aws-ec2'; - -export class CdkDemoAppStack extends Stack { - constructor(scope: Construct, id: string, props?: StackProps) { - super(scope, id, props); - - // Define a new VPC - const vpc = new ec2.Vpc(this, 'MyVpc', { - maxAzs: 3, // Maximum number of availability zones to use - }); - - // Define an RDS database cluster - const dbCluster = new rds.DatabaseCluster(this, 'MyRDSCluster', { - engine: rds.DatabaseClusterEngine.AURORA, - instanceProps: { - vpc, - }, - }); - - // Get the port token (this is a token encoded as a number) - const portToken = dbCluster.clusterEndpoint.port; - - // Print the value for our token at synthesis - console.log("portToken: " + portToken); - } -} ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const { Stack, Duration } = require('aws-cdk-lib'); -const lambda = require('aws-cdk-lib/aws-lambda'); -const rds = require('aws-cdk-lib/aws-rds'); -const ec2 = require('aws-cdk-lib/aws-ec2'); - -class CdkDemoAppStack extends Stack { - constructor(scope, id, props) { - super(scope, id, props); - - // Define a new VPC - const vpc = new ec2.Vpc(this, 'MyVpc', { - maxAzs: 3, // Maximum number of availability zones to use - }); - - // Define an RDS database cluster - const dbCluster = new rds.DatabaseCluster(this, 'MyRDSCluster', { - engine: rds.DatabaseClusterEngine.AURORA, - instanceProps: { - vpc, - }, - }); - - // Get the port token (this is a token encoded as a number) - const portToken = dbCluster.clusterEndpoint.port; - - // Print the value for our token at synthesis - console.log("portToken: " + portToken); - } -} - -module.exports = { CdkDemoAppStack } ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -from aws_cdk import ( - Duration, - Stack, -) -from aws_cdk import aws_rds as rds -from aws_cdk import aws_ec2 as ec2 -from constructs import Construct - -class CdkDemoAppStack(Stack): - - def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: - super().__init__(scope, construct_id, **kwargs) - - # Define a new VPC - vpc = ec2.Vpc(self, 'MyVpc', - max_azs=3 # Maximum number of availability zones to use - ) - - # Define an RDS database cluster - db_cluster = rds.DatabaseCluster(self, 'MyRDSCluster', - engine=rds.DatabaseClusterEngine.AURORA, - instance_props=rds.InstanceProps( - vpc=vpc - ) - ) - - # Get the port token (this is a token encoded as a number) - port_token = db_cluster.cluster_endpoint.port - - # Print the value for our token at synthesis - print(f"portToken: {port_token}") ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -package com.myorg; - -import software.constructs.Construct; -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.StackProps; -import software.amazon.awscdk.services.ec2.Vpc; -import software.amazon.awscdk.services.rds.DatabaseCluster; -import software.amazon.awscdk.services.rds.DatabaseClusterEngine; -import software.amazon.awscdk.services.rds.InstanceProps; - -public class CdkDemoAppStack extends Stack { - public CdkDemoAppStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public CdkDemoAppStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - // Define a new VPC - Vpc vpc = Vpc.Builder.create(this, "MyVpc") - .maxAzs(3) // Maximum number of availability zones to use - .build(); - - // Define an RDS database cluster - DatabaseCluster dbCluster = DatabaseCluster.Builder.create(this, "MyRDSCluster") - .engine(DatabaseClusterEngine.AURORA) - .instanceProps(InstanceProps.builder() - .vpc(vpc) - .build()) - .build(); - - // Get the port token (this is a token encoded as a number) - Number portToken = dbCluster.getClusterEndpoint().getPort(); - - // Print the value for our token at synthesis - System.out.println("portToken: " + portToken); - } -} ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -using Amazon.CDK; -using Constructs; -using Amazon.CDK.{aws}.EC2; -using Amazon.CDK.{aws}.RDS; -using System; -using System.Collections.Generic; - -namespace CdkDemoApp -{ - public class CdkDemoAppStack : Stack - { - internal CdkDemoAppStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) - { - // Define a new VPC - var vpc = new Vpc(this, "MyVpc", new VpcProps - { - MaxAzs = 3 // Maximum number of availability zones to use - }); - - // Define an RDS database cluster - var dbCluster = new DatabaseCluster(this, "MyRDSCluster", new DatabaseClusterProps - { - Engine = DatabaseClusterEngine.AURORA, // Remove parentheses - InstanceProps = new Amazon.CDK.{aws}.RDS.InstanceProps // Specify RDS InstanceProps - { - Vpc = vpc - } - }); - - // Get the port token (this is a token encoded as a number) - var portToken = dbCluster.ClusterEndpoint.Port; - - // Print the value for our token at synthesis - System.Console.WriteLine($"portToken: {portToken}"); - } - } -} ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -package main - -import ( - "fmt" - - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/aws-cdk-go/awscdk/v2/awsec2" - "github.com/aws/aws-cdk-go/awscdk/v2/awsrds" - "github.com/aws/constructs-go/constructs/v10" - "github.com/aws/jsii-runtime-go" -) - -type CdkDemoAppStackProps struct { - awscdk.StackProps -} - -func NewCdkDemoAppStack(scope constructs.Construct, id string, props *CdkDemoAppStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - stack := awscdk.NewStack(scope, &id, &sprops) - - // Define a new VPC - vpc := awsec2.NewVpc(stack, jsii.String("MyVpc"), &awsec2.VpcProps{ - MaxAzs: jsii.Number(3), // Maximum number of availability zones to use - }) - - // Define an RDS database cluster - dbCluster := awsrds.NewDatabaseCluster(stack, jsii.String("MyRDSCluster"), &awsrds.DatabaseClusterProps{ - Engine: awsrds.DatabaseClusterEngine_AURORA(), - InstanceProps: &awsrds.InstanceProps{ - Vpc: vpc, - }, - }) - - // Get the port token (this is a token encoded as a number) - portToken := dbCluster.ClusterEndpoint().Port() - - // Print the value for our token at synthesis - fmt.Println("portToken: ", portToken) - - return stack -} - -// ... ----- -==== - -When we run `cdk synth`, the value for `portToken` is displayed as a number-encoded token: - -[source,bash,subs="verbatim,attributes"] ----- -$ cdk synth --quiet -portToken: -1.8881545897087968e+289 ----- - -[#tokens-number-pass] -=== Pass number-encoded tokens - -When you pass number-encoded tokens to other constructs, it may make sense to convert them to strings first. For example, if you want to use the value of a number-encoded string as part of a concatenated string, converting it helps with readability. - -In the following example,`portToken` is a number-encoded token that we want to pass to our Lambda function as part of `connectionString`: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -import { Stack, Duration, CfnOutput, StackProps } from 'aws-cdk-lib'; -// ... -import * as lambda from 'aws-cdk-lib/aws-lambda'; - -export class CdkDemoAppStack extends Stack { - constructor(scope: Construct, id: string, props?: StackProps) { - super(scope, id, props); - - // Define a new VPC - // ... - - // Define an RDS database cluster - // ... - - // Get the port token (this is a token encoded as a number) - const portToken = dbCluster.clusterEndpoint.port; - - // ... - - // Example connection string with the port token as a number - const connectionString = `jdbc:mysql://mydb.cluster.amazonaws.com:${portToken}/mydatabase`; - - // Use the connection string as an environment variable in a Lambda function - const myFunction = new lambda.Function(this, 'MyLambdaFunction', { - runtime: lambda.Runtime.NODEJS_20_X, - handler: 'index.handler', - code: lambda.Code.fromInline(` - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello World!'), - }; - }; - `), - environment: { - DATABASE_CONNECTION_STRING: connectionString, // Using the port token as part of the string - }, - }); - - // Output the value of our connection string at synthesis - console.log("connectionString: " + connectionString); - - // Output the connection string - new CfnOutput(this, 'ConnectionString', { - value: connectionString, - }); - } -} ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const { Stack, Duration, CfnOutput } = require('aws-cdk-lib'); -// ... -const lambda = require('aws-cdk-lib/aws-lambda'); - -class CdkDemoAppStack extends Stack { - constructor(scope, id, props) { - super(scope, id, props); - - // Define a new VPC - // ... - - // Define an RDS database cluster - // ... - - // Get the port token (this is a token encoded as a number) - const portToken = dbCluster.clusterEndpoint.port; - - // ... - - // Example connection string with the port token as a number - const connectionString = `jdbc:mysql://mydb.cluster.amazonaws.com:${portToken}/mydatabase`; - - // Use the connection string as an environment variable in a Lambda function - const myFunction = new lambda.Function(this, 'MyLambdaFunction', { - runtime: lambda.Runtime.NODEJS_20_X, - handler: 'index.handler', - code: lambda.Code.fromInline(` - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello World!'), - }; - }; - `), - environment: { - DATABASE_CONNECTION_STRING: connectionString, // Using the port token as part of the string - }, - }); - - // Output the value of our connection string at synthesis - console.log("connectionString: " + connectionString); - - // Output the connection string - new CfnOutput(this, 'ConnectionString', { - value: connectionString, - }); - } -} - -module.exports = { CdkDemoAppStack } ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -from aws_cdk import ( - Duration, - Stack, - CfnOutput, -) -from aws_cdk import aws_lambda as _lambda -# ... - -class CdkDemoAppStack(Stack): - - def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: - super().__init__(scope, construct_id, **kwargs) - - # Define a new VPC - # ... - - # Define an RDS database cluster - # ... - - # Get the port token (this is a token encoded as a number) - port_token = db_cluster.cluster_endpoint.port - - # ... - - # Example connection string with the port token as a number - connection_string = f"jdbc:mysql://mydb.cluster.amazonaws.com:{port_token}/mydatabase" - - # Use the connection string as an environment variable in a Lambda function - my_function = _lambda.Function(self, 'MyLambdaFunction', - runtime=_lambda.Runtime.NODEJS_20_X, - handler='index.handler', - code=_lambda.Code.from_inline(""" - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello World!'), - }; - }; - """), - environment={ - 'DATABASE_CONNECTION_STRING': connection_string # Using the port token as part of the string - } - ) - - # Output the value of our connection string at synthesis - print(f"connectionString: {connection_string}") - - # Output the connection string - CfnOutput(self, 'ConnectionString', - value=connection_string - ) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -// ... -import software.amazon.awscdk.CfnOutput; -import software.amazon.awscdk.services.lambda.Function; -import software.amazon.awscdk.services.lambda.Runtime; -import software.amazon.awscdk.services.lambda.Code; - -import java.util.Map; - -public class CdkDemoAppStack extends Stack { - public CdkDemoAppStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public CdkDemoAppStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - // Define a new VPC - // ... - - // Define an RDS database cluster - // ... - - // Get the port token (this is a token encoded as a number) - Number portToken = dbCluster.getClusterEndpoint().getPort(); - - // ... - - // Example connection string with the port token as a number - String connectionString = "jdbc:mysql://mydb.cluster.amazonaws.com:" + portToken + "/mydatabase"; - - // Use the connection string as an environment variable in a Lambda function - Function myFunction = Function.Builder.create(this, "MyLambdaFunction") - .runtime(Runtime.NODEJS_20_X) - .handler("index.handler") - .code(Code.fromInline( - "exports.handler = async function(event) {\n" + - " return {\n" + - " statusCode: 200,\n" + - " body: JSON.stringify('Hello World!'),\n" + - " };\n" + - "};")) - .environment(Map.of( - "DATABASE_CONNECTION_STRING", connectionString // Using the port token as part of the string - )) - .build(); - - // Output the value of our connection string at synthesis - System.out.println("connectionString: " + connectionString); - - // Output the connection string - CfnOutput.Builder.create(this, "ConnectionString") - .value(connectionString) - .build(); - } -} ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -// ... -using Amazon.CDK.AWS.Lambda; -using Amazon.CDK.AWS.RDS; -using Amazon.CDK; -using Constructs; -using System; -using System.Collections.Generic; - -namespace CdkDemoApp -{ - public class CdkDemoAppStack : Stack - { - internal CdkDemoAppStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) - { - // Define a new VPC - // ... - - // Define an RDS database cluster - var dbCluster = new DatabaseCluster(this, "MyRDSCluster", new DatabaseClusterProps - { - // ... properties would go here - }); - - // Get the port token (this is a token encoded as a number) - var portToken = dbCluster.ClusterEndpoint.Port; - - // ... - - // Example connection string with the port token as a number - var connectionString = $"jdbc:mysql://mydb.cluster.amazonaws.com:{portToken}/mydatabase"; - - // Use the connection string as an environment variable in a Lambda function - var myFunction = new Function(this, "MyLambdaFunction", new FunctionProps - { - Runtime = Runtime.NODEJS_20_X, - Handler = "index.handler", - Code = Code.FromInline(@" - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello World!'), - }; - }; - "), - Environment = new Dictionary<string, string> - { - { "DATABASE_CONNECTION_STRING", connectionString } // Using the port token as part of the string - } - }); - - // Output the value of our connection string at synthesis - Console.WriteLine($"connectionString: {connectionString}"); - - // Output the connection string - new CfnOutput(this, "ConnectionString", new CfnOutputProps - { - Value = connectionString - }); - } - } -} - ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -// ... - "github.com/aws/aws-cdk-go/awscdk/v2/awslambda" -) - -type CdkDemoAppStackProps struct { - awscdk.StackProps -} - -func NewCdkDemoAppStack(scope constructs.Construct, id string, props *CdkDemoAppStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - stack := awscdk.NewStack(scope, &id, &sprops) - - // Define a new VPC - // ... - - // Define an RDS database cluster - // ... - - // Get the port token (this is a token encoded as a number) - portToken := dbCluster.ClusterEndpoint().Port() - - // ... - - // Example connection string with the port token as a number - connectionString := fmt.Sprintf("jdbc:mysql://mydb.cluster.amazonaws.com:%s/mydatabase", portToken) - - // Use the connection string as an environment variable in a Lambda function - myFunction := awslambda.NewFunction(stack, jsii.String("MyLambdaFunction"), &awslambda.FunctionProps{ - Runtime: awslambda.Runtime_NODEJS_20_X(), - Handler: jsii.String("index.handler"), - Code: awslambda.Code_FromInline(jsii.String(` - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello World!'), - }; - }; - `)), - Environment: &map[string]*string{ - "DATABASE_CONNECTION_STRING": jsii.String(connectionString), // Using the port token as part of the string - }, - }) - - // Output the value of our connection string at synthesis - fmt.Println("connectionString: ", connectionString) - - // Output the connection string - awscdk.NewCfnOutput(stack, jsii.String("ConnectionString"), &awscdk.CfnOutputProps{ - Value: jsii.String(connectionString), - }) - - return stack -} - -// ... ----- -==== - -If we pass this value to `connectionString`, the output value when we run `cdk synth` may be confusing due to the number-encoded string: - -[source,none,subs="verbatim,attributes"] ----- -$ cdk synth --quiet -connectionString: jdbc:mysql://mydb.cluster.amazonaws.com:-1.888154589708796e+289/mydatabase ----- - -To convert a number-encoded token to a string, use https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Tokenization.html#static-stringifywbrnumberx[`cdk.Tokenization.stringifyNumber(<token>)`]. In the following example, we convert the number-encoded token to a string before defining our connection string: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -import { Stack, Duration, Tokenization, CfnOutput, StackProps } from 'aws-cdk-lib'; -// ... - -export class CdkDemoAppStack extends Stack { - constructor(scope: Construct, id: string, props?: StackProps) { - super(scope, id, props); - - // Define a new VPC - // ... - - // Define an RDS database cluster - // ... - - // Get the port token (this is a token encoded as a number) - const portToken = dbCluster.clusterEndpoint.port; - - // ... - - // Convert the encoded number to an encoded string for use in the connection string - const portAsString = Tokenization.stringifyNumber(portToken); - - // Example connection string with the port token as a string - const connectionString = `jdbc:mysql://mydb.cluster.amazonaws.com:${portAsString}/mydatabase`; - - // Use the connection string as an environment variable in a Lambda function - const myFunction = new lambda.Function(this, 'MyLambdaFunction', { - // ... - environment: { - DATABASE_CONNECTION_STRING: connectionString, // Using the port token as part of the string - }, - }); - - // Output the value of our connection string at synthesis - console.log("connectionString: " + connectionString); - - // Output the connection string - new CfnOutput(this, 'ConnectionString', { - value: connectionString, - }); - } -} ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const { Stack, Duration, Tokenization, CfnOutput } = require('aws-cdk-lib'); -// ... - -class CdkDemoAppStack extends Stack { - constructor(scope, id, props) { - super(scope, id, props); - - // Define a new VPC - // ... - - // Define an RDS database cluster - // ... - - // Get the port token (this is a token encoded as a number) - const portToken = dbCluster.clusterEndpoint.port; - - // ... - - // Convert the encoded number to an encoded string for use in the connection string - const portAsString = Tokenization.stringifyNumber(portToken); - - // Example connection string with the port token as a string - const connectionString = `jdbc:mysql://mydb.cluster.amazonaws.com:${portAsString}/mydatabase`; - - // Use the connection string as an environment variable in a Lambda function - const myFunction = new lambda.Function(this, 'MyLambdaFunction', { - // ... - environment: { - DATABASE_CONNECTION_STRING: connectionString, // Using the port token as part of the string - }, - }); - - // Output the value of our connection string at synthesis - console.log("connectionString: " + connectionString); - - // Output the connection string - new CfnOutput(this, 'ConnectionString', { - value: connectionString, - }); - } -} - -module.exports = { CdkDemoAppStack } ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -from aws_cdk import ( - Duration, - Stack, - Tokenization, - CfnOutput, -) -# ... - -class CdkDemoAppStack(Stack): - - def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: - super().__init__(scope, construct_id, **kwargs) - - # Define a new VPC - # ... - - # Define an RDS database cluster - # ... - - # Get the port token (this is a token encoded as a number) - port_token = db_cluster.cluster_endpoint.port - - # Convert the encoded number to an encoded string for use in the connection string - port_as_string = Tokenization.stringify_number(port_token) - - # Example connection string with the port token as a string - connection_string = f"jdbc:mysql://mydb.cluster.amazonaws.com:{port_as_string}/mydatabase" - - # Use the connection string as an environment variable in a Lambda function - my_function = _lambda.Function(self, 'MyLambdaFunction', - # ... - environment={ - 'DATABASE_CONNECTION_STRING': connection_string # Using the port token as part of the string - } - ) - - # Output the value of our connection string at synthesis - print(f"connectionString: {connection_string}") - - # Output the connection string - CfnOutput(self, 'ConnectionString', - value=connection_string - ) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -// ... -import software.amazon.awscdk.Tokenization; - -public class CdkDemoAppStack extends Stack { - public CdkDemoAppStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public CdkDemoAppStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - // Define a new VPC - // ... - - // Define an RDS database cluster - // ... - - // Get the port token (this is a token encoded as a number) - Number portToken = dbCluster.getClusterEndpoint().getPort(); - - // ... - - // Convert the encoded number to an encoded string for use in the connection string - String portAsString = Tokenization.stringifyNumber(portToken); - - // Example connection string with the port token as a string - String connectionString = "jdbc:mysql://mydb.cluster.amazonaws.com:" + portAsString + "/mydatabase"; - - // Use the connection string as an environment variable in a Lambda function - Function myFunction = Function.Builder.create(this, "MyLambdaFunction") - // ... - .environment(Map.of( - "DATABASE_CONNECTION_STRING", connectionString // Using the port token as part of the string - )) - .build(); - - // Output the value of our connection string at synthesis - System.out.println("connectionString: " + connectionString); - - // Output the connection string - CfnOutput.Builder.create(this, "ConnectionString") - .value(connectionString) - .build(); - } -} ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -// ... - -namespace CdkDemoApp -{ - public class CdkDemoAppStack : Stack - { - internal CdkDemoAppStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) - { - // Define a new VPC - // ... - - // Define an RDS database cluster - // ... - - // Get the port token (this is a token encoded as a number) - var portToken = dbCluster.ClusterEndpoint.Port; - - // ... - - // Convert the encoded number to an encoded string for use in the connection string - var portAsString = Tokenization.StringifyNumber(portToken); - - // Example connection string with the port token as a string - var connectionString = $"jdbc:mysql://mydb.cluster.amazonaws.com:{portAsString}/mydatabase"; - - // Use the connection string as an environment variable in a Lambda function - var myFunction = new Function(this, "MyLambdaFunction", new FunctionProps - { - // ... - Environment = new Dictionary<string, string> - { - { "DATABASE_CONNECTION_STRING", connectionString } // Using the port token as part of the string - } - }); - - // Output the value of our connection string at synthesis - Console.WriteLine($"connectionString: {connectionString}"); - - // Output the connection string - new CfnOutput(this, "ConnectionString", new CfnOutputProps - { - Value = connectionString - }); - } - } -} ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -// ... - -func NewCdkDemoAppStack(scope constructs.Construct, id string, props *CdkDemoAppStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - stack := awscdk.NewStack(scope, &id, &sprops) - - // Define a new VPC - // ... - - // Define an RDS database cluster - // ... - - // Get the port token (this is a token encoded as a number) - portToken := dbCluster.ClusterEndpoint().Port() - - // ... - - // Convert the encoded number to an encoded string for use in the connection string - portAsString := awscdk.Tokenization_StringifyNumber(portToken) - - // Example connection string with the port token as a string - connectionString := fmt.Sprintf("jdbc:mysql://mydb.cluster.amazonaws.com:%s/mydatabase", portAsString) - - // Use the connection string as an environment variable in a Lambda function - myFunction := awslambda.NewFunction(stack, jsii.String("MyLambdaFunction"), &awslambda.FunctionProps{ - // ... - Environment: &map[string]*string{ - "DATABASE_CONNECTION_STRING": jsii.String(connectionString), // Using the port token as part of the string - }, - }) - - // Output the value of our connection string at synthesis - fmt.Println("connectionString: ", connectionString) - - // Output the connection string - awscdk.NewCfnOutput(stack, jsii.String("ConnectionString"), &awscdk.CfnOutputProps{ - Value: jsii.String(connectionString), - }) - - fmt.Println(myFunction) - - return stack -} - -// ... ----- -==== - -When we run `cdk synth`, the value for our connection string is represented in a cleaner and clearer format: - -[source,bash,subs="verbatim,attributes"] ----- -$ cdk synth --quiet -connectionString: jdbc:mysql://mydb.cluster.amazonaws.com:${Token[TOKEN.242]}/mydatabase ----- - -[#tokens-lazy] -== Lazy values - -In addition to representing deploy-time values, such as {aws} CloudFormation xref:parameters[parameters], tokens are also commonly used to represent synthesis-time lazy values. These are values for which the final value will be determined before synthesis has completed, but not at the point where the value is constructed. Use tokens to pass a literal string or number value to another construct, while the actual value at synthesis time might depend on some calculation that has yet to occur. - -You can construct tokens representing synth-time lazy values using static methods on the `Lazy` class, such as https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Lazy.html#static-stringproducer-options[`Lazy.string`] and https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Lazy.html#static-numberproducer[`Lazy.number`]. These methods accept an object whose `produce` property is a function that accepts a context argument and returns the final value when called. - -The following example creates an Auto Scaling group whose capacity is determined after its creation. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -let actualValue: number; - -new AutoScalingGroup(this, 'Group', { - desiredCapacity: Lazy.numberValue({ - produce(context) { - return actualValue; - } - }) -}); - -// At some later point -actualValue = 10; ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -let actualValue; - -new AutoScalingGroup(this, 'Group', { - desiredCapacity: Lazy.numberValue({ - produce(context) { - return (actualValue); - } - }) -}); - -// At some later point -actualValue = 10; ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -class Producer: - def __init__(self, func): - self.produce = func - -actual_value = None - -AutoScalingGroup(self, "Group", - desired_capacity=Lazy.number_value(Producer(lambda context: actual_value)) -) - -# At some later point -actual_value = 10 ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -double actualValue = 0; - -class ProduceActualValue implements INumberProducer { - - @Override - public Number produce(IResolveContext context) { - return actualValue; - } -} - -AutoScalingGroup.Builder.create(this, "Group") - .desiredCapacity(Lazy.numberValue(new ProduceActualValue())).build(); - -// At some later point -actualValue = 10; ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -public class NumberProducer : INumberProducer -{ - Func<Double> function; - - public NumberProducer(Func<Double> function) - { - this.function = function; - } - - public Double Produce(IResolveContext context) - { - return function(); - } -} - -double actualValue = 0; - -new AutoScalingGroup(this, "Group", new AutoScalingGroupProps -{ - DesiredCapacity = Lazy.NumberValue(new NumberProducer(() => actualValue)) -}); - -// At some later point -actualValue = 10; ----- -==== - -[#tokens-json] -== Converting to JSON - -Sometimes you want to produce a JSON string of arbitrary data, and you may not know whether the data contains tokens. To properly JSON-encode any data structure, regardless of whether it contains tokens, use the method https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html#towbrjsonwbrstringobj-space[`stack.toJsonString`], as shown in the following example. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const stack = Stack.of(this); -const str = stack.toJsonString({ - value: bucket.bucketName -}); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const stack = Stack.of(this); -const str = stack.toJsonString({ - value: bucket.bucketName -}); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -stack = Stack.of(self) -string = stack.to_json_string(dict(value=bucket.bucket_name)) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -Stack stack = Stack.of(this); -String stringVal = stack.toJsonString(java.util.Map.of( // Map.of requires Java 9+ - put("value", bucket.getBucketName()))); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -var stack = Stack.Of(this); -var stringVal = stack.ToJsonString(new Dictionary<string, string> -{ - ["value"] = bucket.BucketName -}); ----- -==== \ No newline at end of file diff --git a/v2/guide/configure-access/configure-access-sso-example-cli.adoc b/v2/guide/configure-access/configure-access-sso-example-cli.adoc deleted file mode 100644 index 722c4aa8..00000000 --- a/v2/guide/configure-access/configure-access-sso-example-cli.adoc +++ /dev/null @@ -1,162 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[#configure-access-sso-example-cli] -= Example: Authenticate with IAM Identity Center automatic token refresh for use with the {aws} CDK CLI -:info_titleabbrev: Example: Authenticate with IAM Identity Center automatic token refresh -:keywords: {aws}, {aws} CDK, {aws} CDK CLI, Programmatic access, Security credentials, IAM, IAM Identity Center - -[abstract] --- -In this example, we configure the {aws} Command Line Interface to authenticate our user with the {aws} IAM Identity Center token provider configuration. The SSO token provider configuration lets the {aws} CLI automatically retrieve refreshed authentication tokens to generate short-term credentials that we can use with the {aws} Cloud Development Kit ({aws} CDK) Command Line Interface ({aws} CDK CLI). --- - -// Content start - -In this example, we configure the {aws} Command Line Interface ({aws} CLI) to authenticate our user with the {aws} IAM Identity Center token provider configuration. The SSO token provider configuration lets the {aws} CLI automatically retrieve refreshed authentication tokens to generate short-term credentials that we can use with the {aws} Cloud Development Kit ({aws} CDK) Command Line Interface ({aws} CDK CLI). - -[#configure-access-sso-example-cli-prerequisites] -== Prerequisites - -This example assumes that the following prerequisites have been completed: - -* Prerequisites required to get set up with {aws} and install our starting CLI tools. For more information, see xref:configure-access-prerequisites[Prerequisites]. -* IAM Identity Center has been set up by our organization as the method of managing users. -* At least one user has been created in IAM Identity Center. - -[#configure-access-sso-example-cli-configure] -== Step 1: Configure the {aws} CLI - -For detailed instructions on this step, see https://docs.aws.amazon.com/cli/latest/userguide/sso-configure-profile-token.html[Configure the {aws} CLI to use IAM Identity Center token provider credentials with automatic authentication refresh] in the _{aws} Command Line Interface User Guide_. - -We sign in to the {aws} access portal provided by our organization to gather our IAM Identity Center information. This includes the *SSO start URL* and **SSO Region**. - -Next, we use the {aws} CLI `aws configure sso` command to configure an IAM Identity Center profile and `sso-session` on our local machine: - -[source,bash,subs="verbatim,attributes"] ----- -$ aws configure sso -SSO session name (Recommended): <my-sso> -SSO start URL [None]: <https://my-sso-portal.awsapps.com/start> -SSO region [None]: <us-east-1> -SSO registration scopes [sso:account:access]: <ENTER> ----- - -The {aws} CLI attempts to open our default browser to begin the login process for our IAM Identity Center account. If the {aws} CLI is unable to open our browser, instructions are provided to manually start the login process. This process associates the IAM Identity Center session with our current {aws} CLI session. - -After establishing our session, the {aws} CLI displays the {aws} accounts available to us: - -[source,none,subs="verbatim,attributes"] ----- -There are 2 {aws} accounts available to you. -> DeveloperAccount, developer-account-admin@example.com (<123456789011>) - ProductionAccount, production-account-admin@example.com (<123456789022>) ----- - -We use the arrow keys to select our **DeveloperAccount**. - -Next, the {aws} CLI displays the IAM roles available to us from our selected account: - -[source,none,subs="verbatim,attributes"] ----- -Using the account ID <123456789011> -There are 2 roles available to you. -> ReadOnly - FullAccess ----- - -We use the arrow keys to select **FullAccess**. - -Next, the {aws} CLI prompts us to complete configuration by specifying a default output format, default {aws} Region, and name for our profile: - -[source,none,subs="verbatim,attributes"] ----- -CLI default client Region [None]: <us-west-2> <ENTER> -CLI default output format [None]: <json> <ENTER> -CLI profile name [123456789011_FullAccess]: <my-dev-profile> <ENTER> ----- - -The {aws} CLI displays a final message, showing how to use the named profile with the {aws} CLI: - -[source,none,subs="verbatim,attributes"] ----- -To use this profile, specify the profile name using --profile, as shown: - -aws s3 ls --profile <my-dev-profile> ----- - -After completing this step, our `config` file will look like the following: - -[source,none,subs="verbatim,attributes"] ----- -[profile <my-dev-profile>] -sso_session = <my-sso> -sso_account_id = \<123456789011> -sso_role_name = <fullAccess> -region = <us-west-2> -output = <json> - -[sso-session <my-sso>] -sso_region = <us-east-1> -sso_start_url = <https://my-sso-portal.awsapps.com/start> -sso_registration_scopes = <sso:account:access> ----- - -We can now use this `sso-session` and named profile to request security credentials. - -[#configure-access-sso-example-cli-credentials] -== Step 2: Use the {aws} CLI to generate security credentials - -For detailed instructions on this step, see https://docs.aws.amazon.com/cli/latest/userguide/sso-using-profile.html[Use an IAM Identity Center named profile] in the _{aws} Command Line Interface User Guide_. - -We use the {aws} CLI `aws sso login` command to request security credentials for our profile: - -[source,bash,subs="verbatim,attributes"] ----- -$ aws sso login --profile <my-dev-profile> ----- - -The {aws} CLI attempts to open our default browser and verifies our IAM log in. If we are not currently signed into IAM Identity Center, we will be prompted to complete the sign in process. If the {aws} CLI is unable to open our browser, instructions are provided to manually start the authorization process. - -After successfully logging in, the {aws} CLI caches our IAM Identity Center session credentials. These credentials include an expiration timestamp. When they expire, the {aws} CLI will request that we sign in to IAM Identity Center again. - -Using valid IAM Identity Center credentials, the {aws} CLI securely retrieves {aws} credentials for the IAM role specified in our profile. From here, we can use the {aws} CDK CLI with our credentials. - -[#configure-access-sso-example-cli-cdk] -== Step 3: Use the CDK CLI - -With any CDK CLI command, we use the ``xref:ref-cli-cmd-options-profile[--profile]`` option to specify the named profile that we generated credentials for. If our credentials are valid, the CDK CLI will successfully perform the command. The following is an example: - -[source,none,subs="verbatim,attributes"] ----- -$ cdk diff --profile <my-dev-profile> -Stack CdkAppStack -Hold on while we create a read-only change set to get a diff with accurate replacement information (use --no-change-set to use a less accurate but faster template-only diff) -Resources -[-] {aws}::S3::Bucket amzn-s3-demo-bucket amzn-s3-demo-bucket5AF9C99B destroy - -Outputs -[-] Output BucketRegion: {"Value":{"Ref":"{aws}::Region"}} - - -✨ Number of stacks with differences: 1 ----- - -When our credentials expire, an error message like the following will display: - -[source,none,subs="verbatim,attributes"] ----- -$ cdk diff --profile <my-dev-profile> -Stack CdkAppStack - -Unable to resolve {aws} account to use. It must be either configured when you define your CDK Stack, or through the environment ----- - -To refresh our credentials, we use the {aws} CLI `aws sso login` command: - -[source,bash,subs="verbatim,attributes"] ----- -$ aws sso login --profile <my-dev-profile> ----- \ No newline at end of file diff --git a/v2/guide/configure-access/configure-access.adoc b/v2/guide/configure-access/configure-access.adoc deleted file mode 100644 index faf54796..00000000 --- a/v2/guide/configure-access/configure-access.adoc +++ /dev/null @@ -1,92 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[#configure-access] -= Configure security credentials for the {aws} CDK CLI -:info_titleabbrev: Configure security credentials -:keywords: {aws}, {aws} CDK, {aws} CDK CLI, Programmatic access, Security credentials, IAM, IAM Identity Center - -[abstract] --- -When you use the {aws} Cloud Development Kit ({aws} CDK) to develop applications in your local environment, you will primarily use the {aws} CDK CLI to interact with {aws} to deploy and manage your CDK stacks. To use the CDK CLI, you must configure security credentials. --- - -// Content start - -When you use the {aws} Cloud Development Kit ({aws} CDK) to develop applications in your local environment, you will primarily use the {aws} CDK Command Line Interface ({aws} CDK CLI) to interact with {aws}. For example, you can use the CDK CLI to deploy your application or to delete your resources from your {aws} environment. - -To use the CDK CLI to interact with {aws}, you must configure security credentials on your local machine. This lets {aws} know who you are and what permissions you have. - -To learn more about security credentials, see https://docs.aws.amazon.com/IAM/latest/UserGuide/security-creds.html[{aws} security credentials] in the _IAM User Guide_. - -[#configure-access-prerequisites,] -== Prerequisites - -Configuring security credentials is part of the _getting started_ process. Complete all prerequisites and previous steps at xref:getting-started[Getting started with the {aws} CDK]. - -[#configure-access-how] -== How to configure security credentials - -How you configure security credentials depends on how you or your organization manages users. Whether you use {aws} Identity and Access Management (IAM) or {aws} IAM Identity Center, we recommend that you use the {aws} Command Line Interface ({aws} CLI) to configure and manage security credentials for the CDK CLI. This includes using {aws} CLI commands like `aws configure` to configure security credentials on your local machine. However, you can use alternative methods such as manually updating your `config` and `credentials` files, or setting environment variables. - -For guidance on configuring security credentials using the {aws} CLI, along with information on configuration and credential precedence when using different methods, see https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-authentication.html[Authentication and access credentials] in the _{aws} Command Line Interface User Guide_. The CDK CLI adheres to the same configuration and credential precedence of the {aws} CLI. The `--profile` command line option takes precedence over environment variables. If you have both the `AWS_PROFILE` and `CDK_DEFAULT_PROFILE` environment variables configured, the `AWS_PROFILE` environment variable takes precedence. - -If you configure multiple profiles, you can use the CDK CLI ``xref:ref-cli-cmd-options-profile[--profile]`` option with any command to specify the profile from your `credentials` and `config` files to use for authentication. If you don't provide `--profile`, the `default` profile will be used. - -If you prefer to quickly configure basic settings, including security credentials, see https://docs.aws.amazon.com/cli/latest/userguide/getting-started-quickstart.html[Set up the {aws} CLI] in the _{aws} Command Line Interface User Guide_. - -Once you've configured security credentials on your local machine, you can use the CDK CLI to interact with {aws}. - -[#configure-access-sso] -== Configure and manage security credentials for IAM Identity Center users - -IAM Identity Center users can authenticate with IAM Identity Center or manually by using short-term credentials. - -[#configure-access-sso-auto] -*Authenticate with IAM Identity Center to generate short-term credentials*:: -+ -You can configure the {aws} CLI to authenticate with IAM Identity Center. This is the recommended approach of configuring security credentials for IAM Identity Center users. IAM Identity Center users can use the {aws} CLI `aws configure sso` wizard to configure an IAM Identity Center profile and `sso-session`, which gets stored in the `config` file on your local machine. For instructions, see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sso.html[Configure the {aws} CLI to use {aws} IAM Identity Center] in the _{aws} Command Line Interface User Guide_. -+ -Next, you can use the {aws} CLI `aws sso login` command to request refreshed credentials. You can also use this command to switch profiles. For instructions, see https://docs.aws.amazon.com/cli/latest/userguide/sso-using-profile.html[Use an IAM Identity Center named profile] in the _{aws} Command Line Interface User Guide_. -+ -Once authenticated, you can use the CDK CLI to interact with {aws} for the duration of your session. For an example, see xref:configure-access-sso-example-cli[Example: Authenticate with IAM Identity Center automatic token refresh for use with the {aws} CDK CLI]. - -[#configure-access-sso-manual] -*Manually configure short-term credentials*:: -+ -As an alternative to using the {aws} CLI and authenticating with IAM Identity Center, IAM Identity Center users can obtain short-term credentials from the {aws} Management Console and manually configure the `credentials` and `config` files on their local machine. Once configured, you can use the CDK CLI to interact with {aws} until your credentials expire. For instructions, see https://docs.aws.amazon.com/cli/latest/userguide/cli-authentication-short-term.html[Authenticate with short-term credentials] in the _{aws} Command Line Interface User Guide_. - -[#configure-access-iam] -== Configure and manage security credentials for IAM users - -IAM users can use an IAM role or IAM user credentials with the CDK CLI. - -[#configure-access-iam-role] -*Use an IAM role to configure short-term credentials*:: -+ -IAM users can assume IAM roles to gain additional (or different) permissions. For IAM users, this is the recommended approach since it provides short-term credentials. -+ -First, the IAM role and user's permission to assume the role must be configured. This is typically performed by an administrator using the {aws} Management Console or {aws} CLI. Then, the IAM user can use the {aws} CLI to assume the role and configure short-term credentials on their local machine. For instructions, see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-role.html[Use an IAM role in the {aws} CLI] in the _{aws} Command Line Interface User Guide_. - -[#configure-access-iam-user] -*Use IAM user credentials*:: -+ -[WARNING] -==== - -To avoid security risks, we don't recommend using IAM user credentials since they provide long-term access. If you must use long-term credentials, we recommend that you link:https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#rotate-credentials[update access keys] as an IAM security best practice. - -==== -+ -IAM users can obtain access keys from the {aws} Management Console. You can then use the {aws} CLI to configure long-term credentials on your local machine. For instructions, see https://docs.aws.amazon.com/cli/latest/userguide/cli-authentication-user.html[Authenticate with IAM user credentials] in the _{aws} Command Line Interface User Guide_. - -[#configure-access-info,] -== Additional information - -To learn about the different ways that you can sign in to {aws}, depending on the type of user you are, see https://docs.aws.amazon.com/signin/latest/userguide/what-is-sign-in.html[What is {aws} Sign-In?] in the _{aws} Sign-In User Guide_. - -For reference information when using {aws} SDKs and tools, including the {aws} CLI, see the https://docs.aws.amazon.com/sdkref/latest/guide/overview.html[{aws} SDKs and Tools Reference Guide]. - -include::configure-access-sso-example-cli.adoc[leveloffset=+1] \ No newline at end of file diff --git a/v2/guide/configure-env.adoc b/v2/guide/configure-env.adoc deleted file mode 100644 index c3f09ec4..00000000 --- a/v2/guide/configure-env.adoc +++ /dev/null @@ -1,722 +0,0 @@ -include::attributes.txt[] - -// Attributes - -[.topic] -[#configure-env] -= Configure environments to use with the {aws} CDK -:info_titleabbrev: Configure environments -:keywords: {aws} CDK, {aws} environments, environments, {aws} account, {aws} Region, env - -[abstract] --- -You can configure {aws} environments in multiple ways to use with the {aws} Cloud Development Kit ({aws} CDK). The best method of managing {aws} environments will vary, based on your specific needs. --- - -// Content start - -You can configure {aws} environments in multiple ways to use with the {aws} Cloud Development Kit ({aws} CDK). The best method of managing {aws} environments will vary, based on your specific needs. - -Each CDK stack in your application must eventually be associated with an environment to determine where the stack gets deployed to. - -For an introduction to {aws} environments, see xref:environments[Environments for the {aws} CDK]. - -[#configure-env-where] -== Where you can specify environments from - -You can specify environments in credentials and configuration files, or by using the `link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html#env[env]` property of the `Stack` construct from the {aws} Construct Library. - -[#configure-env-where-files] -=== Credentials and configuration files - -You can use the {aws} Command Line Interface ({aws} CLI) to create `credentials` and `config` files that store, organize, and manage your {aws} environment information. To learn more about these files, see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html[Configuration and credential file settings] in the _{aws} Command Line Interface User Guide_. - -Values stored in these files are organized by _profiles_. How you name your profiles and the key-value pairs in these files will vary based on your method of configuring programmatic access. To learn more about the different methods, see xref:configure-access[Configure security credentials for the {aws} CDK CLI]. - -In general, the {aws} CDK resolves {aws} account information from your `credentials` file and {aws} Region information from your `config` file. - -Once you have your `credentials` and `config` files configured, you can specify the environment to use with the {aws} CDK CLI and through environment variables. - -[#configure-env-where-env] -=== env property of the Stack construct - -You can specify the environment for each stack by using the `link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html#env[env]` property of the `Stack` construct. This property defines an account and Region to use. You can pass hard-coded values to this property or pass environment variables that are offered by the CDK. - -To pass environment variables, use the `AWS_DEFAULT_ACCOUNT` and `AWS_DEFAULT_REGION` environment variables. These environment variables can pass values from your `credentials` and `config` files. You can also use logic within your CDK code to determine the values of these environment variables. - -[#configure-env-precedence] -== Environment precedence with the {aws} CDK - -If you use multiple methods of specifying environments, the {aws} CDK adheres to the following precedence: - -. Hard-coded values specified with the `env` property of the `Stack` construct. -. `AWS_DEFAULT_ACCOUNT` and `AWS_DEFAULT_REGION` environment variables specified with the `env` property of the `Stack` construct. -. Environment information associated with the profile from your `credentials` and `config` files and passed to the CDK CLI using the `--profile` option. -. The `default` profile from your `credentials` and `config` files. - -[#configure-env-when] -== When to specify environments - -When you develop with the CDK, you start by defining CDK stacks, which contain constructs that represent {aws} resources. Next, you synthesize each CDK stack into an {aws} CloudFormation template. You then deploy the CloudFormation template to your environment. How you specify environments determines when your environment information gets applied and can affect CDK behavior and outcomes. - -[#configure-env-when-synth] -=== Specify environments at template synthesis - -When you specify environment information using the `env` property of the `Stack` construct, your environment information is applied at template synthesis. Running `cdk synth` or `cdk deploy` produces an environment-specific CloudFormation template. - -If you use environment variables within the `env` property, you must use the `--profile` option with CDK CLI commands to pass in the profile containing your environment information from your credentials and configuration files. This information will then be applied at template synthesis to produce an environment-specific template. - -Environment information within the CloudFormation template takes precedence over other methods. For example, if you provide a different environment with `cdk deploy --profile <profile>`, the profile will be ignored. - -When you provide environment information in this way, you can use environment-dependent code and logic within your CDK app. This also means that the synthesized template could be different, based on the machine, user, or session that it's synthesized under. This approach is often acceptable or desirable during development, but is not recommended for production use. - -[#configure-env-when-deploy,] -=== Specify environments at stack deployment - -If you don't specify an environment using the `env` property of the `Stack` construct, the CDK CLI will produce an environment-agnostic CloudFormation template at synthesis. You can then specify the environment to deploy to by using `cdk deploy --profile <profile>`. - -If you don't specify a profile when deploying an environment-agnostic template, the CDK CLI will attempt to use environment values from the `default` profile of your `credentials` and `config` files at deployment. - -If environment information is not available at deployment, {aws} CloudFormation will attempt to resolve environment information at deployment through environment-related attributes such as `stack.account`, `stack.region`, and `stack.availabilityZones`. - -For environment-agnostic stacks, constructs within the stack cannot use environment information and you cannot use logic that requires environment information. For example, you cannot write code like `if (stack.region ==== 'us-east-1')` or use construct methods that require environment information such as `link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.Vpc.html#static-fromwbrlookupscope-id-options[Vpc.fromLookup]`. To use these features, you must specify an environment with the `env` property. - -For environment-agnostic stacks, any construct that uses Availability Zones will see two Availability Zones, allowing the stack to be deployed to any Region. - -[#configure-env-how] -== How to specify environments with the {aws} CDK - -[#configure-env-how-hard-coded] -=== Specify hard-coded environments for each stack - -Use the `env` property of the `Stack` construct to specify {aws} environment values for your stack. The following is an example: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const envEU = { account: '2383838383', region: 'eu-west-1' }; -const envUSA = { account: '8373873873', region: 'us-west-2' }; - -new MyFirstStack(app, 'first-stack-us', { env: envUSA }); -new MyFirstStack(app, 'first-stack-eu', { env: envEU }); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const envEU = { account: '2383838383', region: 'eu-west-1' }; -const envUSA = { account: '8373873873', region: 'us-west-2' }; - -new MyFirstStack(app, 'first-stack-us', { env: envUSA }); -new MyFirstStack(app, 'first-stack-eu', { env: envEU }); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -env_EU = cdk.Environment(account="8373873873", region="eu-west-1") -env_USA = cdk.Environment(account="2383838383", region="us-west-2") - -MyFirstStack(app, "first-stack-us", env=env_USA) -MyFirstStack(app, "first-stack-eu", env=env_EU) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -public class MyApp { - - // Helper method to build an environment - static Environment makeEnv(String account, String region) { - return Environment.builder() - .account(account) - .region(region) - .build(); - } - - public static void main(final String argv[]) { - App app = new App(); - - Environment envEU = makeEnv("8373873873", "eu-west-1"); - Environment envUSA = makeEnv("2383838383", "us-west-2"); - - new MyFirstStack(app, "first-stack-us", StackProps.builder() - .env(envUSA).build()); - new MyFirstStack(app, "first-stack-eu", StackProps.builder() - .env(envEU).build()); - - app.synth(); - } -} ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -Amazon.CDK.Environment makeEnv(string account, string region) -{ - return new Amazon.CDK.Environment - { - Account = account, - Region = region - }; -} - -var envEU = makeEnv(account: "8373873873", region: "eu-west-1"); -var envUSA = makeEnv(account: "2383838383", region: "us-west-2"); - -new MyFirstStack(app, "first-stack-us", new StackProps { Env=envUSA }); -new MyFirstStack(app, "first-stack-eu", new StackProps { Env=envEU }); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -env_EU := awscdk.Environment{ - Account: jsii.String("8373873873"), - Region: jsii.String("eu-west-1"), -} - -env_USA := awscdk.Environment{ - Account: jsii.String("2383838383"), - Region: jsii.String("us-west-2"), -} - -MyFirstStack(app, "first-stack-us", &awscdk.StackProps{ - Env: &env_USA, -}) - -MyFirstStack(app, "first-stack-eu", &awscdk.StackProps{ - Env: &env_EU, -}) ----- -==== - -We recommend this approach for production environments. By explicitly specifying the environment in this way, you can ensure that the stack is always deployed to the specific environment. - -[#configure-env-how-env] -=== Specify environments using environment variables - -The {aws} CDK provides two environment variables that you can use within your CDK code: `CDK_DEFAULT_ACCOUNT` and `CDK_DEFAULT_REGION`. When you use these environment variables within the `env` property of your stack instance, you can pass environment information from your credentials and configuration files using the CDK CLI `--profile` option. - -The following is an example of how to specify these environment variables: - -==== -[role="tablist"] -TypeScript:: -Access environment variables via Node's `process` object. -+ -[NOTE] --- -You need the `DefinitelyTyped` module to use `process` in TypeScript. `cdk init` installs this module for you. However, you should install this module manually if you are working with a project created before it was added, or if you didn't set up your project using `cdk init`. - -[source,none,subs="verbatim,attributes"] ----- -npm install @types/node ----- --- -+ - -[source,javascript,subs="verbatim,attributes"] ----- -new MyDevStack(app, 'dev', { - env: { - account: process.env.CDK_DEFAULT_ACCOUNT, - region: process.env.CDK_DEFAULT_REGION -}}); ----- - -JavaScript:: -Access environment variables via Node's `process` object. -+ -[source,javascript,subs="verbatim,attributes"] ----- -new MyDevStack(app, 'dev', { - env: { - account: process.env.CDK_DEFAULT_ACCOUNT, - region: process.env.CDK_DEFAULT_REGION -}}); ----- - -Python:: -Use the `os` module's `environ` dictionary to access environment variables. -+ -[source,python,subs="verbatim,attributes"] ----- -import os -MyDevStack(app, "dev", env=cdk.Environment( - account=os.environ["CDK_DEFAULT_ACCOUNT"], - region=os.environ["CDK_DEFAULT_REGION"])) ----- - -Java:: -Use `System.getenv()` to get the value of an environment variable. -+ -[source,java,subs="verbatim,attributes"] ----- -public class MyApp { - - // Helper method to build an environment - static Environment makeEnv(String account, String region) { - account = (account == null) ? System.getenv("CDK_DEFAULT_ACCOUNT") : account; - region = (region == null) ? System.getenv("CDK_DEFAULT_REGION") : region; - - return Environment.builder() - .account(account) - .region(region) - .build(); - } - - public static void main(final String argv[]) { - App app = new App(); - - Environment envEU = makeEnv(null, null); - Environment envUSA = makeEnv(null, null); - - new MyDevStack(app, "first-stack-us", StackProps.builder() - .env(envUSA).build()); - new MyDevStack(app, "first-stack-eu", StackProps.builder() - .env(envEU).build()); - - app.synth(); - } -} ----- - -C#:: -Use `System.Environment.GetEnvironmentVariable()` to get the value of an environment variable. -+ -[source,csharp,subs="verbatim,attributes"] ----- -Amazon.CDK.Environment makeEnv(string account=null, string region=null) -{ - return new Amazon.CDK.Environment - { - Account = account ?? System.Environment.GetEnvironmentVariable("CDK_DEFAULT_ACCOUNT"), - Region = region ?? System.Environment.GetEnvironmentVariable("CDK_DEFAULT_REGION") - }; -} - -new MyDevStack(app, "dev", new StackProps { Env = makeEnv() }); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -import "os" - -MyDevStack(app, "dev", &awscdk.StackProps{ - Env: &awscdk.Environment{ - Account: jsii.String(os.Getenv("CDK_DEFAULT_ACCOUNT")), - Region: jsii.String(os.Getenv("CDK_DEFAULT_REGION")), - }, -}) ----- -==== - -By specifying environments using environment variables, you can have the same CDK stack synthesize to {aws} CloudFormation templates for different environments. This means that you can deploy the same CDK stack to different {aws} environments without having to modify your CDK code. You only have to specify the profile to use when running `cdk synth`. - -This approach is great for development environments when deploying the same stack to different environments. However, we do not recommend this approach for production environments since the same CDK code can synthesize different templates, depending on the machine, user, or session that it's synthesized under. - -[#configure-env-how-files] -=== Specify environments from your credentials and configuration files with the CDK CLI - -When deploying an environment-agnostic template, use the `--profile` option with any CDK CLI command to specify the profile to use. The following is an example that deploys a CDK stack named `myStack` using the `prod` profile that is defined in the `credentials` and `config` files: - -[source,bash,subs="verbatim,attributes"] ----- -$ cdk deploy <myStack> --profile <prod> ----- - -For more information on the `--profile` option, along with other CDK CLI commands and options, see xref:ref-cli-cmd[{aws} CDK CLI command reference]. - -[#configure-env-considerations] -== Considerations when configuring environments with the {aws} CDK - -Services that you define by using constructs within your stacks must support the Region that you are deploying to. For a list of supported {aws} services per region, see https://aws.amazon.com/about-aws/global-infrastructure/regional-product-services/[{aws} Services by Region]. - -You must have valid {aws} Identity and Access Management (IAM) credentials to perform stack deployments with the {aws} CDK into your specified environments. - -[#configure-env-examples] -== Examples - -[#configure-env-examples-agnostic] -=== Synthesize an environment–agnostic CloudFormation template from a CDK stack - -In this example, we create an environment-agnostic CloudFormation template from our CDK stack. We can then deploy this template to any environment. - -The following is our example CDK stack. This stack defines an Amazon S3 bucket and a CloudFormation stack output for the bucket's Region. For this example, `env` is not defined: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -export class CdkAppStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - // Create the S3 bucket - const bucket = new s3.Bucket(this, 'amzn-s3-demo-bucket', { - removalPolicy: cdk.RemovalPolicy.DESTROY, - }); - - // Create an output for the bucket's Region - new cdk.CfnOutput(this, 'BucketRegion', { - value: bucket.env.region, - }); - } -} ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -class CdkAppStack extends cdk.Stack { - constructor(scope, id, props) { - super(scope, id, props); - - // Create the S3 bucket - const bucket = new s3.Bucket(this, 'amzn-s3-demo-bucket', { - removalPolicy: cdk.RemovalPolicy.DESTROY, - }); - - // Create an output for the bucket's Region - new cdk.CfnOutput(this, 'BucketRegion', { - value: bucket.env.region, - }); - } -} ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -class CdkAppStack(cdk.Stack): - - def __init__(self, scope: cdk.Construct, id: str, **kwargs) -> None: - super().__init__(scope, id, **kwargs) - - # Create the S3 bucket - bucket = s3.Bucket(self, 'amzn-s3-demo-bucket', - removal_policy=cdk.RemovalPolicy.DESTROY - ) - - # Create an output for the bucket's Region - cdk.CfnOutput(self, 'BucketRegion', - value=bucket.env.region - ) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -public class CdkAppStack extends Stack { - - public CdkAppStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - // Create the S3 bucket - Bucket bucket = Bucket.Builder.create(this, "amzn-s3-demo-bucket") - .removalPolicy(RemovalPolicy.DESTROY) - .build(); - - // Create an output for the bucket's Region - CfnOutput.Builder.create(this, "BucketRegion") - .value(this.getRegion()) - .build(); - } -} ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -namespace MyCdkApp -{ - public class CdkAppStack : Stack - { - public CdkAppStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) - { - // Create the S3 bucket - var bucket = new Bucket(this, "amzn-s3-demo-bucket", new BucketProps - { - RemovalPolicy = RemovalPolicy.DESTROY - }); - - // Create an output for the bucket's Region - new CfnOutput(this, "BucketRegion", new CfnOutputProps - { - Value = this.Region - }); - } - } -} ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -func NewCdkAppStack(scope constructs.Construct, id string, props *CdkAppStackProps) awscdk.Stack { - stack := awscdk.NewStack(scope, &id, &props.StackProps) - - // Create the S3 bucket - bucket := awss3.NewBucket(stack, jsii.String("amzn-s3-demo-bucket"), &awss3.BucketProps{ - RemovalPolicy: awscdk.RemovalPolicy_DESTROY, - }) - - // Create an output for the bucket's Region - awscdk.NewCfnOutput(stack, jsii.String("BucketRegion"), &awscdk.CfnOutputProps{ - Value: stack.Region(), - }) - - return stack -} ----- -==== - -When we run `cdk synth`, the CDK CLI produces a CloudFormation template with the pseudo parameter `{aws}::Region` as the output value for the bucket's Region. This parameter will be resolved at deployment: - -[source,yaml,subs="verbatim,attributes"] ----- -Outputs: - BucketRegion: - Value: - Ref: {aws}::Region ----- - -To deploy this stack to an environment that is specified in the `dev` profile of our credentials and configuration files, we run the following: - -[source,bash,subs="verbatim,attributes"] ----- -$ cdk deploy CdkAppStack --profile dev ----- - -If we don't specify a profile, the CDK CLI will attempt to use environment information from the `default` profile in our credentials and configuration files. - -[#configure-env-example-logic] -=== Use logic to determine environment information at template synthesis - -In this example, we configure the `env` property of our `stack` instance to use a valid expression. We specify two additional environment variables, `CDK_DEPLOY_ACCOUNT` and `CDK_DEPLOY_REGION`. These environment variables can override defaults at synthesis time if they exist: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -new MyDevStack(app, 'dev', { - env: { - account: process.env.CDK_DEPLOY_ACCOUNT || process.env.CDK_DEFAULT_ACCOUNT, - region: process.env.CDK_DEPLOY_REGION || process.env.CDK_DEFAULT_REGION -}}); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -new MyDevStack(app, 'dev', { - env: { - account: process.env.CDK_DEPLOY_ACCOUNT || process.env.CDK_DEFAULT_ACCOUNT, - region: process.env.CDK_DEPLOY_REGION || process.env.CDK_DEFAULT_REGION -}}); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -MyDevStack(app, "dev", env=cdk.Environment( - account=os.environ.get("CDK_DEPLOY_ACCOUNT", os.environ["CDK_DEFAULT_ACCOUNT"]), - region=os.environ.get("CDK_DEPLOY_REGION", os.environ["CDK_DEFAULT_REGION"]) - ) -) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -public class MyApp { - - // Helper method to build an environment - static Environment makeEnv(String account, String region) { - account = (account == null) ? System.getenv("CDK_DEPLOY_ACCOUNT") : account; - region = (region == null) ? System.getenv("CDK_DEPLOY_REGION") : region; - account = (account == null) ? System.getenv("CDK_DEFAULT_ACCOUNT") : account; - region = (region == null) ? System.getenv("CDK_DEFAULT_REGION") : region; - - return Environment.builder() - .account(account) - .region(region) - .build(); - } - - public static void main(final String argv[]) { - App app = new App(); - - Environment envEU = makeEnv(null, null); - Environment envUSA = makeEnv(null, null); - - new MyDevStack(app, "first-stack-us", StackProps.builder() - .env(envUSA).build()); - new MyDevStack(app, "first-stack-eu", StackProps.builder() - .env(envEU).build()); - - app.synth(); - } -} ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -Amazon.CDK.Environment makeEnv(string account=null, string region=null) -{ - return new Amazon.CDK.Environment - { - Account = account ?? - System.Environment.GetEnvironmentVariable("CDK_DEPLOY_ACCOUNT") ?? - System.Environment.GetEnvironmentVariable("CDK_DEFAULT_ACCOUNT"), - Region = region ?? - System.Environment.GetEnvironmentVariable("CDK_DEPLOY_REGION") ?? - System.Environment.GetEnvironmentVariable("CDK_DEFAULT_REGION") - }; -} - -new MyDevStack(app, "dev", new StackProps { Env = makeEnv() }); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -var account, region string -var b bool - -if account, b = os.LookupEnv("CDK_DEPLOY_ACCOUNT"); !b || len(account) == 0 { - account = os.Getenv("CDK_DEFAULT_ACCOUNT") -} -if region, b = os.LookupEnv("CDK_DEPLOY_REGION"); !b || len(region) == 0 { - region = os.Getenv("CDK_DEFAULT_REGION") -} - -MyDevStack(app, "dev", &awscdk.StackProps{ - Env: &awscdk.Environment{ - Account: &account, - Region: ®ion, - }, -}) ----- -==== - -With our stack`'s environment declared this way, we can then write a short script or batch file and set variables from command line arguments, then call ``cdk deploy``. The following is an example. Any arguments beyond the first two are passed through to `cdk deploy` to specify command line options or arguments: - -==== -[role="tablist"] -macOS/Linux:: -+ -[source,bash,subs="verbatim,attributes"] ----- -#!/usr/bin/env bash -if [[ $# -ge 2 ]]; then - export CDK_DEPLOY_ACCOUNT=$1 - export CDK_DEPLOY_REGION=$2 - shift; shift - npx cdk deploy "$@" - exit $? -else - echo 1>&2 "Provide account and region as first two args." - echo 1>&2 "Additional args are passed through to cdk deploy." - exit 1 -fi ----- -+ -Save the script as `cdk-deploy-to.sh`, then execute `chmod +x cdk-deploy-to.sh` to make it executable. - -Windows:: -+ -[source,bat,subs="verbatim,attributes"] ----- -@findstr /B /V @ %~dpnx0 > %~dpn0.ps1 && powershell -ExecutionPolicy Bypass %~dpn0.ps1 %* -@exit /B %ERRORLEVEL% -if ($args.length -ge 2) { - $env:CDK_DEPLOY_ACCOUNT, $args = $args - $env:CDK_DEPLOY_REGION, $args = $args - npx cdk deploy $args - exit $lastExitCode -} else { - [console]::error.writeline("Provide account and region as first two args.") - [console]::error.writeline("Additional args are passed through to cdk deploy.") - exit 1 -} ----- -+ -The Windows version of the script uses PowerShell to provide the same functionality as the macOS/Linux version. It also contains instructions to allow it to be run as a batch file so it can be easily invoked from a command line. It should be saved as `cdk-deploy-to.bat`. The file `cdk-deploy-to.ps1` will be created when the batch file is invoked. - -==== - -We can then write additional scripts that use the `cdk-deploy-to` script to deploy to specific environments. The following is an example: - -==== -[role="tablist"] -macOS/Linux:: -+ -[source,bash,subs="verbatim,attributes"] ----- -#!/usr/bin/env bash -# cdk-deploy-to-test.sh -./cdk-deploy-to.sh 123457689 us-east-1 "$@" ----- - -Windows:: -+ -[source,bat,subs="verbatim,attributes"] ----- -@echo off -rem cdk-deploy-to-test.bat -cdk-deploy-to 135792469 us-east-1 %* ----- -==== - -The following is an example that uses the `cdk-deploy-to` script to deploy to multiple environments. If the first deployment fails, the process stops: - -==== -[role="tablist"] -macOS/Linux:: -+ -[source,bash,subs="verbatim,attributes"] ----- -#!/usr/bin/env bash -# cdk-deploy-to-prod.sh -./cdk-deploy-to.sh 135792468 us-west-1 "$@" || exit -./cdk-deploy-to.sh 246813579 eu-west-1 "$@" ----- - -Windows:: -+ -[source,bat,subs="verbatim,attributes"] ----- -@echo off -rem cdk-deploy-to-prod.bat -cdk-deploy-to 135792469 us-west-1 %* || exit /B -cdk-deploy-to 245813579 eu-west-1 %* ----- -==== \ No newline at end of file diff --git a/v2/guide/configure-synth/configure-synth.adoc b/v2/guide/configure-synth/configure-synth.adoc deleted file mode 100644 index 97b0f942..00000000 --- a/v2/guide/configure-synth/configure-synth.adoc +++ /dev/null @@ -1,789 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[#configure-synth] -= Configure and perform CDK stack synthesis -:info_titleabbrev: Configure and perform synthesis -:keywords: {aws} CDK, {aws} CloudFormation stack, synthesis, cdk synth, {aws} CloudFormation template - -[abstract] --- -Before you can deploy an {aws} Cloud Development Kit ({aws} CDK) stack, it must first be synthesized. Stack synthesis is the process of creating an {aws} CloudFormation template from a CDK stack. The CloudFormation template is what you then deploy to provision your resources on {aws}. --- - -// Content start - -Before you can deploy an {aws} Cloud Development Kit ({aws} CDK) stack, it must first be synthesized. _Stack synthesis_ is the process of producing an {aws} CloudFormation template and deployment artifacts from a CDK stack. The template and artifacts are known as the _cloud assembly_. The cloud assembly is what gets deployed to provision your resources on {aws}. For more information on how deployments work, see xref:deploy-how[How {aws} CDK deployments work]. - -[#configure-synth-bootstrap] -== How synthesis and bootstrapping work together - -For your CDK apps to properly deploy, the CloudFormation templates produced during synthesis must correctly specify the resources created during bootstrapping. Therefore, bootstrapping and synthesis must complement one another for a deployment to be successful: - -* Bootstrapping is a one-time process of setting up an {aws} environment for {aws} CDK deployments. It configures specific {aws} resources in your environment that are used by the CDK for deployments. These are commonly referred to as _bootstrap resources_. For instructions on bootstrapping, see xref:bootstrapping-env[Bootstrap your environment for use with the {aws} CDK]. -* CloudFormation templates produced during synthesis include information on which bootstrap resources to use. During synthesis, the CDK CLI doesn't know specifically how your {aws} environment has been bootstrapped. Instead, the CDK CLI produces CloudFormation templates based on the synthesizer you configure for each CDK stack. For a deployment to be successful, the synthesizer must produce CloudFormation templates that reference the correct bootstrap resources to use. - -The CDK comes with a default synthesizer and bootstrapping configuration that are designed to work together. If you customize one, you must apply relevant customizations to the other. - -[#bootstrapping-synthesizers] -== How to configure CDK stack synthesis - -You configure CDK stack synthesis using the `synthesizer` property of your link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html[`Stack`] instance. This property specifies how your CDK stacks will be synthesized. You provide an instance of a class that implements link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.IStackSynthesizer.html[`IStackSynthesizer`] or link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.IReusableStackSynthesizer.html[`IReusableStackSynthesizer`]. Its methods will be invoked every time an asset is added to the stack or when the stack is synthesized. The following is a basic example of using this property within your stack: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -new MyStack(this, 'MyStack', { - // stack properties - synthesizer: new DefaultStackSynthesizer({ - // synthesizer properties - }), -}); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -new MyStack(this, 'MyStack', { - // stack properties - synthesizer: new DefaultStackSynthesizer({ - // synthesizer properties - }), -}); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -MyStack(self, "MyStack", - # stack properties - synthesizer=DefaultStackSynthesizer( - # synthesizer properties -)) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -new MyStack(app, "MyStack", StackProps.builder() - // stack properties - .synthesizer(DefaultStackSynthesizer.Builder.create() - // synthesizer properties - .build()) - .build(); -) ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -new MyStack(app, "MyStack", new StackProps -// stack properties -{ - Synthesizer = new DefaultStackSynthesizer(new DefaultStackSynthesizerProps - { - // synthesizer properties - }) -}); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -func main() { - app := awscdk.NewApp(nil) - - NewMyStack(app, "MyStack", &MyStackProps{ - StackProps: awscdk.StackProps{ - Synthesizer: awscdk.NewDefaultStackSynthesizer(&awscdk.DefaultStackSynthesizerProps{ - // synthesizer properties - }), - }, - }) - - app.Synth(nil) -} ----- -==== - -You can also configure a synthesizer for all CDK stacks in your CDK app using the `defaultStackSynthesizer` property of your `App` instance: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -import { App, Stack, DefaultStackSynthesizer } from 'aws-cdk-lib'; - -const app = new App({ - // Configure for all stacks in this app - defaultStackSynthesizer: new DefaultStackSynthesizer({ - /* ... */ - }), -}); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const { App, Stack, DefaultStackSynthesizer } = require('aws-cdk-lib'); - -const app = new App({ - // Configure for all stacks in this app - defaultStackSynthesizer: new DefaultStackSynthesizer({ - /* ... */ - }), -}); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -from aws_cdk import App, Stack, DefaultStackSynthesizer - -app = App( - default_stack_synthesizer=DefaultStackSynthesizer( - # Configure for all stacks in this app - # ... - ) -) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -import software.amazon.awscdk.App; -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.DefaultStackSynthesizer; - -public class Main { - public static void main(final String[] args) { - App app = new App(AppProps.builder() - // Configure for all stacks in this app - .defaultStackSynthesizer(DefaultStackSynthesizer.Builder.create().build()) - .build() - ); - } -} ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -using Amazon.CDK; -using Amazon.CDK.Synthesizers; - -namespace MyNamespace -{ - sealed class Program - { - public static void Main(string[] args) - { - var app = new App(new AppProps - { - // Configure for all stacks in this app - DefaultStackSynthesizer = new DefaultStackSynthesizer(new DefaultStackSynthesizerProps - { - // ... - }) - }); - } - } -} ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -package main - -import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/constructs-go/constructs/v10" - "github.com/aws/jsii-runtime-go" -) - -func main() { - defer jsii.Close() - - app := awscdk.NewApp(&awscdk.AppProps{ - // Configure for all stacks in this app - DefaultStackSynthesizer: awscdk.NewDefaultStackSynthesizer(&awscdk.DefaultStackSynthesizerProps{ - // ... - }), - }) -} ----- -==== - -By default, the {aws} CDK uses `link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.DefaultStackSynthesizer.html[`DefaultStackSynthesizer`]. If you don't configure a synthesizer, this synthesizer will be used. - -If you don't modify bootstrapping, such as making changes to the bootstrap stack or template, you don't have to modify stack synthesis. You don't even have to provide a synthesizer. The CDK will use the default `DefaultStackSynthesizer` class to configure CDK stack synthesis to properly interact with your bootstrap stack. - -[#configure-synth-stack] -== How to synthesize a CDK stack - -To synthesize a CDK stack, use the {aws} CDK Command Line Interface ({aws} CDK CLI) `cdk synth` command. For more information about this command, including options that you can use with this command, see xref:ref-cli-cmd-synth[cdk synthesize]. - -If your CDK app contains a single stack, or to synthesize all stacks, you don't have to provide the CDK stack name as an argument. By default, the CDK CLI will synthesize your CDK stacks into {aws} CloudFormation templates. A `json` formatted template for each stack is saved to the `cdk.out` directory. If your app contains a single stack, a `yaml` formatted template is printed to `stdout`. The following is an example: - -[source,none,subs="verbatim,attributes"] ----- -$ cdk synth -Resources: - CDKMetadata: - Type: {aws}::CDK::Metadata - Properties: - Analytics: v2:deflate64:H4sIAAAAAAAA/unique-identifier - Metadata: - aws:cdk:path: CdkAppStack/CDKMetadata/Default - Condition: CDKMetadataAvailable - ... ----- - -If your CDK app contains multiple stacks, you can provide the logical ID of a stack to synthesize a single stack. The following is an example: - -[source,none,subs="verbatim,attributes"] ----- -$ cdk synth MyStackName ----- - -If you don't synthesize a stack and run `cdk deploy`, the CDK CLI will automatically synthesize your stack before deployment. - -[#how-synth-default] -== How synthesis works by default - -[#how-synth-default-logical-ids] -*Generated logical IDs in your {aws} CloudFormation template*:: -+ -When you synthesize a CDK stack to produce a CloudFormation template, logical IDs are generated from the following sources, formatted as `<construct-path><construct-ID><unique-hash>`: -+ -* *Construct path* – The entire path to the construct in your CDK app. This path excludes the ID of the L1 construct, which is always `Resource` or `Default`, and the ID of the top-level stack that it's a part of. -* *Construct ID* – The ID that you provide as the second argument when instantiating your construct. -* *Unique hash* – The {aws} CDK generates an 8 character unique hash using a deterministic hashing algorithm. This unique hash helps to ensure that logical ID values in your template are unique from one another. The deterministic behavior of this hash generation ensures that the generated logical ID value for each construct remains the same every time that you perform synthesis. The hash value will only change if you modify specific construct values such as your construct's ID or its path. -+ -Logical IDs have a maximum length of 255 characters. Therefore, the {aws} CDK will truncate the construct path and construct ID if necessary to keep within that limit. -+ -The following is an example of a construct that defines an Amazon Simple Storage Service (Amazon S3) bucket. Here, we pass `myBucket` as the ID for our construct: -+ -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -import * as cdk from 'aws-cdk-lib'; -import { Construct} from 'constructs'; -import * as s3 from 'aws-cdk-lib/aws-s3'; - -export class MyCdkAppStack extends cdk.Stack { - constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - // Define the S3 bucket - new s3.Bucket(this, 'myBucket', { - versioned: true, - removalPolicy: cdk.RemovalPolicy.DESTROY, - }); - } -} ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const cdk = require('aws-cdk-lib'); -const s3 = require('aws-cdk-lib/aws-s3'); - -class MyCdkAppStack extends cdk.Stack { - - constructor(scope, id, props) { - super(scope, id, props); - - new s3.Bucket(this, 'myBucket', { - versioned: true, - removalPolicy: cdk.RemovalPolicy.DESTROY, - }); - } -} - -module.exports = { MyCdkAppStack } ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -import aws_cdk as cdk -from constructs import Construct -from aws_cdk import Stack -from aws_cdk import aws_s3 as s3 - -class MyCdkAppStack(Stack): - def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: - super().__init__(scope, construct_id, **kwargs) - - s3.Bucket(self, 'MyBucket', - versioned=True, - removal_policy=cdk.RemovalPolicy.DESTROY - ) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -package com.myorg; - -import software.constructs.Construct; -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.StackProps; -import software.amazon.awscdk.services.s3.Bucket; -import software.amazon.awscdk.services.s3.BucketProps; -import software.amazon.awscdk.RemovalPolicy; - -public class MyCdkAppStack extends Stack { - public MyCdkAppStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public MyCdkAppStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - Bucket.Builder.create(this, "myBucket") - .versioned(true) - .removalPolicy(RemovalPolicy.DESTROY) - .build(); - } -} ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -using Amazon.CDK; -using Constructs; -using Amazon.CDK.{aws}.S3; - -namespace MyCdkApp -{ - public class MyCdkAppStack : Stack - { - public MyCdkAppStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) - { - new Bucket(this, "myBucket", new BucketProps - { - Versioned = true, - RemovalPolicy = RemovalPolicy.DESTROY - }); - } - } -} ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -package main - -import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/aws-cdk-go/awscdk/v2/awss3" - "github.com/aws/constructs-go/constructs/v10" - "github.com/aws/jsii-runtime-go" -) - -type MyCdkAppStackProps struct { - awscdk.StackProps -} - -func NewMyCdkAppStack(scope constructs.Construct, id string, props *MyCdkAppStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - stack := awscdk.NewStack(scope, &id, &sprops) - - awss3.NewBucket(stack, jsii.String("myBucket"), &awss3.BucketProps{ - Versioned: jsii.Bool(true), - RemovalPolicy: awscdk.RemovalPolicy_DESTROY, - }) - - return stack -} - -// ... ----- -==== -+ -When we run `cdk synth`, a logical ID in the format of `myBucket<unique-hash>` gets generated. The following is an example of this resource in the generated {aws} CloudFormation template: -+ -[source,yaml,subs="verbatim,attributes"] ----- -Resources: - myBucket5AF9C99B: - Type: {aws}::S3::Bucket - Properties: - VersioningConfiguration: - Status: Enabled - UpdateReplacePolicy: Delete - DeletionPolicy: Delete - Metadata: - aws:cdk:path: S3BucketAppStack/myBucket/Resource ----- -+ -The following is an example of a custom construct named `Bar` that defines an Amazon S3 bucket. The `Bar` construct includes the custom construct `Foo` in its path: -+ -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -import * as cdk from 'aws-cdk-lib'; -import { Construct } from 'constructs'; -import * as s3 from 'aws-cdk-lib/aws-s3'; - -// Define the Bar construct -export class Bar extends Construct { - constructor(scope: Construct, id: string) { - super(scope, id); - - // Define an S3 bucket inside of Bar - new s3.Bucket(this, 'Bucket', { - versioned: true, - removalPolicy: cdk.RemovalPolicy.DESTROY, - } ); - } -} - -// Define the Foo construct -export class Foo extends Construct { - constructor(scope: Construct, id: string) { - super(scope, id); - - // Create an instance of Bar inside Foo - new Bar(this, 'Bar'); - } -} - -// Define the CDK stack -export class MyCustomAppStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - // Instantiate Foo construct in the stack - new Foo(this, 'Foo'); - } -} ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const cdk = require('aws-cdk-lib'); -const s3 = require('aws-cdk-lib/aws-s3'); -const { Construct } = require('constructs'); - -// Define the Bar construct -class Bar extends Construct { - constructor(scope, id) { - super(scope, id); - - // Define an S3 bucket inside of Bar - new s3.Bucket(this, 'Bucket', { - versioned: true, - removalPolicy: cdk.RemovalPolicy.DESTROY, - }); - } -} - -// Define the Foo construct -class Foo extends Construct { - constructor(scope, id) { - super(scope, id); - - // Create an instance of Bar inside Foo - new Bar(this, 'Bar'); - } -} - -// Define the CDK stack -class MyCustomAppStack extends cdk.Stack { - constructor(scope, id, props) { - super(scope, id, props); - - // Instantiate Foo construct in the stack - new Foo(this, 'Foo'); - } -} - -module.exports = { MyCustomAppStack } ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -import aws_cdk as cdk -from constructs import Construct -from aws_cdk import ( - Stack, - aws_s3 as s3, - RemovalPolicy, -) - -# Define the Bar construct -class Bar(Construct): - def __init__(self, scope: Construct, id: str) -> None: - super().__init__(scope, id) - - # Define an S3 bucket inside of Bar - s3.Bucket(self, 'Bucket', - versioned=True, - removal_policy=RemovalPolicy.DESTROY - ) - -# Define the Foo construct -class Foo(Construct): - def __init__(self, scope: Construct, id: str) -> None: - super().__init__(scope, id) - - # Create an instance of Bar inside Foo - Bar(self, 'Bar') - -# Define the CDK stack -class MyCustomAppStack(Stack): - def __init__(self, scope: Construct, id: str, **kwargs) -> None: - super().__init__(scope, id, **kwargs) - - # Instantiate Foo construct in the stack - Foo(self, 'Foo') ----- - -Java:: -In `my-custom-app/src/main/java/com/myorg/Bar.java`: -+ -[source,java,subs="verbatim,attributes"] ----- -package com.myorg; - -import software.constructs.Construct; -import software.amazon.awscdk.services.s3.Bucket; -import software.amazon.awscdk.services.s3.BucketProps; -import software.amazon.awscdk.RemovalPolicy; - -public class Bar extends Construct { - public Bar(final Construct scope, final String id) { - super(scope, id); - - // Define an S3 bucket inside Bar - Bucket.Builder.create(this, "Bucket") - .versioned(true) - .removalPolicy(RemovalPolicy.DESTROY) - .build(); - } -} ----- -+ -In `my-custom-app/src/main/java/com/myorg/Foo.java`: -+ -[source,java,subs="verbatim,attributes"] ----- -package com.myorg; - -import software.constructs.Construct; - -public class Foo extends Construct { - public Foo(final Construct scope, final String id) { - super(scope, id); - - // Create an instance of Bar inside Foo - new Bar(this, "Bar"); - } -} ----- -+ -In `my-custom-app/src/main/java/com/myorg/MyCustomAppStack.java`: -+ -[source,java,subs="verbatim,attributes"] ----- -package com.myorg; - -import software.constructs.Construct; -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.StackProps; - -public class MyCustomAppStack extends Stack { - public MyCustomAppStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - // Instantiate Foo construct in the stack - new Foo(this, "Foo"); - } - - // Overload constructor in case StackProps is not provided - public MyCustomAppStack(final Construct scope, final String id) { - this(scope, id, null); - } -} ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -using Amazon.CDK; -using Constructs; -using Amazon.CDK.{aws}.S3; - -namespace MyCustomApp -{ - // Define the Bar construct - public class Bar : Construct - { - public Bar(Construct scope, string id) : base(scope, id) - { - // Define an S3 bucket inside Bar - new Bucket(this, "Bucket", new BucketProps - { - Versioned = true, - RemovalPolicy = RemovalPolicy.DESTROY - }); - } - } - - // Define the Foo construct - public class Foo : Construct - { - public Foo(Construct scope, string id) : base(scope, id) - { - // Create an instance of Bar inside Foo - new Bar(this, "Bar"); - } - } - - // Define the CDK Stack - public class MyCustomAppStack : Stack - { - public MyCustomAppStack(Construct scope, string id, StackProps props = null) : base(scope, id, props) - { - // Instantiate Foo construct in the stack - new Foo(this, "Foo"); - } - } -} ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -package main - -import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/aws-cdk-go/awscdk/v2/awss3" - "github.com/aws/constructs-go/constructs/v10" - "github.com/aws/jsii-runtime-go" -) - -// Define the Bar construct -type Bar struct { - constructs.Construct -} - -func NewBar(scope constructs.Construct, id string) constructs.Construct { - bar := constructs.NewConstruct(scope, &id) - - // Define an S3 bucket inside Bar - awss3.NewBucket(bar, jsii.String("Bucket"), &awss3.BucketProps{ - Versioned: jsii.Bool(true), - RemovalPolicy: awscdk.RemovalPolicy_DESTROY, - }) - - return bar -} - -// Define the Foo construct -type Foo struct { - constructs.Construct -} - -func NewFoo(scope constructs.Construct, id string) constructs.Construct { - foo := constructs.NewConstruct(scope, &id) - - // Create an instance of Bar inside Foo - NewBar(foo, "Bar") - - return foo -} - -// Define the CDK Stack -type MyCustomAppStackProps struct { - awscdk.StackProps -} - -func NewMyCustomAppStack(scope constructs.Construct, id string, props *MyCustomAppStackProps) awscdk.Stack { - stack := awscdk.NewStack(scope, &id, &props.StackProps) - - // Instantiate Foo construct in the stack - NewFoo(stack, "Foo") - - return stack -} - -// Define the CDK App -func main() { - app := awscdk.NewApp(nil) - - NewMyCustomAppStack(app, "MyCustomAppStack", &MyCustomAppStackProps{ - StackProps: awscdk.StackProps{}, - }) - - app.Synth(nil) -} ----- -==== -+ -When we run `cdk synth`, a logical ID in the format of `FooBarBucket<unique-hash>` gets generated. The following is an example of this resource in the generated {aws} CloudFormation template: -+ -[source,yaml,subs="verbatim,attributes"] ----- -Resources: - FooBarBucketBA3ED1FA: - Type: {aws}::S3::Bucket - Properties: - VersioningConfiguration: - Status: Enabled - UpdateReplacePolicy: Delete - DeletionPolicy: Delete - # ... ----- - -[#bootstrapping-custom-synth] -== Customize CDK stack synthesis - -If the default CDK synthesis behavior doesn't suit your needs, you can customize CDK synthesis. To do this, you modify `DefaultStackSynthesizer`, use other available built-in synthesizers, or create your own synthesizer. For instructions, see xref:customize-synth[Customize CDK stack synthesis]. - -include::customize-synth.adoc[leveloffset=+1] \ No newline at end of file diff --git a/v2/guide/configure-synth/customize-synth.adoc b/v2/guide/configure-synth/customize-synth.adoc deleted file mode 100644 index d71c7996..00000000 --- a/v2/guide/configure-synth/customize-synth.adoc +++ /dev/null @@ -1,663 +0,0 @@ -include::../attributes.txt[] - -[.topic] -[#customize-synth] -= Customize CDK stack synthesis -:info_titleabbrev: Customize CDK synthesis -:keywords: {aws} CDK, {aws} CloudFormation stack, synthesis, cdk synth, {aws} CloudFormation template, Customize - -[abstract] --- -You can customize {aws} Cloud Development Kit ({aws} CDK) stack synthesis by modifying the default synthesizer, using other available built-in synthesizers, or create your own synthesizer. --- - -// Content start - -You can customize {aws} Cloud Development Kit ({aws} CDK) stack synthesis by modifying the default synthesizer, using other available built-in synthesizers, or creating your own synthesizer. - -The {aws} CDK includes the following built-in synthesizers that you can use to customize synthesis behavior: - -* link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.DefaultStackSynthesizer.html[`DefaultStackSynthesizer`] – If you don`'t specify a synthesizer, this one is used automatically. It supports cross-account deployments and deployments using the https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.pipelines-readme.html[CDK Pipelines] construct. Its bootstrap contract requires an existing Amazon S3 bucket with a known name, an existing Amazon ECR repository with a known name, and five existing IAM roles with known names. The default bootstrapping template meets these requirements. -* link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.CliCredentialsStackSynthesizer.html[`CliCredentialsStackSynthesizer`] – This synthesizer's bootstrap contract requires an existing Amazon S3 bucket and existing Amazon ECR repository. It does not require any IAM roles. To perform deployments, this synthesizer relies on the permissions of the CDK CLI user and is recommend for organizations that want to restrict IAM deployment credentials. This synthesizer doesn't support cross-account deployments or CDK Pipelines. -* link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.LegacyStackSynthesizer.html[`LegacyStackSynthesizer`] – This synthesizer emulates CDK v1 synthesis behavior. Its bootstrap contract requires an existing Amazon S3 bucket of an arbitrary name and expects the locations of assets to be passed in as CloudFormation stack parameters. If you use this synthesizer, you must use the CDK CLI to perform deployment. - -If none of these built-in synthesizers are appropriate for your use case, you can write your own synthesizer as a class that implements `IStackSynthesizer` or look at link:https://constructs.dev/search?q=synthesizer&cdk=aws-cdk[synthesizers] from the Construct Hub. - -[#bootstrapping-custom-synth-default] -== Customize the `DefaultStackSynthesizer` - -The `DefaultStackSynthesizer` is the default synthesizer for the {aws} CDK. It is designed to allow cross-account deployments of CDK applications, as well as deploying CDK apps from a CI/CD system that does not have explicit support for the {aws} CDK, but supports regular CloudFormation deployments, such as {aws} CodePipeline. This synthesizer is the best option for most use cases. - -[#bootstrapping-custom-synth-default-contract] -=== `DefaultStackSynthesizer` bootstrap contract - -`DefaultStackSynthesizer` requires the following bootstrap contract. These are the resources that must be created during bootstrapping: - -[cols="1,1,1,1", frame="all", options="header"] -|=== -| Bootstrap resource -| Description -| Default expected resource name -| Purpose - -|Amazon S3 bucket -|Staging bucket -|cdk-hnb659fds-assets-<ACCOUNT>-<REGION> -|Stores file assets. - -|Amazon ECR repository -|Staging repository -|cdk-hnb659fds-container-assets-<ACCOUNT>-<REGION> -|Stores and manages Docker image assets. - -|IAM role -|Deploy role -|cdk-hnb659fds-deploy-role-<ACCOUNT>-<REGION> -|Assumed by the CDK CLI and potentially CodePipeline to assume other roles and start the {aws} CloudFormation deployment. - -The trust policy of this role controls who can deploy with the {aws} CDK in this {aws} environment. - -|IAM role -|{aws} CloudFormation execution role -|cdk-hnb659fds-cfn-exec-role-<ACCOUNT>-<REGION> -|This role is used by {aws} CloudFormation to perform the deployment. - -The policies of this role control what operations the CDK deployment can perform. - -|IAM role -|Lookup role -|cdk-hnb659fds-lookup-role-<ACCOUNT>-<REGION> -|This role is used when the CDK CLI needs to perform environmental context lookups. - -The trust policy of this role controls who can look up information in the environment. - -|IAM role -|File publishing role -|cdk-hnb659fds-file-publishing-role-<ACCOUNT>-<REGION> -|This role is used to upload assets to the Amazon S3 staging bucket. It is assumed from the deploy role. - -|IAM role -|Image publishing role -|cdk-hnb659fds-image-publishing-role-<ACCOUNT>-<REGION> -|This role is used to upload Docker images to the Amazon ECR staging repository. It is assumed from the deploy role. - -|SSM parameter -|Bootstrap version parameter -|/cdk-bootstrap/hnb659fds/<version> -|The version of the bootstrap template. It is used by the bootstrap template and the CDK CLI to validate requirements. -|=== - -One way to customize CDK stack synthesis, is by modifying the link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.DefaultStackSynthesizer.html[`DefaultStackSynthesizer`]. You can customize this synthesizer for a single CDK stack using the `synthesizer` property of your `Stack` instance. You can also modify `DefaultStackSynthesizer` for all stacks in your CDK app using the `defaultStackSynthesizer` property of your `App` instance. - -[#bootstrapping-custom-synth-qualifiers] -=== Change the qualifier - -The _qualifier_ is added to the name of resources created during bootstrapping. By default, this value is `hnb659fds`. When you modify the qualifier during bootstrapping, you need to customize CDK stack synthesis to use the same qualifier. - -To change the qualifier, configure the `qualifier` property of `DefaultStackSynthesizer` or configure the qualifier as a context key in your CDK project`'s `cdk.json` file. - -The following is an example of configuring the `qualifier` property of the `DefaultStackSynthesizer`: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -new MyStack(this, 'MyStack', { - synthesizer: new DefaultStackSynthesizer({ - qualifier: 'MYQUALIFIER', - }), -}); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -new MyStack(this, 'MyStack', { - synthesizer: new DefaultStackSynthesizer({ - qualifier: 'MYQUALIFIER', - }), -}) ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -MyStack(self, "MyStack", - synthesizer=DefaultStackSynthesizer( - qualifier="MYQUALIFIER" -)) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -new MyStack(app, "MyStack", StackProps.builder() - .synthesizer(DefaultStackSynthesizer.Builder.create() - .qualifier("MYQUALIFIER") - .build()) - .build(); -) ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -new MyStack(app, "MyStack", new StackProps -{ - Synthesizer = new DefaultStackSynthesizer(new DefaultStackSynthesizerProps - { - Qualifier = "MYQUALIFIER" - }) -}); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -func NewMyStack(scope constructs.Construct, id string, props *MyStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - stack := awscdk.NewStack(scope, &id, &sprops) - - synth := awscdk.NewDefaultStackSynthesizer(&awscdk.DefaultStackSynthesizerProps{ - Qualifier: jsii.String("MYQUALIFIER"), - }) - - stack.SetSynthesizer(synth) - - return stack -} ----- -==== - -The following is an example of configuring the qualifier as a context key in `cdk.json`: - -[source,json,subs="verbatim,attributes"] ----- -{ - "app": "...", - "context": { - "@aws-cdk/core:bootstrapQualifier": "MYQUALIFIER" - } -} ----- - -[#bootstrapping-custom-synth-names] -=== Change resource names - -All of the other `DefaultStackSynthesizer` properties relate to the names of the resources in the bootstrap template. You only need to provide any of these properties if you modified the bootstrap template and changed the resource names or naming scheme. - -All properties accept the special placeholders `${Qualifier}`, `${AWS::Partition}`, `${AWS::AccountId}`, and `${AWS::Region}`. These placeholders are replaced with the values of the `qualifier` parameter and the {aws} partition, account ID, and {aws} Region values for the stack's environment, respectively. - -The following example shows the most commonly used properties for `DefaultStackSynthesizer` along with their default values, as if you were instantiating the synthesizer. For a complete list, see link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.DefaultStackSynthesizerProps.html#properties[`DefaultStackSynthesizerProps`]: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript] ----- -new DefaultStackSynthesizer({ - // Name of the S3 bucket for file assets - fileAssetsBucketName: 'cdk-${Qualifier}-assets-${AWS::AccountId}-${AWS::Region}', - bucketPrefix: '', - - // Name of the ECR repository for Docker image assets - imageAssetsRepositoryName: 'cdk-${Qualifier}-container-assets-${AWS::AccountId}-${AWS::Region}', - dockerTagPrefix: '', - - // ARN of the role assumed by the CLI and Pipeline to deploy here - deployRoleArn: 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-deploy-role-${AWS::AccountId}-${AWS::Region}', - deployRoleExternalId: '', - - // ARN of the role used for file asset publishing (assumed from the CLI role) - fileAssetPublishingRoleArn: 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-file-publishing-role-${AWS::AccountId}-${AWS::Region}', - fileAssetPublishingExternalId: '', - - // ARN of the role used for Docker asset publishing (assumed from the CLI role) - imageAssetPublishingRoleArn: 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-image-publishing-role-${AWS::AccountId}-${AWS::Region}', - imageAssetPublishingExternalId: '', - - // ARN of the role passed to CloudFormation to execute the deployments - cloudFormationExecutionRole: 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-cfn-exec-role-${AWS::AccountId}-${AWS::Region}', - - // ARN of the role used to look up context information in an environment - lookupRoleArn: 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-lookup-role-${AWS::AccountId}-${AWS::Region}', - lookupRoleExternalId: '', - - // Name of the SSM parameter which describes the bootstrap stack version number - bootstrapStackVersionSsmParameter: '/cdk-bootstrap/${Qualifier}/version', - - // Add a rule to every template which verifies the required bootstrap stack version - generateBootstrapVersionRule: true, - -}) ----- - -JavaScript:: -+ -[source,javascript] ----- -new DefaultStackSynthesizer({ - // Name of the S3 bucket for file assets - fileAssetsBucketName: 'cdk-${Qualifier}-assets-${AWS::AccountId}-${AWS::Region}', - bucketPrefix: '', - - // Name of the ECR repository for Docker image assets - imageAssetsRepositoryName: 'cdk-${Qualifier}-container-assets-${AWS::AccountId}-${AWS::Region}', - dockerTagPrefix: '', - - // ARN of the role assumed by the CLI and Pipeline to deploy here - deployRoleArn: 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-deploy-role-${AWS::AccountId}-${AWS::Region}', - deployRoleExternalId: '', - - // ARN of the role used for file asset publishing (assumed from the CLI role) - fileAssetPublishingRoleArn: 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-file-publishing-role-${AWS::AccountId}-${AWS::Region}', - fileAssetPublishingExternalId: '', - - // ARN of the role used for Docker asset publishing (assumed from the CLI role) - imageAssetPublishingRoleArn: 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-image-publishing-role-${AWS::AccountId}-${AWS::Region}', - imageAssetPublishingExternalId: '', - - // ARN of the role passed to CloudFormation to execute the deployments - cloudFormationExecutionRole: 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-cfn-exec-role-${AWS::AccountId}-${AWS::Region}', - - // ARN of the role used to look up context information in an environment - lookupRoleArn: 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-lookup-role-${AWS::AccountId}-${AWS::Region}', - lookupRoleExternalId: '', - - // Name of the SSM parameter which describes the bootstrap stack version number - bootstrapStackVersionSsmParameter: '/cdk-bootstrap/${Qualifier}/version', - - // Add a rule to every template which verifies the required bootstrap stack version - generateBootstrapVersionRule: true, -}) ----- - -Python:: -+ -[source,python] ----- -DefaultStackSynthesizer( - # Name of the S3 bucket for file assets - file_assets_bucket_name="cdk-${Qualifier}-assets-${AWS::AccountId}-${AWS::Region}", - bucket_prefix="", - - # Name of the ECR repository for Docker image assets - image_assets_repository_name="cdk-${Qualifier}-container-assets-${AWS::AccountId}-${AWS::Region}", - docker_tag_prefix="", - - # ARN of the role assumed by the CLI and Pipeline to deploy here - deploy_role_arn="arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-deploy-role-${AWS::AccountId}-${AWS::Region}", - deploy_role_external_id="", - - # ARN of the role used for file asset publishing (assumed from the CLI role) - file_asset_publishing_role_arn="arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-file-publishing-role-${AWS::AccountId}-${AWS::Region}", - file_asset_publishing_external_id="", - - # ARN of the role used for Docker asset publishing (assumed from the CLI role) - image_asset_publishing_role_arn="arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-image-publishing-role-${AWS::AccountId}-${AWS::Region}", - image_asset_publishing_external_id="", - - # ARN of the role passed to CloudFormation to execute the deployments - cloud_formation_execution_role="arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - - # ARN of the role used to look up context information in an environment - lookup_role_arn="arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-lookup-role-${AWS::AccountId}-${AWS::Region}", - lookup_role_external_id="", - - # Name of the SSM parameter which describes the bootstrap stack version number - bootstrap_stack_version_ssm_parameter="/cdk-bootstrap/${Qualifier}/version", - - # Add a rule to every template which verifies the required bootstrap stack version - generate_bootstrap_version_rule=True, -) ----- - -Java:: -+ -[source,java] ----- -DefaultStackSynthesizer.Builder.create() - // Name of the S3 bucket for file assets - .fileAssetsBucketName("cdk-${Qualifier}-assets-${AWS::AccountId}-${AWS::Region}") - .bucketPrefix('') - - // Name of the ECR repository for Docker image assets - .imageAssetsRepositoryName("cdk-${Qualifier}-container-assets-${AWS::AccountId}-${AWS::Region}") - .dockerTagPrefix('') - - // ARN of the role assumed by the CLI and Pipeline to deploy here - .deployRoleArn("arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-deploy-role-${AWS::AccountId}-${AWS::Region}") - .deployRoleExternalId("") - - // ARN of the role used for file asset publishing (assumed from the CLI role) - .fileAssetPublishingRoleArn("arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-file-publishing-role-${AWS::AccountId}-${AWS::Region}") - .fileAssetPublishingExternalId("") - - // ARN of the role used for Docker asset publishing (assumed from the CLI role) - .imageAssetPublishingRoleArn("arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-image-publishing-role-${AWS::AccountId}-${AWS::Region}") - .imageAssetPublishingExternalId("") - - // ARN of the role passed to CloudFormation to execute the deployments - .cloudFormationExecutionRole("arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-cfn-exec-role-${AWS::AccountId}-${AWS::Region}") - - .lookupRoleArn("arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-lookup-role-${AWS::AccountId}-${AWS::Region}") - .lookupRoleExternalId("") - - // Name of the SSM parameter which describes the bootstrap stack version number - .bootstrapStackVersionSsmParameter("/cdk-bootstrap/${Qualifier}/version") - - // Add a rule to every template which verifies the required bootstrap stack version - .generateBootstrapVersionRule(true) -.build() ----- - -C#:: -+ -[source,csharp] ----- -new DefaultStackSynthesizer(new DefaultStackSynthesizerProps -{ - // Name of the S3 bucket for file assets - FileAssetsBucketName = "cdk-${Qualifier}-assets-${AWS::AccountId}-${AWS::Region}", - BucketPrefix = "", - - // Name of the ECR repository for Docker image assets - ImageAssetsRepositoryName = "cdk-${Qualifier}-container-assets-${AWS::AccountId}-${AWS::Region}", - DockerTagPrefix = "", - - // ARN of the role assumed by the CLI and Pipeline to deploy here - DeployRoleArn = "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-deploy-role-${AWS::AccountId}-${AWS::Region}", - DeployRoleExternalId = "", - - // ARN of the role used for file asset publishing (assumed from the CLI role) - FileAssetPublishingRoleArn = "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-file-publishing-role-${AWS::AccountId}-${AWS::Region}", - FileAssetPublishingExternalId = "", - - // ARN of the role used for Docker asset publishing (assumed from the CLI role) - ImageAssetPublishingRoleArn = "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-image-publishing-role-${AWS::AccountId}-${AWS::Region}", - ImageAssetPublishingExternalId = "", - - // ARN of the role passed to CloudFormation to execute the deployments - CloudFormationExecutionRole = "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - - LookupRoleArn = "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-lookup-role-${AWS::AccountId}-${AWS::Region}", - LookupRoleExternalId = "", - - // Name of the SSM parameter which describes the bootstrap stack version number - BootstrapStackVersionSsmParameter = "/cdk-bootstrap/${Qualifier}/version", - - // Add a rule to every template which verifies the required bootstrap stack version - GenerateBootstrapVersionRule = true, -}) ----- -==== - -[#bootstrapping-custom-synth-cli] -== Use `CliCredentialsStackSynthesizer` - -To modify the security credentials used to provide permissions during CDK deployments, you can customize synthesis by using link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.CliCredentialsStackSynthesizer.html[`CliCredentialsStackSynthesizer`]. This synthesizer works with the default {aws} resources that are created during bootstrapping to store assets, such as the Amazon S3 bucket and Amazon ECR repository. Instead of using the default IAM roles created by the CDK during bootstrapping, it uses the security credentials of the actor initiating deployment. Therefore, the security credentials of the actor must have valid permissions to perform all deployment actions. The following diagram illustrates the deployment process when using this synthesizer: - -image::images/CliCredentialsStackSynthesizer-deploy-process_cdk_flowchart.png[Flowchart of the default {aws} CDK deployment process.] - -When using `CliCredentialsStackSynthesizer`: - -* By default, CloudFormation performs API calls in your account using the permissions of the actor. Therefore, the current identity must have permission to make necessary changes to the {aws} resources in the CloudFormation stack, along with the permissions to perform necessary CloudFormation operations, such as `CreateStack` or `UpdateStack`. Deployment capabilities will be limited to the permissions of the actor. -* Asset publishing and CloudFormation deployments will be done using the current IAM identity. This identity must have sufficient permissions to both read from and write to the asset bucket and repository. -* Lookups are performed using the current IAM identity, and lookups are subject to its policies. - -When using this synthesizer, you can use a separate CloudFormation execution role by specifying it using the xref:ref-cli-cmd-options-role-arn[`--role-arn`] option with any CDK CLI command. - -[#bootstrapping-custom-synth-cli-contract] -=== `CliCredentialsStackSynthesizer` bootstrap contract - -`CliCredentialsStackSynthesizer` requires the following bootstrap contract. These are the resources that must be created during bootstrapping: - -[cols="1,1,1,1", frame="all", options="header"] -|=== -| Bootstrap resource -| Description -| Default expected resource name -| Purpose - -|Amazon S3 bucket -|Staging bucket -|cdk-hnb659fds-assets-<ACCOUNT>-<REGION> -|Stores file assets. - -|Amazon ECR repository -|Staging repository -|cdk-hnb659fds-container-assets-<ACCOUNT>-<REGION> -|Stores and manages Docker image assets. -|=== - -The string `hnb659fds` in the resource name is called the _qualifier_. Its default value has no special significance. You can have multiple copies of the bootstrap resources in a single environment as long as they have a different qualifier. Having multiple copies can be useful for keeping assets of different applications in the same environment separated. - -You can deploy the default bootstrap template to satisfy ``CliCredentialsStackSynthesizer``'s bootstrap contract. The default bootstrap template will create IAM roles, but this synthesizer will not use them. You can also customize the bootstrap template to remove the IAM roles. - -[#bootstrapping-custom-synth-cli-modify] -=== Modify `CliCredentialsStackSynthesizer` - -If you change the qualifier or any of the default bootstrap resource names during bootstrapping, you have to modify the synthesizer to use the same names. You can modify the synthesizer for a single stack or for all stacks in your app. The following is an example: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript] ----- -new MyStack(this, 'MyStack', { - synthesizer: new CliCredentialsStackSynthesizer({ - qualifier: 'MYQUALIFIER', - }), -}); ----- - -JavaScript:: -+ -[source,javascript] ----- -new MyStack(this, 'MyStack', { - synthesizer: new CliCredentialsStackSynthesizer({ - qualifier: 'MYQUALIFIER', - }), -}) ----- - -Python:: -+ -[source,python] ----- -MyStack(self, "MyStack", - synthesizer=CliCredentialsStackSynthesizer( - qualifier="MYQUALIFIER" -)) ----- - -Java:: -+ -[source,java] ----- -new MyStack(app, "MyStack", StackProps.builder() - .synthesizer(CliCredentialsStackSynthesizer.Builder.create() - .qualifier("MYQUALIFIER") - .build()) - .build(); -) ----- - -C#:: -+ -[source,csharp] ----- -new MyStack(app, "MyStack", new StackProps -{ - Synthesizer = new CliCredentialsStackSynthesizer(new CliCredentialsStackSynthesizerProps - { - Qualifier = "MYQUALIFIER" - }) -}); ----- -==== - -The following example shows the most commonly used properties for `CliCredentialsStackSynthesizer` along with their default values. For a complete list, see link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.CliCredentialsStackSynthesizerProps.html[`CliCredentialsStackSynthesizerProps`]: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript] ----- -new CliCredentialsStackSynthesizer({ - // Value for '${Qualifier}' in the resource names - qualifier: 'hnb659fds', - - // Name of the S3 bucket for file assets - fileAssetsBucketName: 'cdk-${Qualifier}-assets-${AWS::AccountId}-${AWS::Region}', - bucketPrefix: '', - - // Name of the ECR repository for Docker image assets - imageAssetsRepositoryName: 'cdk-${Qualifier}-container-assets-${AWS::AccountId}-${AWS::Region}', - dockerTagPrefix: '', -}) ----- - -JavaScript:: -+ -[source,javascript] ----- -new CliCredentialsStackSynthesizer({ - // Value for '${Qualifier}' in the resource names - qualifier: 'hnb659fds', - - // Name of the S3 bucket for file assets - fileAssetsBucketName: 'cdk-${Qualifier}-assets-${AWS::AccountId}-${AWS::Region}', - bucketPrefix: '', - - // Name of the ECR repository for Docker image assets - imageAssetsRepositoryName: 'cdk-${Qualifier}-container-assets-${AWS::AccountId}-${AWS::Region}', - dockerTagPrefix: '', -}) ----- - -Python:: -+ -[source,python] ----- -CliCredentialsStackSynthesizer( - # Value for '${Qualifier}' in the resource names - qualifier="hnb659fds", - - # Name of the S3 bucket for file assets - file_assets_bucket_name="cdk-${Qualifier}-assets-${AWS::AccountId}-${AWS::Region}", - bucket_prefix="", - - # Name of the ECR repository for Docker image assets - image_assets_repository_name="cdk-${Qualifier}-container-assets-${AWS::AccountId}-${AWS::Region}", - docker_tag_prefix="", -) ----- - -Java:: -+ -[source,java] ----- -CliCredentialsStackSynthesizer.Builder.create() - // Value for '${Qualifier}' in the resource names - .qualifier("hnb659fds") - - // Name of the S3 bucket for file assets - .fileAssetsBucketName("cdk-${Qualifier}-assets-${AWS::AccountId}-${AWS::Region}") - .bucketPrefix('') - - // Name of the ECR repository for Docker image assets - .imageAssetsRepositoryName("cdk-${Qualifier}-container-assets-${AWS::AccountId}-${AWS::Region}") - .dockerTagPrefix('') -.build() ----- - -C#:: -+ -[source,csharp] ----- -new CliCredentialsStackSynthesizer(new CliCredentialsStackSynthesizerProps -{ - - // Value for '${Qualifier}' in the resource names - Qualifier = "hnb659fds", - - // Name of the S3 bucket for file assets - FileAssetsBucketName = "cdk-${Qualifier}-assets-${AWS::AccountId}-${AWS::Region}", - BucketPrefix = "", - - // Name of the ECR repository for Docker image assets - ImageAssetsRepositoryName = "cdk-${Qualifier}-container-assets-${AWS::AccountId}-${AWS::Region}", - DockerTagPrefix = "", -}) ----- -==== - -[#bootstrapping-custom-synth-legacy] -== Use `LegacyStackSynthesizer` - -The `LegacyStackSynthesizer` emulates the behavior of CDK v1 deployments. The security credentials of the actor performing deployment will be used to establish permissions. File assets will be uploaded to a bucket that must be created using a {aws} CloudFormation stack named `CDKToolkit`. The CDK CLI will create an unmanaged Amazon ECR repository named `aws-cdk/assets` to store Docker image assets. You will be responsible to clean up and manage this repository. Stacks synthesized using the `LegacyStackSynthesizer` can only be deployed using the CDK CLI. - -You can use the `LegacyStackSynthesizer` if you are migrating from CDK v1 to CDK v2, and are unable to re-bootstrap your environments. For new projects, we recommend that you don't use `LegacyStackSynthesizer`. - -[#bootstrapping-custom-synth-legacy-contract] -=== `LegacyStackSynthesizer` bootstrap contract - -`LegacyStackSynthesizer` requires the following bootstrap contract. These are the resources that must be created during bootstrapping: - -[cols="1,1,1,1", frame="all", options="header"] -|=== -| Bootstrap resource -| Description -| Default expected resource name -| Purpose - -|Amazon S3 bucket -|Staging bucket -|cdk-hnb659fds-assets-<ACCOUNT>-<REGION> -|Stores file assets. - -|CloudFormation output -|Bucket name output -|Stack – `CDKToolkit` - -Output name – `BucketName` -| - -A CloudFormation output describing the name of the staging bucket -|=== - -The `LegacyStackSynthesizer` does not assume the existence of an Amazon S3 bucket with a fixed name. Instead, the synthesized CloudFormation template will contain three CloudFormation parameters for each file asset. These parameters will store the Amazon S3 bucket name, Amazon S3 object key, and artifact hash for each file asset. - -[noloc]``Docker`` image assets will be published to an Amazon ECR repository named ``aws-cdk/assets``. This name can be changed per asset. The repositories will be created if they do not exist. - -A CloudFormation stack must exist with the default name ``CDKToolkit``. This stack must have a CloudFormation export named `BucketName` that refers to the staging bucket. - -The default bootstrap template satisfies the `LegacyStackSynthesizer` bootstrap contract. However, only the Amazon S3 bucket from the bootstrap resources of the bootstrap template will be used. You can customize the bootstrap template to remove the Amazon ECR, IAM, and SSM bootstrap resources. - -[[bootstrapping-custom-synth-legacy-deploy,bootstrapping-custom-synth-legacy-deploy.title]] -=== `LegacyStackSynthesizer` deployment process - -When you use this synthesizer, the following process is performed during deployment: - - - -* The CDK [noloc]``CLI`` looks for a CloudFormation stack named `CDKToolkit` in your environment. From this stack, the CDK [noloc]``CLI`` reads the CloudFormation output named ``BucketName``. You can use the `--toolkit-stack-name` option with `cdk deploy` to specify a different stack name. -* The security credentials of the actor initiating deployment will be used to establish permissions for deployment. Therefore, the actor must have sufficient permissions to perform all deployment actions. This includes reading and writing to the Amazon S3 staging bucket, creating and writing to the Amazon ECR repository, starting and monitoring {aws} CloudFormation deployments, and performing any API calls necessary for deployment. -* If necessary, and if permissions are valid, file assets will be published to the Amazon S3 staging bucket. -* If necessary, and if permissions are valid, [noloc]``Docker`` image assets are published to the repository named by the `repositoryName` property of the asset. The default value is `'aws-cdk/assets'` if you don`'t provide a repository name. -* If permissions are valid, the {aws} CloudFormation deployment is performed. The locations of the Amazon S3 staging bucket and keys are passed as CloudFormation parameters. \ No newline at end of file diff --git a/v2/guide/configure-synth/images/CliCredentialsStackSynthesizer-deploy-process_cdk_flowchart.png b/v2/guide/configure-synth/images/CliCredentialsStackSynthesizer-deploy-process_cdk_flowchart.png deleted file mode 100644 index 69866507..00000000 Binary files a/v2/guide/configure-synth/images/CliCredentialsStackSynthesizer-deploy-process_cdk_flowchart.png and /dev/null differ diff --git a/v2/guide/configure-synth/images/CliCredentialsStackSynthesizer-deploy-process_cdk_flowchart.svg b/v2/guide/configure-synth/images/CliCredentialsStackSynthesizer-deploy-process_cdk_flowchart.svg deleted file mode 100644 index 36874724..00000000 --- a/v2/guide/configure-synth/images/CliCredentialsStackSynthesizer-deploy-process_cdk_flowchart.svg +++ /dev/null @@ -1,70 +0,0 @@ -<svg width="1328" height="452" viewBox="0 0 1328 452" fill="none" xmlns="http://www.w3.org/2000/svg"> -<rect width="1328" height="452" fill="white"/> -<rect x="11" y="11" width="1306" height="430" rx="19" stroke="black" stroke-width="2"/> -<path d="M312 111L312 110L311 110L39 110L38 110L38 111L38 405C38 411.075 42.9249 416 49 416L301 416C307.075 416 312 411.075 312 405L312 111Z" fill="white" stroke="#000716" stroke-width="2"/> -<path d="M1015 111L1015 110L1014 110L313 110L312 110L312 111L312 405C312 411.075 316.925 416 323 416L1004 416C1010.08 416 1015 411.075 1015 405L1015 111Z" fill="white" stroke="#000716" stroke-width="2"/> -<path d="M1290 111L1290 110L1289 110L1016 110L1015 110L1015 111L1015 405C1015 411.075 1019.92 416 1026 416L1279 416C1285.08 416 1290 411.075 1290 405L1290 111Z" fill="white" stroke="#000716" stroke-width="2"/> -<mask id="path-5-outside-1_18_1526" maskUnits="userSpaceOnUse" x="310" y="37" width="706" height="74" fill="black"> -<rect fill="white" x="310" y="37" width="706" height="74"/> -<path d="M312 49C312 43.4771 316.477 39 322 39L1004 39C1009.52 39 1014 43.4771 1014 49L1014 109L312 109L312 49Z"/> -</mask> -<path d="M312 49C312 43.4771 316.477 39 322 39L1004 39C1009.52 39 1014 43.4771 1014 49L1014 109L312 109L312 49Z" fill="#033160"/> -<path d="M1014 109L1014 111L1016 111L1016 109L1014 109ZM312 109L310 109L310 111L312 111L312 109ZM322 41L1004 41L1004 37L322 37L322 41ZM1012 49L1012 109L1016 109L1016 49L1012 49ZM1014 107L312 107L312 111L1014 111L1014 107ZM314 109L314 49L310 49L310 109L314 109ZM1004 41C1008.42 41 1012 44.5817 1012 49L1016 49C1016 42.3726 1010.63 37 1004 37L1004 41ZM322 37C315.373 37 310 42.3726 310 49L314 49C314 44.5817 317.582 41 322 41L322 37Z" fill="#000716" mask="url(#path-5-outside-1_18_1526)"/> -<path d="M550.165 76.446L550.165 81L547.537 81L547.537 68.526L552.307 68.526C553.603 68.526 554.629 68.88 555.385 69.588C556.141 70.296 556.519 71.262 556.519 72.486C556.519 73.71 556.141 74.676 555.385 75.384C554.629 76.092 553.603 76.446 552.307 76.446L550.165 76.446ZM550.165 74.43L552.001 74.43C552.601 74.43 553.057 74.268 553.369 73.944C553.693 73.608 553.855 73.122 553.855 72.486C553.855 71.85 553.693 71.37 553.369 71.046C553.057 70.71 552.601 70.542 552.001 70.542L550.165 70.542L550.165 74.43ZM560.287 77.04C560.335 77.832 560.575 78.408 561.007 78.768C561.439 79.116 562.117 79.29 563.041 79.29C563.845 79.29 564.781 79.14 565.849 78.84L565.849 80.586C565.429 80.802 564.925 80.97 564.337 81.09C563.761 81.21 563.161 81.27 562.537 81.27C561.013 81.27 559.849 80.856 559.045 80.028C558.253 79.2 557.857 77.988 557.857 76.392C557.857 74.856 558.253 73.662 559.045 72.81C559.837 71.958 560.935 71.532 562.339 71.532C563.527 71.532 564.439 71.862 565.075 72.522C565.723 73.17 566.047 74.1 566.047 75.312C566.047 75.576 566.029 75.876 565.993 76.212C565.957 76.548 565.915 76.824 565.867 77.04L560.287 77.04ZM562.249 73.35C561.661 73.35 561.193 73.53 560.845 73.89C560.509 74.238 560.317 74.748 560.269 75.42L563.797 75.42L563.797 75.114C563.797 73.938 563.281 73.35 562.249 73.35ZM568.064 81L568.064 71.802L570.224 71.802L570.548 73.17C571.028 72.642 571.478 72.27 571.898 72.054C572.33 71.826 572.786 71.712 573.266 71.712C573.494 71.712 573.734 71.73 573.986 71.766L573.986 74.196C573.65 74.124 573.278 74.088 572.87 74.088C572.09 74.088 571.364 74.226 570.692 74.502L570.692 81L568.064 81ZM586.753 81L586.753 74.772C586.753 73.956 586.387 73.548 585.655 73.548C585.007 73.548 584.353 73.704 583.693 74.016L583.693 74.196L583.693 81L581.065 81L581.065 74.772C581.065 73.956 580.699 73.548 579.967 73.548C579.295 73.548 578.635 73.71 577.987 74.034L577.987 81L575.359 81L575.359 71.802L577.519 71.802L577.753 72.684C578.389 72.264 578.959 71.97 579.463 71.802C579.979 71.622 580.507 71.532 581.047 71.532C582.127 71.532 582.889 71.916 583.333 72.684C583.945 72.276 584.521 71.982 585.061 71.802C585.601 71.622 586.159 71.532 586.735 71.532C587.575 71.532 588.223 71.766 588.679 72.234C589.147 72.702 589.381 73.356 589.381 74.196L589.381 81L586.753 81ZM591.936 81L591.936 71.802L594.564 71.802L594.564 81L591.936 81ZM593.25 70.38C592.794 70.38 592.428 70.254 592.152 70.002C591.876 69.75 591.738 69.408 591.738 68.976C591.738 68.544 591.876 68.202 592.152 67.95C592.428 67.698 592.794 67.572 593.25 67.572C593.706 67.572 594.072 67.698 594.348 67.95C594.624 68.202 594.762 68.544 594.762 68.976C594.762 69.408 594.624 69.75 594.348 70.002C594.072 70.254 593.706 70.38 593.25 70.38ZM601.062 78.462C601.062 78.222 600.99 78.036 600.846 77.904C600.714 77.772 600.438 77.628 600.018 77.472L598.614 76.914C597.882 76.626 597.354 76.272 597.03 75.852C596.706 75.432 596.544 74.898 596.544 74.25C596.544 73.434 596.868 72.78 597.516 72.288C598.176 71.784 599.052 71.532 600.144 71.532C601.152 71.532 602.082 71.73 602.934 72.126L602.934 73.872C602.022 73.596 601.17 73.458 600.378 73.458C599.886 73.458 599.526 73.518 599.298 73.638C599.07 73.758 598.956 73.95 598.956 74.214C598.956 74.418 599.022 74.586 599.154 74.718C599.298 74.838 599.592 74.988 600.036 75.168L601.404 75.726C602.148 76.026 602.676 76.374 602.988 76.77C603.312 77.166 603.474 77.682 603.474 78.318C603.474 79.206 603.132 79.926 602.448 80.478C601.776 81.018 600.888 81.288 599.784 81.288C598.548 81.288 597.456 81.042 596.508 80.55L596.508 78.804C597.696 79.176 598.782 79.362 599.766 79.362C600.63 79.362 601.062 79.062 601.062 78.462ZM609.077 78.462C609.077 78.222 609.005 78.036 608.861 77.904C608.729 77.772 608.453 77.628 608.033 77.472L606.629 76.914C605.897 76.626 605.369 76.272 605.045 75.852C604.721 75.432 604.559 74.898 604.559 74.25C604.559 73.434 604.883 72.78 605.531 72.288C606.191 71.784 607.067 71.532 608.159 71.532C609.167 71.532 610.097 71.73 610.949 72.126L610.949 73.872C610.037 73.596 609.185 73.458 608.393 73.458C607.901 73.458 607.541 73.518 607.313 73.638C607.085 73.758 606.971 73.95 606.971 74.214C606.971 74.418 607.037 74.586 607.169 74.718C607.313 74.838 607.607 74.988 608.051 75.168L609.419 75.726C610.163 76.026 610.691 76.374 611.003 76.77C611.327 77.166 611.489 77.682 611.489 78.318C611.489 79.206 611.147 79.926 610.463 80.478C609.791 81.018 608.903 81.288 607.799 81.288C606.563 81.288 605.471 81.042 604.523 80.55L604.523 78.804C605.711 79.176 606.797 79.362 607.781 79.362C608.645 79.362 609.077 79.062 609.077 78.462ZM613.259 81L613.259 71.802L615.887 71.802L615.887 81L613.259 81ZM614.573 70.38C614.117 70.38 613.751 70.254 613.475 70.002C613.199 69.75 613.061 69.408 613.061 68.976C613.061 68.544 613.199 68.202 613.475 67.95C613.751 67.698 614.117 67.572 614.573 67.572C615.029 67.572 615.395 67.698 615.671 67.95C615.947 68.202 616.085 68.544 616.085 68.976C616.085 69.408 615.947 69.75 615.671 70.002C615.395 70.254 615.029 70.38 614.573 70.38ZM622.564 81.27C621.136 81.27 620.02 80.844 619.216 79.992C618.412 79.128 618.01 77.928 618.01 76.392C618.01 74.868 618.412 73.68 619.216 72.828C620.02 71.964 621.136 71.532 622.564 71.532C623.992 71.532 625.108 71.964 625.912 72.828C626.716 73.68 627.118 74.868 627.118 76.392C627.118 77.928 626.716 79.128 625.912 79.992C625.108 80.844 623.992 81.27 622.564 81.27ZM622.564 79.254C623.824 79.254 624.454 78.3 624.454 76.392C624.454 74.496 623.824 73.548 622.564 73.548C621.304 73.548 620.674 74.496 620.674 76.392C620.674 78.3 621.304 79.254 622.564 79.254ZM635.069 81L635.069 74.97C635.069 74.478 634.961 74.118 634.745 73.89C634.529 73.662 634.199 73.548 633.755 73.548C633.095 73.548 632.441 73.752 631.793 74.16L631.793 81L629.165 81L629.165 71.802L631.325 71.802L631.577 72.792C632.657 71.952 633.809 71.532 635.033 71.532C635.885 71.532 636.539 71.766 636.995 72.234C637.463 72.69 637.697 73.344 637.697 74.196L637.697 81L635.069 81ZM644.093 78.462C644.093 78.222 644.021 78.036 643.877 77.904C643.745 77.772 643.469 77.628 643.049 77.472L641.645 76.914C640.913 76.626 640.385 76.272 640.061 75.852C639.737 75.432 639.575 74.898 639.575 74.25C639.575 73.434 639.899 72.78 640.547 72.288C641.207 71.784 642.083 71.532 643.175 71.532C644.183 71.532 645.113 71.73 645.965 72.126L645.965 73.872C645.053 73.596 644.201 73.458 643.409 73.458C642.917 73.458 642.557 73.518 642.329 73.638C642.101 73.758 641.987 73.95 641.987 74.214C641.987 74.418 642.053 74.586 642.185 74.718C642.329 74.838 642.623 74.988 643.067 75.168L644.435 75.726C645.179 76.026 645.707 76.374 646.019 76.77C646.343 77.166 646.505 77.682 646.505 78.318C646.505 79.206 646.163 79.926 645.479 80.478C644.807 81.018 643.919 81.288 642.815 81.288C641.579 81.288 640.487 81.042 639.539 80.55L639.539 78.804C640.727 79.176 641.813 79.362 642.797 79.362C643.661 79.362 644.093 79.062 644.093 78.462ZM658.187 81L657.971 80.19C657.599 80.526 657.167 80.796 656.675 81C656.195 81.192 655.727 81.288 655.271 81.288C654.383 81.288 653.669 81.036 653.129 80.532C652.601 80.028 652.337 79.356 652.337 78.516C652.337 77.94 652.481 77.436 652.769 77.004C653.057 76.56 653.471 76.212 654.011 75.96C654.551 75.708 655.187 75.582 655.919 75.582C656.495 75.582 657.131 75.66 657.827 75.816L657.827 74.916C657.827 74.364 657.713 73.986 657.485 73.782C657.257 73.578 656.837 73.476 656.225 73.476C655.241 73.476 654.155 73.662 652.967 74.034L652.967 72.288C653.411 72.06 653.969 71.88 654.641 71.748C655.313 71.604 655.997 71.532 656.693 71.532C657.929 71.532 658.829 71.784 659.393 72.288C659.969 72.78 660.257 73.56 660.257 74.628L660.257 81L658.187 81ZM656.009 79.524C656.309 79.524 656.615 79.458 656.927 79.326C657.251 79.194 657.551 79.014 657.827 78.786L657.827 77.22C657.299 77.136 656.825 77.094 656.405 77.094C655.361 77.094 654.839 77.514 654.839 78.354C654.839 78.726 654.941 79.014 655.145 79.218C655.349 79.422 655.637 79.524 656.009 79.524ZM662.739 81L662.739 71.802L664.899 71.802L665.223 73.17C665.703 72.642 666.153 72.27 666.573 72.054C667.005 71.826 667.461 71.712 667.941 71.712C668.169 71.712 668.409 71.73 668.661 71.766L668.661 74.196C668.325 74.124 667.953 74.088 667.545 74.088C666.765 74.088 666.039 74.226 665.367 74.502L665.367 81L662.739 81ZM671.996 77.04C672.044 77.832 672.284 78.408 672.716 78.768C673.148 79.116 673.826 79.29 674.75 79.29C675.554 79.29 676.49 79.14 677.558 78.84L677.558 80.586C677.138 80.802 676.634 80.97 676.046 81.09C675.47 81.21 674.87 81.27 674.246 81.27C672.722 81.27 671.558 80.856 670.754 80.028C669.962 79.2 669.566 77.988 669.566 76.392C669.566 74.856 669.962 73.662 670.754 72.81C671.546 71.958 672.644 71.532 674.048 71.532C675.236 71.532 676.148 71.862 676.784 72.522C677.432 73.17 677.756 74.1 677.756 75.312C677.756 75.576 677.738 75.876 677.702 76.212C677.666 76.548 677.624 76.824 677.576 77.04L671.996 77.04ZM673.958 73.35C673.37 73.35 672.902 73.53 672.554 73.89C672.218 74.238 672.026 74.748 671.978 75.42L675.506 75.42L675.506 75.114C675.506 73.938 674.99 73.35 673.958 73.35ZM686.446 77.04C686.494 77.832 686.734 78.408 687.166 78.768C687.598 79.116 688.276 79.29 689.2 79.29C690.004 79.29 690.94 79.14 692.008 78.84L692.008 80.586C691.588 80.802 691.084 80.97 690.496 81.09C689.92 81.21 689.32 81.27 688.696 81.27C687.172 81.27 686.008 80.856 685.204 80.028C684.412 79.2 684.016 77.988 684.016 76.392C684.016 74.856 684.412 73.662 685.204 72.81C685.996 71.958 687.094 71.532 688.498 71.532C689.686 71.532 690.598 71.862 691.234 72.522C691.882 73.17 692.206 74.1 692.206 75.312C692.206 75.576 692.188 75.876 692.152 76.212C692.116 76.548 692.074 76.824 692.026 77.04L686.446 77.04ZM688.408 73.35C687.82 73.35 687.352 73.53 687.004 73.89C686.668 74.238 686.476 74.748 686.428 75.42L689.956 75.42L689.956 75.114C689.956 73.938 689.44 73.35 688.408 73.35ZM698.128 78.462C698.128 78.222 698.056 78.036 697.912 77.904C697.78 77.772 697.504 77.628 697.084 77.472L695.68 76.914C694.948 76.626 694.42 76.272 694.096 75.852C693.772 75.432 693.61 74.898 693.61 74.25C693.61 73.434 693.934 72.78 694.582 72.288C695.242 71.784 696.118 71.532 697.21 71.532C698.218 71.532 699.148 71.73 700 72.126L700 73.872C699.088 73.596 698.236 73.458 697.444 73.458C696.952 73.458 696.592 73.518 696.364 73.638C696.136 73.758 696.022 73.95 696.022 74.214C696.022 74.418 696.088 74.586 696.22 74.718C696.364 74.838 696.658 74.988 697.102 75.168L698.47 75.726C699.214 76.026 699.742 76.374 700.054 76.77C700.378 77.166 700.54 77.682 700.54 78.318C700.54 79.206 700.198 79.926 699.514 80.478C698.842 81.018 697.954 81.288 696.85 81.288C695.614 81.288 694.522 81.042 693.574 80.55L693.574 78.804C694.762 79.176 695.848 79.362 696.832 79.362C697.696 79.362 698.128 79.062 698.128 78.462ZM707.71 80.766C707.062 81.018 706.336 81.144 705.532 81.144C704.512 81.144 703.756 80.904 703.264 80.424C702.784 79.944 702.544 79.2 702.544 78.192L702.544 73.746L701.158 73.746L701.158 72.126L702.616 71.838L703.012 69.318L705.172 69.318L705.172 71.802L707.656 71.802L707.656 73.746L705.172 73.746L705.172 78.066C705.172 78.45 705.268 78.72 705.46 78.876C705.652 79.032 705.976 79.11 706.432 79.11C706.804 79.11 707.23 79.074 707.71 79.002L707.71 80.766ZM714.596 81L714.38 80.19C714.008 80.526 713.576 80.796 713.084 81C712.604 81.192 712.136 81.288 711.68 81.288C710.792 81.288 710.078 81.036 709.538 80.532C709.01 80.028 708.746 79.356 708.746 78.516C708.746 77.94 708.89 77.436 709.178 77.004C709.466 76.56 709.88 76.212 710.42 75.96C710.96 75.708 711.596 75.582 712.328 75.582C712.904 75.582 713.54 75.66 714.236 75.816L714.236 74.916C714.236 74.364 714.122 73.986 713.894 73.782C713.666 73.578 713.246 73.476 712.634 73.476C711.65 73.476 710.564 73.662 709.376 74.034L709.376 72.288C709.82 72.06 710.378 71.88 711.05 71.748C711.722 71.604 712.406 71.532 713.102 71.532C714.338 71.532 715.238 71.784 715.802 72.288C716.378 72.78 716.666 73.56 716.666 74.628L716.666 81L714.596 81ZM712.418 79.524C712.718 79.524 713.024 79.458 713.336 79.326C713.66 79.194 713.96 79.014 714.236 78.786L714.236 77.22C713.708 77.136 713.234 77.094 712.814 77.094C711.77 77.094 711.248 77.514 711.248 78.354C711.248 78.726 711.35 79.014 711.554 79.218C711.758 79.422 712.046 79.524 712.418 79.524ZM719.148 81L719.148 67.68L721.776 67.68L721.776 72.504C722.124 72.204 722.532 71.97 723 71.802C723.468 71.622 723.93 71.532 724.386 71.532C725.55 71.532 726.468 71.958 727.14 72.81C727.824 73.662 728.166 74.814 728.166 76.266C728.166 77.214 728.01 78.06 727.698 78.804C727.386 79.548 726.936 80.136 726.348 80.568C725.76 80.988 725.082 81.198 724.314 81.198C723.762 81.198 723.246 81.102 722.766 80.91C722.286 80.718 721.884 80.448 721.56 80.1L721.326 81L719.148 81ZM723.54 73.512C722.916 73.512 722.328 73.674 721.776 73.998L721.776 78.732C722.304 79.056 722.892 79.218 723.54 79.218C724.212 79.218 724.704 78.99 725.016 78.534C725.34 78.078 725.502 77.358 725.502 76.374C725.502 75.378 725.346 74.652 725.034 74.196C724.722 73.74 724.224 73.512 723.54 73.512ZM734.272 80.82C733.768 81.024 733.228 81.126 732.652 81.126C731.032 81.126 730.222 80.22 730.222 78.408L730.222 67.68L732.85 67.68L732.85 78.192C732.85 78.528 732.904 78.768 733.012 78.912C733.132 79.044 733.324 79.11 733.588 79.11C733.756 79.11 733.984 79.092 734.272 79.056L734.272 80.82ZM736.147 81L736.147 71.802L738.775 71.802L738.775 81L736.147 81ZM737.461 70.38C737.005 70.38 736.639 70.254 736.363 70.002C736.087 69.75 735.949 69.408 735.949 68.976C735.949 68.544 736.087 68.202 736.363 67.95C736.639 67.698 737.005 67.572 737.461 67.572C737.917 67.572 738.283 67.698 738.559 67.95C738.835 68.202 738.973 68.544 738.973 68.976C738.973 69.408 738.835 69.75 738.559 70.002C738.283 70.254 737.917 70.38 737.461 70.38ZM745.272 78.462C745.272 78.222 745.2 78.036 745.056 77.904C744.924 77.772 744.648 77.628 744.228 77.472L742.824 76.914C742.092 76.626 741.564 76.272 741.24 75.852C740.916 75.432 740.754 74.898 740.754 74.25C740.754 73.434 741.078 72.78 741.726 72.288C742.386 71.784 743.262 71.532 744.354 71.532C745.362 71.532 746.292 71.73 747.144 72.126L747.144 73.872C746.232 73.596 745.38 73.458 744.588 73.458C744.096 73.458 743.736 73.518 743.508 73.638C743.28 73.758 743.166 73.95 743.166 74.214C743.166 74.418 743.232 74.586 743.364 74.718C743.508 74.838 743.802 74.988 744.246 75.168L745.614 75.726C746.358 76.026 746.886 76.374 747.198 76.77C747.522 77.166 747.684 77.682 747.684 78.318C747.684 79.206 747.342 79.926 746.658 80.478C745.986 81.018 745.098 81.288 743.994 81.288C742.758 81.288 741.666 81.042 740.718 80.55L740.718 78.804C741.906 79.176 742.992 79.362 743.976 79.362C744.84 79.362 745.272 79.062 745.272 78.462ZM755.286 81L755.286 74.97C755.286 74.478 755.178 74.118 754.962 73.89C754.746 73.662 754.416 73.548 753.972 73.548C753.312 73.548 752.658 73.752 752.01 74.16L752.01 81L749.382 81L749.382 67.68L752.01 67.68L752.01 72.63C753.042 71.898 754.122 71.532 755.25 71.532C756.102 71.532 756.756 71.766 757.212 72.234C757.68 72.69 757.914 73.344 757.914 74.196L757.914 81L755.286 81ZM762.366 77.04C762.414 77.832 762.654 78.408 763.086 78.768C763.518 79.116 764.196 79.29 765.12 79.29C765.924 79.29 766.86 79.14 767.928 78.84L767.928 80.586C767.508 80.802 767.004 80.97 766.416 81.09C765.84 81.21 765.24 81.27 764.616 81.27C763.092 81.27 761.928 80.856 761.124 80.028C760.332 79.2 759.936 77.988 759.936 76.392C759.936 74.856 760.332 73.662 761.124 72.81C761.916 71.958 763.014 71.532 764.418 71.532C765.606 71.532 766.518 71.862 767.154 72.522C767.802 73.17 768.126 74.1 768.126 75.312C768.126 75.576 768.108 75.876 768.072 76.212C768.036 76.548 767.994 76.824 767.946 77.04L762.366 77.04ZM764.328 73.35C763.74 73.35 763.272 73.53 762.924 73.89C762.588 74.238 762.396 74.748 762.348 75.42L765.876 75.42L765.876 75.114C765.876 73.938 765.36 73.35 764.328 73.35ZM776.352 81L776.136 80.19C775.392 80.862 774.51 81.198 773.49 81.198C772.734 81.198 772.068 81.012 771.492 80.64C770.916 80.256 770.466 79.704 770.142 78.984C769.83 78.264 769.674 77.418 769.674 76.446C769.674 74.958 770.028 73.77 770.736 72.882C771.444 71.982 772.38 71.532 773.544 71.532C774.492 71.532 775.314 71.802 776.01 72.342L776.01 67.68L778.638 67.68L778.638 81L776.352 81ZM774.354 79.218C774.93 79.218 775.482 79.05 776.01 78.714L776.01 73.962C775.494 73.662 774.9 73.512 774.228 73.512C773.592 73.512 773.118 73.752 772.806 74.232C772.494 74.7 772.338 75.414 772.338 76.374C772.338 77.334 772.5 78.048 772.824 78.516C773.16 78.984 773.67 79.218 774.354 79.218Z" fill="white"/> -<mask id="path-8-outside-2_18_1526" maskUnits="userSpaceOnUse" x="1014" y="37" width="277" height="74" fill="black"> -<rect fill="white" x="1014" y="37" width="277" height="74"/> -<path d="M1016 49C1016 43.4772 1020.48 39 1026 39L1279 39C1284.52 39 1289 43.4771 1289 49L1289 109L1016 109L1016 49Z"/> -</mask> -<path d="M1016 49C1016 43.4772 1020.48 39 1026 39L1279 39C1284.52 39 1289 43.4771 1289 49L1289 109L1016 109L1016 49Z" fill="#033160"/> -<path d="M1289 109L1289 111L1291 111L1291 109L1289 109ZM1016 109L1014 109L1014 111L1016 111L1016 109ZM1026 41L1279 41L1279 37L1026 37L1026 41ZM1287 49L1287 109L1291 109L1291 49L1287 49ZM1289 107L1016 107L1016 111L1289 111L1289 107ZM1018 109L1018 49L1014 49L1014 109L1018 109ZM1279 41C1283.42 41 1287 44.5817 1287 49L1291 49C1291 42.3726 1285.63 37 1279 37L1279 41ZM1026 37C1019.37 37 1014 42.3726 1014 49L1018 49C1018 44.5817 1021.58 41 1026 41L1026 37Z" fill="#000716" mask="url(#path-8-outside-2_18_1526)"/> -<path d="M1045.15 81L1045.15 68.526L1049.63 68.526C1051.49 68.526 1052.92 69.066 1053.91 70.146C1054.92 71.214 1055.43 72.75 1055.43 74.754C1055.43 76.746 1054.92 78.288 1053.91 79.38C1052.92 80.46 1051.51 81 1049.68 81L1045.15 81ZM1047.85 70.614L1047.85 78.912L1049.4 78.912C1051.57 78.912 1052.65 77.586 1052.65 74.934L1052.65 74.574C1052.65 71.934 1051.56 70.614 1049.38 70.614L1047.85 70.614ZM1059.73 77.04C1059.78 77.832 1060.02 78.408 1060.45 78.768C1060.88 79.116 1061.56 79.29 1062.48 79.29C1063.29 79.29 1064.22 79.14 1065.29 78.84L1065.29 80.586C1064.87 80.802 1064.37 80.97 1063.78 81.09C1063.2 81.21 1062.6 81.27 1061.98 81.27C1060.45 81.27 1059.29 80.856 1058.49 80.028C1057.69 79.2 1057.3 77.988 1057.3 76.392C1057.3 74.856 1057.69 73.662 1058.49 72.81C1059.28 71.958 1060.38 71.532 1061.78 71.532C1062.97 71.532 1063.88 71.862 1064.52 72.522C1065.16 73.17 1065.49 74.1 1065.49 75.312C1065.49 75.576 1065.47 75.876 1065.43 76.212C1065.4 76.548 1065.36 76.824 1065.31 77.04L1059.73 77.04ZM1061.69 73.35C1061.1 73.35 1060.63 73.53 1060.29 73.89C1059.95 74.238 1059.76 74.748 1059.71 75.42L1063.24 75.42L1063.24 75.114C1063.24 73.938 1062.72 73.35 1061.69 73.35ZM1067.5 84.708L1067.5 71.802L1069.66 71.802L1069.88 72.666C1070.24 72.318 1070.67 72.042 1071.18 71.838C1071.69 71.634 1072.21 71.532 1072.74 71.532C1073.91 71.532 1074.82 71.958 1075.5 72.81C1076.18 73.662 1076.52 74.814 1076.52 76.266C1076.52 77.214 1076.37 78.06 1076.05 78.804C1075.74 79.548 1075.29 80.136 1074.7 80.568C1074.12 80.988 1073.44 81.198 1072.67 81.198C1072.18 81.198 1071.71 81.12 1071.27 80.964C1070.82 80.808 1070.44 80.592 1070.13 80.316L1070.13 84.708L1067.5 84.708ZM1071.9 73.512C1071.27 73.512 1070.68 73.674 1070.13 73.998L1070.13 78.732C1070.66 79.056 1071.25 79.218 1071.9 79.218C1072.57 79.218 1073.06 78.99 1073.37 78.534C1073.7 78.078 1073.86 77.358 1073.86 76.374C1073.86 75.378 1073.7 74.652 1073.39 74.196C1073.08 73.74 1072.58 73.512 1071.9 73.512ZM1082.63 80.82C1082.12 81.024 1081.58 81.126 1081.01 81.126C1079.39 81.126 1078.58 80.22 1078.58 78.408L1078.58 67.68L1081.21 67.68L1081.21 78.192C1081.21 78.528 1081.26 78.768 1081.37 78.912C1081.49 79.044 1081.68 79.11 1081.94 79.11C1082.11 79.11 1082.34 79.092 1082.63 79.056L1082.63 80.82ZM1088.34 81.27C1086.91 81.27 1085.8 80.844 1084.99 79.992C1084.19 79.128 1083.79 77.928 1083.79 76.392C1083.79 74.868 1084.19 73.68 1084.99 72.828C1085.8 71.964 1086.91 71.532 1088.34 71.532C1089.77 71.532 1090.89 71.964 1091.69 72.828C1092.49 73.68 1092.9 74.868 1092.9 76.392C1092.9 77.928 1092.49 79.128 1091.69 79.992C1090.89 80.844 1089.77 81.27 1088.34 81.27ZM1088.34 79.254C1089.6 79.254 1090.23 78.3 1090.23 76.392C1090.23 74.496 1089.6 73.548 1088.34 73.548C1087.08 73.548 1086.45 74.496 1086.45 76.392C1086.45 78.3 1087.08 79.254 1088.34 79.254ZM1097.22 81.144L1093.58 71.802L1096.37 71.802L1098.42 78.678L1100.37 71.802L1103.08 71.802L1099.2 82.242C1098.85 83.19 1098.42 83.874 1097.92 84.294C1097.41 84.714 1096.78 84.924 1096.01 84.924C1095.41 84.924 1094.83 84.828 1094.26 84.636L1094.26 82.854C1094.65 82.89 1094.99 82.908 1095.29 82.908C1095.79 82.908 1096.18 82.788 1096.46 82.548C1096.74 82.32 1096.97 81.918 1097.16 81.342L1097.22 81.144ZM1115.81 81L1115.81 74.772C1115.81 73.956 1115.45 73.548 1114.71 73.548C1114.07 73.548 1113.41 73.704 1112.75 74.016L1112.75 74.196L1112.75 81L1110.12 81L1110.12 74.772C1110.12 73.956 1109.76 73.548 1109.03 73.548C1108.35 73.548 1107.69 73.71 1107.05 74.034L1107.05 81L1104.42 81L1104.42 71.802L1106.58 71.802L1106.81 72.684C1107.45 72.264 1108.02 71.97 1108.52 71.802C1109.04 71.622 1109.57 71.532 1110.11 71.532C1111.19 71.532 1111.95 71.916 1112.39 72.684C1113 72.276 1113.58 71.982 1114.12 71.802C1114.66 71.622 1115.22 71.532 1115.79 71.532C1116.63 71.532 1117.28 71.766 1117.74 72.234C1118.21 72.702 1118.44 73.356 1118.44 74.196L1118.44 81L1115.81 81ZM1122.89 77.04C1122.93 77.832 1123.17 78.408 1123.61 78.768C1124.04 79.116 1124.72 79.29 1125.64 79.29C1126.44 79.29 1127.38 79.14 1128.45 78.84L1128.45 80.586C1128.03 80.802 1127.52 80.97 1126.94 81.09C1126.36 81.21 1125.76 81.27 1125.14 81.27C1123.61 81.27 1122.45 80.856 1121.64 80.028C1120.85 79.2 1120.46 77.988 1120.46 76.392C1120.46 74.856 1120.85 73.662 1121.64 72.81C1122.44 71.958 1123.53 71.532 1124.94 71.532C1126.13 71.532 1127.04 71.862 1127.67 72.522C1128.32 73.17 1128.65 74.1 1128.65 75.312C1128.65 75.576 1128.63 75.876 1128.59 76.212C1128.56 76.548 1128.51 76.824 1128.47 77.04L1122.89 77.04ZM1124.85 73.35C1124.26 73.35 1123.79 73.53 1123.44 73.89C1123.11 74.238 1122.92 74.748 1122.87 75.42L1126.4 75.42L1126.4 75.114C1126.4 73.938 1125.88 73.35 1124.85 73.35ZM1136.57 81L1136.57 74.97C1136.57 74.478 1136.46 74.118 1136.24 73.89C1136.03 73.662 1135.7 73.548 1135.25 73.548C1134.59 73.548 1133.94 73.752 1133.29 74.16L1133.29 81L1130.66 81L1130.66 71.802L1132.82 71.802L1133.07 72.792C1134.15 71.952 1135.31 71.532 1136.53 71.532C1137.38 71.532 1138.04 71.766 1138.49 72.234C1138.96 72.69 1139.19 73.344 1139.19 74.196L1139.19 81L1136.57 81ZM1147.16 80.766C1146.51 81.018 1145.78 81.144 1144.98 81.144C1143.96 81.144 1143.2 80.904 1142.71 80.424C1142.23 79.944 1141.99 79.2 1141.99 78.192L1141.99 73.746L1140.6 73.746L1140.6 72.126L1142.06 71.838L1142.46 69.318L1144.62 69.318L1144.62 71.802L1147.1 71.802L1147.1 73.746L1144.62 73.746L1144.62 78.066C1144.62 78.45 1144.71 78.72 1144.91 78.876C1145.1 79.032 1145.42 79.11 1145.88 79.11C1146.25 79.11 1146.68 79.074 1147.16 79.002L1147.16 80.766ZM1153.55 81L1153.55 71.802L1156.18 71.802L1156.18 81L1153.55 81ZM1154.86 70.38C1154.41 70.38 1154.04 70.254 1153.77 70.002C1153.49 69.75 1153.35 69.408 1153.35 68.976C1153.35 68.544 1153.49 68.202 1153.77 67.95C1154.04 67.698 1154.41 67.572 1154.86 67.572C1155.32 67.572 1155.69 67.698 1155.96 67.95C1156.24 68.202 1156.38 68.544 1156.38 68.976C1156.38 69.408 1156.24 69.75 1155.96 70.002C1155.69 70.254 1155.32 70.38 1154.86 70.38ZM1162.68 78.462C1162.68 78.222 1162.6 78.036 1162.46 77.904C1162.33 77.772 1162.05 77.628 1161.63 77.472L1160.23 76.914C1159.5 76.626 1158.97 76.272 1158.64 75.852C1158.32 75.432 1158.16 74.898 1158.16 74.25C1158.16 73.434 1158.48 72.78 1159.13 72.288C1159.79 71.784 1160.67 71.532 1161.76 71.532C1162.77 71.532 1163.7 71.73 1164.55 72.126L1164.55 73.872C1163.64 73.596 1162.78 73.458 1161.99 73.458C1161.5 73.458 1161.14 73.518 1160.91 73.638C1160.68 73.758 1160.57 73.95 1160.57 74.214C1160.57 74.418 1160.64 74.586 1160.77 74.718C1160.91 74.838 1161.21 74.988 1161.65 75.168L1163.02 75.726C1163.76 76.026 1164.29 76.374 1164.6 76.77C1164.93 77.166 1165.09 77.682 1165.09 78.318C1165.09 79.206 1164.75 79.926 1164.06 80.478C1163.39 81.018 1162.5 81.288 1161.4 81.288C1160.16 81.288 1159.07 81.042 1158.12 80.55L1158.12 78.804C1159.31 79.176 1160.4 79.362 1161.38 79.362C1162.24 79.362 1162.68 79.062 1162.68 78.462ZM1171.5 84.708L1171.5 71.802L1173.66 71.802L1173.87 72.666C1174.23 72.318 1174.66 72.042 1175.17 71.838C1175.68 71.634 1176.21 71.532 1176.73 71.532C1177.9 71.532 1178.82 71.958 1179.49 72.81C1180.17 73.662 1180.51 74.814 1180.51 76.266C1180.51 77.214 1180.36 78.06 1180.05 78.804C1179.73 79.548 1179.28 80.136 1178.7 80.568C1178.11 80.988 1177.43 81.198 1176.66 81.198C1176.17 81.198 1175.7 81.12 1175.26 80.964C1174.81 80.808 1174.44 80.592 1174.12 80.316L1174.12 84.708L1171.5 84.708ZM1175.89 73.512C1175.26 73.512 1174.68 73.674 1174.12 73.998L1174.12 78.732C1174.65 79.056 1175.24 79.218 1175.89 79.218C1176.56 79.218 1177.05 78.99 1177.36 78.534C1177.69 78.078 1177.85 77.358 1177.85 76.374C1177.85 75.378 1177.69 74.652 1177.38 74.196C1177.07 73.74 1176.57 73.512 1175.89 73.512ZM1184.53 77.04C1184.58 77.832 1184.82 78.408 1185.25 78.768C1185.68 79.116 1186.36 79.29 1187.29 79.29C1188.09 79.29 1189.03 79.14 1190.09 78.84L1190.09 80.586C1189.67 80.802 1189.17 80.97 1188.58 81.09C1188.01 81.21 1187.41 81.27 1186.78 81.27C1185.26 81.27 1184.09 80.856 1183.29 80.028C1182.5 79.2 1182.1 77.988 1182.1 76.392C1182.1 74.856 1182.5 73.662 1183.29 72.81C1184.08 71.958 1185.18 71.532 1186.58 71.532C1187.77 71.532 1188.68 71.862 1189.32 72.522C1189.97 73.17 1190.29 74.1 1190.29 75.312C1190.29 75.576 1190.27 75.876 1190.24 76.212C1190.2 76.548 1190.16 76.824 1190.11 77.04L1184.53 77.04ZM1186.49 73.35C1185.91 73.35 1185.44 73.53 1185.09 73.89C1184.75 74.238 1184.56 74.748 1184.51 75.42L1188.04 75.42L1188.04 75.114C1188.04 73.938 1187.53 73.35 1186.49 73.35ZM1192.31 81L1192.31 71.802L1194.47 71.802L1194.79 73.17C1195.27 72.642 1195.72 72.27 1196.14 72.054C1196.57 71.826 1197.03 71.712 1197.51 71.712C1197.74 71.712 1197.98 71.73 1198.23 71.766L1198.23 74.196C1197.89 74.124 1197.52 74.088 1197.11 74.088C1196.33 74.088 1195.61 74.226 1194.94 74.502L1194.94 81L1192.31 81ZM1200.77 81L1200.77 73.746L1199.32 73.746L1199.32 72.126L1200.77 71.856L1200.77 71.028C1200.77 69.816 1201.05 68.916 1201.6 68.328C1202.17 67.728 1203.02 67.428 1204.16 67.428C1204.48 67.428 1204.82 67.464 1205.17 67.536C1205.51 67.596 1205.82 67.68 1206.08 67.788L1206.08 69.57C1205.6 69.498 1205.2 69.462 1204.86 69.462C1204.31 69.462 1203.92 69.552 1203.71 69.732C1203.5 69.912 1203.4 70.23 1203.4 70.686L1203.4 71.802L1205.98 71.802L1205.98 73.746L1203.4 73.746L1203.4 81L1200.77 81ZM1211.39 81.27C1209.96 81.27 1208.84 80.844 1208.04 79.992C1207.24 79.128 1206.83 77.928 1206.83 76.392C1206.83 74.868 1207.24 73.68 1208.04 72.828C1208.84 71.964 1209.96 71.532 1211.39 71.532C1212.82 71.532 1213.93 71.964 1214.74 72.828C1215.54 73.68 1215.94 74.868 1215.94 76.392C1215.94 77.928 1215.54 79.128 1214.74 79.992C1213.93 80.844 1212.82 81.27 1211.39 81.27ZM1211.39 79.254C1212.65 79.254 1213.28 78.3 1213.28 76.392C1213.28 74.496 1212.65 73.548 1211.39 73.548C1210.13 73.548 1209.5 74.496 1209.5 76.392C1209.5 78.3 1210.13 79.254 1211.39 79.254ZM1217.99 81L1217.99 71.802L1220.15 71.802L1220.47 73.17C1220.95 72.642 1221.4 72.27 1221.82 72.054C1222.26 71.826 1222.71 71.712 1223.19 71.712C1223.42 71.712 1223.66 71.73 1223.91 71.766L1223.91 74.196C1223.58 74.124 1223.2 74.088 1222.8 74.088C1222.02 74.088 1221.29 74.226 1220.62 74.502L1220.62 81L1217.99 81ZM1236.68 81L1236.68 74.772C1236.68 73.956 1236.31 73.548 1235.58 73.548C1234.93 73.548 1234.28 73.704 1233.62 74.016L1233.62 74.196L1233.62 81L1230.99 81L1230.99 74.772C1230.99 73.956 1230.63 73.548 1229.89 73.548C1229.22 73.548 1228.56 73.71 1227.91 74.034L1227.91 81L1225.29 81L1225.29 71.802L1227.45 71.802L1227.68 72.684C1228.32 72.264 1228.89 71.97 1229.39 71.802C1229.91 71.622 1230.43 71.532 1230.97 71.532C1232.05 71.532 1232.82 71.916 1233.26 72.684C1233.87 72.276 1234.45 71.982 1234.99 71.802C1235.53 71.622 1236.09 71.532 1236.66 71.532C1237.5 71.532 1238.15 71.766 1238.61 72.234C1239.07 72.702 1239.31 73.356 1239.31 74.196L1239.31 81L1236.68 81ZM1243.75 77.04C1243.8 77.832 1244.04 78.408 1244.47 78.768C1244.91 79.116 1245.58 79.29 1246.51 79.29C1247.31 79.29 1248.25 79.14 1249.32 78.84L1249.32 80.586C1248.9 80.802 1248.39 80.97 1247.8 81.09C1247.23 81.21 1246.63 81.27 1246 81.27C1244.48 81.27 1243.32 80.856 1242.51 80.028C1241.72 79.2 1241.32 77.988 1241.32 76.392C1241.32 74.856 1241.72 73.662 1242.51 72.81C1243.3 71.958 1244.4 71.532 1245.81 71.532C1246.99 71.532 1247.91 71.862 1248.54 72.522C1249.19 73.17 1249.51 74.1 1249.51 75.312C1249.51 75.576 1249.5 75.876 1249.46 76.212C1249.42 76.548 1249.38 76.824 1249.33 77.04L1243.75 77.04ZM1245.72 73.35C1245.13 73.35 1244.66 73.53 1244.31 73.89C1243.98 74.238 1243.78 74.748 1243.74 75.42L1247.26 75.42L1247.26 75.114C1247.26 73.938 1246.75 73.35 1245.72 73.35ZM1257.74 81L1257.52 80.19C1256.78 80.862 1255.9 81.198 1254.88 81.198C1254.12 81.198 1253.46 81.012 1252.88 80.64C1252.3 80.256 1251.85 79.704 1251.53 78.984C1251.22 78.264 1251.06 77.418 1251.06 76.446C1251.06 74.958 1251.42 73.77 1252.12 72.882C1252.83 71.982 1253.77 71.532 1254.93 71.532C1255.88 71.532 1256.7 71.802 1257.4 72.342L1257.4 67.68L1260.03 67.68L1260.03 81L1257.74 81ZM1255.74 79.218C1256.32 79.218 1256.87 79.05 1257.4 78.714L1257.4 73.962C1256.88 73.662 1256.29 73.512 1255.62 73.512C1254.98 73.512 1254.51 73.752 1254.19 74.232C1253.88 74.7 1253.73 75.414 1253.73 76.374C1253.73 77.334 1253.89 78.048 1254.21 78.516C1254.55 78.984 1255.06 79.218 1255.74 79.218Z" fill="white"/> -<mask id="path-11-outside-3_18_1526" maskUnits="userSpaceOnUse" x="37" y="37" width="276" height="74" fill="black"> -<rect fill="white" x="37" y="37" width="276" height="74"/> -<path d="M39 49C39 43.4772 43.4772 39 49 39L301 39C306.523 39 311 43.4771 311 49L311 109L39 109L39 49Z"/> -</mask> -<path d="M39 49C39 43.4772 43.4772 39 49 39L301 39C306.523 39 311 43.4771 311 49L311 109L39 109L39 49Z" fill="#033160"/> -<path d="M311 109L311 111L313 111L313 109L311 109ZM39 109L37 109L37 111L39 111L39 109ZM49 41L301 41L301 37L49 37L49 41ZM309 49L309 109L313 109L313 49L309 49ZM311 107L39 107L39 111L311 111L311 107ZM41 109L41 49L37 49L37 109L41 109ZM301 41C305.418 41 309 44.5817 309 49L313 49C313 42.3726 307.627 37 301 37L301 41ZM49 37C42.3726 37 37 42.3726 37 49L41 49C41 44.5817 44.5817 41 49 41L49 37Z" fill="#000716" mask="url(#path-11-outside-3_18_1526)"/> -<path d="M70.9358 81L70.0538 78.156L65.7878 78.156L64.9418 81L62.1158 81L66.5078 68.526L69.4778 68.526L73.8698 81L70.9358 81ZM66.3638 76.212L69.4958 76.212L67.9118 70.992L66.3638 76.212ZM81.8805 80.604C81.5565 80.796 81.1665 80.94 80.7105 81.036C80.2545 81.144 79.7805 81.198 79.2885 81.198C77.8245 81.198 76.7025 80.79 75.9225 79.974C75.1545 79.158 74.7705 77.982 74.7705 76.446C74.7705 74.922 75.1785 73.734 75.9945 72.882C76.8105 72.03 77.9445 71.604 79.3965 71.604C80.2725 71.604 81.0825 71.796 81.8265 72.18L81.8265 73.926C81.1185 73.722 80.4705 73.62 79.8825 73.62C79.0425 73.62 78.4245 73.836 78.0285 74.268C77.6325 74.688 77.4345 75.36 77.4345 76.284L77.4345 76.536C77.4345 77.448 77.6265 78.12 78.0105 78.552C78.4065 78.972 79.0125 79.182 79.8285 79.182C80.4165 79.182 81.1005 79.074 81.8805 78.858L81.8805 80.604ZM89.5699 80.766C88.9219 81.018 88.1959 81.144 87.3919 81.144C86.3719 81.144 85.6159 80.904 85.1239 80.424C84.6439 79.944 84.4039 79.2 84.4039 78.192L84.4039 73.746L83.0179 73.746L83.0179 72.126L84.4759 71.838L84.8719 69.318L87.0319 69.318L87.0319 71.802L89.5159 71.802L89.5159 73.746L87.0319 73.746L87.0319 78.066C87.0319 78.45 87.1279 78.72 87.3199 78.876C87.5119 79.032 87.8359 79.11 88.2919 79.11C88.6639 79.11 89.0899 79.074 89.5699 79.002L89.5699 80.766ZM95.2679 81.27C93.8399 81.27 92.7239 80.844 91.9199 79.992C91.1159 79.128 90.7139 77.928 90.7139 76.392C90.7139 74.868 91.1159 73.68 91.9199 72.828C92.7239 71.964 93.8399 71.532 95.2679 71.532C96.6959 71.532 97.8119 71.964 98.6159 72.828C99.4199 73.68 99.8219 74.868 99.8219 76.392C99.8219 77.928 99.4199 79.128 98.6159 79.992C97.8119 80.844 96.6959 81.27 95.2679 81.27ZM95.2679 79.254C96.5279 79.254 97.1579 78.3 97.1579 76.392C97.1579 74.496 96.5279 73.548 95.2679 73.548C94.0079 73.548 93.3779 74.496 93.3779 76.392C93.3779 78.3 94.0079 79.254 95.2679 79.254ZM101.869 81L101.869 71.802L104.029 71.802L104.353 73.17C104.833 72.642 105.283 72.27 105.703 72.054C106.135 71.826 106.591 71.712 107.071 71.712C107.299 71.712 107.539 71.73 107.791 71.766L107.791 74.196C107.455 74.124 107.083 74.088 106.675 74.088C105.895 74.088 105.169 74.226 104.497 74.502L104.497 81L101.869 81ZM113.947 81L113.947 71.802L116.575 71.802L116.575 81L113.947 81ZM115.261 70.38C114.805 70.38 114.439 70.254 114.163 70.002C113.887 69.75 113.749 69.408 113.749 68.976C113.749 68.544 113.887 68.202 114.163 67.95C114.439 67.698 114.805 67.572 115.261 67.572C115.717 67.572 116.083 67.698 116.359 67.95C116.635 68.202 116.773 68.544 116.773 68.976C116.773 69.408 116.635 69.75 116.359 70.002C116.083 70.254 115.717 70.38 115.261 70.38ZM125.07 81L125.07 74.97C125.07 74.478 124.962 74.118 124.746 73.89C124.53 73.662 124.2 73.548 123.756 73.548C123.096 73.548 122.442 73.752 121.794 74.16L121.794 81L119.166 81L119.166 71.802L121.326 71.802L121.578 72.792C122.658 71.952 123.81 71.532 125.034 71.532C125.886 71.532 126.54 71.766 126.996 72.234C127.464 72.69 127.698 73.344 127.698 74.196L127.698 81L125.07 81ZM130.26 81L130.26 71.802L132.888 71.802L132.888 81L130.26 81ZM131.574 70.38C131.118 70.38 130.752 70.254 130.476 70.002C130.2 69.75 130.062 69.408 130.062 68.976C130.062 68.544 130.2 68.202 130.476 67.95C130.752 67.698 131.118 67.572 131.574 67.572C132.03 67.572 132.396 67.698 132.672 67.95C132.948 68.202 133.086 68.544 133.086 68.976C133.086 69.408 132.948 69.75 132.672 70.002C132.396 70.254 132.03 70.38 131.574 70.38ZM140.951 80.766C140.303 81.018 139.577 81.144 138.773 81.144C137.753 81.144 136.997 80.904 136.505 80.424C136.025 79.944 135.785 79.2 135.785 78.192L135.785 73.746L134.399 73.746L134.399 72.126L135.857 71.838L136.253 69.318L138.413 69.318L138.413 71.802L140.897 71.802L140.897 73.746L138.413 73.746L138.413 78.066C138.413 78.45 138.509 78.72 138.701 78.876C138.893 79.032 139.217 79.11 139.673 79.11C140.045 79.11 140.471 79.074 140.951 79.002L140.951 80.766ZM142.635 81L142.635 71.802L145.263 71.802L145.263 81L142.635 81ZM143.949 70.38C143.493 70.38 143.127 70.254 142.851 70.002C142.575 69.75 142.437 69.408 142.437 68.976C142.437 68.544 142.575 68.202 142.851 67.95C143.127 67.698 143.493 67.572 143.949 67.572C144.405 67.572 144.771 67.698 145.047 67.95C145.323 68.202 145.461 68.544 145.461 68.976C145.461 69.408 145.323 69.75 145.047 70.002C144.771 70.254 144.405 70.38 143.949 70.38ZM153.128 81L152.912 80.19C152.54 80.526 152.108 80.796 151.616 81C151.136 81.192 150.668 81.288 150.212 81.288C149.324 81.288 148.61 81.036 148.07 80.532C147.542 80.028 147.278 79.356 147.278 78.516C147.278 77.94 147.422 77.436 147.71 77.004C147.998 76.56 148.412 76.212 148.952 75.96C149.492 75.708 150.128 75.582 150.86 75.582C151.436 75.582 152.072 75.66 152.768 75.816L152.768 74.916C152.768 74.364 152.654 73.986 152.426 73.782C152.198 73.578 151.778 73.476 151.166 73.476C150.182 73.476 149.096 73.662 147.908 74.034L147.908 72.288C148.352 72.06 148.91 71.88 149.582 71.748C150.254 71.604 150.938 71.532 151.634 71.532C152.87 71.532 153.77 71.784 154.334 72.288C154.91 72.78 155.198 73.56 155.198 74.628L155.198 81L153.128 81ZM150.95 79.524C151.25 79.524 151.556 79.458 151.868 79.326C152.192 79.194 152.492 79.014 152.768 78.786L152.768 77.22C152.24 77.136 151.766 77.094 151.346 77.094C150.302 77.094 149.78 77.514 149.78 78.354C149.78 78.726 149.882 79.014 150.086 79.218C150.29 79.422 150.578 79.524 150.95 79.524ZM163.152 80.766C162.504 81.018 161.778 81.144 160.974 81.144C159.954 81.144 159.198 80.904 158.706 80.424C158.226 79.944 157.986 79.2 157.986 78.192L157.986 73.746L156.6 73.746L156.6 72.126L158.058 71.838L158.454 69.318L160.614 69.318L160.614 71.802L163.098 71.802L163.098 73.746L160.614 73.746L160.614 78.066C160.614 78.45 160.71 78.72 160.902 78.876C161.094 79.032 161.418 79.11 161.874 79.11C162.246 79.11 162.672 79.074 163.152 79.002L163.152 80.766ZM166.726 77.04C166.774 77.832 167.014 78.408 167.446 78.768C167.878 79.116 168.556 79.29 169.48 79.29C170.284 79.29 171.22 79.14 172.288 78.84L172.288 80.586C171.868 80.802 171.364 80.97 170.776 81.09C170.2 81.21 169.6 81.27 168.976 81.27C167.452 81.27 166.288 80.856 165.484 80.028C164.692 79.2 164.296 77.988 164.296 76.392C164.296 74.856 164.692 73.662 165.484 72.81C166.276 71.958 167.374 71.532 168.778 71.532C169.966 71.532 170.878 71.862 171.514 72.522C172.162 73.17 172.486 74.1 172.486 75.312C172.486 75.576 172.468 75.876 172.432 76.212C172.396 76.548 172.354 76.824 172.306 77.04L166.726 77.04ZM168.688 73.35C168.1 73.35 167.632 73.53 167.284 73.89C166.948 74.238 166.756 74.748 166.708 75.42L170.236 75.42L170.236 75.114C170.236 73.938 169.72 73.35 168.688 73.35ZM178.408 78.462C178.408 78.222 178.336 78.036 178.192 77.904C178.06 77.772 177.784 77.628 177.364 77.472L175.96 76.914C175.228 76.626 174.7 76.272 174.376 75.852C174.052 75.432 173.89 74.898 173.89 74.25C173.89 73.434 174.214 72.78 174.862 72.288C175.522 71.784 176.398 71.532 177.49 71.532C178.498 71.532 179.428 71.73 180.28 72.126L180.28 73.872C179.368 73.596 178.516 73.458 177.724 73.458C177.232 73.458 176.872 73.518 176.644 73.638C176.416 73.758 176.302 73.95 176.302 74.214C176.302 74.418 176.368 74.586 176.5 74.718C176.644 74.838 176.938 74.988 177.382 75.168L178.75 75.726C179.494 76.026 180.022 76.374 180.334 76.77C180.658 77.166 180.82 77.682 180.82 78.318C180.82 79.206 180.478 79.926 179.794 80.478C179.122 81.018 178.234 81.288 177.13 81.288C175.894 81.288 174.802 81.042 173.854 80.55L173.854 78.804C175.042 79.176 176.128 79.362 177.112 79.362C177.976 79.362 178.408 79.062 178.408 78.462ZM193.439 81L193.223 80.19C192.479 80.862 191.597 81.198 190.577 81.198C189.821 81.198 189.155 81.012 188.579 80.64C188.003 80.256 187.553 79.704 187.229 78.984C186.917 78.264 186.761 77.418 186.761 76.446C186.761 74.958 187.115 73.77 187.823 72.882C188.531 71.982 189.467 71.532 190.631 71.532C191.579 71.532 192.401 71.802 193.097 72.342L193.097 67.68L195.725 67.68L195.725 81L193.439 81ZM191.441 79.218C192.017 79.218 192.569 79.05 193.097 78.714L193.097 73.962C192.581 73.662 191.987 73.512 191.315 73.512C190.679 73.512 190.205 73.752 189.893 74.232C189.581 74.7 189.425 75.414 189.425 76.374C189.425 77.334 189.587 78.048 189.911 78.516C190.247 78.984 190.757 79.218 191.441 79.218ZM200.212 77.04C200.26 77.832 200.5 78.408 200.932 78.768C201.364 79.116 202.042 79.29 202.966 79.29C203.77 79.29 204.706 79.14 205.774 78.84L205.774 80.586C205.354 80.802 204.85 80.97 204.262 81.09C203.686 81.21 203.086 81.27 202.462 81.27C200.938 81.27 199.774 80.856 198.97 80.028C198.178 79.2 197.782 77.988 197.782 76.392C197.782 74.856 198.178 73.662 198.97 72.81C199.762 71.958 200.86 71.532 202.264 71.532C203.452 71.532 204.364 71.862 205 72.522C205.648 73.17 205.972 74.1 205.972 75.312C205.972 75.576 205.954 75.876 205.918 76.212C205.882 76.548 205.84 76.824 205.792 77.04L200.212 77.04ZM202.174 73.35C201.586 73.35 201.118 73.53 200.77 73.89C200.434 74.238 200.242 74.748 200.194 75.42L203.722 75.42L203.722 75.114C203.722 73.938 203.206 73.35 202.174 73.35ZM207.989 84.708L207.989 71.802L210.149 71.802L210.365 72.666C210.725 72.318 211.157 72.042 211.661 71.838C212.177 71.634 212.699 71.532 213.227 71.532C214.391 71.532 215.309 71.958 215.981 72.81C216.665 73.662 217.007 74.814 217.007 76.266C217.007 77.214 216.851 78.06 216.539 78.804C216.227 79.548 215.777 80.136 215.189 80.568C214.601 80.988 213.923 81.198 213.155 81.198C212.663 81.198 212.195 81.12 211.751 80.964C211.307 80.808 210.929 80.592 210.617 80.316L210.617 84.708L207.989 84.708ZM212.381 73.512C211.757 73.512 211.169 73.674 210.617 73.998L210.617 78.732C211.145 79.056 211.733 79.218 212.381 79.218C213.053 79.218 213.545 78.99 213.857 78.534C214.181 78.078 214.343 77.358 214.343 76.374C214.343 75.378 214.187 74.652 213.875 74.196C213.563 73.74 213.065 73.512 212.381 73.512ZM223.113 80.82C222.609 81.024 222.069 81.126 221.493 81.126C219.873 81.126 219.063 80.22 219.063 78.408L219.063 67.68L221.691 67.68L221.691 78.192C221.691 78.528 221.745 78.768 221.853 78.912C221.973 79.044 222.165 79.11 222.429 79.11C222.597 79.11 222.825 79.092 223.113 79.056L223.113 80.82ZM228.826 81.27C227.398 81.27 226.282 80.844 225.478 79.992C224.674 79.128 224.272 77.928 224.272 76.392C224.272 74.868 224.674 73.68 225.478 72.828C226.282 71.964 227.398 71.532 228.826 71.532C230.254 71.532 231.37 71.964 232.174 72.828C232.978 73.68 233.38 74.868 233.38 76.392C233.38 77.928 232.978 79.128 232.174 79.992C231.37 80.844 230.254 81.27 228.826 81.27ZM228.826 79.254C230.086 79.254 230.716 78.3 230.716 76.392C230.716 74.496 230.086 73.548 228.826 73.548C227.566 73.548 226.936 74.496 226.936 76.392C226.936 78.3 227.566 79.254 228.826 79.254ZM237.7 81.144L234.064 71.802L236.854 71.802L238.906 78.678L240.85 71.802L243.568 71.802L239.68 82.242C239.332 83.19 238.906 83.874 238.402 84.294C237.898 84.714 237.262 84.924 236.494 84.924C235.894 84.924 235.312 84.828 234.748 84.636L234.748 82.854C235.132 82.89 235.474 82.908 235.774 82.908C236.278 82.908 236.668 82.788 236.944 82.548C237.22 82.32 237.454 81.918 237.646 81.342L237.7 81.144ZM256.297 81L256.297 74.772C256.297 73.956 255.931 73.548 255.199 73.548C254.551 73.548 253.897 73.704 253.237 74.016L253.237 74.196L253.237 81L250.609 81L250.609 74.772C250.609 73.956 250.243 73.548 249.511 73.548C248.839 73.548 248.179 73.71 247.531 74.034L247.531 81L244.903 81L244.903 71.802L247.063 71.802L247.297 72.684C247.933 72.264 248.503 71.97 249.007 71.802C249.523 71.622 250.051 71.532 250.591 71.532C251.671 71.532 252.433 71.916 252.877 72.684C253.489 72.276 254.065 71.982 254.605 71.802C255.145 71.622 255.703 71.532 256.279 71.532C257.119 71.532 257.767 71.766 258.223 72.234C258.691 72.702 258.925 73.356 258.925 74.196L258.925 81L256.297 81ZM263.37 77.04C263.418 77.832 263.658 78.408 264.09 78.768C264.522 79.116 265.2 79.29 266.124 79.29C266.928 79.29 267.864 79.14 268.932 78.84L268.932 80.586C268.512 80.802 268.008 80.97 267.42 81.09C266.844 81.21 266.244 81.27 265.62 81.27C264.096 81.27 262.932 80.856 262.128 80.028C261.336 79.2 260.94 77.988 260.94 76.392C260.94 74.856 261.336 73.662 262.128 72.81C262.92 71.958 264.018 71.532 265.422 71.532C266.61 71.532 267.522 71.862 268.158 72.522C268.806 73.17 269.13 74.1 269.13 75.312C269.13 75.576 269.112 75.876 269.076 76.212C269.04 76.548 268.998 76.824 268.95 77.04L263.37 77.04ZM265.332 73.35C264.744 73.35 264.276 73.53 263.928 73.89C263.592 74.238 263.4 74.748 263.352 75.42L266.88 75.42L266.88 75.114C266.88 73.938 266.364 73.35 265.332 73.35ZM277.051 81L277.051 74.97C277.051 74.478 276.943 74.118 276.727 73.89C276.511 73.662 276.181 73.548 275.737 73.548C275.077 73.548 274.423 73.752 273.775 74.16L273.775 81L271.147 81L271.147 71.802L273.307 71.802L273.559 72.792C274.639 71.952 275.791 71.532 277.015 71.532C277.867 71.532 278.521 71.766 278.977 72.234C279.445 72.69 279.679 73.344 279.679 74.196L279.679 81L277.051 81ZM287.64 80.766C286.992 81.018 286.266 81.144 285.462 81.144C284.442 81.144 283.686 80.904 283.194 80.424C282.714 79.944 282.474 79.2 282.474 78.192L282.474 73.746L281.088 73.746L281.088 72.126L282.546 71.838L282.942 69.318L285.102 69.318L285.102 71.802L287.586 71.802L287.586 73.746L285.102 73.746L285.102 78.066C285.102 78.45 285.198 78.72 285.39 78.876C285.582 79.032 285.906 79.11 286.362 79.11C286.734 79.11 287.16 79.074 287.64 79.002L287.64 80.766Z" fill="white"/> -<rect x="340" y="243" width="223" height="46" rx="5" fill="#0972D3"/> -<rect x="340" y="243" width="223" height="46" rx="5" stroke="#000716" stroke-width="2"/> -<path d="M395.021 272V260.912H397.421V272H395.021ZM406.627 272L405.843 269.472H402.051L401.299 272H398.787L402.691 260.912H405.331L409.235 272H406.627ZM402.563 267.744H405.347L403.939 263.104L402.563 267.744ZM419.684 272V264.32L417.236 269.296H415.092L412.644 264.32V272H410.532V260.912H413.156L416.18 267.216L419.22 260.912H421.796V272H419.684ZM434.131 271.648C433.843 271.819 433.497 271.947 433.091 272.032C432.686 272.128 432.265 272.176 431.827 272.176C430.526 272.176 429.529 271.813 428.835 271.088C428.153 270.363 427.811 269.317 427.811 267.952C427.811 266.597 428.174 265.541 428.899 264.784C429.625 264.027 430.633 263.648 431.923 263.648C432.702 263.648 433.422 263.819 434.083 264.16V265.712C433.454 265.531 432.878 265.44 432.355 265.44C431.609 265.44 431.059 265.632 430.707 266.016C430.355 266.389 430.179 266.987 430.179 267.808V268.032C430.179 268.843 430.35 269.44 430.691 269.824C431.043 270.197 431.582 270.384 432.307 270.384C432.83 270.384 433.438 270.288 434.131 270.096V271.648ZM435.71 272V263.824H437.63L437.918 265.04C438.344 264.571 438.744 264.24 439.118 264.048C439.502 263.845 439.907 263.744 440.334 263.744C440.536 263.744 440.75 263.76 440.974 263.792V265.952C440.675 265.888 440.344 265.856 439.982 265.856C439.288 265.856 438.643 265.979 438.046 266.224V272H435.71ZM443.858 268.48C443.901 269.184 444.114 269.696 444.498 270.016C444.882 270.325 445.485 270.48 446.306 270.48C447.021 270.48 447.853 270.347 448.802 270.08V271.632C448.429 271.824 447.981 271.973 447.458 272.08C446.946 272.187 446.413 272.24 445.858 272.24C444.503 272.24 443.469 271.872 442.754 271.136C442.05 270.4 441.698 269.323 441.698 267.904C441.698 266.539 442.05 265.477 442.754 264.72C443.458 263.963 444.434 263.584 445.682 263.584C446.738 263.584 447.549 263.877 448.114 264.464C448.69 265.04 448.978 265.867 448.978 266.944C448.978 267.179 448.962 267.445 448.93 267.744C448.898 268.043 448.861 268.288 448.818 268.48H443.858ZM445.602 265.2C445.079 265.2 444.663 265.36 444.354 265.68C444.055 265.989 443.885 266.443 443.842 267.04H446.978V266.768C446.978 265.723 446.519 265.2 445.602 265.2ZM456.21 272L456.018 271.28C455.357 271.877 454.573 272.176 453.666 272.176C452.994 272.176 452.402 272.011 451.89 271.68C451.378 271.339 450.978 270.848 450.69 270.208C450.413 269.568 450.274 268.816 450.274 267.952C450.274 266.629 450.589 265.573 451.218 264.784C451.848 263.984 452.68 263.584 453.714 263.584C454.557 263.584 455.288 263.824 455.906 264.304V260.16H458.242V272H456.21ZM454.434 270.416C454.946 270.416 455.437 270.267 455.906 269.968V265.744C455.448 265.477 454.92 265.344 454.322 265.344C453.757 265.344 453.336 265.557 453.058 265.984C452.781 266.4 452.642 267.035 452.642 267.888C452.642 268.741 452.786 269.376 453.074 269.792C453.373 270.208 453.826 270.416 454.434 270.416ZM462.151 268.48C462.194 269.184 462.407 269.696 462.791 270.016C463.175 270.325 463.778 270.48 464.599 270.48C465.314 270.48 466.146 270.347 467.095 270.08V271.632C466.722 271.824 466.274 271.973 465.751 272.08C465.239 272.187 464.706 272.24 464.151 272.24C462.797 272.24 461.762 271.872 461.047 271.136C460.343 270.4 459.991 269.323 459.991 267.904C459.991 266.539 460.343 265.477 461.047 264.72C461.751 263.963 462.727 263.584 463.975 263.584C465.031 263.584 465.842 263.877 466.407 264.464C466.983 265.04 467.271 265.867 467.271 266.944C467.271 267.179 467.255 267.445 467.223 267.744C467.191 268.043 467.154 268.288 467.111 268.48H462.151ZM463.895 265.2C463.373 265.2 462.957 265.36 462.647 265.68C462.349 265.989 462.178 266.443 462.135 267.04H465.271V266.768C465.271 265.723 464.813 265.2 463.895 265.2ZM474.231 272V266.64C474.231 266.203 474.135 265.883 473.943 265.68C473.751 265.477 473.458 265.376 473.063 265.376C472.477 265.376 471.895 265.557 471.319 265.92V272H468.983V263.824H470.903L471.127 264.704C472.087 263.957 473.111 263.584 474.199 263.584C474.957 263.584 475.538 263.792 475.943 264.208C476.359 264.613 476.567 265.195 476.567 265.952V272H474.231ZM483.564 271.792C482.988 272.016 482.343 272.128 481.628 272.128C480.722 272.128 480.05 271.915 479.612 271.488C479.186 271.061 478.972 270.4 478.972 269.504V265.552H477.74V264.112L479.036 263.856L479.388 261.616H481.308V263.824H483.516V265.552H481.308V269.392C481.308 269.733 481.394 269.973 481.564 270.112C481.735 270.251 482.023 270.32 482.428 270.32C482.759 270.32 483.138 270.288 483.564 270.224V271.792ZM484.981 272V263.824H487.317V272H484.981ZM486.149 262.56C485.744 262.56 485.419 262.448 485.173 262.224C484.928 262 484.805 261.696 484.805 261.312C484.805 260.928 484.928 260.624 485.173 260.4C485.419 260.176 485.744 260.064 486.149 260.064C486.555 260.064 486.88 260.176 487.125 260.4C487.371 260.624 487.493 260.928 487.493 261.312C487.493 261.696 487.371 262 487.125 262.224C486.88 262.448 486.555 262.56 486.149 262.56ZM494.228 272L494.036 271.28C493.706 271.579 493.322 271.819 492.884 272C492.458 272.171 492.042 272.256 491.636 272.256C490.847 272.256 490.212 272.032 489.732 271.584C489.263 271.136 489.028 270.539 489.028 269.792C489.028 269.28 489.156 268.832 489.412 268.448C489.668 268.053 490.036 267.744 490.516 267.52C490.996 267.296 491.562 267.184 492.212 267.184C492.724 267.184 493.29 267.253 493.908 267.392V266.592C493.908 266.101 493.807 265.765 493.604 265.584C493.402 265.403 493.028 265.312 492.484 265.312C491.61 265.312 490.644 265.477 489.588 265.808V264.256C489.983 264.053 490.479 263.893 491.076 263.776C491.674 263.648 492.282 263.584 492.9 263.584C493.999 263.584 494.799 263.808 495.3 264.256C495.812 264.693 496.068 265.387 496.068 266.336V272H494.228ZM492.292 270.688C492.559 270.688 492.831 270.629 493.108 270.512C493.396 270.395 493.663 270.235 493.908 270.032V268.64C493.439 268.565 493.018 268.528 492.644 268.528C491.716 268.528 491.252 268.901 491.252 269.648C491.252 269.979 491.343 270.235 491.524 270.416C491.706 270.597 491.962 270.688 492.292 270.688ZM501.795 271.84C501.347 272.021 500.867 272.112 500.355 272.112C498.915 272.112 498.195 271.307 498.195 269.696V260.16H500.531V269.504C500.531 269.803 500.579 270.016 500.675 270.144C500.781 270.261 500.952 270.32 501.187 270.32C501.336 270.32 501.539 270.304 501.795 270.272V271.84ZM506.79 269.744C506.79 269.531 506.726 269.365 506.598 269.248C506.48 269.131 506.235 269.003 505.862 268.864L504.614 268.368C503.963 268.112 503.494 267.797 503.206 267.424C502.918 267.051 502.774 266.576 502.774 266C502.774 265.275 503.062 264.693 503.638 264.256C504.224 263.808 505.003 263.584 505.974 263.584C506.87 263.584 507.696 263.76 508.454 264.112V265.664C507.643 265.419 506.886 265.296 506.182 265.296C505.744 265.296 505.424 265.349 505.222 265.456C505.019 265.563 504.918 265.733 504.918 265.968C504.918 266.149 504.976 266.299 505.094 266.416C505.222 266.523 505.483 266.656 505.878 266.816L507.094 267.312C507.755 267.579 508.224 267.888 508.502 268.24C508.79 268.592 508.934 269.051 508.934 269.616C508.934 270.405 508.63 271.045 508.022 271.536C507.424 272.016 506.635 272.256 505.654 272.256C504.555 272.256 503.584 272.037 502.742 271.6V270.048C503.798 270.379 504.763 270.544 505.638 270.544C506.406 270.544 506.79 270.277 506.79 269.744Z" fill="white"/> -<path d="M338.707 173.707C339.098 173.317 339.098 172.683 338.707 172.293L332.343 165.929C331.953 165.538 331.319 165.538 330.929 165.929C330.538 166.319 330.538 166.953 330.929 167.343L336.586 173L330.929 178.657C330.538 179.047 330.538 179.681 330.929 180.071C331.319 180.462 331.953 180.462 332.343 180.071L338.707 173.707ZM288 174H338V172H288V174Z" fill="black"/> -<path d="M338.707 266.707C339.098 266.317 339.098 265.683 338.707 265.293L332.343 258.929C331.953 258.538 331.319 258.538 330.929 258.929C330.538 259.319 330.538 259.953 330.929 260.343L336.586 266L330.929 271.657C330.538 272.047 330.538 272.681 330.929 273.071C331.319 273.462 331.953 273.462 332.343 273.071L338.707 266.707ZM287 267H338V265H287V267Z" fill="black"/> -<rect x="65" y="137" width="222" height="71" stroke="#7D8998" stroke-width="2"/> -<path fill-rule="evenodd" clip-rule="evenodd" d="M109.025 193C109.524 183.085 117.395 175.178 127 175.178C130.248 175.178 133.43 176.092 136.205 177.822C141.354 181.033 144.653 186.783 144.974 193H109.025ZM117.192 162.878C117.192 157.432 121.592 153 127.001 153C132.408 153 136.807 157.432 136.807 162.878C136.807 168.325 132.408 172.757 127.001 172.757C121.592 172.757 117.192 168.325 117.192 162.878ZM137.263 176.125C135.53 175.044 133.65 174.26 131.698 173.771C135.877 171.939 138.807 167.749 138.807 162.878C138.807 156.329 133.51 151 127.001 151C120.489 151 115.192 156.329 115.192 162.878C115.192 167.755 118.13 171.95 122.317 173.778C113.545 175.981 107 184.2 107 194C107 194.552 107.447 195 108 195H146C146.552 195 147 194.552 147 194C147 186.719 143.269 179.87 137.263 176.125Z" fill="#000716"/> -<path d="M163.28 179V167.912H167.264C168.917 167.912 170.187 168.392 171.072 169.352C171.968 170.301 172.416 171.667 172.416 173.448C172.416 175.219 171.968 176.589 171.072 177.56C170.187 178.52 168.933 179 167.312 179H163.28ZM165.68 169.768V177.144H167.056C168.987 177.144 169.952 175.965 169.952 173.608V173.288C169.952 170.941 168.981 169.768 167.04 169.768H165.68ZM176.239 175.48C176.282 176.184 176.495 176.696 176.879 177.016C177.263 177.325 177.866 177.48 178.687 177.48C179.402 177.48 180.234 177.347 181.183 177.08V178.632C180.81 178.824 180.362 178.973 179.839 179.08C179.327 179.187 178.794 179.24 178.239 179.24C176.884 179.24 175.85 178.872 175.135 178.136C174.431 177.4 174.079 176.323 174.079 174.904C174.079 173.539 174.431 172.477 175.135 171.72C175.839 170.963 176.815 170.584 178.063 170.584C179.119 170.584 179.93 170.877 180.495 171.464C181.071 172.04 181.359 172.867 181.359 173.944C181.359 174.179 181.343 174.445 181.311 174.744C181.279 175.043 181.242 175.288 181.199 175.48H176.239ZM177.983 172.2C177.46 172.2 177.044 172.36 176.735 172.68C176.436 172.989 176.266 173.443 176.223 174.04H179.359V173.768C179.359 172.723 178.9 172.2 177.983 172.2ZM185.199 179L182.095 170.824H184.575L186.319 176.904L188.095 170.824H190.511L187.423 179H185.199ZM193.286 175.48C193.329 176.184 193.542 176.696 193.926 177.016C194.31 177.325 194.913 177.48 195.734 177.48C196.449 177.48 197.281 177.347 198.23 177.08V178.632C197.857 178.824 197.409 178.973 196.886 179.08C196.374 179.187 195.841 179.24 195.286 179.24C193.931 179.24 192.897 178.872 192.182 178.136C191.478 177.4 191.126 176.323 191.126 174.904C191.126 173.539 191.478 172.477 192.182 171.72C192.886 170.963 193.862 170.584 195.11 170.584C196.166 170.584 196.977 170.877 197.542 171.464C198.118 172.04 198.406 172.867 198.406 173.944C198.406 174.179 198.39 174.445 198.358 174.744C198.326 175.043 198.289 175.288 198.246 175.48H193.286ZM195.03 172.2C194.507 172.2 194.091 172.36 193.782 172.68C193.483 172.989 193.313 173.443 193.27 174.04H196.406V173.768C196.406 172.723 195.947 172.2 195.03 172.2ZM203.798 178.84C203.35 179.021 202.87 179.112 202.358 179.112C200.918 179.112 200.198 178.307 200.198 176.696V167.16H202.534V176.504C202.534 176.803 202.582 177.016 202.678 177.144C202.785 177.261 202.955 177.32 203.19 177.32C203.339 177.32 203.542 177.304 203.798 177.272V178.84ZM208.877 179.24C207.608 179.24 206.616 178.861 205.901 178.104C205.186 177.336 204.829 176.269 204.829 174.904C204.829 173.549 205.186 172.493 205.901 171.736C206.616 170.968 207.608 170.584 208.877 170.584C210.146 170.584 211.138 170.968 211.853 171.736C212.568 172.493 212.925 173.549 212.925 174.904C212.925 176.269 212.568 177.336 211.853 178.104C211.138 178.861 210.146 179.24 208.877 179.24ZM208.877 177.448C209.997 177.448 210.557 176.6 210.557 174.904C210.557 173.219 209.997 172.376 208.877 172.376C207.757 172.376 207.197 173.219 207.197 174.904C207.197 176.6 207.757 177.448 208.877 177.448ZM214.745 182.296V170.824H216.665L216.857 171.592C217.177 171.283 217.561 171.037 218.009 170.856C218.468 170.675 218.932 170.584 219.401 170.584C220.436 170.584 221.252 170.963 221.849 171.72C222.457 172.477 222.761 173.501 222.761 174.792C222.761 175.635 222.622 176.387 222.345 177.048C222.068 177.709 221.668 178.232 221.145 178.616C220.622 178.989 220.02 179.176 219.337 179.176C218.9 179.176 218.484 179.107 218.089 178.968C217.694 178.829 217.358 178.637 217.081 178.392V182.296H214.745ZM218.649 172.344C218.094 172.344 217.572 172.488 217.081 172.776V176.984C217.55 177.272 218.073 177.416 218.649 177.416C219.246 177.416 219.684 177.213 219.961 176.808C220.249 176.403 220.393 175.763 220.393 174.888C220.393 174.003 220.254 173.357 219.977 172.952C219.7 172.547 219.257 172.344 218.649 172.344ZM226.333 175.48C226.375 176.184 226.589 176.696 226.973 177.016C227.357 177.325 227.959 177.48 228.781 177.48C229.495 177.48 230.327 177.347 231.277 177.08V178.632C230.903 178.824 230.455 178.973 229.933 179.08C229.421 179.187 228.887 179.24 228.333 179.24C226.978 179.24 225.943 178.872 225.229 178.136C224.525 177.4 224.173 176.323 224.173 174.904C224.173 173.539 224.525 172.477 225.229 171.72C225.933 170.963 226.909 170.584 228.157 170.584C229.213 170.584 230.023 170.877 230.589 171.464C231.165 172.04 231.453 172.867 231.453 173.944C231.453 174.179 231.437 174.445 231.405 174.744C231.373 175.043 231.335 175.288 231.293 175.48H226.333ZM228.077 172.2C227.554 172.2 227.138 172.36 226.829 172.68C226.53 172.989 226.359 173.443 226.317 174.04H229.453V173.768C229.453 172.723 228.994 172.2 228.077 172.2ZM233.245 179V170.824H235.165L235.453 172.04C235.88 171.571 236.28 171.24 236.653 171.048C237.037 170.845 237.442 170.744 237.869 170.744C238.072 170.744 238.285 170.76 238.509 170.792V172.952C238.21 172.888 237.88 172.856 237.517 172.856C236.824 172.856 236.178 172.979 235.581 173.224V179H233.245Z" fill="#414D5C"/> -<rect x="368" y="147" width="48" height="48" fill="#DD344C"/> -<path fill-rule="evenodd" clip-rule="evenodd" d="M408.463 184.395L399.536 175.468C399.351 175.283 399.307 174.999 399.427 174.768C400.674 172.366 400.195 169.339 398.263 167.407C396.886 166.029 394.983 165.375 393.049 165.608C391.111 165.842 389.402 166.961 388.362 168.677C387.139 170.693 387.193 173.278 388.5 175.265C390.312 178.022 393.846 178.975 396.718 177.485C396.951 177.365 397.233 177.408 397.419 177.594L398.9 179.075C399.012 179.187 399.075 179.34 399.075 179.499V181.445H401.021C401.179 181.445 401.332 181.508 401.445 181.62L402.294 182.468C402.406 182.581 402.47 182.733 402.47 182.893V184.838H404.415C404.575 184.838 404.727 184.902 404.839 185.014L405.952 186.128L408.318 186.285L408.463 184.395ZM409.68 184.212L409.468 186.969C409.444 187.284 409.182 187.523 408.871 187.523C408.857 187.523 408.844 187.523 408.83 187.522L405.648 187.31C405.502 187.3 405.366 187.238 405.264 187.136L404.167 186.038H401.87C401.538 186.038 401.27 185.77 401.27 185.438V183.141L400.773 182.645H398.475C398.144 182.645 397.875 182.376 397.875 182.045V179.747L396.872 178.743C393.528 180.235 389.565 179.07 387.496 175.924C385.938 173.553 385.875 170.464 387.335 168.055C388.569 166.021 390.599 164.695 392.904 164.417C395.209 164.139 397.472 164.919 399.112 166.559C401.304 168.75 401.922 172.13 400.685 174.92L409.506 183.741C409.63 183.866 409.694 184.037 409.68 184.212V184.212ZM395.254 171.807C395.254 171.407 395.098 171.03 394.814 170.747C394.53 170.463 394.153 170.307 393.753 170.307C393.353 170.307 392.976 170.463 392.693 170.746C392.108 171.331 392.108 172.283 392.693 172.868C393.277 173.453 394.229 173.453 394.814 172.868V172.868C395.098 172.584 395.254 172.208 395.254 171.807V171.807ZM395.662 169.898C396.173 170.408 396.454 171.086 396.454 171.807C396.454 172.528 396.173 173.206 395.662 173.716V173.717C395.136 174.243 394.445 174.506 393.753 174.506C393.062 174.506 392.371 174.243 391.845 173.716C390.792 172.663 390.792 170.95 391.845 169.898C392.354 169.388 393.032 169.107 393.753 169.107C394.475 169.107 395.152 169.388 395.662 169.898V169.898ZM381.201 173.953H384.8V175.153H381.2C377.688 175.145 374.796 172.654 374.614 169.481C374.607 169.331 374.6 169.192 374.6 169.053C374.6 165.138 377.376 163.683 379.011 163.167C379 162.994 378.994 162.819 378.994 162.642C378.994 159.432 381.249 156.109 384.238 154.913C387.722 153.507 391.417 154.206 394.116 156.784C394.828 157.456 395.739 158.46 396.377 159.685C397.059 159.086 397.828 158.793 398.71 158.793C400.452 158.793 402.404 160.194 402.759 163.258C406.37 164.083 408.2 166.065 408.2 169.153C408.2 172.409 406.267 174.594 402.897 175.145L402.703 173.961C404.663 173.64 407 172.545 407 169.153C407 166.524 405.438 164.996 402.085 164.342C401.817 164.289 401.617 164.062 401.601 163.789C401.466 161.554 400.277 159.993 398.71 159.993C397.909 159.993 397.281 160.341 396.673 161.121C396.54 161.293 396.325 161.378 396.109 161.346C395.895 161.313 395.714 161.167 395.638 160.964C395.115 159.566 394.072 158.393 393.29 157.655C390.939 155.409 387.723 154.802 384.685 156.027C382.166 157.034 380.194 159.94 380.194 162.642C380.194 162.945 380.212 163.236 380.25 163.533C380.253 163.555 380.254 163.578 380.254 163.601V163.602V163.603V163.604V163.605V163.605V163.607V163.607V163.607V163.608V163.609C380.254 163.912 380.03 164.165 379.738 164.207C378.239 164.587 375.8 165.719 375.8 169.053C375.8 169.171 375.806 169.289 375.812 169.403C375.957 171.952 378.325 173.947 381.201 173.953V173.953Z" fill="white"/> -<path d="M428.344 167V155.912H430.744V167H428.344ZM440.03 167L439.246 164.472H435.454L434.702 167H432.19L436.094 155.912H438.734L442.638 167H440.03ZM435.966 162.744H438.75L437.342 158.104L435.966 162.744ZM453.166 167V159.32L450.718 164.296H448.574L446.126 159.32V167H444.014V155.912H446.638L449.662 162.216L452.702 155.912H455.278V167H453.166ZM428.344 186V174.912H430.744V186H428.344ZM438.734 186L438.542 185.28C437.88 185.877 437.096 186.176 436.19 186.176C435.518 186.176 434.926 186.011 434.414 185.68C433.902 185.339 433.502 184.848 433.214 184.208C432.936 183.568 432.798 182.816 432.798 181.952C432.798 180.629 433.112 179.573 433.742 178.784C434.371 177.984 435.203 177.584 436.238 177.584C437.08 177.584 437.811 177.824 438.43 178.304V174.16H440.766V186H438.734ZM436.958 184.416C437.47 184.416 437.96 184.267 438.43 183.968V179.744C437.971 179.477 437.443 179.344 436.846 179.344C436.28 179.344 435.859 179.557 435.582 179.984C435.304 180.4 435.166 181.035 435.166 181.888C435.166 182.741 435.31 183.376 435.598 183.792C435.896 184.208 436.35 184.416 436.958 184.416ZM444.755 182.48C444.797 183.184 445.011 183.696 445.395 184.016C445.779 184.325 446.381 184.48 447.203 184.48C447.917 184.48 448.749 184.347 449.699 184.08V185.632C449.325 185.824 448.877 185.973 448.355 186.08C447.843 186.187 447.309 186.24 446.755 186.24C445.4 186.24 444.365 185.872 443.651 185.136C442.947 184.4 442.595 183.323 442.595 181.904C442.595 180.539 442.947 179.477 443.651 178.72C444.355 177.963 445.331 177.584 446.579 177.584C447.635 177.584 448.445 177.877 449.011 178.464C449.587 179.04 449.875 179.867 449.875 180.944C449.875 181.179 449.859 181.445 449.827 181.744C449.795 182.043 449.757 182.288 449.715 182.48H444.755ZM446.499 179.2C445.976 179.2 445.56 179.36 445.251 179.68C444.952 179.989 444.781 180.443 444.739 181.04H447.875V180.768C447.875 179.723 447.416 179.2 446.499 179.2ZM456.915 186V180.64C456.915 180.203 456.819 179.883 456.627 179.68C456.435 179.477 456.142 179.376 455.747 179.376C455.16 179.376 454.579 179.557 454.003 179.92V186H451.667V177.824H453.587L453.811 178.704C454.771 177.957 455.795 177.584 456.883 177.584C457.64 177.584 458.222 177.792 458.627 178.208C459.043 178.613 459.251 179.195 459.251 179.952V186H456.915ZM466.328 185.792C465.752 186.016 465.106 186.128 464.392 186.128C463.485 186.128 462.813 185.915 462.376 185.488C461.949 185.061 461.736 184.4 461.736 183.504V179.552H460.504V178.112L461.8 177.856L462.152 175.616H464.072V177.824H466.28V179.552H464.072V183.392C464.072 183.733 464.157 183.973 464.328 184.112C464.498 184.251 464.786 184.32 465.192 184.32C465.522 184.32 465.901 184.288 466.328 184.224V185.792ZM467.825 186V177.824H470.161V186H467.825ZM468.993 176.56C468.587 176.56 468.262 176.448 468.017 176.224C467.771 176 467.649 175.696 467.649 175.312C467.649 174.928 467.771 174.624 468.017 174.4C468.262 174.176 468.587 174.064 468.993 174.064C469.398 174.064 469.723 174.176 469.969 174.4C470.214 174.624 470.337 174.928 470.337 175.312C470.337 175.696 470.214 176 469.969 176.224C469.723 176.448 469.398 176.56 468.993 176.56ZM477.328 185.792C476.752 186.016 476.106 186.128 475.392 186.128C474.485 186.128 473.813 185.915 473.376 185.488C472.949 185.061 472.736 184.4 472.736 183.504V179.552H471.504V178.112L472.8 177.856L473.152 175.616H475.072V177.824H477.28V179.552H475.072V183.392C475.072 183.733 475.157 183.973 475.328 184.112C475.498 184.251 475.786 184.32 476.192 184.32C476.522 184.32 476.901 184.288 477.328 184.224V185.792ZM481.421 186.128L478.189 177.824H480.669L482.493 183.936L484.221 177.824H486.637L483.181 187.104C482.872 187.947 482.493 188.555 482.045 188.928C481.597 189.301 481.032 189.488 480.349 189.488C479.816 189.488 479.298 189.403 478.797 189.232V187.648C479.138 187.68 479.442 187.696 479.709 187.696C480.157 187.696 480.504 187.589 480.749 187.376C480.994 187.173 481.202 186.816 481.373 186.304L481.421 186.128ZM500.235 185.712C499.371 186.043 498.405 186.208 497.339 186.208C495.536 186.208 494.171 185.728 493.243 184.768C492.315 183.797 491.851 182.379 491.851 180.512C491.851 178.667 492.336 177.237 493.307 176.224C494.277 175.211 495.643 174.704 497.403 174.704C498.341 174.704 499.232 174.853 500.075 175.152V177.04C499.104 176.827 498.309 176.72 497.691 176.72C496.581 176.72 495.749 177.013 495.195 177.6C494.651 178.187 494.379 179.083 494.379 180.288V180.656C494.379 181.851 494.645 182.741 495.179 183.328C495.712 183.904 496.528 184.192 497.627 184.192C498.245 184.192 499.115 184.069 500.235 183.824V185.712ZM503.598 182.48C503.641 183.184 503.854 183.696 504.238 184.016C504.622 184.325 505.225 184.48 506.046 184.48C506.761 184.48 507.593 184.347 508.542 184.08V185.632C508.169 185.824 507.721 185.973 507.198 186.08C506.686 186.187 506.153 186.24 505.598 186.24C504.244 186.24 503.209 185.872 502.494 185.136C501.79 184.4 501.438 183.323 501.438 181.904C501.438 180.539 501.79 179.477 502.494 178.72C503.198 177.963 504.174 177.584 505.422 177.584C506.478 177.584 507.289 177.877 507.854 178.464C508.43 179.04 508.718 179.867 508.718 180.944C508.718 181.179 508.702 181.445 508.67 181.744C508.638 182.043 508.601 182.288 508.558 182.48H503.598ZM505.342 179.2C504.82 179.2 504.404 179.36 504.094 179.68C503.796 179.989 503.625 180.443 503.582 181.04H506.718V180.768C506.718 179.723 506.26 179.2 505.342 179.2ZM515.759 186V180.64C515.759 180.203 515.663 179.883 515.471 179.68C515.279 179.477 514.985 179.376 514.591 179.376C514.004 179.376 513.423 179.557 512.847 179.92V186H510.511V177.824H512.431L512.655 178.704C513.615 177.957 514.639 177.584 515.727 177.584C516.484 177.584 517.065 177.792 517.471 178.208C517.887 178.613 518.095 179.195 518.095 179.952V186H515.759ZM525.172 185.792C524.596 186.016 523.95 186.128 523.236 186.128C522.329 186.128 521.657 185.915 521.22 185.488C520.793 185.061 520.58 184.4 520.58 183.504V179.552H519.348V178.112L520.644 177.856L520.996 175.616H522.916V177.824H525.124V179.552H522.916V183.392C522.916 183.733 523.001 183.973 523.172 184.112C523.342 184.251 523.63 184.32 524.036 184.32C524.366 184.32 524.745 184.288 525.172 184.224V185.792ZM528.348 182.48C528.391 183.184 528.604 183.696 528.988 184.016C529.372 184.325 529.975 184.48 530.796 184.48C531.511 184.48 532.343 184.347 533.292 184.08V185.632C532.919 185.824 532.471 185.973 531.948 186.08C531.436 186.187 530.903 186.24 530.348 186.24C528.994 186.24 527.959 185.872 527.244 185.136C526.54 184.4 526.188 183.323 526.188 181.904C526.188 180.539 526.54 179.477 527.244 178.72C527.948 177.963 528.924 177.584 530.172 177.584C531.228 177.584 532.039 177.877 532.604 178.464C533.18 179.04 533.468 179.867 533.468 180.944C533.468 181.179 533.452 181.445 533.42 181.744C533.388 182.043 533.351 182.288 533.308 182.48H528.348ZM530.092 179.2C529.57 179.2 529.154 179.36 528.844 179.68C528.546 179.989 528.375 180.443 528.332 181.04H531.468V180.768C531.468 179.723 531.01 179.2 530.092 179.2ZM535.261 186V177.824H537.181L537.469 179.04C537.895 178.571 538.295 178.24 538.669 178.048C539.053 177.845 539.458 177.744 539.885 177.744C540.087 177.744 540.301 177.76 540.525 177.792V179.952C540.226 179.888 539.895 179.856 539.533 179.856C538.839 179.856 538.194 179.979 537.597 180.224V186H535.261Z" fill="#414D5C"/> -<rect x="341" y="137" width="222" height="71" stroke="#7D8998" stroke-width="2"/> -<path d="M289.5 173L313 173C318.523 173 323 177.477 323 183L323 256C323 261.523 327.477 266 333 266L338.5 266" stroke="black" stroke-width="2"/> -<rect x="731" y="243" width="257" height="46" rx="5" fill="#0972D3"/> -<rect x="731" y="243" width="257" height="46" rx="5" stroke="#000716" stroke-width="2"/> -<path d="M755.642 271.712C754.778 272.043 753.812 272.208 752.746 272.208C750.943 272.208 749.578 271.728 748.65 270.768C747.722 269.797 747.258 268.379 747.258 266.512C747.258 264.667 747.743 263.237 748.714 262.224C749.684 261.211 751.05 260.704 752.81 260.704C753.748 260.704 754.639 260.853 755.482 261.152V263.04C754.511 262.827 753.716 262.72 753.098 262.72C751.988 262.72 751.156 263.013 750.602 263.6C750.058 264.187 749.786 265.083 749.786 266.288V266.656C749.786 267.851 750.052 268.741 750.586 269.328C751.119 269.904 751.935 270.192 753.034 270.192C753.652 270.192 754.522 270.069 755.642 269.824V271.712ZM760.782 271.84C760.334 272.021 759.854 272.112 759.342 272.112C757.902 272.112 757.182 271.307 757.182 269.696V260.16H759.518V269.504C759.518 269.803 759.566 270.016 759.662 270.144C759.768 270.261 759.939 270.32 760.174 270.32C760.323 270.32 760.526 270.304 760.782 270.272V271.84ZM765.78 272.24C764.511 272.24 763.519 271.861 762.804 271.104C762.09 270.336 761.732 269.269 761.732 267.904C761.732 266.549 762.09 265.493 762.804 264.736C763.519 263.968 764.511 263.584 765.78 263.584C767.05 263.584 768.042 263.968 768.756 264.736C769.471 265.493 769.828 266.549 769.828 267.904C769.828 269.269 769.471 270.336 768.756 271.104C768.042 271.861 767.05 272.24 765.78 272.24ZM765.78 270.448C766.9 270.448 767.46 269.6 767.46 267.904C767.46 266.219 766.9 265.376 765.78 265.376C764.66 265.376 764.1 266.219 764.1 267.904C764.1 269.6 764.66 270.448 765.78 270.448ZM777.008 272L776.784 271.136C775.835 271.872 774.843 272.24 773.808 272.24C773.083 272.24 772.518 272.027 772.112 271.6C771.707 271.163 771.504 270.565 771.504 269.808V263.824H773.84V269.152C773.84 270.016 774.214 270.448 774.96 270.448C775.515 270.448 776.059 270.277 776.592 269.936V263.824H778.928V272H777.008ZM786.602 272L786.41 271.28C785.749 271.877 784.965 272.176 784.058 272.176C783.386 272.176 782.794 272.011 782.282 271.68C781.77 271.339 781.37 270.848 781.082 270.208C780.805 269.568 780.666 268.816 780.666 267.952C780.666 266.629 780.981 265.573 781.61 264.784C782.24 263.984 783.072 263.584 784.106 263.584C784.949 263.584 785.68 263.824 786.298 264.304V260.16H788.634V272H786.602ZM784.826 270.416C785.338 270.416 785.829 270.267 786.298 269.968V265.744C785.84 265.477 785.312 265.344 784.714 265.344C784.149 265.344 783.728 265.557 783.45 265.984C783.173 266.4 783.034 267.035 783.034 267.888C783.034 268.741 783.178 269.376 783.466 269.792C783.765 270.208 784.218 270.416 784.826 270.416ZM790.959 272V260.912H797.935V262.768H793.359V265.552H797.007V267.408H793.359V272H790.959ZM802.835 272.24C801.566 272.24 800.574 271.861 799.859 271.104C799.145 270.336 798.787 269.269 798.787 267.904C798.787 266.549 799.145 265.493 799.859 264.736C800.574 263.968 801.566 263.584 802.835 263.584C804.105 263.584 805.097 263.968 805.811 264.736C806.526 265.493 806.883 266.549 806.883 267.904C806.883 269.269 806.526 270.336 805.811 271.104C805.097 271.861 804.105 272.24 802.835 272.24ZM802.835 270.448C803.955 270.448 804.515 269.6 804.515 267.904C804.515 266.219 803.955 265.376 802.835 265.376C801.715 265.376 801.155 266.219 801.155 267.904C801.155 269.6 801.715 270.448 802.835 270.448ZM808.623 272V263.824H810.543L810.831 265.04C811.258 264.571 811.658 264.24 812.031 264.048C812.415 263.845 812.821 263.744 813.247 263.744C813.45 263.744 813.663 263.76 813.887 263.792V265.952C813.589 265.888 813.258 265.856 812.895 265.856C812.202 265.856 811.557 265.979 810.959 266.224V272H808.623ZM825.156 272V266.464C825.156 265.739 824.83 265.376 824.18 265.376C823.604 265.376 823.022 265.515 822.436 265.792V265.952V272H820.1V266.464C820.1 265.739 819.774 265.376 819.124 265.376C818.526 265.376 817.94 265.52 817.364 265.808V272H815.028V263.824H816.948L817.156 264.608C817.721 264.235 818.228 263.973 818.676 263.824C819.134 263.664 819.604 263.584 820.084 263.584C821.044 263.584 821.721 263.925 822.116 264.608C822.66 264.245 823.172 263.984 823.652 263.824C824.132 263.664 824.628 263.584 825.14 263.584C825.886 263.584 826.462 263.792 826.868 264.208C827.284 264.624 827.492 265.205 827.492 265.952V272H825.156ZM834.308 272L834.116 271.28C833.785 271.579 833.401 271.819 832.964 272C832.537 272.171 832.121 272.256 831.716 272.256C830.926 272.256 830.292 272.032 829.812 271.584C829.342 271.136 829.108 270.539 829.108 269.792C829.108 269.28 829.236 268.832 829.492 268.448C829.748 268.053 830.116 267.744 830.596 267.52C831.076 267.296 831.641 267.184 832.292 267.184C832.804 267.184 833.369 267.253 833.988 267.392V266.592C833.988 266.101 833.886 265.765 833.684 265.584C833.481 265.403 833.108 265.312 832.564 265.312C831.689 265.312 830.724 265.477 829.668 265.808V264.256C830.062 264.053 830.558 263.893 831.156 263.776C831.753 263.648 832.361 263.584 832.98 263.584C834.078 263.584 834.878 263.808 835.38 264.256C835.892 264.693 836.148 265.387 836.148 266.336V272H834.308ZM832.372 270.688C832.638 270.688 832.91 270.629 833.188 270.512C833.476 270.395 833.742 270.235 833.988 270.032V268.64C833.518 268.565 833.097 268.528 832.724 268.528C831.796 268.528 831.332 268.901 831.332 269.648C831.332 269.979 831.422 270.235 831.604 270.416C831.785 270.597 832.041 270.688 832.372 270.688ZM843.138 271.792C842.562 272.016 841.917 272.128 841.202 272.128C840.295 272.128 839.623 271.915 839.186 271.488C838.759 271.061 838.546 270.4 838.546 269.504V265.552H837.314V264.112L838.61 263.856L838.962 261.616H840.882V263.824H843.09V265.552H840.882V269.392C840.882 269.733 840.967 269.973 841.138 270.112C841.309 270.251 841.597 270.32 842.002 270.32C842.333 270.32 842.711 270.288 843.138 270.224V271.792ZM844.555 272V263.824H846.891V272H844.555ZM845.723 262.56C845.318 262.56 844.992 262.448 844.747 262.224C844.502 262 844.379 261.696 844.379 261.312C844.379 260.928 844.502 260.624 844.747 260.4C844.992 260.176 845.318 260.064 845.723 260.064C846.128 260.064 846.454 260.176 846.699 260.4C846.944 260.624 847.067 260.928 847.067 261.312C847.067 261.696 846.944 262 846.699 262.224C846.454 262.448 846.128 262.56 845.723 262.56ZM852.746 272.24C851.477 272.24 850.485 271.861 849.77 271.104C849.055 270.336 848.698 269.269 848.698 267.904C848.698 266.549 849.055 265.493 849.77 264.736C850.485 263.968 851.477 263.584 852.746 263.584C854.015 263.584 855.007 263.968 855.722 264.736C856.437 265.493 856.794 266.549 856.794 267.904C856.794 269.269 856.437 270.336 855.722 271.104C855.007 271.861 854.015 272.24 852.746 272.24ZM852.746 270.448C853.866 270.448 854.426 269.6 854.426 267.904C854.426 266.219 853.866 265.376 852.746 265.376C851.626 265.376 851.066 266.219 851.066 267.904C851.066 269.6 851.626 270.448 852.746 270.448ZM863.782 272V266.64C863.782 266.203 863.686 265.883 863.494 265.68C863.302 265.477 863.009 265.376 862.614 265.376C862.027 265.376 861.446 265.557 860.87 265.92V272H858.534V263.824H860.454L860.678 264.704C861.638 263.957 862.662 263.584 863.75 263.584C864.507 263.584 865.089 263.792 865.494 264.208C865.91 264.613 866.118 265.195 866.118 265.952V272H863.782ZM868.411 272V260.912H875.707V262.768H870.811V265.392H874.795V267.248H870.811V270.144H875.707V272H868.411ZM881.821 272L880.269 269.408L878.781 272H876.365L879.101 267.872L876.397 263.824H878.909L880.397 266.304L881.789 263.824H884.205L881.533 267.744L884.333 272H881.821ZM887.022 268.48C887.065 269.184 887.278 269.696 887.662 270.016C888.046 270.325 888.649 270.48 889.47 270.48C890.185 270.48 891.017 270.347 891.966 270.08V271.632C891.593 271.824 891.145 271.973 890.622 272.08C890.11 272.187 889.577 272.24 889.022 272.24C887.668 272.24 886.633 271.872 885.918 271.136C885.214 270.4 884.862 269.323 884.862 267.904C884.862 266.539 885.214 265.477 885.918 264.72C886.622 263.963 887.598 263.584 888.846 263.584C889.902 263.584 890.713 263.877 891.278 264.464C891.854 265.04 892.142 265.867 892.142 266.944C892.142 267.179 892.126 267.445 892.094 267.744C892.062 268.043 892.025 268.288 891.982 268.48H887.022ZM888.766 265.2C888.244 265.2 887.828 265.36 887.518 265.68C887.22 265.989 887.049 266.443 887.006 267.04H890.142V266.768C890.142 265.723 889.684 265.2 888.766 265.2ZM899.759 271.648C899.471 271.819 899.124 271.947 898.719 272.032C898.313 272.128 897.892 272.176 897.455 272.176C896.153 272.176 895.156 271.813 894.463 271.088C893.78 270.363 893.439 269.317 893.439 267.952C893.439 266.597 893.801 265.541 894.527 264.784C895.252 264.027 896.26 263.648 897.551 263.648C898.329 263.648 899.049 263.819 899.711 264.16V265.712C899.081 265.531 898.505 265.44 897.983 265.44C897.236 265.44 896.687 265.632 896.335 266.016C895.983 266.389 895.807 266.987 895.807 267.808V268.032C895.807 268.843 895.977 269.44 896.319 269.824C896.671 270.197 897.209 270.384 897.935 270.384C898.457 270.384 899.065 270.288 899.759 270.096V271.648ZM906.777 272L906.553 271.136C905.604 271.872 904.612 272.24 903.577 272.24C902.852 272.24 902.287 272.027 901.881 271.6C901.476 271.163 901.273 270.565 901.273 269.808V263.824H903.609V269.152C903.609 270.016 903.983 270.448 904.729 270.448C905.284 270.448 905.828 270.277 906.361 269.936V263.824H908.697V272H906.777ZM915.715 271.792C915.139 272.016 914.494 272.128 913.779 272.128C912.872 272.128 912.2 271.915 911.763 271.488C911.336 271.061 911.123 270.4 911.123 269.504V265.552H909.891V264.112L911.187 263.856L911.539 261.616H913.459V263.824H915.667V265.552H913.459V269.392C913.459 269.733 913.544 269.973 913.715 270.112C913.886 270.251 914.174 270.32 914.579 270.32C914.91 270.32 915.288 270.288 915.715 270.224V271.792ZM917.132 272V263.824H919.468V272H917.132ZM918.3 262.56C917.894 262.56 917.569 262.448 917.324 262.224C917.078 262 916.956 261.696 916.956 261.312C916.956 260.928 917.078 260.624 917.324 260.4C917.569 260.176 917.894 260.064 918.3 260.064C918.705 260.064 919.03 260.176 919.276 260.4C919.521 260.624 919.644 260.928 919.644 261.312C919.644 261.696 919.521 262 919.276 262.224C919.03 262.448 918.705 262.56 918.3 262.56ZM925.323 272.24C924.054 272.24 923.062 271.861 922.347 271.104C921.632 270.336 921.275 269.269 921.275 267.904C921.275 266.549 921.632 265.493 922.347 264.736C923.062 263.968 924.054 263.584 925.323 263.584C926.592 263.584 927.584 263.968 928.299 264.736C929.014 265.493 929.371 266.549 929.371 267.904C929.371 269.269 929.014 270.336 928.299 271.104C927.584 271.861 926.592 272.24 925.323 272.24ZM925.323 270.448C926.443 270.448 927.003 269.6 927.003 267.904C927.003 266.219 926.443 265.376 925.323 265.376C924.203 265.376 923.643 266.219 923.643 267.904C923.643 269.6 924.203 270.448 925.323 270.448ZM936.359 272V266.64C936.359 266.203 936.263 265.883 936.071 265.68C935.879 265.477 935.586 265.376 935.191 265.376C934.604 265.376 934.023 265.557 933.447 265.92V272H931.111V263.824H933.031L933.255 264.704C934.215 263.957 935.239 263.584 936.327 263.584C937.084 263.584 937.666 263.792 938.071 264.208C938.487 264.613 938.695 265.195 938.695 265.952V272H936.359ZM940.988 272V260.912H945.26C946.412 260.912 947.324 261.216 947.996 261.824C948.668 262.432 949.004 263.259 949.004 264.304C949.004 264.944 948.828 265.52 948.476 266.032C948.124 266.544 947.628 266.944 946.988 267.232L949.74 272H947.26L944.86 267.696H943.292V272H940.988ZM943.292 266.032H944.956C946.076 266.032 946.636 265.467 946.636 264.336C946.636 263.227 946.086 262.672 944.988 262.672H943.292V266.032ZM954.411 272.24C953.142 272.24 952.15 271.861 951.435 271.104C950.72 270.336 950.363 269.269 950.363 267.904C950.363 266.549 950.72 265.493 951.435 264.736C952.15 263.968 953.142 263.584 954.411 263.584C955.68 263.584 956.672 263.968 957.387 264.736C958.102 265.493 958.459 266.549 958.459 267.904C958.459 269.269 958.102 270.336 957.387 271.104C956.672 271.861 955.68 272.24 954.411 272.24ZM954.411 270.448C955.531 270.448 956.091 269.6 956.091 267.904C956.091 266.219 955.531 265.376 954.411 265.376C953.291 265.376 952.731 266.219 952.731 267.904C952.731 269.6 953.291 270.448 954.411 270.448ZM963.799 271.84C963.351 272.021 962.871 272.112 962.359 272.112C960.919 272.112 960.199 271.307 960.199 269.696V260.16H962.535V269.504C962.535 269.803 962.583 270.016 962.679 270.144C962.786 270.261 962.956 270.32 963.191 270.32C963.34 270.32 963.543 270.304 963.799 270.272V271.84ZM966.91 268.48C966.953 269.184 967.166 269.696 967.55 270.016C967.934 270.325 968.537 270.48 969.358 270.48C970.073 270.48 970.905 270.347 971.854 270.08V271.632C971.481 271.824 971.033 271.973 970.51 272.08C969.998 272.187 969.465 272.24 968.91 272.24C967.555 272.24 966.521 271.872 965.806 271.136C965.102 270.4 964.75 269.323 964.75 267.904C964.75 266.539 965.102 265.477 965.806 264.72C966.51 263.963 967.486 263.584 968.734 263.584C969.79 263.584 970.601 263.877 971.166 264.464C971.742 265.04 972.03 265.867 972.03 266.944C972.03 267.179 972.014 267.445 971.982 267.744C971.95 268.043 971.913 268.288 971.87 268.48H966.91ZM968.654 265.2C968.131 265.2 967.715 265.36 967.406 265.68C967.107 265.989 966.937 266.443 966.894 267.04H970.03V266.768C970.03 265.723 969.571 265.2 968.654 265.2Z" fill="white"/> -<path d="M589.707 266.707C590.098 266.317 590.098 265.683 589.707 265.293L583.343 258.929C582.953 258.538 582.319 258.538 581.929 258.929C581.538 259.319 581.538 259.953 581.929 260.343L587.586 266L581.929 271.657C581.538 272.047 581.538 272.681 581.929 273.071C582.319 273.462 582.953 273.462 583.343 273.071L589.707 266.707ZM564 267H589V265H564V267Z" fill="black"/> -<path d="M1038.71 355.707C1039.1 355.317 1039.1 354.683 1038.71 354.293L1032.34 347.929C1031.95 347.538 1031.32 347.538 1030.93 347.929C1030.54 348.319 1030.54 348.953 1030.93 349.343L1036.59 355L1030.93 360.657C1030.54 361.047 1030.54 361.681 1030.93 362.071C1031.32 362.462 1031.95 362.462 1032.34 362.071L1038.71 355.707ZM572 275V345H574V275H572ZM583 356H1038V354H583V356ZM572 345C572 351.075 576.925 356 583 356V354C578.029 354 574 349.971 574 345H572ZM564 267C568.418 267 572 270.582 572 275H574C574 269.477 569.523 265 564 265V267Z" fill="black"/> -<path d="M1039.71 173.707C1040.1 173.317 1040.1 172.683 1039.71 172.293L1033.34 165.929C1032.95 165.538 1032.32 165.538 1031.93 165.929C1031.54 166.319 1031.54 166.953 1031.93 167.343L1037.59 173L1031.93 178.657C1031.54 179.047 1031.54 179.681 1031.93 180.071C1032.32 180.462 1032.95 180.462 1033.34 180.071L1039.71 173.707ZM573.5 257.5V183H571.5V257.5H573.5ZM582.5 174H1039V172H582.5V174ZM573.5 183C573.5 178.029 577.529 174 582.5 174V172C576.425 172 571.5 176.925 571.5 183H573.5ZM564 267C569.247 267 573.5 262.747 573.5 257.5H571.5C571.5 261.642 568.142 265 564 265V267Z" fill="black"/> -<rect x="591" y="241" width="112" height="49" rx="24.5" fill="#F2FCF3"/> -<rect x="591" y="241" width="112" height="49" rx="24.5" stroke="#037F0C" stroke-width="2"/> -<path fill-rule="evenodd" clip-rule="evenodd" d="M610 273.5C605.582 273.5 602 269.918 602 265.5C602 261.082 605.582 257.5 610 257.5C614.418 257.5 618 261.082 618 265.5C618 269.918 614.418 273.5 610 273.5ZM610 271.5C613.314 271.5 616 268.814 616 265.5C616 262.186 613.314 259.5 610 259.5C606.686 259.5 604 262.186 604 265.5C604 268.814 606.686 271.5 610 271.5ZM605.586 265.5L607 264.086L609 266.086L612.52 262.566L613.934 263.98L609 268.914L605.586 265.5Z" fill="#037F0C"/> -<path d="M633.022 257.458V261H630.978V251.298H634.688C635.696 251.298 636.494 251.573 637.082 252.124C637.67 252.675 637.964 253.426 637.964 254.378C637.964 255.33 637.67 256.081 637.082 256.632C636.494 257.183 635.696 257.458 634.688 257.458H633.022ZM633.022 255.89H634.45C634.917 255.89 635.272 255.764 635.514 255.512C635.766 255.251 635.892 254.873 635.892 254.378C635.892 253.883 635.766 253.51 635.514 253.258C635.272 252.997 634.917 252.866 634.45 252.866H633.022V255.89ZM643.472 261L643.304 260.37C643.014 260.631 642.678 260.841 642.296 261C641.922 261.149 641.558 261.224 641.204 261.224C640.513 261.224 639.958 261.028 639.538 260.636C639.127 260.244 638.922 259.721 638.922 259.068C638.922 258.62 639.034 258.228 639.258 257.892C639.482 257.547 639.804 257.276 640.224 257.08C640.644 256.884 641.138 256.786 641.708 256.786C642.156 256.786 642.65 256.847 643.192 256.968V256.268C643.192 255.839 643.103 255.545 642.926 255.386C642.748 255.227 642.422 255.148 641.946 255.148C641.18 255.148 640.336 255.293 639.412 255.582V254.224C639.757 254.047 640.191 253.907 640.714 253.804C641.236 253.692 641.768 253.636 642.31 253.636C643.271 253.636 643.971 253.832 644.41 254.224C644.858 254.607 645.082 255.213 645.082 256.044V261H643.472ZM641.778 259.852C642.011 259.852 642.249 259.801 642.492 259.698C642.744 259.595 642.977 259.455 643.192 259.278V258.06C642.781 257.995 642.412 257.962 642.086 257.962C641.274 257.962 640.868 258.289 640.868 258.942C640.868 259.231 640.947 259.455 641.106 259.614C641.264 259.773 641.488 259.852 641.778 259.852ZM650.05 259.026C650.05 258.839 649.994 258.695 649.882 258.592C649.78 258.489 649.565 258.377 649.238 258.256L648.146 257.822C647.577 257.598 647.166 257.323 646.914 256.996C646.662 256.669 646.536 256.254 646.536 255.75C646.536 255.115 646.788 254.607 647.292 254.224C647.806 253.832 648.487 253.636 649.336 253.636C650.12 253.636 650.844 253.79 651.506 254.098V255.456C650.797 255.241 650.134 255.134 649.518 255.134C649.136 255.134 648.856 255.181 648.678 255.274C648.501 255.367 648.412 255.517 648.412 255.722C648.412 255.881 648.464 256.011 648.566 256.114C648.678 256.207 648.907 256.324 649.252 256.464L650.316 256.898C650.895 257.131 651.306 257.402 651.548 257.71C651.8 258.018 651.926 258.419 651.926 258.914C651.926 259.605 651.66 260.165 651.128 260.594C650.606 261.014 649.915 261.224 649.056 261.224C648.095 261.224 647.246 261.033 646.508 260.65V259.292C647.432 259.581 648.277 259.726 649.042 259.726C649.714 259.726 650.05 259.493 650.05 259.026ZM656.285 259.026C656.285 258.839 656.229 258.695 656.117 258.592C656.014 258.489 655.799 258.377 655.473 258.256L654.381 257.822C653.811 257.598 653.401 257.323 653.149 256.996C652.897 256.669 652.771 256.254 652.771 255.75C652.771 255.115 653.023 254.607 653.527 254.224C654.04 253.832 654.721 253.636 655.571 253.636C656.355 253.636 657.078 253.79 657.741 254.098V255.456C657.031 255.241 656.369 255.134 655.753 255.134C655.37 255.134 655.09 255.181 654.913 255.274C654.735 255.367 654.647 255.517 654.647 255.722C654.647 255.881 654.698 256.011 654.801 256.114C654.913 256.207 655.141 256.324 655.487 256.464L656.551 256.898C657.129 257.131 657.54 257.402 657.783 257.71C658.035 258.018 658.161 258.419 658.161 258.914C658.161 259.605 657.895 260.165 657.363 260.594C656.84 261.014 656.149 261.224 655.291 261.224C654.329 261.224 653.48 261.033 652.743 260.65V259.292C653.667 259.581 654.511 259.726 655.277 259.726C655.949 259.726 656.285 259.493 656.285 259.026ZM663.145 261V253.846H664.825L665.077 254.91C665.45 254.499 665.8 254.21 666.127 254.042C666.463 253.865 666.818 253.776 667.191 253.776C667.368 253.776 667.555 253.79 667.751 253.818V255.708C667.49 255.652 667.2 255.624 666.883 255.624C666.276 255.624 665.712 255.731 665.189 255.946V261H663.145ZM671.997 261.21C670.886 261.21 670.018 260.879 669.393 260.216C668.768 259.544 668.455 258.611 668.455 257.416C668.455 256.231 668.768 255.307 669.393 254.644C670.018 253.972 670.886 253.636 671.997 253.636C673.108 253.636 673.976 253.972 674.601 254.644C675.226 255.307 675.539 256.231 675.539 257.416C675.539 258.611 675.226 259.544 674.601 260.216C673.976 260.879 673.108 261.21 671.997 261.21ZM671.997 259.642C672.977 259.642 673.467 258.9 673.467 257.416C673.467 255.941 672.977 255.204 671.997 255.204C671.017 255.204 670.527 255.941 670.527 257.416C670.527 258.9 671.017 259.642 671.997 259.642ZM680.281 260.86C679.889 261.019 679.469 261.098 679.021 261.098C677.761 261.098 677.131 260.393 677.131 258.984V250.64H679.175V258.816C679.175 259.077 679.217 259.264 679.301 259.376C679.395 259.479 679.544 259.53 679.749 259.53C679.88 259.53 680.057 259.516 680.281 259.488V260.86ZM683.073 257.92C683.111 258.536 683.297 258.984 683.633 259.264C683.969 259.535 684.497 259.67 685.215 259.67C685.841 259.67 686.569 259.553 687.399 259.32V260.678C687.073 260.846 686.681 260.977 686.223 261.07C685.775 261.163 685.309 261.21 684.823 261.21C683.638 261.21 682.733 260.888 682.107 260.244C681.491 259.6 681.183 258.657 681.183 257.416C681.183 256.221 681.491 255.293 682.107 254.63C682.723 253.967 683.577 253.636 684.669 253.636C685.593 253.636 686.303 253.893 686.797 254.406C687.301 254.91 687.553 255.633 687.553 256.576C687.553 256.781 687.539 257.015 687.511 257.276C687.483 257.537 687.451 257.752 687.413 257.92H683.073ZM684.599 255.05C684.142 255.05 683.778 255.19 683.507 255.47C683.246 255.741 683.097 256.137 683.059 256.66H685.803V256.422C685.803 255.507 685.402 255.05 684.599 255.05ZM629.048 282.016C628.414 281.129 627.928 280.149 627.592 279.076C627.256 277.993 627.088 276.878 627.088 275.73C627.088 274.591 627.256 273.481 627.592 272.398C627.928 271.315 628.414 270.331 629.048 269.444H630.994C630.434 270.312 630 271.287 629.692 272.37C629.394 273.453 629.244 274.573 629.244 275.73C629.244 276.887 629.394 278.007 629.692 279.09C630 280.173 630.434 281.148 630.994 282.016H629.048ZM635.343 280.21C634.232 280.21 633.364 279.879 632.739 279.216C632.113 278.544 631.801 277.611 631.801 276.416C631.801 275.231 632.113 274.307 632.739 273.644C633.364 272.972 634.232 272.636 635.343 272.636C636.453 272.636 637.321 272.972 637.947 273.644C638.572 274.307 638.885 275.231 638.885 276.416C638.885 277.611 638.572 278.544 637.947 279.216C637.321 279.879 636.453 280.21 635.343 280.21ZM635.343 278.642C636.323 278.642 636.813 277.9 636.813 276.416C636.813 274.941 636.323 274.204 635.343 274.204C634.363 274.204 633.873 274.941 633.873 276.416C633.873 277.9 634.363 278.642 635.343 278.642ZM640.477 282.884V272.846H642.157L642.325 273.518C642.605 273.247 642.941 273.033 643.333 272.874C643.734 272.715 644.14 272.636 644.551 272.636C645.456 272.636 646.17 272.967 646.693 273.63C647.225 274.293 647.491 275.189 647.491 276.318C647.491 277.055 647.37 277.713 647.127 278.292C646.884 278.871 646.534 279.328 646.077 279.664C645.62 279.991 645.092 280.154 644.495 280.154C644.112 280.154 643.748 280.093 643.403 279.972C643.058 279.851 642.764 279.683 642.521 279.468V282.884H640.477ZM643.893 274.176C643.408 274.176 642.95 274.302 642.521 274.554V278.236C642.932 278.488 643.389 278.614 643.893 278.614C644.416 278.614 644.798 278.437 645.041 278.082C645.293 277.727 645.419 277.167 645.419 276.402C645.419 275.627 645.298 275.063 645.055 274.708C644.812 274.353 644.425 274.176 643.893 274.176ZM653.346 279.818C652.842 280.014 652.278 280.112 651.652 280.112C650.859 280.112 650.271 279.925 649.888 279.552C649.515 279.179 649.328 278.6 649.328 277.816V274.358H648.25V273.098L649.384 272.874L649.692 270.914H651.372V272.846H653.304V274.358H651.372V277.718C651.372 278.017 651.447 278.227 651.596 278.348C651.746 278.469 651.998 278.53 652.352 278.53C652.642 278.53 652.973 278.502 653.346 278.446V279.818ZM654.656 280V272.846H656.7V280H654.656ZM655.678 271.74C655.323 271.74 655.039 271.642 654.824 271.446C654.609 271.25 654.502 270.984 654.502 270.648C654.502 270.312 654.609 270.046 654.824 269.85C655.039 269.654 655.323 269.556 655.678 269.556C656.033 269.556 656.317 269.654 656.532 269.85C656.747 270.046 656.854 270.312 656.854 270.648C656.854 270.984 656.747 271.25 656.532 271.446C656.317 271.642 656.033 271.74 655.678 271.74ZM661.893 280.21C660.783 280.21 659.915 279.879 659.289 279.216C658.664 278.544 658.351 277.611 658.351 276.416C658.351 275.231 658.664 274.307 659.289 273.644C659.915 272.972 660.783 272.636 661.893 272.636C663.004 272.636 663.872 272.972 664.497 273.644C665.123 274.307 665.435 275.231 665.435 276.416C665.435 277.611 665.123 278.544 664.497 279.216C663.872 279.879 663.004 280.21 661.893 280.21ZM661.893 278.642C662.873 278.642 663.363 277.9 663.363 276.416C663.363 274.941 662.873 274.204 661.893 274.204C660.913 274.204 660.423 274.941 660.423 276.416C660.423 277.9 660.913 278.642 661.893 278.642ZM671.62 280V275.31C671.62 274.927 671.536 274.647 671.368 274.47C671.2 274.293 670.943 274.204 670.598 274.204C670.085 274.204 669.576 274.363 669.072 274.68V280H667.028V272.846H668.708L668.904 273.616C669.744 272.963 670.64 272.636 671.592 272.636C672.255 272.636 672.763 272.818 673.118 273.182C673.482 273.537 673.664 274.045 673.664 274.708V280H671.62ZM679.702 280L679.534 279.37C679.245 279.631 678.909 279.841 678.526 280C678.153 280.149 677.789 280.224 677.434 280.224C676.743 280.224 676.188 280.028 675.768 279.636C675.357 279.244 675.152 278.721 675.152 278.068C675.152 277.62 675.264 277.228 675.488 276.892C675.712 276.547 676.034 276.276 676.454 276.08C676.874 275.884 677.369 275.786 677.938 275.786C678.386 275.786 678.881 275.847 679.422 275.968V275.268C679.422 274.839 679.333 274.545 679.156 274.386C678.979 274.227 678.652 274.148 678.176 274.148C677.411 274.148 676.566 274.293 675.642 274.582V273.224C675.987 273.047 676.421 272.907 676.944 272.804C677.467 272.692 677.999 272.636 678.54 272.636C679.501 272.636 680.201 272.832 680.64 273.224C681.088 273.607 681.312 274.213 681.312 275.044V280H679.702ZM678.008 278.852C678.241 278.852 678.479 278.801 678.722 278.698C678.974 278.595 679.207 278.455 679.422 278.278V277.06C679.011 276.995 678.643 276.962 678.316 276.962C677.504 276.962 677.098 277.289 677.098 277.942C677.098 278.231 677.177 278.455 677.336 278.614C677.495 278.773 677.719 278.852 678.008 278.852ZM686.393 279.86C686.001 280.019 685.581 280.098 685.133 280.098C683.873 280.098 683.243 279.393 683.243 277.984V269.64H685.287V277.816C685.287 278.077 685.329 278.264 685.413 278.376C685.506 278.479 685.655 278.53 685.861 278.53C685.991 278.53 686.169 278.516 686.393 278.488V279.86ZM688.957 269.444C689.592 270.331 690.077 271.315 690.413 272.398C690.749 273.481 690.917 274.591 690.917 275.73C690.917 276.878 690.749 277.993 690.413 279.076C690.077 280.149 689.592 281.129 688.957 282.016H687.011C687.571 281.148 688.001 280.173 688.299 279.09C688.607 278.007 688.761 276.887 688.761 275.73C688.761 274.573 688.607 273.453 688.299 272.37C688.001 271.287 687.571 270.312 687.011 269.444H688.957Z" fill="#037F0C"/> -<path d="M729.707 266.707C730.098 266.317 730.098 265.683 729.707 265.293L723.343 258.929C722.953 258.538 722.319 258.538 721.929 258.929C721.538 259.319 721.538 259.953 721.929 260.343L727.586 266L721.929 271.657C721.538 272.047 721.538 272.681 721.929 273.071C722.319 273.462 722.953 273.462 723.343 273.071L729.707 266.707ZM704 267H729V265H704V267Z" fill="black"/> -<path d="M1039.71 266.707C1040.1 266.317 1040.1 265.683 1039.71 265.293L1033.34 258.929C1032.95 258.538 1032.32 258.538 1031.93 258.929C1031.54 259.319 1031.54 259.953 1031.93 260.343L1037.59 266L1031.93 271.657C1031.54 272.047 1031.54 272.681 1031.93 273.071C1032.32 273.462 1032.95 273.462 1033.34 273.071L1039.71 266.707ZM987 267H1039V265H987V267Z" fill="black"/> -<path d="M451.293 241.707C451.683 242.098 452.317 242.098 452.707 241.707L459.071 235.343C459.462 234.953 459.462 234.319 459.071 233.929C458.681 233.538 458.047 233.538 457.657 233.929L452 239.586L446.343 233.929C445.953 233.538 445.319 233.538 444.929 233.929C444.538 234.319 444.538 234.953 444.929 235.343L451.293 241.707ZM451 209V241H453V209H451Z" fill="black"/> -<rect x="1041" y="230" width="222" height="71" stroke="#7D8998" stroke-width="2"/> -<rect x="1068" y="240" width="48" height="48" fill="#E7157B"/> -<path fill-rule="evenodd" clip-rule="evenodd" d="M1099.8 263.978H1102.8V262.776H1099.8V263.978ZM1084.8 271.189H1087.8V269.987H1084.8V271.189ZM1078.8 271.189H1083V269.987H1078.8V271.189ZM1078.8 267.583H1086V266.382H1078.8V267.583ZM1078.8 260.372H1084.2V259.171H1078.8V260.372ZM1078.8 263.978H1098.6V262.776H1078.8V263.978ZM1090.2 277.198H1076.4V256.767H1090.2V261.574H1091.4V256.166C1091.4 255.834 1091.13 255.565 1090.8 255.565H1075.8C1075.47 255.565 1075.2 255.834 1075.2 256.166V277.799C1075.2 278.131 1075.47 278.4 1075.8 278.4H1090.8C1091.13 278.4 1091.4 278.131 1091.4 277.799V265.781H1090.2V277.198ZM1108.8 262.175C1108.8 266.058 1105.3 267.409 1103.46 267.581L1093.8 267.583V266.382H1103.4C1103.52 266.368 1107.6 265.927 1107.6 262.175C1107.6 258.758 1104.52 258.065 1103.9 257.96C1103.59 257.908 1103.38 257.629 1103.4 257.318C1103.4 257.307 1103.4 257.296 1103.41 257.285C1103.37 255.354 1102.19 254.751 1101.68 254.58C1100.72 254.262 1099.65 254.566 1099.09 255.323C1098.95 255.501 1098.74 255.592 1098.52 255.558C1098.3 255.525 1098.12 255.375 1098.04 255.166C1097.67 254.122 1097.13 253.445 1096.38 252.692C1094.5 250.823 1091.94 250.307 1089.56 251.312C1088.3 251.84 1087.21 253.037 1086.55 254.596L1085.45 254.13C1086.22 252.285 1087.55 250.853 1089.09 250.204C1091.94 249.003 1094.98 249.615 1097.22 251.841C1097.86 252.484 1098.4 253.111 1098.81 253.922C1099.71 253.259 1100.91 253.06 1102.05 253.44C1103.51 253.925 1104.44 255.192 1104.59 256.877C1106.63 257.393 1108.8 259.027 1108.8 262.175V262.175Z" fill="white"/> -<path d="M1136.34 269.712C1135.48 270.043 1134.51 270.208 1133.45 270.208C1131.65 270.208 1130.28 269.728 1129.35 268.768C1128.42 267.797 1127.96 266.379 1127.96 264.512C1127.96 262.667 1128.45 261.237 1129.42 260.224C1130.39 259.211 1131.75 258.704 1133.51 258.704C1134.45 258.704 1135.34 258.853 1136.18 259.152V261.04C1135.21 260.827 1134.42 260.72 1133.8 260.72C1132.69 260.72 1131.86 261.013 1131.3 261.6C1130.76 262.187 1130.49 263.083 1130.49 264.288V264.656C1130.49 265.851 1130.75 266.741 1131.29 267.328C1131.82 267.904 1132.64 268.192 1133.74 268.192C1134.35 268.192 1135.22 268.069 1136.34 267.824V269.712ZM1141.56 269.84C1141.12 270.021 1140.64 270.112 1140.12 270.112C1138.68 270.112 1137.96 269.307 1137.96 267.696V258.16H1140.3V267.504C1140.3 267.803 1140.35 268.016 1140.44 268.144C1140.55 268.261 1140.72 268.32 1140.96 268.32C1141.11 268.32 1141.31 268.304 1141.56 268.272V269.84ZM1146.64 270.24C1145.37 270.24 1144.38 269.861 1143.67 269.104C1142.95 268.336 1142.59 267.269 1142.59 265.904C1142.59 264.549 1142.95 263.493 1143.67 262.736C1144.38 261.968 1145.37 261.584 1146.64 261.584C1147.91 261.584 1148.9 261.968 1149.62 262.736C1150.33 263.493 1150.69 264.549 1150.69 265.904C1150.69 267.269 1150.33 268.336 1149.62 269.104C1148.9 269.861 1147.91 270.24 1146.64 270.24ZM1146.64 268.448C1147.76 268.448 1148.32 267.6 1148.32 265.904C1148.32 264.219 1147.76 263.376 1146.64 263.376C1145.52 263.376 1144.96 264.219 1144.96 265.904C1144.96 267.6 1145.52 268.448 1146.64 268.448ZM1157.95 270L1157.73 269.136C1156.78 269.872 1155.79 270.24 1154.75 270.24C1154.03 270.24 1153.46 270.027 1153.05 269.6C1152.65 269.163 1152.45 268.565 1152.45 267.808V261.824H1154.78V267.152C1154.78 268.016 1155.16 268.448 1155.9 268.448C1156.46 268.448 1157 268.277 1157.53 267.936V261.824H1159.87V270H1157.95ZM1167.62 270L1167.43 269.28C1166.77 269.877 1165.99 270.176 1165.08 270.176C1164.41 270.176 1163.82 270.011 1163.3 269.68C1162.79 269.339 1162.39 268.848 1162.1 268.208C1161.83 267.568 1161.69 266.816 1161.69 265.952C1161.69 264.629 1162 263.573 1162.63 262.784C1163.26 261.984 1164.09 261.584 1165.13 261.584C1165.97 261.584 1166.7 261.824 1167.32 262.304V258.16H1169.66V270H1167.62ZM1165.85 268.416C1166.36 268.416 1166.85 268.267 1167.32 267.968V263.744C1166.86 263.477 1166.33 263.344 1165.74 263.344C1165.17 263.344 1164.75 263.557 1164.47 263.984C1164.2 264.4 1164.06 265.035 1164.06 265.888C1164.06 266.741 1164.2 267.376 1164.49 267.792C1164.79 268.208 1165.24 268.416 1165.85 268.416ZM1172.06 270V258.912H1179.04V260.768H1174.46V263.552H1178.11V265.408H1174.46V270H1172.06ZM1184.02 270.24C1182.75 270.24 1181.76 269.861 1181.04 269.104C1180.33 268.336 1179.97 267.269 1179.97 265.904C1179.97 264.549 1180.33 263.493 1181.04 262.736C1181.76 261.968 1182.75 261.584 1184.02 261.584C1185.29 261.584 1186.28 261.968 1186.99 262.736C1187.71 263.493 1188.07 264.549 1188.07 265.904C1188.07 267.269 1187.71 268.336 1186.99 269.104C1186.28 269.861 1185.29 270.24 1184.02 270.24ZM1184.02 268.448C1185.14 268.448 1185.7 267.6 1185.7 265.904C1185.7 264.219 1185.14 263.376 1184.02 263.376C1182.9 263.376 1182.34 264.219 1182.34 265.904C1182.34 267.6 1182.9 268.448 1184.02 268.448ZM1189.89 270V261.824H1191.81L1192.09 263.04C1192.52 262.571 1192.92 262.24 1193.29 262.048C1193.68 261.845 1194.08 261.744 1194.51 261.744C1194.71 261.744 1194.93 261.76 1195.15 261.792V263.952C1194.85 263.888 1194.52 263.856 1194.16 263.856C1193.46 263.856 1192.82 263.979 1192.22 264.224V270H1189.89ZM1206.5 270V264.464C1206.5 263.739 1206.17 263.376 1205.52 263.376C1204.95 263.376 1204.36 263.515 1203.78 263.792V263.952V270H1201.44V264.464C1201.44 263.739 1201.12 263.376 1200.47 263.376C1199.87 263.376 1199.28 263.52 1198.71 263.808V270H1196.37V261.824H1198.29L1198.5 262.608C1199.06 262.235 1199.57 261.973 1200.02 261.824C1200.48 261.664 1200.95 261.584 1201.43 261.584C1202.39 261.584 1203.06 261.925 1203.46 262.608C1204 262.245 1204.51 261.984 1204.99 261.824C1205.47 261.664 1205.97 261.584 1206.48 261.584C1207.23 261.584 1207.8 261.792 1208.21 262.208C1208.63 262.624 1208.83 263.205 1208.83 263.952V270H1206.5ZM1215.73 270L1215.54 269.28C1215.21 269.579 1214.82 269.819 1214.39 270C1213.96 270.171 1213.54 270.256 1213.14 270.256C1212.35 270.256 1211.71 270.032 1211.23 269.584C1210.76 269.136 1210.53 268.539 1210.53 267.792C1210.53 267.28 1210.66 266.832 1210.91 266.448C1211.17 266.053 1211.54 265.744 1212.02 265.52C1212.5 265.296 1213.06 265.184 1213.71 265.184C1214.23 265.184 1214.79 265.253 1215.41 265.392V264.592C1215.41 264.101 1215.31 263.765 1215.11 263.584C1214.9 263.403 1214.53 263.312 1213.99 263.312C1213.11 263.312 1212.15 263.477 1211.09 263.808V262.256C1211.48 262.053 1211.98 261.893 1212.58 261.776C1213.18 261.648 1213.78 261.584 1214.4 261.584C1215.5 261.584 1216.3 261.808 1216.8 262.256C1217.31 262.693 1217.57 263.387 1217.57 264.336V270H1215.73ZM1213.79 268.688C1214.06 268.688 1214.33 268.629 1214.61 268.512C1214.9 268.395 1215.16 268.235 1215.41 268.032V266.64C1214.94 266.565 1214.52 266.528 1214.15 266.528C1213.22 266.528 1212.75 266.901 1212.75 267.648C1212.75 267.979 1212.84 268.235 1213.03 268.416C1213.21 268.597 1213.46 268.688 1213.79 268.688ZM1224.64 269.792C1224.06 270.016 1223.42 270.128 1222.7 270.128C1221.8 270.128 1221.13 269.915 1220.69 269.488C1220.26 269.061 1220.05 268.4 1220.05 267.504V263.552H1218.82V262.112L1220.11 261.856L1220.46 259.616H1222.38V261.824H1224.59V263.552H1222.38V267.392C1222.38 267.733 1222.47 267.973 1222.64 268.112C1222.81 268.251 1223.1 268.32 1223.5 268.32C1223.83 268.32 1224.21 268.288 1224.64 268.224V269.792ZM1226.14 270V261.824H1228.47V270H1226.14ZM1227.31 260.56C1226.9 260.56 1226.57 260.448 1226.33 260.224C1226.08 260 1225.96 259.696 1225.96 259.312C1225.96 258.928 1226.08 258.624 1226.33 258.4C1226.57 258.176 1226.9 258.064 1227.31 258.064C1227.71 258.064 1228.04 258.176 1228.28 258.4C1228.53 258.624 1228.65 258.928 1228.65 259.312C1228.65 259.696 1228.53 260 1228.28 260.224C1228.04 260.448 1227.71 260.56 1227.31 260.56ZM1234.41 270.24C1233.14 270.24 1232.15 269.861 1231.43 269.104C1230.72 268.336 1230.36 267.269 1230.36 265.904C1230.36 264.549 1230.72 263.493 1231.43 262.736C1232.15 261.968 1233.14 261.584 1234.41 261.584C1235.68 261.584 1236.67 261.968 1237.38 262.736C1238.1 263.493 1238.46 264.549 1238.46 265.904C1238.46 267.269 1238.1 268.336 1237.38 269.104C1236.67 269.861 1235.68 270.24 1234.41 270.24ZM1234.41 268.448C1235.53 268.448 1236.09 267.6 1236.09 265.904C1236.09 264.219 1235.53 263.376 1234.41 263.376C1233.29 263.376 1232.73 264.219 1232.73 265.904C1232.73 267.6 1233.29 268.448 1234.41 268.448ZM1245.52 270V264.64C1245.52 264.203 1245.43 263.883 1245.24 263.68C1245.04 263.477 1244.75 263.376 1244.36 263.376C1243.77 263.376 1243.19 263.557 1242.61 263.92V270H1240.28V261.824H1242.2L1242.42 262.704C1243.38 261.957 1244.4 261.584 1245.49 261.584C1246.25 261.584 1246.83 261.792 1247.24 262.208C1247.65 262.613 1247.86 263.195 1247.86 263.952V270H1245.52Z" fill="#414D5C"/> -<rect x="1041" y="138" width="222" height="71" stroke="#7D8998" stroke-width="2"/> -<rect x="1068" y="150" width="48" height="48" fill="#ED7100"/> -<path fill-rule="evenodd" clip-rule="evenodd" d="M1091.27 172.547C1090.98 172.719 1090.79 173.04 1090.79 173.384V190.032L1078.2 182.991V166.625L1092.33 158.435L1104.89 164.657L1091.27 172.547ZM1106.35 164.641C1106.35 164.297 1106.17 163.975 1105.84 163.785L1092.81 157.329C1092.51 157.157 1092.14 157.157 1091.84 157.329L1077.48 165.65C1077.18 165.823 1077 166.144 1077 166.488V183.129C1077 183.474 1077.18 183.794 1077.49 183.972L1090.54 191.271C1090.69 191.357 1090.86 191.4 1091.03 191.4C1091.19 191.4 1091.36 191.357 1091.51 191.271C1091.81 191.099 1091.99 190.778 1091.99 190.434V173.521L1105.87 165.479C1106.17 165.307 1106.35 164.986 1106.35 164.641V164.641ZM1106.38 183.028L1094.99 189.997V183.757L1100.93 179.924L1100.97 179.655C1100.98 179.584 1100.98 179.584 1100.98 179.26L1101 171.816L1106.4 168.689L1106.38 183.028ZM1107.12 167.443C1106.82 167.269 1106.45 167.27 1106.15 167.443L1100.41 170.771C1100.23 170.869 1099.8 171.1 1099.8 171.575L1099.79 179.23L1094.31 182.764C1093.98 182.959 1093.79 183.267 1093.79 183.593V190.385C1093.79 190.725 1093.97 191.035 1094.28 191.212C1094.44 191.304 1094.62 191.351 1094.79 191.351C1094.97 191.351 1095.14 191.307 1095.3 191.215L1107.1 183.998C1107.4 183.826 1107.58 183.505 1107.58 183.163L1107.6 168.28C1107.6 167.936 1107.42 167.615 1107.12 167.443V167.443Z" fill="white"/> -<path d="M1125.28 179V167.912H1132.58V169.768H1127.68V172.392H1131.66V174.248H1127.68V177.144H1132.58V179H1125.28ZM1142.28 178.712C1141.42 179.043 1140.45 179.208 1139.39 179.208C1137.58 179.208 1136.22 178.728 1135.29 177.768C1134.36 176.797 1133.9 175.379 1133.9 173.512C1133.9 171.667 1134.38 170.237 1135.35 169.224C1136.32 168.211 1137.69 167.704 1139.45 167.704C1140.39 167.704 1141.28 167.853 1142.12 168.152V170.04C1141.15 169.827 1140.36 169.72 1139.74 169.72C1138.63 169.72 1137.8 170.013 1137.24 170.6C1136.7 171.187 1136.43 172.083 1136.43 173.288V173.656C1136.43 174.851 1136.69 175.741 1137.23 176.328C1137.76 176.904 1138.57 177.192 1139.67 177.192C1140.29 177.192 1141.16 177.069 1142.28 176.824V178.712ZM1144.06 179V167.912H1148.33C1149.49 167.912 1150.4 168.216 1151.07 168.824C1151.74 169.432 1152.08 170.259 1152.08 171.304C1152.08 171.944 1151.9 172.52 1151.55 173.032C1151.2 173.544 1150.7 173.944 1150.06 174.232L1152.81 179H1150.33L1147.93 174.696H1146.37V179H1144.06ZM1146.37 173.032H1148.03C1149.15 173.032 1149.71 172.467 1149.71 171.336C1149.71 170.227 1149.16 169.672 1148.06 169.672H1146.37V173.032Z" fill="#414D5C"/> -<rect x="1040" y="322" width="222" height="71" stroke="#7D8998" stroke-width="2"/> -<rect x="1067" y="334" width="48" height="48" fill="#7AA116"/> -<path fill-rule="evenodd" clip-rule="evenodd" d="M1103.5 359.736L1103.73 358.113C1105.86 359.386 1105.88 359.911 1105.88 359.926C1105.88 359.929 1105.52 360.231 1103.5 359.736V359.736ZM1102.34 359.412C1098.66 358.3 1093.55 355.954 1091.48 354.976C1091.48 354.968 1091.48 354.96 1091.48 354.952C1091.48 354.157 1090.84 353.51 1090.04 353.51C1089.25 353.51 1088.6 354.157 1088.6 354.952C1088.6 355.747 1089.25 356.394 1090.04 356.394C1090.39 356.394 1090.71 356.263 1090.96 356.056C1093.39 357.209 1098.47 359.521 1102.16 360.613L1100.7 370.936C1100.7 370.965 1100.7 370.993 1100.7 371.021C1100.7 371.93 1096.67 373.6 1090.1 373.6C1083.45 373.6 1079.38 371.93 1079.38 371.021C1079.38 370.993 1079.38 370.966 1079.38 370.939L1076.32 348.615C1078.97 350.436 1084.66 351.4 1090.1 351.4C1095.53 351.4 1101.21 350.44 1103.86 348.624L1102.34 359.412ZM1076 346.287C1076.04 345.497 1080.58 342.4 1090.1 342.4C1099.62 342.4 1104.16 345.496 1104.2 346.287V346.556C1103.68 348.327 1097.8 350.2 1090.1 350.2C1082.39 350.2 1076.51 348.321 1076 346.548V346.287ZM1105.4 346.3C1105.4 344.221 1099.44 341.2 1090.1 341.2C1080.76 341.2 1074.8 344.221 1074.8 346.3L1074.86 346.752L1078.19 371.067C1078.26 373.786 1085.52 374.8 1090.1 374.8C1095.78 374.8 1101.82 373.493 1101.9 371.068L1103.33 360.93C1104.13 361.122 1104.79 361.219 1105.32 361.219C1106.03 361.219 1106.51 361.046 1106.8 360.699C1107.04 360.415 1107.13 360.07 1107.06 359.704C1106.91 358.873 1105.92 357.978 1103.91 356.833L1105.34 346.776L1105.4 346.3Z" fill="white"/> -<path d="M1129.44 358.152C1128.49 357.8 1127.81 357.373 1127.39 356.872C1126.98 356.36 1126.77 355.715 1126.77 354.936C1126.77 353.933 1127.14 353.133 1127.87 352.536C1128.62 351.939 1129.62 351.64 1130.86 351.64C1131.91 351.64 1132.93 351.832 1133.94 352.216V354.04C1132.9 353.72 1131.94 353.56 1131.06 353.56C1129.8 353.56 1129.17 353.965 1129.17 354.776C1129.17 355.075 1129.27 355.32 1129.49 355.512C1129.71 355.704 1130.12 355.907 1130.72 356.12L1131.9 356.552C1132.9 356.915 1133.6 357.341 1134.02 357.832C1134.44 358.312 1134.66 358.941 1134.66 359.72C1134.66 360.819 1134.26 361.688 1133.47 362.328C1132.68 362.957 1131.6 363.272 1130.22 363.272C1129.63 363.272 1129.03 363.213 1128.43 363.096C1127.83 362.989 1127.32 362.84 1126.9 362.648V360.824C1127.43 360.984 1128 361.112 1128.61 361.208C1129.22 361.304 1129.77 361.352 1130.26 361.352C1130.89 361.352 1131.37 361.24 1131.71 361.016C1132.05 360.781 1132.22 360.451 1132.22 360.024C1132.22 359.693 1132.12 359.432 1131.9 359.24C1131.7 359.048 1131.29 358.835 1130.66 358.6L1129.44 358.152ZM1140.42 356.536C1141.44 356.589 1142.24 356.893 1142.83 357.448C1143.42 358.003 1143.71 358.733 1143.71 359.64C1143.71 360.344 1143.54 360.968 1143.18 361.512C1142.84 362.056 1142.34 362.483 1141.68 362.792C1141.02 363.091 1140.24 363.24 1139.36 363.24C1138.36 363.24 1137.35 363.021 1136.34 362.584V360.776C1137.53 361.181 1138.51 361.384 1139.28 361.384C1139.96 361.384 1140.48 361.24 1140.83 360.952C1141.19 360.653 1141.38 360.221 1141.38 359.656C1141.38 359.155 1141.21 358.787 1140.88 358.552C1140.55 358.307 1140.04 358.184 1139.34 358.184C1139.2 358.184 1138.96 358.2 1138.62 358.232C1138.29 358.253 1138.04 358.275 1137.86 358.296V356.824L1140.72 353.736H1136.48V351.912H1143.23V353.672L1140.42 356.536Z" fill="#414D5C"/> -<rect x="65" y="230" width="222" height="71" stroke="#7D8998" stroke-width="2"/> -<rect x="103" y="242" width="48" height="48" fill="#BD41CA"/> -<path fill-rule="evenodd" clip-rule="evenodd" d="M121 260.6H124V259.4H121V260.6ZM125 278.7L123.89 278.244L128.445 267.131L129.555 267.586L125 278.7ZM130.343 275.468L133.641 272.575L130.345 269.718L131.132 268.811L134.947 272.119C135.078 272.232 135.153 272.397 135.154 272.571C135.155 272.744 135.08 272.909 134.949 273.024L131.134 276.37L130.343 275.468ZM118.305 272.629C118.304 272.455 118.378 272.29 118.508 272.176L122.31 268.815L123.105 269.714L119.817 272.62L123.087 275.438L122.303 276.347L118.513 273.079C118.382 272.967 118.307 272.802 118.305 272.629V272.629ZM140.521 263H114.079C112.933 263 112 262.068 112 260.922V260.6H119.2V259.4H112V253.078C112 251.932 112.933 251 114.079 251H140.521C141.667 251 142.6 251.932 142.6 253.078V259.4H125.8V260.6H142.6V260.922C142.6 262.068 141.667 263 140.521 263V263ZM116.2 281.6H137.8V264.2H116.2V281.6ZM140.521 249.8H114.079C112.271 249.8 110.8 251.271 110.8 253.078V260.922C110.8 262.729 112.271 264.2 114.079 264.2H115V282.2C115 282.531 115.268 282.8 115.6 282.8H138.4C138.732 282.8 139 282.531 139 282.2V264.2H140.521C142.329 264.2 143.8 262.729 143.8 260.922V253.078C143.8 251.271 142.329 249.8 140.521 249.8V249.8Z" fill="white"/> -<path d="M171.344 271.712C170.48 272.043 169.515 272.208 168.448 272.208C166.645 272.208 165.28 271.728 164.352 270.768C163.424 269.797 162.96 268.379 162.96 266.512C162.96 264.667 163.445 263.237 164.416 262.224C165.387 261.211 166.752 260.704 168.512 260.704C169.451 260.704 170.341 260.853 171.184 261.152V263.04C170.213 262.827 169.419 262.72 168.8 262.72C167.691 262.72 166.859 263.013 166.304 263.6C165.76 264.187 165.488 265.083 165.488 266.288V266.656C165.488 267.851 165.755 268.741 166.288 269.328C166.821 269.904 167.637 270.192 168.736 270.192C169.355 270.192 170.224 270.069 171.344 269.824V271.712ZM176.596 272.24C175.326 272.24 174.334 271.861 173.62 271.104C172.905 270.336 172.548 269.269 172.548 267.904C172.548 266.549 172.905 265.493 173.62 264.736C174.334 263.968 175.326 263.584 176.596 263.584C177.865 263.584 178.857 263.968 179.572 264.736C180.286 265.493 180.644 266.549 180.644 267.904C180.644 269.269 180.286 270.336 179.572 271.104C178.857 271.861 177.865 272.24 176.596 272.24ZM176.596 270.448C177.716 270.448 178.276 269.6 178.276 267.904C178.276 266.219 177.716 265.376 176.596 265.376C175.476 265.376 174.916 266.219 174.916 267.904C174.916 269.6 175.476 270.448 176.596 270.448ZM187.984 272L187.792 271.28C187.13 271.877 186.346 272.176 185.44 272.176C184.768 272.176 184.176 272.011 183.664 271.68C183.152 271.339 182.752 270.848 182.464 270.208C182.186 269.568 182.048 268.816 182.048 267.952C182.048 266.629 182.362 265.573 182.992 264.784C183.621 263.984 184.453 263.584 185.488 263.584C186.33 263.584 187.061 263.824 187.68 264.304V260.16H190.016V272H187.984ZM186.208 270.416C186.72 270.416 187.21 270.267 187.68 269.968V265.744C187.221 265.477 186.693 265.344 186.096 265.344C185.53 265.344 185.109 265.557 184.832 265.984C184.554 266.4 184.416 267.035 184.416 267.888C184.416 268.741 184.56 269.376 184.848 269.792C185.146 270.208 185.6 270.416 186.208 270.416ZM194.005 268.48C194.047 269.184 194.261 269.696 194.645 270.016C195.029 270.325 195.631 270.48 196.453 270.48C197.167 270.48 197.999 270.347 198.949 270.08V271.632C198.575 271.824 198.127 271.973 197.605 272.08C197.093 272.187 196.559 272.24 196.005 272.24C194.65 272.24 193.615 271.872 192.901 271.136C192.197 270.4 191.845 269.323 191.845 267.904C191.845 266.539 192.197 265.477 192.901 264.72C193.605 263.963 194.581 263.584 195.829 263.584C196.885 263.584 197.695 263.877 198.261 264.464C198.837 265.04 199.125 265.867 199.125 266.944C199.125 267.179 199.109 267.445 199.077 267.744C199.045 268.043 199.007 268.288 198.965 268.48H194.005ZM195.749 265.2C195.226 265.2 194.81 265.36 194.501 265.68C194.202 265.989 194.031 266.443 193.989 267.04H197.125V266.768C197.125 265.723 196.666 265.2 195.749 265.2ZM203.413 267.952V272H201.077V260.912H205.317C206.469 260.912 207.381 261.227 208.053 261.856C208.725 262.485 209.061 263.344 209.061 264.432C209.061 265.52 208.725 266.379 208.053 267.008C207.381 267.637 206.469 267.952 205.317 267.952H203.413ZM203.413 266.16H205.045C205.578 266.16 205.984 266.016 206.261 265.728C206.549 265.429 206.693 264.997 206.693 264.432C206.693 263.867 206.549 263.44 206.261 263.152C205.984 262.853 205.578 262.704 205.045 262.704H203.413V266.16ZM210.887 272V263.824H213.223V272H210.887ZM212.055 262.56C211.65 262.56 211.324 262.448 211.079 262.224C210.834 262 210.711 261.696 210.711 261.312C210.711 260.928 210.834 260.624 211.079 260.4C211.324 260.176 211.65 260.064 212.055 260.064C212.46 260.064 212.786 260.176 213.031 260.4C213.276 260.624 213.399 260.928 213.399 261.312C213.399 261.696 213.276 262 213.031 262.224C212.786 262.448 212.46 262.56 212.055 262.56ZM215.526 275.296V263.824H217.446L217.638 264.592C217.958 264.283 218.342 264.037 218.79 263.856C219.249 263.675 219.713 263.584 220.182 263.584C221.217 263.584 222.033 263.963 222.63 264.72C223.238 265.477 223.542 266.501 223.542 267.792C223.542 268.635 223.404 269.387 223.126 270.048C222.849 270.709 222.449 271.232 221.926 271.616C221.404 271.989 220.801 272.176 220.118 272.176C219.681 272.176 219.265 272.107 218.87 271.968C218.476 271.829 218.14 271.637 217.862 271.392V275.296H215.526ZM219.43 265.344C218.876 265.344 218.353 265.488 217.862 265.776V269.984C218.332 270.272 218.854 270.416 219.43 270.416C220.028 270.416 220.465 270.213 220.742 269.808C221.03 269.403 221.174 268.763 221.174 267.888C221.174 267.003 221.036 266.357 220.758 265.952C220.481 265.547 220.038 265.344 219.43 265.344ZM227.114 268.48C227.157 269.184 227.37 269.696 227.754 270.016C228.138 270.325 228.741 270.48 229.562 270.48C230.277 270.48 231.109 270.347 232.058 270.08V271.632C231.685 271.824 231.237 271.973 230.714 272.08C230.202 272.187 229.669 272.24 229.114 272.24C227.759 272.24 226.725 271.872 226.01 271.136C225.306 270.4 224.954 269.323 224.954 267.904C224.954 266.539 225.306 265.477 226.01 264.72C226.714 263.963 227.69 263.584 228.938 263.584C229.994 263.584 230.805 263.877 231.37 264.464C231.946 265.04 232.234 265.867 232.234 266.944C232.234 267.179 232.218 267.445 232.186 267.744C232.154 268.043 232.117 268.288 232.074 268.48H227.114ZM228.858 265.2C228.335 265.2 227.919 265.36 227.61 265.68C227.311 265.989 227.141 266.443 227.098 267.04H230.234V266.768C230.234 265.723 229.775 265.2 228.858 265.2ZM237.626 271.84C237.178 272.021 236.698 272.112 236.186 272.112C234.746 272.112 234.026 271.307 234.026 269.696V260.16H236.362V269.504C236.362 269.803 236.41 270.016 236.506 270.144C236.613 270.261 236.784 270.32 237.018 270.32C237.168 270.32 237.37 270.304 237.626 270.272V271.84ZM239.293 272V263.824H241.629V272H239.293ZM240.461 262.56C240.056 262.56 239.731 262.448 239.485 262.224C239.24 262 239.117 261.696 239.117 261.312C239.117 260.928 239.24 260.624 239.485 260.4C239.731 260.176 240.056 260.064 240.461 260.064C240.867 260.064 241.192 260.176 241.437 260.4C241.683 260.624 241.805 260.928 241.805 261.312C241.805 261.696 241.683 262 241.437 262.224C241.192 262.448 240.867 262.56 240.461 262.56ZM249.181 272V266.64C249.181 266.203 249.085 265.883 248.893 265.68C248.701 265.477 248.407 265.376 248.013 265.376C247.426 265.376 246.845 265.557 246.269 265.92V272H243.933V263.824H245.853L246.077 264.704C247.037 263.957 248.061 263.584 249.149 263.584C249.906 263.584 250.487 263.792 250.892 264.208C251.309 264.613 251.517 265.195 251.517 265.952V272H249.181ZM255.473 268.48C255.516 269.184 255.729 269.696 256.113 270.016C256.497 270.325 257.1 270.48 257.921 270.48C258.636 270.48 259.468 270.347 260.417 270.08V271.632C260.044 271.824 259.596 271.973 259.073 272.08C258.561 272.187 258.028 272.24 257.473 272.24C256.119 272.24 255.084 271.872 254.369 271.136C253.665 270.4 253.313 269.323 253.313 267.904C253.313 266.539 253.665 265.477 254.369 264.72C255.073 263.963 256.049 263.584 257.297 263.584C258.353 263.584 259.164 263.877 259.729 264.464C260.305 265.04 260.593 265.867 260.593 266.944C260.593 267.179 260.577 267.445 260.545 267.744C260.513 268.043 260.476 268.288 260.433 268.48H255.473ZM257.217 265.2C256.695 265.2 256.279 265.36 255.969 265.68C255.671 265.989 255.5 266.443 255.457 267.04H258.593V266.768C258.593 265.723 258.135 265.2 257.217 265.2Z" fill="#414D5C"/> -</svg> diff --git a/v2/guide/deploy/build-containers.adoc b/v2/guide/deploy/build-containers.adoc deleted file mode 100644 index 0042a15c..00000000 --- a/v2/guide/deploy/build-containers.adoc +++ /dev/null @@ -1,133 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[#build-containers] -= Build and deploy container image assets in CDK apps -:info_titleabbrev: Build and deploy container image assets -:keywords: Docker, Dockerfile, Finch, Container, Container image, Container image asset, Amazon ECR, {aws} CDK, {aws} CDK CLI, Deploy, Build - -[abstract] --- -When you build container image assets with the {aws} Cloud Development Kit ({aws} CDK), Docker is utilized by default to perform these actions. If you want to use a different container management tool, you can replace Docker through the `CDK_DOCKER` environment variable. --- - -// Content start - -When you build container image assets with the {aws} Cloud Development Kit ({aws} CDK), Docker is utilized by default to perform these actions. If you want to use a different container management tool, you can replace Docker through the `CDK_DOCKER` environment variable. - -[#build-containers-intro-example] -== Example: Build and publish a container image asset with the {aws} CDK - -The following is a simple example of an {aws} CDK app that builds and publishes a container asset to Amazon Elastic Container Registry (Amazon ECR) using Docker by default: - -*Project structure*:: -+ -[source,none] ----- -my-cdk-app/ -├── lib/ -│ ├── my-stack.ts -│ └── docker/ -│ ├── Dockerfile -│ └── app/ -│ └── index.js -├── bin/ -│ └── my-cdk-app.ts -├── package.json -├── tsconfig.json -└── cdk.json ----- - -*Dockerfile*:: -+ -[source,auto] ----- -FROM public.ecr.aws/lambda/nodejs:16 - -# Copy application code -COPY app/ /var/task/ - -# (Optional) Install dependencies -# RUN npm install - -# The Lambda Node.js base image looks for index.handler by default ----- - -*Application code*:: -+ -In `lib/docker/app/index.js`: -+ -[source,javascript] ----- -console.log("Hello from inside the container!"); ----- - -*CDK stack*:: -+ -[source,javascript] ----- -import * as cdk from 'aws-cdk-lib'; -import { Construct } from 'constructs'; -import * as ecr_assets from 'aws-cdk-lib/aws-ecr-assets'; - -export class MyStack extends cdk.Stack { - constructor(scope: Construct, id: string) { - super(scope, id); - - // Define a Docker image asset - const dockerImageAsset = new ecr_assets.DockerImageAsset(this, 'MyDockerImage', { - directory: 'lib/docker', // Path to the directory containing the Dockerfile - }); - - // Output the ECR URI - new cdk.CfnOutput(this, 'ECRImageUri', { - value: dockerImageAsset.imageUri, - }); - } -} ----- - -*CDK app*:: -+ -[source,javascript] ----- -#!/usr/bin/env node -import * as cdk from 'aws-cdk-lib'; -import { MyStack } from '../lib/my-stack'; - -const app = new cdk.App(); -new MyStack(app, 'MyStack'); ----- - -When we run `cdk deploy`, the {aws} Cloud Development Kit ({aws} CDK) Command Line Interface (CLI) does the following: - -. *Build the Docker image* – Run `docker build` locally based on the `Dockerfile` in the specified directory (`lib/docker`). -. *Tag the image* – Run `docker tag` to tag the built image with a unique hash, based on the image contents. -. *Publish to Amazon ECR* – Run `docker push` to publish the container image to an Amazon ECR repository. This repository must already exist. It is created during the default bootstrapping process. -. *Output the Image URI* – After a successful deployment, the Amazon ECR URI of the published container image is output in your command prompt. This is the URI of our Docker image in Amazon ECR. - -[#build-container-replace] -== How to replace Docker with another container management tool - -Use the `CDK_DOCKER` environment variable to specify the path to the binary of your replacement container management tool. The following is an example of replacing Docker with [noloc]``Finch``: - -[source,none,subs="verbatim,attributes"] ----- -$ which finch -/usr/local/bin/finch # Locate the path to the binary - -$ export CDK_DOCKER='/usr/local/bin/finch' # Set the environment variable - -$ cdk deploy # Deploy using the replacement ----- - -Aliasing or linking is not supported. To replace Docker, you must use the `CDK_DOCKER` environment variable. - -[#build-container-supported] -== Supported Docker drop-in replacement engines - -[noloc]`Finch` is supported, although there may be some Docker features that are unavailable or may work differently as the tool evolves. For more information on Finch, see https://aws.amazon.com/blogs/opensource/ready-for-flight-announcing-finch-1-0-ga/[Ready for Flight: Announcing Finch 1.0 GA!] in the _{aws} Open Source Blog_. - -Other container management tools may work. The CDK doesn't check which Docker replacement you are using to determine if it's supported. If the tool has equivalent Docker commands and behaves similarly, it should work. \ No newline at end of file diff --git a/v2/guide/deploy/chapter-deploy.adoc b/v2/guide/deploy/chapter-deploy.adoc deleted file mode 100644 index 74a99f0b..00000000 --- a/v2/guide/deploy/chapter-deploy.adoc +++ /dev/null @@ -1,234 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -:https---docs-aws-amazon-com-cdk-api-v2-docs-aws-cdk-lib-aws-cloudformation-readme-html: https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_cloudformation-readme.html -:https---docs-aws-amazon-com-cdk-api-v2-docs-aws-cdk-lib-readme-html-stack-synthesizers: https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib-readme.html#stack-synthesizers -[.topic] -[#deploy] -= Deploy {aws} CDK applications -:keywords: {aws} CDK, IaC, Infrastructure as code, {aws}, {aws} Cloud, serverless, modern applications - -[abstract] --- -An {aws} Cloud Development Kit ({aws} CDK) deployment is the process of provisioning your infrastructure on {aws}. --- - -// Content start - -An {aws} Cloud Development Kit ({aws} CDK) deployment is the process of provisioning your infrastructure on {aws}. - -[#deploy-how] -== How {aws} CDK deployments work - -The {aws} CDK utilizes the {aws} CloudFormation service to perform deployments. Before you deploy, you synthesize your CDK stacks. This creates a CloudFormation template and deployment artifacts for each CDK stack in your app. Deployments are initiated from a local development machine or from a _continuous integration and continuous delivery (CI/CD)_ environment. During deployment, assets are uploaded to the bootstrapped resources and the CloudFormation template is submitted to CloudFormation to provision your {aws} resources. - -For a deployment to be successful, the following is required: - -* The {aws} CDK Command Line Interface ({aws} CDK CLI) must be provided with valid permissions. -* The {aws} environment must be bootstrapped. -* The {aws} CDK must know the bootstrapped resources to upload assets into. - -[#deploy-prerequisites] -== Prerequisites for CDK deployments - -Before you can deploy an {aws} CDK application, you must complete the following: - -* Configure security credentials for the CDK CLI. -* Bootstrap your {aws} environment. -* Configure an {aws} environment for each of your CDK stacks. -* Develop your CDK app. - -[#deploy-prerequisites-creds] -*Configure security credentials*:: -+ -To use the CDK CLI to interact with {aws}, you must configure security credentials on your local machine. For instructions, see xref:configure-access[Configure security credentials for the {aws} CDK CLI]. - -[#deploy-prerequisites-bootstrap] -*Bootstrap your {aws} environment*:: -+ -A deployment is always associated with one or more {aws} xref:environments[environments]. Before you can deploy, the environment must first be xref:bootstrapping[bootstrapped]. Bootstrapping provisions resources in your environment that the CDK uses to perform and manage deployments. These resources include an Amazon Simple Storage Service (Amazon S3) bucket and Amazon Elastic Container Registry (Amazon ECR) repository to store and manage xref:assets[assets]. These resources also include {aws} Identity and Access Management (IAM) roles that are used to provide permissions during development and deployment. -+ -We recommend that you use the {aws} CDK Command Line Interface ({aws} CDK CLI) `cdk bootstrap` command to bootstrap your environment. You can customize bootstrapping or manually create these resources in your environment if necessary. For instructions, see xref:bootstrapping-env[Bootstrap your environment for use with the {aws} CDK]. - -[#deploy-prerequisites-env] -*Configure {aws} environments*:: -+ -Each CDK stack must be associated with an environment to determine where the stack is deployed to. For instructions, see xref:configure-env[Configure environments to use with the {aws} CDK]. - -[#deploy-prerequisites-develop] -*Develop your CDK app*:: -+ -Within a CDK xref:projects[project], you create and develop your CDK app. Within your app, you create one or more CDK xref:stacks[stacks]. Within your stacks, you import and use xref:constructs[constructs] from the {aws} Construct Library to define your infrastructure. Before you can deploy, your CDK app must contain at least one stack. - -[#deploy-how-synth] -== CDK app synthesis - -To perform synthesis, we recommend that you use the CDK CLI `cdk synth` command. The `cdk deploy` command will also perform synthesis before initiating deployment. However, by using `cdk synth`, you can validate your CDK app and catch errors before initiating deployment. - -Synthesis behavior is determined by the link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib-readme.html#stack-synthesizers[stack synthesizer] that you configure for your CDK stack. If you don`'t configure a synthesizer, `https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.DefaultStackSynthesizer.html[DefaultStackSynthesizer]` will be used. You can also configure and customize synthesis to meet your needs. For instructions, see xref:configure-synth[Configure and perform CDK stack synthesis]. - -For your synthesized CloudFormation template to deploy successfully into your environment, it must be compatible with how your environment was bootstrapped. For example, your CloudFormation template must specify the correct Amazon S3 bucket to deploy assets into. If you use the default method of bootstrapping your environment, the default stack synthesizer will work. If you customize CDK behavior, such as customizing bootstrapping or synthesis, CDK deployment behavior may vary. - -[#deploy-how-synth-app] -*The app lifecycle*:: -+ -When you perform synthesis, your CDK app is run through the following phases, known as the __app lifecycle__: -+ -*Construction (or Initialization)*::: -+ -Your code instantiates all of the defined constructs and then links them together. In this stage, all of the constructs (app, stacks, and their child constructs) are instantiated and the constructor chain is run. Most of your app code is run in this stage. -+ -*Preparation*::: -All constructs that have implemented the `prepare` method participate in a final round of modifications, to set up their final state. The preparation phase happens automatically. As a user, you don't see any feedback from this phase. It's rare to need to use the "prepare" hook, and generally not recommended. Be very careful when mutating the construct tree during this phase, because the order of operations could impact behavior. -+ -During this phase, once the construct tree has been built, any xref:aspects[aspects] that you have configured are applied as well. -+ -*Validation*::: -+ -All constructs that have implemented the `validate` method can validate themselves to ensure that they're in a state that will correctly deploy. You will get notified of any validation failures that happen during this phase. Generally, we recommend performing validation as soon as possible (usually as soon as you get some input) and throwing exceptions as early as possible. Performing validation early improves reliability as stack traces will be more accurate, and ensures that your code can continue to execute safely. -+ -*Synthesis*::: -+ -This is the final stage of running your CDK app. It's triggered by a call to `app.synth()`, and it traverses the construct tree and invokes the `synthesize` method on all constructs. Constructs that implement `synthesize` can participate in synthesis and produce deployment artifacts to the resulting cloud assembly. These artifacts include CloudFormation templates, {aws} Lambda application bundles, file and Docker image assets, and other deployment artifacts. In most cases, you won't need to implement the `synthesize` method. - -[#deploy-how-synth-run] -*Running your app*:: -+ -The CDK CLI needs to know how to run your CDK app. If you created the project from a template using the `cdk init` command, your app's `cdk.json` file includes an `app` key. This key specifies the necessary command for the language that the app is written in. If your language requires compilation, the command line performs this step before running the app automatically. -+ -==== -[role="tablist"] -TypeScript:: -+ -[source,json,subs="verbatim,attributes"] ----- -{ - "app": "npx ts-node --prefer-ts-exts bin/my-app.ts" -} ----- - -JavaScript:: -+ -[source,json,subs="verbatim,attributes"] ----- -{ - "app": "node bin/my-app.js" -} ----- - -Python:: -+ -[source,json,subs="verbatim,attributes"] ----- -{ - "app": "python app.py" -} ----- - -Java:: -+ -[source,json,subs="verbatim,attributes"] ----- -{ - "app": "mvn -e -q compile exec:java" -} ----- - -C#:: -+ -[source,json,subs="verbatim,attributes"] ----- -{ - "app": "dotnet run -p src/MyApp/MyApp.csproj" -} ----- - -Go:: -+ -[source,json,subs="verbatim,attributes"] ----- -{ - "app": "go mod download && go run my-app.go" -} ----- -==== -+ -If you didn't create your project using the CDK CLI, or if you want to override the command line given in `cdk.json`, you can provide the `xref:ref-cli-cmd-options-app[--app]` option when running the `cdk` command. - -[source,none,subs="verbatim,attributes"] ----- -$ cdk --app '<executable>' <cdk-command> ... ----- - -The `<executable>` part of the command indicates the command that should be run to execute your CDK application. Use quotation marks as shown, since such commands contain spaces. The `<cdk-command>` is a subcommand like `synth` or `deploy` that tells the CDK CLI what you want to do with your app. Follow this with any additional options needed for that subcommand. - -The CDK CLI can also interact directly with an already-synthesized cloud assembly. To do that, pass the directory in which the cloud assembly is stored in `--app`. The following example lists the stacks defined in the cloud assembly stored under `./my-cloud-assembly`. - -[source,none,subs="verbatim,attributes"] ----- -$ cdk --app <./my-cloud-assembly> ls ----- - -[#deploy-how-synth-assemblies] -*Cloud assemblies*:: -+ -The call to `app.synth()` is what tells the {aws} CDK to synthesize a cloud assembly from an app. Typically you don't interact directly with cloud assemblies. They are files that include everything needed to deploy your app to a cloud environment. For example, it includes an {aws} CloudFormation template for each stack in your app. It also includes a copy of any file assets or Docker images that you reference in your app. -+ -See the https://github.com/aws/aws-cdk/blob/master/design/cloud-assembly.md[cloud assembly specification] for details on how cloud assemblies are formatted. -+ -To interact with the cloud assembly that your {aws} CDK app creates, you typically use the {aws} CDK CLI. However, any tool that can read the cloud assembly format can be used to deploy your app. - -[#deploy-how-deploy] -== Deploy your application - -To deploy your application, we recommend that you use the CDK CLI `cdk deploy` command to initiate deployments or to configure automated deployments. - -When you run `cdk deploy`, the CDK CLI initiates `cdk synth` to prepare for deployment. The following diagram illustrates the app lifecycle in the context of a deployment: - -image::images/app-lifecycle_cdk-flowchart.png[Flowchart of the {aws} CDK app lifecycle.,scaledwidth=100%] - -During deployment, the CDK CLI takes the cloud assembly produced by synthesis and deploys it to an {aws} environment. Assets are uploaded to Amazon S3 and Amazon ECR and the CloudFormation template is submitted to {aws} CloudFormation for deployment. - -By the time the {aws} CloudFormation deployment phase starts, your CDK app has already finished running and exited. This has the following implications: - -* The CDK app can't respond to events that happen during deployment, such as a resource being created or the whole deployment finishing. To run code during the deployment phase, you must inject it into the {aws} CloudFormation template as a xref:develop-customize-custom[custom resource]. For more information about adding a custom resource to your app, see the link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_cloudformation-readme.html[{aws} CloudFormation module], or the link:https://github.com/aws-samples/aws-cdk-examples/tree/master/typescript/custom-resource/[custom-resource] example. You can also configure the link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.triggers-readme.html[Triggers] module to run code during deployments. -* The CDK app might have to work with values that can't be known at the time it runs. For example, if the {aws} CDK app defines an Amazon S3 bucket with an automatically generated name, and you retrieve the `bucket.bucketName` (Python: `bucket_name`) attribute, that value is not the name of the deployed bucket. Instead, you get a `Token` value. To determine whether a particular value is available, call `cdk.isUnresolved(value)` (Python: `is_unresolved`). See xref:tokens[Tokens and the {aws} CDK] for details. - -[#deploy-how-deploy-permissions] -*Deployment permissions*:: -+ -Before deployment can be performed, permissions must be established. The following diagram illustrates the permissions that are used during a default deployment, when using the default bootstrapping process and stack synthesizer: -+ -image::images/default-deploy-process_cdk_flowchart.png[Flowchart of the default {aws} CDK deployment process.,scaledwidth=100%] -+ -*Actor initiates deployment*::: -+ -Deployments are initiated by an _actor_, using the CDK CLI. An actor can either be a person, or a service such as {aws} CodePipeline. -+ -If necessary, the CDK CLI runs `cdk synth` when you run `cdk deploy`. During synthesis, the {aws} identity assumes the `LookupRole` to perform context lookups in the {aws} environment. -+ -*Permissions are established*::: -+ -First, the actor's security credentials are used to authenticate to {aws} and obtain the first IAM identity in the process. For human actors, how security credentials are configured and obtained depends on how you or your organization manages users. For more information, see xref:configure-access[Configure security credentials for the {aws} CDK CLI]. For service actors, such as CodePipeline, an IAM execution role is assumed and used. -+ -Next, the IAM roles created in your {aws} environment during bootstrapping are used to establish permissions to perform the actions needed for deployment. For more information about these roles and what they grant permissions for, see xref:bootstrapping-env-roles[IAM roles created during bootstrapping]. This process includes the following: -+ --- -* The {aws} identity assumes the `DeploymentActionRole` role and passes the `CloudFormationExecutionRole` role to CloudFormation, ensuring that CloudFormation assumes the role when it performs any actions in your {aws} environment. `DeploymentActionRole` grants permission to perform deployments into your environment and `CloudFormationExecutionRole` determines what actions CloudFormation can perform. -* The {aws} identity assumes the `FilePublishingRole`, which determines the actions that can be performed on the Amazon S3 bucket created during bootstrapping. -* The {aws} identity assumes the `ImagePublishingRole`, which determines the actions that can be performed on the Amazon ECR repository created during bootstrapping. -* If necessary, the {aws} identity assumes the `LookupRole` to perform context lookups in the {aws} environment. This action may also be performed during template synthesis. --- -+ -*Deployment is performed*::: -+ -During deployment, the CDK CLI reads the bootstrap version parameter to confirm the bootstrap version number. {aws} CloudFormation also reads this parameter at deployment time to confirm. If permissions across the deployment workflow are valid, deployment is performed. Assets are uploaded to the bootstrapped resources and the CloudFormation template produced at synthesis is deployed using the CloudFormation service as a CloudFormation stack to provision your resources. - -include::policy-validation-synthesis.adoc[leveloffset=+1] - -include::create-cdk-pipeline.adoc[leveloffset=+1] - -include::build-containers.adoc[leveloffset=+1] - -include::deploy-troubleshoot.adoc[leveloffset=+1] \ No newline at end of file diff --git a/v2/guide/deploy/deploy-troubleshoot.adoc b/v2/guide/deploy/deploy-troubleshoot.adoc deleted file mode 100644 index 79293638..00000000 --- a/v2/guide/deploy/deploy-troubleshoot.adoc +++ /dev/null @@ -1,66 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[#deploy-troubleshoot] -= Troubleshoot {aws} CDK deployments -:info_titleabbrev: Troubleshoot CDK deployments -:keywords: {aws} CDK, Deploy, Troubleshoot - -[abstract] --- -Troubleshoot common issues when deploying {aws} Cloud Development Kit ({aws} CDK) applications. --- - -// Content start - -Troubleshoot common issues when deploying {aws} Cloud Development Kit ({aws} CDK) applications. - -[#deploy-troubleshoot-sp] -== Incorrect service principals are being created at deployment - -When deploying CDK applications that contain {aws} Identity and Access Management (IAM) roles with service principals, you find that incorrect domains for the service principals are being created. - -The following is a basic example of creating an IAM role that can be assumed by Amazon CloudWatch Logs using its service principal: - -[source,javascript,subs="verbatim,attributes"] ----- -import * as cdk from 'aws-cdk-lib'; -import * as iam from 'aws-cdk-lib/aws-iam'; -import { Construct } from 'constructs'; - -export class MyCdkProjectStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - // Create an IAM role for CloudWatch Logs to assume - const cloudWatchLogsRole = new iam.Role(this, 'CloudWatchLogsRole', { - assumedBy: new iam.ServicePrincipal('logs.amazonaws.com'), // This is for CloudWatch Logs - managedPolicies: [ - iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSCloudWatchLogsFullAccess') - ] - }); - - // You can then use this role in other constructs or configurations where CloudWatch Logs needs to assume a role - } -} ----- - -When you deploy this stack, a service principal named `logs.amazonaws.com` should be created. In most cases, {aws} services use the following naming for service principals: `<service>.amazonaws.com`. - -[#deploy-troubleshoot-sp-causes] -=== Common causes - -If you are using a version of the {aws} CDK older than v2.150.0, you may encounter this bug. In older {aws} CDK versions, the naming of service principals were not standardized, which could lead to the creation of service principals with incorrect domains. - -In {aws} CDK v2.51.0, a fix was implemented by standardizing all automatically created service principals to use `<service>.amazonaws.com` when possible. This fix was available by allowing the `@aws-cdk/aws-iam:standardizedServicePrincipals` feature flag. - -Starting in {aws} CDK v2.150.0, this became default behavior. - -[#deploy-troubleshoot-sp-resolution] -=== Resolution - -Upgrade to {aws} CDK v2.150.0 or newer. - -If you are unable to upgrade to {aws} CDK v2.150.0 or newer, you must upgrade to at least v2.51.0 or newer. Then, allow the following feature flag in your `cdk.json` file: `@aws-cdk/aws-iam:standardizedServicePrincipals`. \ No newline at end of file diff --git a/v2/guide/deploy/deploy.txt b/v2/guide/deploy/deploy.txt deleted file mode 100644 index 9552e2e3..00000000 --- a/v2/guide/deploy/deploy.txt +++ /dev/null @@ -1,25 +0,0 @@ -HelloCdkStack: deploying... -[0%] start: Publishing 4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392:current -[100%] success: Published 4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392:current -HelloCdkStack: creating CloudFormation changeset... - 0/5 | 4:32:31 PM | UPDATE_IN_PROGRESS | AWS::CloudFormation::Stack | HelloCdkStack User Initiated - 0/5 | 4:32:36 PM | CREATE_IN_PROGRESS | AWS::IAM::Role | Custom::S3AutoDeleteObjectsCustomResourceProvider/Role (CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092) - 1/5 | 4:32:36 PM | UPDATE_COMPLETE | AWS::S3::Bucket | MyFirstBucket (MyFirstBucketB8884501) - 1/5 | 4:32:36 PM | CREATE_IN_PROGRESS | AWS::IAM::Role | Custom::S3AutoDeleteObjectsCustomResourceProvider/Role (CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092) Resource creation Initiated - 3/5 | 4:32:54 PM | CREATE_COMPLETE | AWS::IAM::Role | Custom::S3AutoDeleteObjectsCustomResourceProvider/Role (CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092) - 3/5 | 4:32:56 PM | CREATE_IN_PROGRESS | AWS::Lambda::Function | Custom::S3AutoDeleteObjectsCustomResourceProvider/Handler (CustomS3AutoDeleteObjectsCustomResourceProviderHandler9D90184F) - 3/5 | 4:32:56 PM | CREATE_IN_PROGRESS | AWS::S3::BucketPolicy | MyFirstBucket/Policy (MyFirstBucketPolicy3243DEFD) - 3/5 | 4:32:56 PM | CREATE_IN_PROGRESS | AWS::Lambda::Function | Custom::S3AutoDeleteObjectsCustomResourceProvider/Handler (CustomS3AutoDeleteObjectsCustomResourceProviderHandler9D90184F) Resource creation Initiated - 3/5 | 4:32:57 PM | CREATE_COMPLETE | AWS::Lambda::Function | Custom::S3AutoDeleteObjectsCustomResourceProvider/Handler (CustomS3AutoDeleteObjectsCustomResourceProviderHandler9D90184F) - 3/5 | 4:32:57 PM | CREATE_IN_PROGRESS | AWS::S3::BucketPolicy | MyFirstBucket/Policy (MyFirstBucketPolicy3243DEFD) Resource creation Initiated - 4/5 | 4:32:57 PM | CREATE_COMPLETE | AWS::S3::BucketPolicy | MyFirstBucket/Policy (MyFirstBucketPolicy3243DEFD) - 4/5 | 4:32:59 PM | CREATE_IN_PROGRESS | Custom::S3AutoDeleteObjects | MyFirstBucket/AutoDeleteObjectsCustomResource/Default (MyFirstBucketAutoDeleteObjectsCustomResourceC52FCF6E) - 5/5 | 4:33:06 PM | CREATE_IN_PROGRESS | Custom::S3AutoDeleteObjects | MyFirstBucket/AutoDeleteObjectsCustomResource/Default (MyFirstBucketAutoDeleteObjectsCustomResourceC52FCF6E) Resource creation Initiated - 5/5 | 4:33:06 PM | CREATE_COMPLETE | Custom::S3AutoDeleteObjects | MyFirstBucket/AutoDeleteObjectsCustomResource/Default (MyFirstBucketAutoDeleteObjectsCustomResourceC52FCF6E) - 5/5 | 4:33:08 PM | UPDATE_COMPLETE_CLEA | AWS::CloudFormation::Stack | HelloCdkStack - 6/5 | 4:33:09 PM | UPDATE_COMPLETE | AWS::CloudFormation::Stack | HelloCdkStack - - ✅ HelloCdkStack - -Stack ARN: -arn:aws:cloudformation:REGION:ACCOUNT:stack/HelloCdkStack/UNIQUE-ID \ No newline at end of file diff --git a/v2/guide/deploy/images/app-lifecycle_cdk-flowchart.png b/v2/guide/deploy/images/app-lifecycle_cdk-flowchart.png deleted file mode 100644 index b1e07e36..00000000 Binary files a/v2/guide/deploy/images/app-lifecycle_cdk-flowchart.png and /dev/null differ diff --git a/v2/guide/deploy/images/app-lifecycle_cdk-flowchart.svg b/v2/guide/deploy/images/app-lifecycle_cdk-flowchart.svg deleted file mode 100644 index 4f8e22a2..00000000 --- a/v2/guide/deploy/images/app-lifecycle_cdk-flowchart.svg +++ /dev/null @@ -1,51 +0,0 @@ -<svg width="1478" height="575" viewBox="0 0 1478 575" fill="none" xmlns="http://www.w3.org/2000/svg"> -<rect width="1478" height="575" fill="white"/> -<rect x="41" y="43" width="153" height="46" rx="23" fill="#033160"/> -<rect x="41" y="43" width="153" height="46" rx="23" stroke="#000716" stroke-width="2"/> -<path d="M61.4328 72V60.912H65.7048C66.8568 60.912 67.7688 61.216 68.4408 61.824C69.1128 62.432 69.4488 63.2587 69.4488 64.304C69.4488 64.944 69.2728 65.52 68.9208 66.032C68.5688 66.544 68.0728 66.944 67.4328 67.232L70.1848 72H67.7048L65.3048 67.696H63.7368V72H61.4328ZM63.7368 66.032H65.4008C66.5208 66.032 67.0808 65.4667 67.0808 64.336C67.0808 63.2267 66.5315 62.672 65.4328 62.672H63.7368V66.032ZM76.8203 72L76.5963 71.136C75.647 71.872 74.655 72.24 73.6203 72.24C72.895 72.24 72.3296 72.0267 71.9243 71.6C71.519 71.1627 71.3163 70.5653 71.3163 69.808V63.824H73.6523V69.152C73.6523 70.016 74.0256 70.448 74.7723 70.448C75.327 70.448 75.871 70.2773 76.4043 69.936V63.824H78.7403V72H76.8203ZM86.1421 72V66.64C86.1421 66.2027 86.0461 65.8827 85.8541 65.68C85.6621 65.4773 85.3687 65.376 84.9741 65.376C84.3874 65.376 83.8061 65.5573 83.2301 65.92V72H80.8941V63.824H82.8141L83.0381 64.704C83.9981 63.9573 85.0221 63.584 86.1101 63.584C86.8674 63.584 87.4487 63.792 87.8541 64.208C88.2701 64.6133 88.4781 65.1947 88.4781 65.952V72H86.1421ZM100.622 71.648C100.334 71.8187 99.9878 71.9467 99.5824 72.032C99.1771 72.128 98.7558 72.176 98.3184 72.176C97.0171 72.176 96.0198 71.8133 95.3264 71.088C94.6438 70.3627 94.3024 69.3173 94.3024 67.952C94.3024 66.5973 94.6651 65.5413 95.3904 64.784C96.1158 64.0267 97.1238 63.648 98.4144 63.648C99.1931 63.648 99.9131 63.8187 100.574 64.16V65.712C99.9451 65.5307 99.3691 65.44 98.8464 65.44C98.0998 65.44 97.5504 65.632 97.1984 66.016C96.8464 66.3893 96.6704 66.9867 96.6704 67.808V68.032C96.6704 68.8427 96.8411 69.44 97.1824 69.824C97.5344 70.1973 98.0731 70.384 98.7984 70.384C99.3211 70.384 99.9291 70.288 100.622 70.096V71.648ZM107.565 72L107.373 71.28C106.711 71.8773 105.927 72.176 105.021 72.176C104.349 72.176 103.757 72.0107 103.245 71.68C102.733 71.3387 102.333 70.848 102.045 70.208C101.767 69.568 101.629 68.816 101.629 67.952C101.629 66.6293 101.943 65.5733 102.573 64.784C103.202 63.984 104.034 63.584 105.069 63.584C105.911 63.584 106.642 63.824 107.261 64.304V60.16H109.597V72H107.565ZM105.789 70.416C106.301 70.416 106.791 70.2667 107.261 69.968V65.744C106.802 65.4773 106.274 65.344 105.677 65.344C105.111 65.344 104.69 65.5573 104.413 65.984C104.135 66.4 103.997 67.0347 103.997 67.888C103.997 68.7413 104.141 69.376 104.429 69.792C104.727 70.208 105.181 70.416 105.789 70.416ZM111.762 72V60.16H114.082V67.312L116.914 63.824H119.698L116.322 67.728L119.954 72H117.106L114.082 68.272V72H111.762ZM130.622 72L130.43 71.28C129.768 71.8773 128.984 72.176 128.078 72.176C127.406 72.176 126.814 72.0107 126.302 71.68C125.79 71.3387 125.39 70.848 125.102 70.208C124.824 69.568 124.686 68.816 124.686 67.952C124.686 66.6293 125 65.5733 125.63 64.784C126.259 63.984 127.091 63.584 128.126 63.584C128.968 63.584 129.699 63.824 130.318 64.304V60.16H132.654V72H130.622ZM128.846 70.416C129.358 70.416 129.848 70.2667 130.318 69.968V65.744C129.859 65.4773 129.331 65.344 128.734 65.344C128.168 65.344 127.747 65.5573 127.47 65.984C127.192 66.4 127.054 67.0347 127.054 67.888C127.054 68.7413 127.198 69.376 127.486 69.792C127.784 70.208 128.238 70.416 128.846 70.416ZM136.562 68.48C136.605 69.184 136.818 69.696 137.202 70.016C137.586 70.3253 138.189 70.48 139.01 70.48C139.725 70.48 140.557 70.3467 141.506 70.08V71.632C141.133 71.824 140.685 71.9733 140.162 72.08C139.65 72.1867 139.117 72.24 138.562 72.24C137.208 72.24 136.173 71.872 135.458 71.136C134.754 70.4 134.402 69.3227 134.402 67.904C134.402 66.5387 134.754 65.4773 135.458 64.72C136.162 63.9627 137.138 63.584 138.386 63.584C139.442 63.584 140.253 63.8773 140.818 64.464C141.394 65.04 141.682 65.8667 141.682 66.944C141.682 67.1787 141.666 67.4453 141.634 67.744C141.602 68.0427 141.565 68.288 141.522 68.48H136.562ZM138.306 65.2C137.784 65.2 137.368 65.36 137.058 65.68C136.76 65.9893 136.589 66.4427 136.546 67.04H139.682V66.768C139.682 65.7227 139.224 65.2 138.306 65.2ZM143.395 75.296V63.824H145.315L145.507 64.592C145.827 64.2827 146.211 64.0373 146.659 63.856C147.117 63.6747 147.581 63.584 148.051 63.584C149.085 63.584 149.901 63.9627 150.499 64.72C151.107 65.4773 151.411 66.5013 151.411 67.792C151.411 68.6347 151.272 69.3867 150.995 70.048C150.717 70.7093 150.317 71.232 149.795 71.616C149.272 71.9893 148.669 72.176 147.987 72.176C147.549 72.176 147.133 72.1067 146.739 71.968C146.344 71.8293 146.008 71.6373 145.731 71.392V75.296H143.395ZM147.299 65.344C146.744 65.344 146.221 65.488 145.731 65.776V69.984C146.2 70.272 146.723 70.416 147.299 70.416C147.896 70.416 148.333 70.2133 148.611 69.808C148.899 69.4027 149.043 68.7627 149.043 67.888C149.043 67.0027 148.904 66.3573 148.627 65.952C148.349 65.5467 147.907 65.344 147.299 65.344ZM156.758 71.84C156.31 72.0213 155.83 72.112 155.318 72.112C153.878 72.112 153.158 71.3067 153.158 69.696V60.16H155.494V69.504C155.494 69.8027 155.542 70.016 155.638 70.144C155.745 70.2613 155.916 70.32 156.15 70.32C156.3 70.32 156.502 70.304 156.758 70.272V71.84ZM161.757 72.24C160.488 72.24 159.496 71.8613 158.781 71.104C158.067 70.336 157.709 69.2693 157.709 67.904C157.709 66.5493 158.067 65.4933 158.781 64.736C159.496 63.968 160.488 63.584 161.757 63.584C163.027 63.584 164.019 63.968 164.733 64.736C165.448 65.4933 165.805 66.5493 165.805 67.904C165.805 69.2693 165.448 70.336 164.733 71.104C164.019 71.8613 163.027 72.24 161.757 72.24ZM161.757 70.448C162.877 70.448 163.437 69.6 163.437 67.904C163.437 66.2187 162.877 65.376 161.757 65.376C160.637 65.376 160.077 66.2187 160.077 67.904C160.077 69.6 160.637 70.448 161.757 70.448ZM169.565 72.128L166.333 63.824H168.813L170.637 69.936L172.365 63.824H174.781L171.325 73.104C171.016 73.9467 170.637 74.5547 170.189 74.928C169.741 75.3013 169.176 75.488 168.493 75.488C167.96 75.488 167.442 75.4027 166.941 75.232V73.648C167.282 73.68 167.586 73.696 167.853 73.696C168.301 73.696 168.648 73.5893 168.893 73.376C169.138 73.1733 169.346 72.816 169.517 72.304L169.565 72.128Z" fill="white"/> -<rect x="473" y="33" width="193" height="66" rx="5" fill="#0972D3"/> -<rect x="473" y="33" width="193" height="66" rx="5" stroke="#000716" stroke-width="2"/> -<path d="M490.244 62V52.832H486.868V50.912H496.02V52.832H492.644V62H490.244ZM502.495 62V56.64C502.495 56.2027 502.399 55.8827 502.207 55.68C502.015 55.4773 501.722 55.376 501.327 55.376C500.741 55.376 500.159 55.5573 499.583 55.92V62H497.247V50.16H499.583V54.56C500.501 53.9093 501.461 53.584 502.463 53.584C503.221 53.584 503.802 53.792 504.207 54.208C504.623 54.6133 504.831 55.1947 504.831 55.952V62H502.495ZM508.708 58.48C508.751 59.184 508.964 59.696 509.348 60.016C509.732 60.3253 510.335 60.48 511.156 60.48C511.871 60.48 512.703 60.3467 513.652 60.08V61.632C513.279 61.824 512.831 61.9733 512.308 62.08C511.796 62.1867 511.263 62.24 510.708 62.24C509.353 62.24 508.319 61.872 507.604 61.136C506.9 60.4 506.548 59.3227 506.548 57.904C506.548 56.5387 506.9 55.4773 507.604 54.72C508.308 53.9627 509.284 53.584 510.532 53.584C511.588 53.584 512.399 53.8773 512.964 54.464C513.54 55.04 513.828 55.8667 513.828 56.944C513.828 57.1787 513.812 57.4453 513.78 57.744C513.748 58.0427 513.711 58.288 513.668 58.48H508.708ZM510.452 55.2C509.929 55.2 509.513 55.36 509.204 55.68C508.905 55.9893 508.735 56.4427 508.692 57.04H511.828V56.768C511.828 55.7227 511.369 55.2 510.452 55.2ZM527.872 61.712C527.008 62.0427 526.042 62.208 524.976 62.208C523.173 62.208 521.808 61.728 520.88 60.768C519.952 59.7973 519.488 58.3787 519.488 56.512C519.488 54.6667 519.973 53.2373 520.944 52.224C521.914 51.2107 523.28 50.704 525.04 50.704C525.978 50.704 526.869 50.8533 527.712 51.152V53.04C526.741 52.8267 525.946 52.72 525.328 52.72C524.218 52.72 523.386 53.0133 522.832 53.6C522.288 54.1867 522.016 55.0827 522.016 56.288V56.656C522.016 57.8507 522.282 58.7413 522.816 59.328C523.349 59.904 524.165 60.192 525.264 60.192C525.882 60.192 526.752 60.0693 527.872 59.824V61.712ZM529.572 62V50.912H533.556C535.209 50.912 536.478 51.392 537.364 52.352C538.26 53.3013 538.708 54.6667 538.708 56.448C538.708 58.2187 538.26 59.5893 537.364 60.56C536.478 61.52 535.225 62 533.604 62H529.572ZM531.972 52.768V60.144H533.348C535.278 60.144 536.244 58.9653 536.244 56.608V56.288C536.244 53.9413 535.273 52.768 533.332 52.768H531.972ZM540.867 62V50.912H543.267V55.664L547.283 50.912H549.987L545.475 56.064L550.371 62H547.507L543.267 56.736V62H540.867ZM563.708 61.712C562.844 62.0427 561.879 62.208 560.812 62.208C559.009 62.208 557.644 61.728 556.716 60.768C555.788 59.7973 555.324 58.3787 555.324 56.512C555.324 54.6667 555.809 53.2373 556.78 52.224C557.751 51.2107 559.116 50.704 560.876 50.704C561.815 50.704 562.705 50.8533 563.548 51.152V53.04C562.577 52.8267 561.783 52.72 561.164 52.72C560.055 52.72 559.223 53.0133 558.668 53.6C558.124 54.1867 557.852 55.0827 557.852 56.288V56.656C557.852 57.8507 558.119 58.7413 558.652 59.328C559.185 59.904 560.001 60.192 561.1 60.192C561.719 60.192 562.588 60.0693 563.708 59.824V61.712ZM565.408 62V50.912H567.808V60.08H572.672V62H565.408ZM574.079 62V50.912H576.479V62H574.079ZM582.977 62V53.824H584.897L585.185 55.04C585.611 54.5707 586.011 54.24 586.385 54.048C586.769 53.8453 587.174 53.744 587.601 53.744C587.803 53.744 588.017 53.76 588.241 53.792V55.952C587.942 55.888 587.611 55.856 587.249 55.856C586.555 55.856 585.91 55.9787 585.313 56.224V62H582.977ZM594.821 62L594.597 61.136C593.648 61.872 592.656 62.24 591.621 62.24C590.896 62.24 590.33 62.0267 589.925 61.6C589.52 61.1627 589.317 60.5653 589.317 59.808V53.824H591.653V59.152C591.653 60.016 592.026 60.448 592.773 60.448C593.328 60.448 593.872 60.2773 594.405 59.936V53.824H596.741V62H594.821ZM604.143 62V56.64C604.143 56.2027 604.047 55.8827 603.855 55.68C603.663 55.4773 603.369 55.376 602.975 55.376C602.388 55.376 601.807 55.5573 601.231 55.92V62H598.895V53.824H600.815L601.039 54.704C601.999 53.9573 603.023 53.584 604.111 53.584C604.868 53.584 605.449 53.792 605.855 54.208C606.271 54.6133 606.479 55.1947 606.479 55.952V62H604.143ZM612.084 59.744C612.084 59.5307 612.02 59.3653 611.892 59.248C611.774 59.1307 611.529 59.0027 611.156 58.864L609.908 58.368C609.257 58.112 608.788 57.7973 608.5 57.424C608.212 57.0507 608.068 56.576 608.068 56C608.068 55.2747 608.356 54.6933 608.932 54.256C609.518 53.808 610.297 53.584 611.268 53.584C612.164 53.584 612.99 53.76 613.748 54.112V55.664C612.937 55.4187 612.18 55.296 611.476 55.296C611.038 55.296 610.718 55.3493 610.516 55.456C610.313 55.5627 610.212 55.7333 610.212 55.968C610.212 56.1493 610.27 56.2987 610.388 56.416C610.516 56.5227 610.777 56.656 611.172 56.816L612.388 57.312C613.049 57.5787 613.518 57.888 613.796 58.24C614.084 58.592 614.228 59.0507 614.228 59.616C614.228 60.4053 613.924 61.0453 613.316 61.536C612.718 62.016 611.929 62.256 610.948 62.256C609.849 62.256 608.878 62.0373 608.036 61.6V60.048C609.092 60.3787 610.057 60.544 610.932 60.544C611.7 60.544 612.084 60.2773 612.084 59.744ZM621.94 62.128L618.708 53.824H621.188L623.012 59.936L624.74 53.824H627.156L623.7 63.104C623.391 63.9467 623.012 64.5547 622.564 64.928C622.116 65.3013 621.551 65.488 620.868 65.488C620.335 65.488 619.817 65.4027 619.316 65.232V63.648C619.657 63.68 619.961 63.696 620.228 63.696C620.676 63.696 621.023 63.5893 621.268 63.376C621.513 63.1733 621.721 62.816 621.892 62.304L621.94 62.128ZM631.738 62.24C630.469 62.24 629.477 61.8613 628.762 61.104C628.047 60.336 627.69 59.2693 627.69 57.904C627.69 56.5493 628.047 55.4933 628.762 54.736C629.477 53.968 630.469 53.584 631.738 53.584C633.007 53.584 633.999 53.968 634.714 54.736C635.429 55.4933 635.786 56.5493 635.786 57.904C635.786 59.2693 635.429 60.336 634.714 61.104C633.999 61.8613 633.007 62.24 631.738 62.24ZM631.738 60.448C632.858 60.448 633.418 59.6 633.418 57.904C633.418 56.2187 632.858 55.376 631.738 55.376C630.618 55.376 630.058 56.2187 630.058 57.904C630.058 59.6 630.618 60.448 631.738 60.448ZM642.966 62L642.742 61.136C641.793 61.872 640.801 62.24 639.766 62.24C639.041 62.24 638.475 62.0267 638.07 61.6C637.665 61.1627 637.462 60.5653 637.462 59.808V53.824H639.798V59.152C639.798 60.016 640.171 60.448 640.918 60.448C641.473 60.448 642.017 60.2773 642.55 59.936V53.824H644.886V62H642.966ZM647.04 62V53.824H648.96L649.248 55.04C649.674 54.5707 650.074 54.24 650.448 54.048C650.832 53.8453 651.237 53.744 651.664 53.744C651.866 53.744 652.08 53.76 652.304 53.792V55.952C652.005 55.888 651.674 55.856 651.312 55.856C650.618 55.856 649.973 55.9787 649.376 56.224V62H647.04ZM561.177 82L560.985 81.28C560.654 81.5787 560.27 81.8187 559.833 82C559.406 82.1707 558.99 82.256 558.585 82.256C557.796 82.256 557.161 82.032 556.681 81.584C556.212 81.136 555.977 80.5387 555.977 79.792C555.977 79.28 556.105 78.832 556.361 78.448C556.617 78.0533 556.985 77.744 557.465 77.52C557.945 77.296 558.51 77.184 559.161 77.184C559.673 77.184 560.238 77.2533 560.857 77.392V76.592C560.857 76.1013 560.756 75.7653 560.553 75.584C560.35 75.4027 559.977 75.312 559.433 75.312C558.558 75.312 557.593 75.4773 556.537 75.808V74.256C556.932 74.0533 557.428 73.8933 558.025 73.776C558.622 73.648 559.23 73.584 559.849 73.584C560.948 73.584 561.748 73.808 562.249 74.256C562.761 74.6933 563.017 75.3867 563.017 76.336V82H561.177ZM559.241 80.688C559.508 80.688 559.78 80.6293 560.057 80.512C560.345 80.3947 560.612 80.2347 560.857 80.032V78.64C560.388 78.5653 559.966 78.528 559.593 78.528C558.665 78.528 558.201 78.9013 558.201 79.648C558.201 79.9787 558.292 80.2347 558.473 80.416C558.654 80.5973 558.91 80.688 559.241 80.688ZM565.143 85.296V73.824H567.063L567.255 74.592C567.575 74.2827 567.959 74.0373 568.407 73.856C568.866 73.6747 569.33 73.584 569.799 73.584C570.834 73.584 571.65 73.9627 572.247 74.72C572.855 75.4773 573.159 76.5013 573.159 77.792C573.159 78.6347 573.021 79.3867 572.743 80.048C572.466 80.7093 572.066 81.232 571.543 81.616C571.021 81.9893 570.418 82.176 569.735 82.176C569.298 82.176 568.882 82.1067 568.487 81.968C568.093 81.8293 567.757 81.6373 567.479 81.392V85.296H565.143ZM569.047 75.344C568.493 75.344 567.97 75.488 567.479 75.776V79.984C567.949 80.272 568.471 80.416 569.047 80.416C569.645 80.416 570.082 80.2133 570.359 79.808C570.647 79.4027 570.791 78.7627 570.791 77.888C570.791 77.0027 570.653 76.3573 570.375 75.952C570.098 75.5467 569.655 75.344 569.047 75.344ZM574.907 85.296V73.824H576.827L577.019 74.592C577.339 74.2827 577.723 74.0373 578.171 73.856C578.63 73.6747 579.094 73.584 579.563 73.584C580.598 73.584 581.414 73.9627 582.011 74.72C582.619 75.4773 582.923 76.5013 582.923 77.792C582.923 78.6347 582.785 79.3867 582.507 80.048C582.23 80.7093 581.83 81.232 581.307 81.616C580.785 81.9893 580.182 82.176 579.499 82.176C579.062 82.176 578.646 82.1067 578.251 81.968C577.857 81.8293 577.521 81.6373 577.243 81.392V85.296H574.907ZM578.811 75.344C578.257 75.344 577.734 75.488 577.243 75.776V79.984C577.713 80.272 578.235 80.416 578.811 80.416C579.409 80.416 579.846 80.2133 580.123 79.808C580.411 79.4027 580.555 78.7627 580.555 77.888C580.555 77.0027 580.417 76.3573 580.139 75.952C579.862 75.5467 579.419 75.344 578.811 75.344Z" fill="white"/> -<rect x="237" y="43" width="193" height="46" rx="5" fill="#0972D3"/> -<rect x="237" y="43" width="193" height="46" rx="5" stroke="#000716" stroke-width="2"/> -<path d="M263.27 71.648C262.982 71.8187 262.636 71.9467 262.23 72.032C261.825 72.128 261.404 72.176 260.966 72.176C259.665 72.176 258.668 71.8133 257.974 71.088C257.292 70.3627 256.95 69.3173 256.95 67.952C256.95 66.5973 257.313 65.5413 258.038 64.784C258.764 64.0267 259.772 63.648 261.062 63.648C261.841 63.648 262.561 63.8187 263.222 64.16V65.712C262.593 65.5307 262.017 65.44 261.494 65.44C260.748 65.44 260.198 65.632 259.846 66.016C259.494 66.3893 259.318 66.9867 259.318 67.808V68.032C259.318 68.8427 259.489 69.44 259.83 69.824C260.182 70.1973 260.721 70.384 261.446 70.384C261.969 70.384 262.577 70.288 263.27 70.096V71.648ZM270.212 72L270.02 71.28C269.359 71.8773 268.575 72.176 267.668 72.176C266.996 72.176 266.404 72.0107 265.892 71.68C265.38 71.3387 264.98 70.848 264.692 70.208C264.415 69.568 264.276 68.816 264.276 67.952C264.276 66.6293 264.591 65.5733 265.22 64.784C265.85 63.984 266.682 63.584 267.716 63.584C268.559 63.584 269.29 63.824 269.908 64.304V60.16H272.244V72H270.212ZM268.436 70.416C268.948 70.416 269.439 70.2667 269.908 69.968V65.744C269.45 65.4773 268.922 65.344 268.324 65.344C267.759 65.344 267.338 65.5573 267.06 65.984C266.783 66.4 266.644 67.0347 266.644 67.888C266.644 68.7413 266.788 69.376 267.076 69.792C267.375 70.208 267.828 70.416 268.436 70.416ZM274.409 72V60.16H276.729V67.312L279.561 63.824H282.345L278.969 67.728L282.601 72H279.753L276.729 68.272V72H274.409ZM291.221 69.744C291.221 69.5307 291.157 69.3653 291.029 69.248C290.912 69.1307 290.667 69.0027 290.293 68.864L289.045 68.368C288.395 68.112 287.925 67.7973 287.637 67.424C287.349 67.0507 287.205 66.576 287.205 66C287.205 65.2747 287.493 64.6933 288.069 64.256C288.656 63.808 289.435 63.584 290.405 63.584C291.301 63.584 292.128 63.76 292.885 64.112V65.664C292.075 65.4187 291.317 65.296 290.613 65.296C290.176 65.296 289.856 65.3493 289.653 65.456C289.451 65.5627 289.349 65.7333 289.349 65.968C289.349 66.1493 289.408 66.2987 289.525 66.416C289.653 66.5227 289.915 66.656 290.309 66.816L291.525 67.312C292.187 67.5787 292.656 67.888 292.933 68.24C293.221 68.592 293.365 69.0507 293.365 69.616C293.365 70.4053 293.061 71.0453 292.453 71.536C291.856 72.016 291.067 72.256 290.085 72.256C288.987 72.256 288.016 72.0373 287.173 71.6V70.048C288.229 70.3787 289.195 70.544 290.069 70.544C290.837 70.544 291.221 70.2773 291.221 69.744ZM296.97 72.128L293.738 63.824H296.218L298.042 69.936L299.77 63.824H302.186L298.73 73.104C298.421 73.9467 298.042 74.5547 297.594 74.928C297.146 75.3013 296.581 75.488 295.898 75.488C295.365 75.488 294.848 75.4027 294.346 75.232V73.648C294.688 73.68 294.992 73.696 295.258 73.696C295.706 73.696 296.053 73.5893 296.298 73.376C296.544 73.1733 296.752 72.816 296.922 72.304L296.97 72.128ZM308.54 72V66.64C308.54 66.2027 308.444 65.8827 308.252 65.68C308.06 65.4773 307.767 65.376 307.372 65.376C306.786 65.376 306.204 65.5573 305.628 65.92V72H303.292V63.824H305.212L305.436 64.704C306.396 63.9573 307.42 63.584 308.508 63.584C309.266 63.584 309.847 63.792 310.252 64.208C310.668 64.6133 310.876 65.1947 310.876 65.952V72H308.54ZM317.873 71.792C317.297 72.016 316.652 72.128 315.937 72.128C315.031 72.128 314.359 71.9147 313.921 71.488C313.495 71.0613 313.281 70.4 313.281 69.504V65.552H312.049V64.112L313.345 63.856L313.697 61.616H315.617V63.824H317.825V65.552H315.617V69.392C315.617 69.7333 315.703 69.9733 315.873 70.112C316.044 70.2507 316.332 70.32 316.737 70.32C317.068 70.32 317.447 70.288 317.873 70.224V71.792ZM324.474 72V66.64C324.474 66.2027 324.378 65.8827 324.186 65.68C323.994 65.4773 323.701 65.376 323.306 65.376C322.72 65.376 322.138 65.5573 321.562 65.92V72H319.226V60.16H321.562V64.56C322.48 63.9093 323.44 63.584 324.442 63.584C325.2 63.584 325.781 63.792 326.186 64.208C326.602 64.6133 326.81 65.1947 326.81 65.952V72H324.474ZM333.115 72V63.824H335.451V72H333.115ZM334.283 62.56C333.877 62.56 333.552 62.448 333.307 62.224C333.061 62 332.939 61.696 332.939 61.312C332.939 60.928 333.061 60.624 333.307 60.4C333.552 60.176 333.877 60.064 334.283 60.064C334.688 60.064 335.013 60.176 335.259 60.4C335.504 60.624 335.627 60.928 335.627 61.312C335.627 61.696 335.504 62 335.259 62.224C335.013 62.448 334.688 62.56 334.283 62.56ZM341.146 69.744C341.146 69.5307 341.082 69.3653 340.954 69.248C340.836 69.1307 340.591 69.0027 340.218 68.864L338.97 68.368C338.319 68.112 337.85 67.7973 337.562 67.424C337.274 67.0507 337.13 66.576 337.13 66C337.13 65.2747 337.418 64.6933 337.994 64.256C338.58 63.808 339.359 63.584 340.33 63.584C341.226 63.584 342.052 63.76 342.81 64.112V65.664C341.999 65.4187 341.242 65.296 340.538 65.296C340.1 65.296 339.78 65.3493 339.578 65.456C339.375 65.5627 339.274 65.7333 339.274 65.968C339.274 66.1493 339.332 66.2987 339.45 66.416C339.578 66.5227 339.839 66.656 340.234 66.816L341.45 67.312C342.111 67.5787 342.58 67.888 342.858 68.24C343.146 68.592 343.29 69.0507 343.29 69.616C343.29 70.4053 342.986 71.0453 342.378 71.536C341.78 72.016 340.991 72.256 340.01 72.256C338.911 72.256 337.94 72.0373 337.098 71.6V70.048C338.154 70.3787 339.119 70.544 339.994 70.544C340.762 70.544 341.146 70.2773 341.146 69.744ZM348.89 72V63.824H351.226V72H348.89ZM350.058 62.56C349.653 62.56 349.328 62.448 349.082 62.224C348.837 62 348.714 61.696 348.714 61.312C348.714 60.928 348.837 60.624 349.082 60.4C349.328 60.176 349.653 60.064 350.058 60.064C350.464 60.064 350.789 60.176 351.034 60.4C351.28 60.624 351.402 60.928 351.402 61.312C351.402 61.696 351.28 62 351.034 62.224C350.789 62.448 350.464 62.56 350.058 62.56ZM358.697 72V66.64C358.697 66.2027 358.601 65.8827 358.409 65.68C358.217 65.4773 357.924 65.376 357.529 65.376C356.943 65.376 356.361 65.5573 355.785 65.92V72H353.449V63.824H355.369L355.593 64.704C356.553 63.9573 357.577 63.584 358.665 63.584C359.423 63.584 360.004 63.792 360.409 64.208C360.825 64.6133 361.033 65.1947 361.033 65.952V72H358.697ZM363.23 72V63.824H365.566V72H363.23ZM364.398 62.56C363.993 62.56 363.668 62.448 363.422 62.224C363.177 62 363.054 61.696 363.054 61.312C363.054 60.928 363.177 60.624 363.422 60.4C363.668 60.176 363.993 60.064 364.398 60.064C364.804 60.064 365.129 60.176 365.374 60.4C365.62 60.624 365.742 60.928 365.742 61.312C365.742 61.696 365.62 62 365.374 62.224C365.129 62.448 364.804 62.56 364.398 62.56ZM372.653 71.792C372.077 72.016 371.432 72.128 370.717 72.128C369.811 72.128 369.139 71.9147 368.701 71.488C368.275 71.0613 368.061 70.4 368.061 69.504V65.552H366.829V64.112L368.125 63.856L368.477 61.616H370.397V63.824H372.605V65.552H370.397V69.392C370.397 69.7333 370.483 69.9733 370.653 70.112C370.824 70.2507 371.112 70.32 371.517 70.32C371.848 70.32 372.227 70.288 372.653 70.224V71.792ZM374.07 72V63.824H376.406V72H374.07ZM375.238 62.56C374.833 62.56 374.508 62.448 374.262 62.224C374.017 62 373.894 61.696 373.894 61.312C373.894 60.928 374.017 60.624 374.262 60.4C374.508 60.176 374.833 60.064 375.238 60.064C375.644 60.064 375.969 60.176 376.214 60.4C376.46 60.624 376.582 60.928 376.582 61.312C376.582 61.696 376.46 62 376.214 62.224C375.969 62.448 375.644 62.56 375.238 62.56ZM383.317 72L383.125 71.28C382.795 71.5787 382.411 71.8187 381.973 72C381.547 72.1707 381.131 72.256 380.725 72.256C379.936 72.256 379.301 72.032 378.821 71.584C378.352 71.136 378.117 70.5387 378.117 69.792C378.117 69.28 378.245 68.832 378.501 68.448C378.757 68.0533 379.125 67.744 379.605 67.52C380.085 67.296 380.651 67.184 381.301 67.184C381.813 67.184 382.379 67.2533 382.997 67.392V66.592C382.997 66.1013 382.896 65.7653 382.693 65.584C382.491 65.4027 382.117 65.312 381.573 65.312C380.699 65.312 379.733 65.4773 378.677 65.808V64.256C379.072 64.0533 379.568 63.8933 380.165 63.776C380.763 63.648 381.371 63.584 381.989 63.584C383.088 63.584 383.888 63.808 384.389 64.256C384.901 64.6933 385.157 65.3867 385.157 66.336V72H383.317ZM381.381 70.688C381.648 70.688 381.92 70.6293 382.197 70.512C382.485 70.3947 382.752 70.2347 382.997 70.032V68.64C382.528 68.5653 382.107 68.528 381.733 68.528C380.805 68.528 380.341 68.9013 380.341 69.648C380.341 69.9787 380.432 70.2347 380.613 70.416C380.795 70.5973 381.051 70.688 381.381 70.688ZM392.148 71.792C391.572 72.016 390.926 72.128 390.212 72.128C389.305 72.128 388.633 71.9147 388.196 71.488C387.769 71.0613 387.556 70.4 387.556 69.504V65.552H386.324V64.112L387.62 63.856L387.972 61.616H389.892V63.824H392.1V65.552H389.892V69.392C389.892 69.7333 389.977 69.9733 390.148 70.112C390.318 70.2507 390.606 70.32 391.012 70.32C391.342 70.32 391.721 70.288 392.148 70.224V71.792ZM395.245 68.48C395.287 69.184 395.501 69.696 395.885 70.016C396.269 70.3253 396.871 70.48 397.693 70.48C398.407 70.48 399.239 70.3467 400.189 70.08V71.632C399.815 71.824 399.367 71.9733 398.845 72.08C398.333 72.1867 397.799 72.24 397.245 72.24C395.89 72.24 394.855 71.872 394.141 71.136C393.437 70.4 393.085 69.3227 393.085 67.904C393.085 66.5387 393.437 65.4773 394.141 64.72C394.845 63.9627 395.821 63.584 397.069 63.584C398.125 63.584 398.935 63.8773 399.501 64.464C400.077 65.04 400.365 65.8667 400.365 66.944C400.365 67.1787 400.349 67.4453 400.317 67.744C400.285 68.0427 400.247 68.288 400.205 68.48H395.245ZM396.989 65.2C396.466 65.2 396.05 65.36 395.741 65.68C395.442 65.9893 395.271 66.4427 395.229 67.04H398.365V66.768C398.365 65.7227 397.906 65.2 396.989 65.2ZM407.597 72L407.405 71.28C406.744 71.8773 405.96 72.176 405.053 72.176C404.381 72.176 403.789 72.0107 403.277 71.68C402.765 71.3387 402.365 70.848 402.077 70.208C401.8 69.568 401.661 68.816 401.661 67.952C401.661 66.6293 401.976 65.5733 402.605 64.784C403.234 63.984 404.066 63.584 405.101 63.584C405.944 63.584 406.674 63.824 407.293 64.304V60.16H409.629V72H407.597ZM405.821 70.416C406.333 70.416 406.824 70.2667 407.293 69.968V65.744C406.834 65.4773 406.306 65.344 405.709 65.344C405.144 65.344 404.722 65.5573 404.445 65.984C404.168 66.4 404.029 67.0347 404.029 67.888C404.029 68.7413 404.173 69.376 404.461 69.792C404.76 70.208 405.213 70.416 405.821 70.416Z" fill="white"/> -<rect x="1011" y="451" width="193" height="86" rx="5" fill="#0972D3"/> -<rect x="1011" y="451" width="193" height="86" rx="5" stroke="#000716" stroke-width="2"/> -<path d="M1056.43 479.712C1055.56 480.043 1054.6 480.208 1053.53 480.208C1051.73 480.208 1050.36 479.728 1049.44 478.768C1048.51 477.797 1048.04 476.379 1048.04 474.512C1048.04 472.667 1048.53 471.237 1049.5 470.224C1050.47 469.211 1051.84 468.704 1053.6 468.704C1054.53 468.704 1055.42 468.853 1056.27 469.152V471.04C1055.3 470.827 1054.5 470.72 1053.88 470.72C1052.77 470.72 1051.94 471.013 1051.39 471.6C1050.84 472.187 1050.57 473.083 1050.57 474.288V474.656C1050.57 475.851 1050.84 476.741 1051.37 477.328C1051.9 477.904 1052.72 478.192 1053.82 478.192C1054.44 478.192 1055.31 478.069 1056.43 477.824V479.712ZM1061.57 479.84C1061.12 480.021 1060.64 480.112 1060.13 480.112C1058.69 480.112 1057.97 479.307 1057.97 477.696V468.16H1060.3V477.504C1060.3 477.803 1060.35 478.016 1060.45 478.144C1060.55 478.261 1060.72 478.32 1060.96 478.32C1061.11 478.32 1061.31 478.304 1061.57 478.272V479.84ZM1066.57 480.24C1065.3 480.24 1064.3 479.861 1063.59 479.104C1062.88 478.336 1062.52 477.269 1062.52 475.904C1062.52 474.549 1062.88 473.493 1063.59 472.736C1064.3 471.968 1065.3 471.584 1066.57 471.584C1067.84 471.584 1068.83 471.968 1069.54 472.736C1070.26 473.493 1070.61 474.549 1070.61 475.904C1070.61 477.269 1070.26 478.336 1069.54 479.104C1068.83 479.861 1067.84 480.24 1066.57 480.24ZM1066.57 478.448C1067.69 478.448 1068.25 477.6 1068.25 475.904C1068.25 474.219 1067.69 473.376 1066.57 473.376C1065.45 473.376 1064.89 474.219 1064.89 475.904C1064.89 477.6 1065.45 478.448 1066.57 478.448ZM1077.79 480L1077.57 479.136C1076.62 479.872 1075.63 480.24 1074.59 480.24C1073.87 480.24 1073.3 480.027 1072.9 479.6C1072.49 479.163 1072.29 478.565 1072.29 477.808V471.824H1074.63V477.152C1074.63 478.016 1075 478.448 1075.75 478.448C1076.3 478.448 1076.84 478.277 1077.38 477.936V471.824H1079.71V480H1077.79ZM1087.39 480L1087.2 479.28C1086.53 479.877 1085.75 480.176 1084.84 480.176C1084.17 480.176 1083.58 480.011 1083.07 479.68C1082.56 479.339 1082.16 478.848 1081.87 478.208C1081.59 477.568 1081.45 476.816 1081.45 475.952C1081.45 474.629 1081.77 473.573 1082.4 472.784C1083.03 471.984 1083.86 471.584 1084.89 471.584C1085.73 471.584 1086.47 471.824 1087.08 472.304V468.16H1089.42V480H1087.39ZM1085.61 478.416C1086.12 478.416 1086.61 478.267 1087.08 477.968V473.744C1086.63 473.477 1086.1 473.344 1085.5 473.344C1084.93 473.344 1084.51 473.557 1084.24 473.984C1083.96 474.4 1083.82 475.035 1083.82 475.888C1083.82 476.741 1083.96 477.376 1084.25 477.792C1084.55 478.208 1085 478.416 1085.61 478.416ZM1091.74 480V468.912H1098.72V470.768H1094.14V473.552H1097.79V475.408H1094.14V480H1091.74ZM1103.62 480.24C1102.35 480.24 1101.36 479.861 1100.65 479.104C1099.93 478.336 1099.57 477.269 1099.57 475.904C1099.57 474.549 1099.93 473.493 1100.65 472.736C1101.36 471.968 1102.35 471.584 1103.62 471.584C1104.89 471.584 1105.88 471.968 1106.6 472.736C1107.31 473.493 1107.67 474.549 1107.67 475.904C1107.67 477.269 1107.31 478.336 1106.6 479.104C1105.88 479.861 1104.89 480.24 1103.62 480.24ZM1103.62 478.448C1104.74 478.448 1105.3 477.6 1105.3 475.904C1105.3 474.219 1104.74 473.376 1103.62 473.376C1102.5 473.376 1101.94 474.219 1101.94 475.904C1101.94 477.6 1102.5 478.448 1103.62 478.448ZM1109.41 480V471.824H1111.33L1111.62 473.04C1112.04 472.571 1112.44 472.24 1112.82 472.048C1113.2 471.845 1113.61 471.744 1114.03 471.744C1114.24 471.744 1114.45 471.76 1114.67 471.792V473.952C1114.37 473.888 1114.04 473.856 1113.68 473.856C1112.99 473.856 1112.34 473.979 1111.75 474.224V480H1109.41ZM1125.94 480V474.464C1125.94 473.739 1125.62 473.376 1124.97 473.376C1124.39 473.376 1123.81 473.515 1123.22 473.792V473.952V480H1120.89V474.464C1120.89 473.739 1120.56 473.376 1119.91 473.376C1119.31 473.376 1118.73 473.52 1118.15 473.808V480H1115.81V471.824H1117.73L1117.94 472.608C1118.51 472.235 1119.01 471.973 1119.46 471.824C1119.92 471.664 1120.39 471.584 1120.87 471.584C1121.83 471.584 1122.51 471.925 1122.9 472.608C1123.45 472.245 1123.96 471.984 1124.44 471.824C1124.92 471.664 1125.41 471.584 1125.93 471.584C1126.67 471.584 1127.25 471.792 1127.65 472.208C1128.07 472.624 1128.28 473.205 1128.28 473.952V480H1125.94ZM1135.09 480L1134.9 479.28C1134.57 479.579 1134.19 479.819 1133.75 480C1133.32 480.171 1132.91 480.256 1132.5 480.256C1131.71 480.256 1131.08 480.032 1130.6 479.584C1130.13 479.136 1129.89 478.539 1129.89 477.792C1129.89 477.28 1130.02 476.832 1130.28 476.448C1130.53 476.053 1130.9 475.744 1131.38 475.52C1131.86 475.296 1132.43 475.184 1133.08 475.184C1133.59 475.184 1134.15 475.253 1134.77 475.392V474.592C1134.77 474.101 1134.67 473.765 1134.47 473.584C1134.27 473.403 1133.89 473.312 1133.35 473.312C1132.47 473.312 1131.51 473.477 1130.45 473.808V472.256C1130.85 472.053 1131.34 471.893 1131.94 471.776C1132.54 471.648 1133.15 471.584 1133.77 471.584C1134.86 471.584 1135.66 471.808 1136.17 472.256C1136.68 472.693 1136.93 473.387 1136.93 474.336V480H1135.09ZM1133.16 478.688C1133.42 478.688 1133.7 478.629 1133.97 478.512C1134.26 478.395 1134.53 478.235 1134.77 478.032V476.64C1134.3 476.565 1133.88 476.528 1133.51 476.528C1132.58 476.528 1132.12 476.901 1132.12 477.648C1132.12 477.979 1132.21 478.235 1132.39 478.416C1132.57 478.597 1132.83 478.688 1133.16 478.688ZM1143.92 479.792C1143.35 480.016 1142.7 480.128 1141.99 480.128C1141.08 480.128 1140.41 479.915 1139.97 479.488C1139.55 479.061 1139.33 478.4 1139.33 477.504V473.552H1138.1V472.112L1139.4 471.856L1139.75 469.616H1141.67V471.824H1143.88V473.552H1141.67V477.392C1141.67 477.733 1141.75 477.973 1141.92 478.112C1142.09 478.251 1142.38 478.32 1142.79 478.32C1143.12 478.32 1143.5 478.288 1143.92 478.224V479.792ZM1145.34 480V471.824H1147.68V480H1145.34ZM1146.51 470.56C1146.1 470.56 1145.78 470.448 1145.53 470.224C1145.29 470 1145.16 469.696 1145.16 469.312C1145.16 468.928 1145.29 468.624 1145.53 468.4C1145.78 468.176 1146.1 468.064 1146.51 468.064C1146.91 468.064 1147.24 468.176 1147.48 468.4C1147.73 468.624 1147.85 468.928 1147.85 469.312C1147.85 469.696 1147.73 470 1147.48 470.224C1147.24 470.448 1146.91 470.56 1146.51 470.56ZM1153.53 480.24C1152.26 480.24 1151.27 479.861 1150.56 479.104C1149.84 478.336 1149.48 477.269 1149.48 475.904C1149.48 474.549 1149.84 473.493 1150.56 472.736C1151.27 471.968 1152.26 471.584 1153.53 471.584C1154.8 471.584 1155.79 471.968 1156.51 472.736C1157.22 473.493 1157.58 474.549 1157.58 475.904C1157.58 477.269 1157.22 478.336 1156.51 479.104C1155.79 479.861 1154.8 480.24 1153.53 480.24ZM1153.53 478.448C1154.65 478.448 1155.21 477.6 1155.21 475.904C1155.21 474.219 1154.65 473.376 1153.53 473.376C1152.41 473.376 1151.85 474.219 1151.85 475.904C1151.85 477.6 1152.41 478.448 1153.53 478.448ZM1164.57 480V474.64C1164.57 474.203 1164.47 473.883 1164.28 473.68C1164.09 473.477 1163.79 473.376 1163.4 473.376C1162.81 473.376 1162.23 473.557 1161.66 473.92V480H1159.32V471.824H1161.24L1161.46 472.704C1162.42 471.957 1163.45 471.584 1164.54 471.584C1165.29 471.584 1165.87 471.792 1166.28 472.208C1166.7 472.613 1166.9 473.195 1166.9 473.952V480H1164.57ZM1030.29 499.792C1029.71 500.016 1029.06 500.128 1028.35 500.128C1027.44 500.128 1026.77 499.915 1026.33 499.488C1025.91 499.061 1025.69 498.4 1025.69 497.504V493.552H1024.46V492.112L1025.76 491.856L1026.11 489.616H1028.03V491.824H1030.24V493.552H1028.03V497.392C1028.03 497.733 1028.12 497.973 1028.29 498.112C1028.46 498.251 1028.74 498.32 1029.15 498.32C1029.48 498.32 1029.86 498.288 1030.29 498.224V499.792ZM1033.38 496.48C1033.43 497.184 1033.64 497.696 1034.02 498.016C1034.41 498.325 1035.01 498.48 1035.83 498.48C1036.55 498.48 1037.38 498.347 1038.33 498.08V499.632C1037.95 499.824 1037.51 499.973 1036.98 500.08C1036.47 500.187 1035.94 500.24 1035.38 500.24C1034.03 500.24 1032.99 499.872 1032.28 499.136C1031.57 498.4 1031.22 497.323 1031.22 495.904C1031.22 494.539 1031.57 493.477 1032.28 492.72C1032.98 491.963 1033.96 491.584 1035.21 491.584C1036.26 491.584 1037.07 491.877 1037.64 492.464C1038.21 493.04 1038.5 493.867 1038.5 494.944C1038.5 495.179 1038.49 495.445 1038.45 495.744C1038.42 496.043 1038.39 496.288 1038.34 496.48H1033.38ZM1035.13 493.2C1034.6 493.2 1034.19 493.36 1033.88 493.68C1033.58 493.989 1033.41 494.443 1033.37 495.04H1036.5V494.768C1036.5 493.723 1036.04 493.2 1035.13 493.2ZM1050.34 500V494.464C1050.34 493.739 1050.02 493.376 1049.37 493.376C1048.79 493.376 1048.21 493.515 1047.62 493.792V493.952V500H1045.29V494.464C1045.29 493.739 1044.96 493.376 1044.31 493.376C1043.71 493.376 1043.13 493.52 1042.55 493.808V500H1040.21V491.824H1042.13L1042.34 492.608C1042.91 492.235 1043.41 491.973 1043.86 491.824C1044.32 491.664 1044.79 491.584 1045.27 491.584C1046.23 491.584 1046.91 491.925 1047.3 492.608C1047.85 492.245 1048.36 491.984 1048.84 491.824C1049.32 491.664 1049.81 491.584 1050.33 491.584C1051.07 491.584 1051.65 491.792 1052.05 492.208C1052.47 492.624 1052.68 493.205 1052.68 493.952V500H1050.34ZM1054.81 503.296V491.824H1056.73L1056.92 492.592C1057.24 492.283 1057.62 492.037 1058.07 491.856C1058.53 491.675 1058.99 491.584 1059.46 491.584C1060.5 491.584 1061.31 491.963 1061.91 492.72C1062.52 493.477 1062.82 494.501 1062.82 495.792C1062.82 496.635 1062.68 497.387 1062.41 498.048C1062.13 498.709 1061.73 499.232 1061.21 499.616C1060.68 499.989 1060.08 500.176 1059.4 500.176C1058.96 500.176 1058.55 500.107 1058.15 499.968C1057.76 499.829 1057.42 499.637 1057.14 499.392V503.296H1054.81ZM1058.71 493.344C1058.16 493.344 1057.63 493.488 1057.14 493.776V497.984C1057.61 498.272 1058.13 498.416 1058.71 498.416C1059.31 498.416 1059.75 498.213 1060.02 497.808C1060.31 497.403 1060.45 496.763 1060.45 495.888C1060.45 495.003 1060.32 494.357 1060.04 493.952C1059.76 493.547 1059.32 493.344 1058.71 493.344ZM1068.17 499.84C1067.72 500.021 1067.24 500.112 1066.73 500.112C1065.29 500.112 1064.57 499.307 1064.57 497.696V488.16H1066.91V497.504C1066.91 497.803 1066.95 498.016 1067.05 498.144C1067.16 498.261 1067.33 498.32 1067.56 498.32C1067.71 498.32 1067.91 498.304 1068.17 498.272V499.84ZM1074.38 500L1074.19 499.28C1073.86 499.579 1073.48 499.819 1073.04 500C1072.61 500.171 1072.2 500.256 1071.79 500.256C1071 500.256 1070.37 500.032 1069.89 499.584C1069.42 499.136 1069.18 498.539 1069.18 497.792C1069.18 497.28 1069.31 496.832 1069.57 496.448C1069.82 496.053 1070.19 495.744 1070.67 495.52C1071.15 495.296 1071.72 495.184 1072.37 495.184C1072.88 495.184 1073.44 495.253 1074.06 495.392V494.592C1074.06 494.101 1073.96 493.765 1073.76 493.584C1073.56 493.403 1073.18 493.312 1072.64 493.312C1071.76 493.312 1070.8 493.477 1069.74 493.808V492.256C1070.14 492.053 1070.63 491.893 1071.23 491.776C1071.83 491.648 1072.44 491.584 1073.05 491.584C1074.15 491.584 1074.95 491.808 1075.45 492.256C1075.97 492.693 1076.22 493.387 1076.22 494.336V500H1074.38ZM1072.45 498.688C1072.71 498.688 1072.98 498.629 1073.26 498.512C1073.55 498.395 1073.82 498.235 1074.06 498.032V496.64C1073.59 496.565 1073.17 496.528 1072.8 496.528C1071.87 496.528 1071.41 496.901 1071.41 497.648C1071.41 497.979 1071.5 498.235 1071.68 498.416C1071.86 498.597 1072.12 498.688 1072.45 498.688ZM1083.21 499.792C1082.64 500.016 1081.99 500.128 1081.28 500.128C1080.37 500.128 1079.7 499.915 1079.26 499.488C1078.83 499.061 1078.62 498.4 1078.62 497.504V493.552H1077.39V492.112L1078.68 491.856L1079.04 489.616H1080.96V491.824H1083.16V493.552H1080.96V497.392C1080.96 497.733 1081.04 497.973 1081.21 498.112C1081.38 498.251 1081.67 498.32 1082.08 498.32C1082.41 498.32 1082.79 498.288 1083.21 498.224V499.792ZM1086.31 496.48C1086.35 497.184 1086.56 497.696 1086.95 498.016C1087.33 498.325 1087.94 498.48 1088.76 498.48C1089.47 498.48 1090.3 498.347 1091.25 498.08V499.632C1090.88 499.824 1090.43 499.973 1089.91 500.08C1089.4 500.187 1088.86 500.24 1088.31 500.24C1086.95 500.24 1085.92 499.872 1085.2 499.136C1084.5 498.4 1084.15 497.323 1084.15 495.904C1084.15 494.539 1084.5 493.477 1085.2 492.72C1085.91 491.963 1086.88 491.584 1088.13 491.584C1089.19 491.584 1090 491.877 1090.56 492.464C1091.14 493.04 1091.43 493.867 1091.43 494.944C1091.43 495.179 1091.41 495.445 1091.38 495.744C1091.35 496.043 1091.31 496.288 1091.27 496.48H1086.31ZM1088.05 493.2C1087.53 493.2 1087.11 493.36 1086.8 493.68C1086.51 493.989 1086.34 494.443 1086.29 495.04H1089.43V494.768C1089.43 493.723 1088.97 493.2 1088.05 493.2ZM1101.94 500L1101.74 499.28C1101.41 499.579 1101.03 499.819 1100.59 500C1100.17 500.171 1099.75 500.256 1099.34 500.256C1098.56 500.256 1097.92 500.032 1097.44 499.584C1096.97 499.136 1096.74 498.539 1096.74 497.792C1096.74 497.28 1096.86 496.832 1097.12 496.448C1097.38 496.053 1097.74 495.744 1098.22 495.52C1098.7 495.296 1099.27 495.184 1099.92 495.184C1100.43 495.184 1101 495.253 1101.62 495.392V494.592C1101.62 494.101 1101.52 493.765 1101.31 493.584C1101.11 493.403 1100.74 493.312 1100.19 493.312C1099.32 493.312 1098.35 493.477 1097.3 493.808V492.256C1097.69 492.053 1098.19 491.893 1098.78 491.776C1099.38 491.648 1099.99 491.584 1100.61 491.584C1101.71 491.584 1102.51 491.808 1103.01 492.256C1103.52 492.693 1103.78 493.387 1103.78 494.336V500H1101.94ZM1100 498.688C1100.27 498.688 1100.54 498.629 1100.82 498.512C1101.1 498.395 1101.37 498.235 1101.62 498.032V496.64C1101.15 496.565 1100.73 496.528 1100.35 496.528C1099.42 496.528 1098.96 496.901 1098.96 497.648C1098.96 497.979 1099.05 498.235 1099.23 498.416C1099.41 498.597 1099.67 498.688 1100 498.688ZM1111.15 500V494.64C1111.15 494.203 1111.06 493.883 1110.86 493.68C1110.67 493.477 1110.38 493.376 1109.98 493.376C1109.4 493.376 1108.82 493.557 1108.24 493.92V500H1105.9V491.824H1107.82L1108.05 492.704C1109.01 491.957 1110.03 491.584 1111.12 491.584C1111.88 491.584 1112.46 491.792 1112.86 492.208C1113.28 492.613 1113.49 493.195 1113.49 493.952V500H1111.15ZM1121.14 500L1120.95 499.28C1120.29 499.877 1119.5 500.176 1118.6 500.176C1117.92 500.176 1117.33 500.011 1116.82 499.68C1116.31 499.339 1115.91 498.848 1115.62 498.208C1115.34 497.568 1115.2 496.816 1115.2 495.952C1115.2 494.629 1115.52 493.573 1116.15 492.784C1116.78 491.984 1117.61 491.584 1118.64 491.584C1119.49 491.584 1120.22 491.824 1120.84 492.304V488.16H1123.17V500H1121.14ZM1119.36 498.416C1119.88 498.416 1120.37 498.267 1120.84 497.968V493.744C1120.38 493.477 1119.85 493.344 1119.25 493.344C1118.69 493.344 1118.27 493.557 1117.99 493.984C1117.71 494.4 1117.57 495.035 1117.57 495.888C1117.57 496.741 1117.72 497.376 1118 497.792C1118.3 498.208 1118.76 498.416 1119.36 498.416ZM1134.13 500L1133.94 499.28C1133.61 499.579 1133.23 499.819 1132.79 500C1132.36 500.171 1131.95 500.256 1131.54 500.256C1130.75 500.256 1130.12 500.032 1129.64 499.584C1129.17 499.136 1128.93 498.539 1128.93 497.792C1128.93 497.28 1129.06 496.832 1129.32 496.448C1129.57 496.053 1129.94 495.744 1130.42 495.52C1130.9 495.296 1131.47 495.184 1132.12 495.184C1132.63 495.184 1133.19 495.253 1133.81 495.392V494.592C1133.81 494.101 1133.71 493.765 1133.51 493.584C1133.31 493.403 1132.93 493.312 1132.39 493.312C1131.51 493.312 1130.55 493.477 1129.49 493.808V492.256C1129.89 492.053 1130.38 491.893 1130.98 491.776C1131.58 491.648 1132.19 491.584 1132.8 491.584C1133.9 491.584 1134.7 491.808 1135.2 492.256C1135.72 492.693 1135.97 493.387 1135.97 494.336V500H1134.13ZM1132.2 498.688C1132.46 498.688 1132.74 498.629 1133.01 498.512C1133.3 498.395 1133.57 498.235 1133.81 498.032V496.64C1133.34 496.565 1132.92 496.528 1132.55 496.528C1131.62 496.528 1131.16 496.901 1131.16 497.648C1131.16 497.979 1131.25 498.235 1131.43 498.416C1131.61 498.597 1131.87 498.688 1132.2 498.688ZM1138.1 500V491.824H1140.02L1140.31 493.04C1140.73 492.571 1141.13 492.24 1141.51 492.048C1141.89 491.845 1142.3 491.744 1142.72 491.744C1142.93 491.744 1143.14 491.76 1143.36 491.792V493.952C1143.06 493.888 1142.73 493.856 1142.37 493.856C1141.68 493.856 1141.03 493.979 1140.43 494.224V500H1138.1ZM1150.01 499.792C1149.43 500.016 1148.79 500.128 1148.07 500.128C1147.17 500.128 1146.49 499.915 1146.06 499.488C1145.63 499.061 1145.42 498.4 1145.42 497.504V493.552H1144.18V492.112L1145.48 491.856L1145.83 489.616H1147.75V491.824H1149.96V493.552H1147.75V497.392C1147.75 497.733 1147.84 497.973 1148.01 498.112C1148.18 498.251 1148.47 498.32 1148.87 498.32C1149.2 498.32 1149.58 498.288 1150.01 498.224V499.792ZM1151.42 500V491.824H1153.76V500H1151.42ZM1152.59 490.56C1152.19 490.56 1151.86 490.448 1151.62 490.224C1151.37 490 1151.25 489.696 1151.25 489.312C1151.25 488.928 1151.37 488.624 1151.62 488.4C1151.86 488.176 1152.19 488.064 1152.59 488.064C1153 488.064 1153.32 488.176 1153.57 488.4C1153.81 488.624 1153.94 488.928 1153.94 489.312C1153.94 489.696 1153.81 490 1153.57 490.224C1153.32 490.448 1153 490.56 1152.59 490.56ZM1156.38 500V493.552H1155.09V492.112L1156.38 491.872V491.136C1156.38 490.059 1156.63 489.259 1157.12 488.736C1157.62 488.203 1158.38 487.936 1159.39 487.936C1159.68 487.936 1159.98 487.968 1160.29 488.032C1160.6 488.085 1160.87 488.16 1161.1 488.256V489.84C1160.68 489.776 1160.31 489.744 1160.02 489.744C1159.53 489.744 1159.18 489.824 1158.99 489.984C1158.81 490.144 1158.72 490.427 1158.72 490.832V491.824H1161.01V493.552H1158.72V500H1156.38ZM1166.79 500L1166.6 499.28C1166.27 499.579 1165.89 499.819 1165.45 500C1165.02 500.171 1164.61 500.256 1164.2 500.256C1163.41 500.256 1162.78 500.032 1162.3 499.584C1161.83 499.136 1161.59 498.539 1161.59 497.792C1161.59 497.28 1161.72 496.832 1161.98 496.448C1162.23 496.053 1162.6 495.744 1163.08 495.52C1163.56 495.296 1164.13 495.184 1164.78 495.184C1165.29 495.184 1165.86 495.253 1166.47 495.392V494.592C1166.47 494.101 1166.37 493.765 1166.17 493.584C1165.97 493.403 1165.59 493.312 1165.05 493.312C1164.18 493.312 1163.21 493.477 1162.15 493.808V492.256C1162.55 492.053 1163.05 491.893 1163.64 491.776C1164.24 491.648 1164.85 491.584 1165.47 491.584C1166.57 491.584 1167.37 491.808 1167.87 492.256C1168.38 492.693 1168.63 493.387 1168.63 494.336V500H1166.79ZM1164.86 498.688C1165.13 498.688 1165.4 498.629 1165.67 498.512C1165.96 498.395 1166.23 498.235 1166.47 498.032V496.64C1166.01 496.565 1165.58 496.528 1165.21 496.528C1164.28 496.528 1163.82 496.901 1163.82 497.648C1163.82 497.979 1163.91 498.235 1164.09 498.416C1164.27 498.597 1164.53 498.688 1164.86 498.688ZM1176.67 499.648C1176.38 499.819 1176.03 499.947 1175.63 500.032C1175.22 500.128 1174.8 500.176 1174.36 500.176C1173.06 500.176 1172.06 499.813 1171.37 499.088C1170.69 498.363 1170.35 497.317 1170.35 495.952C1170.35 494.597 1170.71 493.541 1171.43 492.784C1172.16 492.027 1173.17 491.648 1174.46 491.648C1175.24 491.648 1175.96 491.819 1176.62 492.16V493.712C1175.99 493.531 1175.41 493.44 1174.89 493.44C1174.14 493.44 1173.59 493.632 1173.24 494.016C1172.89 494.389 1172.71 494.987 1172.71 495.808V496.032C1172.71 496.843 1172.88 497.44 1173.23 497.824C1173.58 498.197 1174.12 498.384 1174.84 498.384C1175.36 498.384 1175.97 498.288 1176.67 498.096V499.648ZM1183.42 499.792C1182.84 500.016 1182.2 500.128 1181.48 500.128C1180.58 500.128 1179.91 499.915 1179.47 499.488C1179.04 499.061 1178.83 498.4 1178.83 497.504V493.552H1177.6V492.112L1178.89 491.856L1179.24 489.616H1181.16V491.824H1183.37V493.552H1181.16V497.392C1181.16 497.733 1181.25 497.973 1181.42 498.112C1181.59 498.251 1181.88 498.32 1182.28 498.32C1182.61 498.32 1182.99 498.288 1183.42 498.224V499.792ZM1188.25 497.744C1188.25 497.531 1188.18 497.365 1188.05 497.248C1187.94 497.131 1187.69 497.003 1187.32 496.864L1186.07 496.368C1185.42 496.112 1184.95 495.797 1184.66 495.424C1184.37 495.051 1184.23 494.576 1184.23 494C1184.23 493.275 1184.52 492.693 1185.09 492.256C1185.68 491.808 1186.46 491.584 1187.43 491.584C1188.33 491.584 1189.15 491.76 1189.91 492.112V493.664C1189.1 493.419 1188.34 493.296 1187.64 493.296C1187.2 493.296 1186.88 493.349 1186.68 493.456C1186.47 493.563 1186.37 493.733 1186.37 493.968C1186.37 494.149 1186.43 494.299 1186.55 494.416C1186.68 494.523 1186.94 494.656 1187.33 494.816L1188.55 495.312C1189.21 495.579 1189.68 495.888 1189.96 496.24C1190.25 496.592 1190.39 497.051 1190.39 497.616C1190.39 498.405 1190.09 499.045 1189.48 499.536C1188.88 500.016 1188.09 500.256 1187.11 500.256C1186.01 500.256 1185.04 500.037 1184.2 499.6V498.048C1185.25 498.379 1186.22 498.544 1187.09 498.544C1187.86 498.544 1188.25 498.277 1188.25 497.744ZM1064.18 520L1063.99 519.28C1063.66 519.579 1063.27 519.819 1062.83 520C1062.41 520.171 1061.99 520.256 1061.59 520.256C1060.8 520.256 1060.16 520.032 1059.68 519.584C1059.21 519.136 1058.98 518.539 1058.98 517.792C1058.98 517.28 1059.11 516.832 1059.36 516.448C1059.62 516.053 1059.99 515.744 1060.47 515.52C1060.95 515.296 1061.51 515.184 1062.16 515.184C1062.67 515.184 1063.24 515.253 1063.86 515.392V514.592C1063.86 514.101 1063.76 513.765 1063.55 513.584C1063.35 513.403 1062.98 513.312 1062.43 513.312C1061.56 513.312 1060.59 513.477 1059.54 513.808V512.256C1059.93 512.053 1060.43 511.893 1061.03 511.776C1061.62 511.648 1062.23 511.584 1062.85 511.584C1063.95 511.584 1064.75 511.808 1065.25 512.256C1065.76 512.693 1066.02 513.387 1066.02 514.336V520H1064.18ZM1062.24 518.688C1062.51 518.688 1062.78 518.629 1063.06 518.512C1063.35 518.395 1063.61 518.235 1063.86 518.032V516.64C1063.39 516.565 1062.97 516.528 1062.59 516.528C1061.67 516.528 1061.2 516.901 1061.2 517.648C1061.2 517.979 1061.29 518.235 1061.47 518.416C1061.66 518.597 1061.91 518.688 1062.24 518.688ZM1068.14 520V511.824H1070.06L1070.35 513.04C1070.78 512.571 1071.18 512.24 1071.55 512.048C1071.94 511.845 1072.34 511.744 1072.77 511.744C1072.97 511.744 1073.18 511.76 1073.41 511.792V513.952C1073.11 513.888 1072.78 513.856 1072.42 513.856C1071.72 513.856 1071.08 513.979 1070.48 514.224V520H1068.14ZM1076.29 516.48C1076.34 517.184 1076.55 517.696 1076.93 518.016C1077.32 518.325 1077.92 518.48 1078.74 518.48C1079.46 518.48 1080.29 518.347 1081.24 518.08V519.632C1080.86 519.824 1080.42 519.973 1079.89 520.08C1079.38 520.187 1078.85 520.24 1078.29 520.24C1076.94 520.24 1075.9 519.872 1075.19 519.136C1074.48 518.4 1074.13 517.323 1074.13 515.904C1074.13 514.539 1074.48 513.477 1075.19 512.72C1075.89 511.963 1076.87 511.584 1078.12 511.584C1079.17 511.584 1079.98 511.877 1080.55 512.464C1081.12 513.04 1081.41 513.867 1081.41 514.944C1081.41 515.179 1081.4 515.445 1081.36 515.744C1081.33 516.043 1081.3 516.288 1081.25 516.48H1076.29ZM1078.04 513.2C1077.51 513.2 1077.1 513.36 1076.79 513.68C1076.49 513.989 1076.32 514.443 1076.28 515.04H1079.41V514.768C1079.41 513.723 1078.95 513.2 1078.04 513.2ZM1087.23 523.296V511.824H1089.15L1089.34 512.592C1089.66 512.283 1090.05 512.037 1090.5 511.856C1090.95 511.675 1091.42 511.584 1091.89 511.584C1092.92 511.584 1093.74 511.963 1094.34 512.72C1094.94 513.477 1095.25 514.501 1095.25 515.792C1095.25 516.635 1095.11 517.387 1094.83 518.048C1094.55 518.709 1094.15 519.232 1093.63 519.616C1093.11 519.989 1092.51 520.176 1091.82 520.176C1091.39 520.176 1090.97 520.107 1090.58 519.968C1090.18 519.829 1089.85 519.637 1089.57 519.392V523.296H1087.23ZM1091.14 513.344C1090.58 513.344 1090.06 513.488 1089.57 513.776V517.984C1090.04 518.272 1090.56 518.416 1091.14 518.416C1091.73 518.416 1092.17 518.213 1092.45 517.808C1092.74 517.403 1092.88 516.763 1092.88 515.888C1092.88 515.003 1092.74 514.357 1092.46 513.952C1092.19 513.547 1091.74 513.344 1091.14 513.344ZM1097 520V511.824H1098.92L1099.2 513.04C1099.63 512.571 1100.03 512.24 1100.4 512.048C1100.79 511.845 1101.19 511.744 1101.62 511.744C1101.82 511.744 1102.04 511.76 1102.26 511.792V513.952C1101.96 513.888 1101.63 513.856 1101.27 513.856C1100.57 513.856 1099.93 513.979 1099.33 514.224V520H1097ZM1107.03 520.24C1105.76 520.24 1104.77 519.861 1104.06 519.104C1103.34 518.336 1102.98 517.269 1102.98 515.904C1102.98 514.549 1103.34 513.493 1104.06 512.736C1104.77 511.968 1105.76 511.584 1107.03 511.584C1108.3 511.584 1109.29 511.968 1110.01 512.736C1110.72 513.493 1111.08 514.549 1111.08 515.904C1111.08 517.269 1110.72 518.336 1110.01 519.104C1109.29 519.861 1108.3 520.24 1107.03 520.24ZM1107.03 518.448C1108.15 518.448 1108.71 517.6 1108.71 515.904C1108.71 514.219 1108.15 513.376 1107.03 513.376C1105.91 513.376 1105.35 514.219 1105.35 515.904C1105.35 517.6 1105.91 518.448 1107.03 518.448ZM1118.34 520L1118.15 519.28C1117.49 519.877 1116.7 520.176 1115.8 520.176C1115.12 520.176 1114.53 520.011 1114.02 519.68C1113.51 519.339 1113.11 518.848 1112.82 518.208C1112.54 517.568 1112.4 516.816 1112.4 515.952C1112.4 514.629 1112.72 513.573 1113.35 512.784C1113.98 511.984 1114.81 511.584 1115.84 511.584C1116.69 511.584 1117.42 511.824 1118.04 512.304V508.16H1120.37V520H1118.34ZM1116.56 518.416C1117.08 518.416 1117.57 518.267 1118.04 517.968V513.744C1117.58 513.477 1117.05 513.344 1116.45 513.344C1115.89 513.344 1115.47 513.557 1115.19 513.984C1114.91 514.4 1114.77 515.035 1114.77 515.888C1114.77 516.741 1114.92 517.376 1115.2 517.792C1115.5 518.208 1115.96 518.416 1116.56 518.416ZM1127.98 520L1127.75 519.136C1126.8 519.872 1125.81 520.24 1124.78 520.24C1124.05 520.24 1123.49 520.027 1123.08 519.6C1122.68 519.163 1122.47 518.565 1122.47 517.808V511.824H1124.81V517.152C1124.81 518.016 1125.18 518.448 1125.93 518.448C1126.48 518.448 1127.03 518.277 1127.56 517.936V511.824H1129.9V520H1127.98ZM1137.95 519.648C1137.67 519.819 1137.32 519.947 1136.91 520.032C1136.51 520.128 1136.09 520.176 1135.65 520.176C1134.35 520.176 1133.35 519.813 1132.66 519.088C1131.98 518.363 1131.63 517.317 1131.63 515.952C1131.63 514.597 1132 513.541 1132.72 512.784C1133.45 512.027 1134.46 511.648 1135.75 511.648C1136.53 511.648 1137.25 511.819 1137.91 512.16V513.712C1137.28 513.531 1136.7 513.44 1136.18 513.44C1135.43 513.44 1134.88 513.632 1134.53 514.016C1134.18 514.389 1134 514.987 1134 515.808V516.032C1134 516.843 1134.17 517.44 1134.51 517.824C1134.87 518.197 1135.41 518.384 1136.13 518.384C1136.65 518.384 1137.26 518.288 1137.95 518.096V519.648ZM1141.12 516.48C1141.16 517.184 1141.38 517.696 1141.76 518.016C1142.15 518.325 1142.75 518.48 1143.57 518.48C1144.28 518.48 1145.12 518.347 1146.07 518.08V519.632C1145.69 519.824 1145.24 519.973 1144.72 520.08C1144.21 520.187 1143.68 520.24 1143.12 520.24C1141.77 520.24 1140.73 519.872 1140.02 519.136C1139.31 518.4 1138.96 517.323 1138.96 515.904C1138.96 514.539 1139.31 513.477 1140.02 512.72C1140.72 511.963 1141.7 511.584 1142.95 511.584C1144 511.584 1144.81 511.877 1145.38 512.464C1145.95 513.04 1146.24 513.867 1146.24 514.944C1146.24 515.179 1146.23 515.445 1146.19 515.744C1146.16 516.043 1146.12 516.288 1146.08 516.48H1141.12ZM1142.87 513.2C1142.34 513.2 1141.93 513.36 1141.62 513.68C1141.32 513.989 1141.15 514.443 1141.11 515.04H1144.24V514.768C1144.24 513.723 1143.78 513.2 1142.87 513.2ZM1153.47 520L1153.28 519.28C1152.62 519.877 1151.84 520.176 1150.93 520.176C1150.26 520.176 1149.67 520.011 1149.15 519.68C1148.64 519.339 1148.24 518.848 1147.95 518.208C1147.68 517.568 1147.54 516.816 1147.54 515.952C1147.54 514.629 1147.85 513.573 1148.48 512.784C1149.11 511.984 1149.94 511.584 1150.98 511.584C1151.82 511.584 1152.55 511.824 1153.17 512.304V508.16H1155.51V520H1153.47ZM1151.7 518.416C1152.21 518.416 1152.7 518.267 1153.17 517.968V513.744C1152.71 513.477 1152.18 513.344 1151.59 513.344C1151.02 513.344 1150.6 513.557 1150.32 513.984C1150.04 514.4 1149.91 515.035 1149.91 515.888C1149.91 516.741 1150.05 517.376 1150.34 517.792C1150.64 518.208 1151.09 518.416 1151.7 518.416Z" fill="white"/> -<rect x="1247" y="461" width="193" height="66" rx="5" fill="#0972D3"/> -<rect x="1247" y="461" width="193" height="66" rx="5" stroke="#000716" stroke-width="2"/> -<path d="M1291.16 490V478.912H1295.14C1296.8 478.912 1298.07 479.392 1298.95 480.352C1299.85 481.301 1300.3 482.667 1300.3 484.448C1300.3 486.219 1299.85 487.589 1298.95 488.56C1298.07 489.52 1296.81 490 1295.19 490H1291.16ZM1293.56 480.768V488.144H1294.94C1296.87 488.144 1297.83 486.965 1297.83 484.608V484.288C1297.83 481.941 1296.86 480.768 1294.92 480.768H1293.56ZM1304.04 486.48C1304.08 487.184 1304.29 487.696 1304.68 488.016C1305.06 488.325 1305.67 488.48 1306.49 488.48C1307.2 488.48 1308.03 488.347 1308.98 488.08V489.632C1308.61 489.824 1308.16 489.973 1307.64 490.08C1307.13 490.187 1306.59 490.24 1306.04 490.24C1304.68 490.24 1303.65 489.872 1302.93 489.136C1302.23 488.4 1301.88 487.323 1301.88 485.904C1301.88 484.539 1302.23 483.477 1302.93 482.72C1303.64 481.963 1304.61 481.584 1305.86 481.584C1306.92 481.584 1307.73 481.877 1308.29 482.464C1308.87 483.04 1309.16 483.867 1309.16 484.944C1309.16 485.179 1309.14 485.445 1309.11 485.744C1309.08 486.043 1309.04 486.288 1309 486.48H1304.04ZM1305.78 483.2C1305.26 483.2 1304.84 483.36 1304.53 483.68C1304.24 483.989 1304.07 484.443 1304.02 485.04H1307.16V484.768C1307.16 483.723 1306.7 483.2 1305.78 483.2ZM1310.87 493.296V481.824H1312.79L1312.98 482.592C1313.3 482.283 1313.69 482.037 1314.13 481.856C1314.59 481.675 1315.06 481.584 1315.53 481.584C1316.56 481.584 1317.38 481.963 1317.97 482.72C1318.58 483.477 1318.89 484.501 1318.89 485.792C1318.89 486.635 1318.75 487.387 1318.47 488.048C1318.19 488.709 1317.79 489.232 1317.27 489.616C1316.75 489.989 1316.15 490.176 1315.46 490.176C1315.03 490.176 1314.61 490.107 1314.21 489.968C1313.82 489.829 1313.48 489.637 1313.21 489.392V493.296H1310.87ZM1314.77 483.344C1314.22 483.344 1313.7 483.488 1313.21 483.776V487.984C1313.68 488.272 1314.2 488.416 1314.77 488.416C1315.37 488.416 1315.81 488.213 1316.09 487.808C1316.37 487.403 1316.52 486.763 1316.52 485.888C1316.52 485.003 1316.38 484.357 1316.1 483.952C1315.83 483.547 1315.38 483.344 1314.77 483.344ZM1324.23 489.84C1323.79 490.021 1323.31 490.112 1322.79 490.112C1321.35 490.112 1320.63 489.307 1320.63 487.696V478.16H1322.97V487.504C1322.97 487.803 1323.02 488.016 1323.11 488.144C1323.22 488.261 1323.39 488.32 1323.63 488.32C1323.78 488.32 1323.98 488.304 1324.23 488.272V489.84ZM1329.23 490.24C1327.96 490.24 1326.97 489.861 1326.26 489.104C1325.54 488.336 1325.19 487.269 1325.19 485.904C1325.19 484.549 1325.54 483.493 1326.26 482.736C1326.97 481.968 1327.96 481.584 1329.23 481.584C1330.5 481.584 1331.49 481.968 1332.21 482.736C1332.92 483.493 1333.28 484.549 1333.28 485.904C1333.28 487.269 1332.92 488.336 1332.21 489.104C1331.49 489.861 1330.5 490.24 1329.23 490.24ZM1329.23 488.448C1330.35 488.448 1330.91 487.6 1330.91 485.904C1330.91 484.219 1330.35 483.376 1329.23 483.376C1328.11 483.376 1327.55 484.219 1327.55 485.904C1327.55 487.6 1328.11 488.448 1329.23 488.448ZM1337.04 490.128L1333.81 481.824H1336.29L1338.11 487.936L1339.84 481.824H1342.26L1338.8 491.104C1338.49 491.947 1338.11 492.555 1337.66 492.928C1337.22 493.301 1336.65 493.488 1335.97 493.488C1335.44 493.488 1334.92 493.403 1334.42 493.232V491.648C1334.76 491.68 1335.06 491.696 1335.33 491.696C1335.78 491.696 1336.12 491.589 1336.37 491.376C1336.61 491.173 1336.82 490.816 1336.99 490.304L1337.04 490.128ZM1353.49 490V484.464C1353.49 483.739 1353.17 483.376 1352.52 483.376C1351.94 483.376 1351.36 483.515 1350.77 483.792V483.952V490H1348.44V484.464C1348.44 483.739 1348.11 483.376 1347.46 483.376C1346.86 483.376 1346.28 483.52 1345.7 483.808V490H1343.36V481.824H1345.28L1345.49 482.608C1346.06 482.235 1346.56 481.973 1347.01 481.824C1347.47 481.664 1347.94 481.584 1348.42 481.584C1349.38 481.584 1350.06 481.925 1350.45 482.608C1351 482.245 1351.51 481.984 1351.99 481.824C1352.47 481.664 1352.96 481.584 1353.48 481.584C1354.22 481.584 1354.8 481.792 1355.2 482.208C1355.62 482.624 1355.83 483.205 1355.83 483.952V490H1353.49ZM1359.7 486.48C1359.74 487.184 1359.96 487.696 1360.34 488.016C1360.72 488.325 1361.33 488.48 1362.15 488.48C1362.86 488.48 1363.69 488.347 1364.64 488.08V489.632C1364.27 489.824 1363.82 489.973 1363.3 490.08C1362.79 490.187 1362.25 490.24 1361.7 490.24C1360.34 490.24 1359.31 489.872 1358.6 489.136C1357.89 488.4 1357.54 487.323 1357.54 485.904C1357.54 484.539 1357.89 483.477 1358.6 482.72C1359.3 481.963 1360.28 481.584 1361.52 481.584C1362.58 481.584 1363.39 481.877 1363.96 482.464C1364.53 483.04 1364.82 483.867 1364.82 484.944C1364.82 485.179 1364.8 485.445 1364.77 485.744C1364.74 486.043 1364.7 486.288 1364.66 486.48H1359.7ZM1361.44 483.2C1360.92 483.2 1360.5 483.36 1360.2 483.68C1359.9 483.989 1359.73 484.443 1359.68 485.04H1362.82V484.768C1362.82 483.723 1362.36 483.2 1361.44 483.2ZM1371.78 490V484.64C1371.78 484.203 1371.68 483.883 1371.49 483.68C1371.3 483.477 1371.01 483.376 1370.61 483.376C1370.02 483.376 1369.44 483.557 1368.87 483.92V490H1366.53V481.824H1368.45L1368.68 482.704C1369.64 481.957 1370.66 481.584 1371.75 481.584C1372.5 481.584 1373.09 481.792 1373.49 482.208C1373.91 482.613 1374.12 483.195 1374.12 483.952V490H1371.78ZM1381.11 489.792C1380.54 490.016 1379.89 490.128 1379.18 490.128C1378.27 490.128 1377.6 489.915 1377.16 489.488C1376.73 489.061 1376.52 488.4 1376.52 487.504V483.552H1375.29V482.112L1376.58 481.856L1376.94 479.616H1378.86V481.824H1381.06V483.552H1378.86V487.392C1378.86 487.733 1378.94 487.973 1379.11 488.112C1379.28 488.251 1379.57 488.32 1379.98 488.32C1380.31 488.32 1380.69 488.288 1381.11 488.224V489.792ZM1386.64 490V481.824H1388.97V490H1386.64ZM1387.8 480.56C1387.4 480.56 1387.07 480.448 1386.83 480.224C1386.58 480 1386.46 479.696 1386.46 479.312C1386.46 478.928 1386.58 478.624 1386.83 478.4C1387.07 478.176 1387.4 478.064 1387.8 478.064C1388.21 478.064 1388.54 478.176 1388.78 478.4C1389.03 478.624 1389.15 478.928 1389.15 479.312C1389.15 479.696 1389.03 480 1388.78 480.224C1388.54 480.448 1388.21 480.56 1387.8 480.56ZM1394.67 487.744C1394.67 487.531 1394.6 487.365 1394.48 487.248C1394.36 487.131 1394.11 487.003 1393.74 486.864L1392.49 486.368C1391.84 486.112 1391.37 485.797 1391.08 485.424C1390.8 485.051 1390.65 484.576 1390.65 484C1390.65 483.275 1390.94 482.693 1391.52 482.256C1392.1 481.808 1392.88 481.584 1393.85 481.584C1394.75 481.584 1395.57 481.76 1396.33 482.112V483.664C1395.52 483.419 1394.76 483.296 1394.06 483.296C1393.62 483.296 1393.3 483.349 1393.1 483.456C1392.9 483.563 1392.8 483.733 1392.8 483.968C1392.8 484.149 1392.85 484.299 1392.97 484.416C1393.1 484.523 1393.36 484.656 1393.76 484.816L1394.97 485.312C1395.63 485.579 1396.1 485.888 1396.38 486.24C1396.67 486.592 1396.81 487.051 1396.81 487.616C1396.81 488.405 1396.51 489.045 1395.9 489.536C1395.3 490.016 1394.51 490.256 1393.53 490.256C1392.43 490.256 1391.46 490.037 1390.62 489.6V488.048C1391.68 488.379 1392.64 488.544 1393.52 488.544C1394.28 488.544 1394.67 488.277 1394.67 487.744ZM1313.16 510V501.824H1315.5V510H1313.16ZM1314.33 500.56C1313.92 500.56 1313.6 500.448 1313.35 500.224C1313.11 500 1312.98 499.696 1312.98 499.312C1312.98 498.928 1313.11 498.624 1313.35 498.4C1313.6 498.176 1313.92 498.064 1314.33 498.064C1314.73 498.064 1315.06 498.176 1315.3 498.4C1315.55 498.624 1315.67 498.928 1315.67 499.312C1315.67 499.696 1315.55 500 1315.3 500.224C1315.06 500.448 1314.73 500.56 1314.33 500.56ZM1322.97 510V504.64C1322.97 504.203 1322.87 503.883 1322.68 503.68C1322.49 503.477 1322.19 503.376 1321.8 503.376C1321.21 503.376 1320.63 503.557 1320.06 503.92V510H1317.72V501.824H1319.64L1319.86 502.704C1320.82 501.957 1321.85 501.584 1322.94 501.584C1323.69 501.584 1324.27 501.792 1324.68 502.208C1325.1 502.613 1325.3 503.195 1325.3 503.952V510H1322.97ZM1327.5 510V501.824H1329.84V510H1327.5ZM1328.67 500.56C1328.26 500.56 1327.94 500.448 1327.69 500.224C1327.45 500 1327.32 499.696 1327.32 499.312C1327.32 498.928 1327.45 498.624 1327.69 498.4C1327.94 498.176 1328.26 498.064 1328.67 498.064C1329.07 498.064 1329.4 498.176 1329.64 498.4C1329.89 498.624 1330.01 498.928 1330.01 499.312C1330.01 499.696 1329.89 500 1329.64 500.224C1329.4 500.448 1329.07 500.56 1328.67 500.56ZM1336.92 509.792C1336.35 510.016 1335.7 510.128 1334.99 510.128C1334.08 510.128 1333.41 509.915 1332.97 509.488C1332.54 509.061 1332.33 508.4 1332.33 507.504V503.552H1331.1V502.112L1332.4 501.856L1332.75 499.616H1334.67V501.824H1336.88V503.552H1334.67V507.392C1334.67 507.733 1334.75 507.973 1334.92 508.112C1335.09 508.251 1335.38 508.32 1335.79 508.32C1336.12 508.32 1336.5 508.288 1336.92 508.224V509.792ZM1338.34 510V501.824H1340.68V510H1338.34ZM1339.51 500.56C1339.1 500.56 1338.78 500.448 1338.53 500.224C1338.29 500 1338.16 499.696 1338.16 499.312C1338.16 498.928 1338.29 498.624 1338.53 498.4C1338.78 498.176 1339.1 498.064 1339.51 498.064C1339.91 498.064 1340.24 498.176 1340.48 498.4C1340.73 498.624 1340.85 498.928 1340.85 499.312C1340.85 499.696 1340.73 500 1340.48 500.224C1340.24 500.448 1339.91 500.56 1339.51 500.56ZM1347.59 510L1347.4 509.28C1347.06 509.579 1346.68 509.819 1346.24 510C1345.82 510.171 1345.4 510.256 1345 510.256C1344.21 510.256 1343.57 510.032 1343.09 509.584C1342.62 509.136 1342.39 508.539 1342.39 507.792C1342.39 507.28 1342.52 506.832 1342.77 506.448C1343.03 506.053 1343.4 505.744 1343.88 505.52C1344.36 505.296 1344.92 505.184 1345.57 505.184C1346.08 505.184 1346.65 505.253 1347.27 505.392V504.592C1347.27 504.101 1347.17 503.765 1346.96 503.584C1346.76 503.403 1346.39 503.312 1345.84 503.312C1344.97 503.312 1344 503.477 1342.95 503.808V502.256C1343.34 502.053 1343.84 501.893 1344.44 501.776C1345.03 501.648 1345.64 501.584 1346.26 501.584C1347.36 501.584 1348.16 501.808 1348.66 502.256C1349.17 502.693 1349.43 503.387 1349.43 504.336V510H1347.59ZM1345.65 508.688C1345.92 508.688 1346.19 508.629 1346.47 508.512C1346.76 508.395 1347.02 508.235 1347.27 508.032V506.64C1346.8 506.565 1346.38 506.528 1346 506.528C1345.08 506.528 1344.61 506.901 1344.61 507.648C1344.61 507.979 1344.7 508.235 1344.88 508.416C1345.06 508.597 1345.32 508.688 1345.65 508.688ZM1356.42 509.792C1355.84 510.016 1355.2 510.128 1354.48 510.128C1353.58 510.128 1352.9 509.915 1352.47 509.488C1352.04 509.061 1351.83 508.4 1351.83 507.504V503.552H1350.59V502.112L1351.89 501.856L1352.24 499.616H1354.16V501.824H1356.37V503.552H1354.16V507.392C1354.16 507.733 1354.25 507.973 1354.42 508.112C1354.59 508.251 1354.88 508.32 1355.28 508.32C1355.61 508.32 1355.99 508.288 1356.42 508.224V509.792ZM1359.51 506.48C1359.56 507.184 1359.77 507.696 1360.15 508.016C1360.54 508.325 1361.14 508.48 1361.96 508.48C1362.68 508.48 1363.51 508.347 1364.46 508.08V509.632C1364.09 509.824 1363.64 509.973 1363.11 510.08C1362.6 510.187 1362.07 510.24 1361.51 510.24C1360.16 510.24 1359.13 509.872 1358.41 509.136C1357.71 508.4 1357.35 507.323 1357.35 505.904C1357.35 504.539 1357.71 503.477 1358.41 502.72C1359.11 501.963 1360.09 501.584 1361.34 501.584C1362.39 501.584 1363.21 501.877 1363.77 502.464C1364.35 503.04 1364.63 503.867 1364.63 504.944C1364.63 505.179 1364.62 505.445 1364.59 505.744C1364.55 506.043 1364.52 506.288 1364.47 506.48H1359.51ZM1361.26 503.2C1360.74 503.2 1360.32 503.36 1360.01 503.68C1359.71 503.989 1359.54 504.443 1359.5 505.04H1362.63V504.768C1362.63 503.723 1362.18 503.2 1361.26 503.2ZM1371.87 510L1371.67 509.28C1371.01 509.877 1370.23 510.176 1369.32 510.176C1368.65 510.176 1368.06 510.011 1367.55 509.68C1367.03 509.339 1366.63 508.848 1366.35 508.208C1366.07 507.568 1365.93 506.816 1365.93 505.952C1365.93 504.629 1366.25 503.573 1366.87 502.784C1367.5 501.984 1368.34 501.584 1369.37 501.584C1370.21 501.584 1370.94 501.824 1371.56 502.304V498.16H1373.9V510H1371.87ZM1370.09 508.416C1370.6 508.416 1371.09 508.267 1371.56 507.968V503.744C1371.1 503.477 1370.58 503.344 1369.98 503.344C1369.41 503.344 1368.99 503.557 1368.71 503.984C1368.44 504.4 1368.3 505.035 1368.3 505.888C1368.3 506.741 1368.44 507.376 1368.73 507.792C1369.03 508.208 1369.48 508.416 1370.09 508.416Z" fill="white"/> -<path d="M235.707 66.7071C236.098 66.3166 236.098 65.6834 235.707 65.2929L229.343 58.9289C228.953 58.5384 228.319 58.5384 227.929 58.9289C227.538 59.3195 227.538 59.9526 227.929 60.3431L233.586 66L227.929 71.6569C227.538 72.0474 227.538 72.6805 227.929 73.0711C228.319 73.4616 228.953 73.4616 229.343 73.0711L235.707 66.7071ZM195 67H235V65H195V67Z" fill="black"/> -<path d="M471.707 66.7071C472.098 66.3166 472.098 65.6834 471.707 65.2929L465.343 58.9289C464.953 58.5384 464.319 58.5384 463.929 58.9289C463.538 59.3195 463.538 59.9526 463.929 60.3431L469.586 66L463.929 71.6569C463.538 72.0474 463.538 72.6805 463.929 73.0711C464.319 73.4616 464.953 73.4616 465.343 73.0711L471.707 66.7071ZM431 67H471V65H431V67Z" fill="black"/> -<path d="M706.707 66.7071C707.098 66.3166 707.098 65.6834 706.707 65.2929L700.343 58.9289C699.953 58.5384 699.319 58.5384 698.929 58.9289C698.538 59.3195 698.538 59.9526 698.929 60.3431L704.586 66L698.929 71.6569C698.538 72.0474 698.538 72.6805 698.929 73.0711C699.319 73.4616 699.953 73.4616 700.343 73.0711L706.707 66.7071ZM666 67H706V65H666V67Z" fill="black"/> -<path d="M1245.71 494.707C1246.1 494.317 1246.1 493.683 1245.71 493.293L1239.34 486.929C1238.95 486.538 1238.32 486.538 1237.93 486.929C1237.54 487.319 1237.54 487.953 1237.93 488.343L1243.59 494L1237.93 499.657C1237.54 500.047 1237.54 500.681 1237.93 501.071C1238.32 501.462 1238.95 501.462 1239.34 501.071L1245.71 494.707ZM1205 495H1245V493H1205V495Z" fill="black"/> -<mask id="path-15-outside-1_92_614" maskUnits="userSpaceOnUse" x="707" y="32" width="254" height="68" fill="black"> -<rect fill="white" x="707" y="32" width="254" height="68"/> -<path d="M709 44C709 38.4772 713.477 34 719 34L949 34C954.523 34 959 38.4771 959 44L959 98L709 98L709 44Z"/> -</mask> -<path d="M709 44C709 38.4772 713.477 34 719 34L949 34C954.523 34 959 38.4771 959 44L959 98L709 98L709 44Z" fill="#0972D3"/> -<path d="M959 98L959 100L961 100L961 98L959 98ZM709 98L707 98L707 100L709 100L709 98ZM719 36L949 36L949 32L719 32L719 36ZM957 44L957 98L961 98L961 44L957 44ZM959 96L709 96L709 100L959 100L959 96ZM711 98L711 44L707 44L707 98L711 98ZM949 36C953.418 36 957 39.5817 957 44L961 44C961 37.3726 955.627 32 949 32L949 36ZM719 32C712.373 32 707 37.3726 707 44L711 44C711 39.5817 714.582 36 719 36L719 32Z" fill="#000716" mask="url(#path-15-outside-1_92_614)"/> -<path d="M766.515 73L766.515 62.686L762.717 62.686L762.717 60.526L773.013 60.526L773.013 62.686L769.215 62.686L769.215 73L766.515 73ZM780.388 73L780.388 66.97C780.388 66.478 780.28 66.118 780.064 65.89C779.848 65.662 779.518 65.548 779.074 65.548C778.414 65.548 777.76 65.752 777.112 66.16L777.112 73L774.484 73L774.484 59.68L777.112 59.68L777.112 64.63C778.144 63.898 779.224 63.532 780.352 63.532C781.204 63.532 781.858 63.766 782.314 64.234C782.782 64.69 783.016 65.344 783.016 66.196L783.016 73L780.388 73ZM787.467 69.04C787.515 69.832 787.755 70.408 788.187 70.768C788.619 71.116 789.297 71.29 790.221 71.29C791.025 71.29 791.961 71.14 793.029 70.84L793.029 72.586C792.609 72.802 792.105 72.97 791.517 73.09C790.941 73.21 790.341 73.27 789.717 73.27C788.193 73.27 787.029 72.856 786.225 72.028C785.433 71.2 785.037 69.988 785.037 68.392C785.037 66.856 785.433 65.662 786.225 64.81C787.017 63.958 788.115 63.532 789.519 63.532C790.707 63.532 791.619 63.862 792.255 64.522C792.903 65.17 793.227 66.1 793.227 67.312C793.227 67.576 793.209 67.876 793.173 68.212C793.137 68.548 793.095 68.824 793.047 69.04L787.467 69.04ZM789.429 65.35C788.841 65.35 788.373 65.53 788.025 65.89C787.689 66.238 787.497 66.748 787.449 67.42L790.977 67.42L790.977 67.114C790.977 65.938 790.461 65.35 789.429 65.35ZM805.228 73L805.012 72.19C804.64 72.526 804.208 72.796 803.716 73C803.236 73.192 802.768 73.288 802.312 73.288C801.424 73.288 800.71 73.036 800.17 72.532C799.642 72.028 799.378 71.356 799.378 70.516C799.378 69.94 799.522 69.436 799.81 69.004C800.098 68.56 800.512 68.212 801.052 67.96C801.592 67.708 802.228 67.582 802.96 67.582C803.536 67.582 804.172 67.66 804.868 67.816L804.868 66.916C804.868 66.364 804.754 65.986 804.526 65.782C804.298 65.578 803.878 65.476 803.266 65.476C802.282 65.476 801.196 65.662 800.008 66.034L800.008 64.288C800.452 64.06 801.01 63.88 801.682 63.748C802.354 63.604 803.038 63.532 803.734 63.532C804.97 63.532 805.87 63.784 806.434 64.288C807.01 64.78 807.298 65.56 807.298 66.628L807.298 73L805.228 73ZM803.05 71.524C803.35 71.524 803.656 71.458 803.968 71.326C804.292 71.194 804.592 71.014 804.868 70.786L804.868 69.22C804.34 69.136 803.866 69.094 803.446 69.094C802.402 69.094 801.88 69.514 801.88 70.354C801.88 70.726 801.982 71.014 802.186 71.218C802.39 71.422 802.678 71.524 803.05 71.524ZM809.781 76.708L809.781 63.802L811.941 63.802L812.157 64.666C812.517 64.318 812.949 64.042 813.453 63.838C813.969 63.634 814.491 63.532 815.019 63.532C816.183 63.532 817.101 63.958 817.773 64.81C818.457 65.662 818.799 66.814 818.799 68.266C818.799 69.214 818.643 70.06 818.331 70.804C818.019 71.548 817.569 72.136 816.981 72.568C816.393 72.988 815.715 73.198 814.947 73.198C814.455 73.198 813.987 73.12 813.543 72.964C813.099 72.808 812.721 72.592 812.409 72.316L812.409 76.708L809.781 76.708ZM814.173 65.512C813.549 65.512 812.961 65.674 812.409 65.998L812.409 70.732C812.937 71.056 813.525 71.218 814.173 71.218C814.845 71.218 815.337 70.99 815.649 70.534C815.973 70.078 816.135 69.358 816.135 68.374C816.135 67.378 815.979 66.652 815.667 66.196C815.355 65.74 814.857 65.512 814.173 65.512ZM820.855 76.708L820.855 63.802L823.015 63.802L823.231 64.666C823.591 64.318 824.023 64.042 824.527 63.838C825.043 63.634 825.565 63.532 826.093 63.532C827.257 63.532 828.175 63.958 828.847 64.81C829.531 65.662 829.873 66.814 829.873 68.266C829.873 69.214 829.717 70.06 829.405 70.804C829.093 71.548 828.643 72.136 828.055 72.568C827.467 72.988 826.789 73.198 826.021 73.198C825.529 73.198 825.061 73.12 824.617 72.964C824.173 72.808 823.795 72.592 823.483 72.316L823.483 76.708L820.855 76.708ZM825.247 65.512C824.623 65.512 824.035 65.674 823.483 65.998L823.483 70.732C824.011 71.056 824.599 71.218 825.247 71.218C825.919 71.218 826.411 70.99 826.723 70.534C827.047 70.078 827.209 69.358 827.209 68.374C827.209 67.378 827.053 66.652 826.741 66.196C826.429 65.74 825.931 65.512 825.247 65.512ZM840.69 72.82C840.186 73.024 839.646 73.126 839.07 73.126C837.45 73.126 836.64 72.22 836.64 70.408L836.64 59.68L839.268 59.68L839.268 70.192C839.268 70.528 839.322 70.768 839.43 70.912C839.55 71.044 839.742 71.11 840.006 71.11C840.174 71.11 840.402 71.092 840.69 71.056L840.69 72.82ZM842.565 73L842.565 63.802L845.193 63.802L845.193 73L842.565 73ZM843.879 62.38C843.423 62.38 843.057 62.254 842.781 62.002C842.505 61.75 842.367 61.408 842.367 60.976C842.367 60.544 842.505 60.202 842.781 59.95C843.057 59.698 843.423 59.572 843.879 59.572C844.335 59.572 844.701 59.698 844.977 59.95C845.253 60.202 845.391 60.544 845.391 60.976C845.391 61.408 845.253 61.75 844.977 62.002C844.701 62.254 844.335 62.38 843.879 62.38ZM848.234 73L848.234 65.746L846.776 65.746L846.776 64.126L848.234 63.856L848.234 63.028C848.234 61.816 848.51 60.916 849.062 60.328C849.626 59.728 850.478 59.428 851.618 59.428C851.942 59.428 852.278 59.464 852.626 59.536C852.974 59.596 853.28 59.68 853.544 59.788L853.544 61.57C853.064 61.498 852.656 61.462 852.32 61.462C851.768 61.462 851.384 61.552 851.168 61.732C850.964 61.912 850.862 62.23 850.862 62.686L850.862 63.802L853.436 63.802L853.436 65.746L850.862 65.746L850.862 73L848.234 73ZM856.725 69.04C856.773 69.832 857.013 70.408 857.445 70.768C857.877 71.116 858.555 71.29 859.479 71.29C860.283 71.29 861.219 71.14 862.287 70.84L862.287 72.586C861.867 72.802 861.363 72.97 860.775 73.09C860.199 73.21 859.599 73.27 858.975 73.27C857.451 73.27 856.287 72.856 855.483 72.028C854.691 71.2 854.295 69.988 854.295 68.392C854.295 66.856 854.691 65.662 855.483 64.81C856.275 63.958 857.373 63.532 858.777 63.532C859.965 63.532 860.877 63.862 861.513 64.522C862.161 65.17 862.485 66.1 862.485 67.312C862.485 67.576 862.467 67.876 862.431 68.212C862.395 68.548 862.353 68.824 862.305 69.04L856.725 69.04ZM858.687 65.35C858.099 65.35 857.631 65.53 857.283 65.89C856.947 66.238 856.755 66.748 856.707 67.42L860.235 67.42L860.235 67.114C860.235 65.938 859.719 65.35 858.687 65.35ZM871.143 72.604C870.819 72.796 870.429 72.94 869.973 73.036C869.517 73.144 869.043 73.198 868.551 73.198C867.087 73.198 865.965 72.79 865.185 71.974C864.417 71.158 864.033 69.982 864.033 68.446C864.033 66.922 864.441 65.734 865.257 64.882C866.073 64.03 867.207 63.604 868.659 63.604C869.535 63.604 870.345 63.796 871.089 64.18L871.089 65.926C870.381 65.722 869.733 65.62 869.145 65.62C868.305 65.62 867.687 65.836 867.291 66.268C866.895 66.688 866.697 67.36 866.697 68.284L866.697 68.536C866.697 69.448 866.889 70.12 867.273 70.552C867.669 70.972 868.275 71.182 869.091 71.182C869.679 71.182 870.363 71.074 871.143 70.858L871.143 72.604ZM875.809 73.144L872.173 63.802L874.963 63.802L877.015 70.678L878.959 63.802L881.677 63.802L877.789 74.242C877.441 75.19 877.015 75.874 876.511 76.294C876.007 76.714 875.371 76.924 874.603 76.924C874.003 76.924 873.421 76.828 872.857 76.636L872.857 74.854C873.241 74.89 873.583 74.908 873.883 74.908C874.387 74.908 874.777 74.788 875.053 74.548C875.329 74.32 875.563 73.918 875.755 73.342L875.809 73.144ZM889.477 72.604C889.153 72.796 888.763 72.94 888.307 73.036C887.851 73.144 887.377 73.198 886.885 73.198C885.421 73.198 884.299 72.79 883.519 71.974C882.751 71.158 882.367 69.982 882.367 68.446C882.367 66.922 882.775 65.734 883.591 64.882C884.407 64.03 885.541 63.604 886.993 63.604C887.869 63.604 888.679 63.796 889.423 64.18L889.423 65.926C888.715 65.722 888.067 65.62 887.479 65.62C886.639 65.62 886.021 65.836 885.625 66.268C885.229 66.688 885.031 67.36 885.031 68.284L885.031 68.536C885.031 69.448 885.223 70.12 885.607 70.552C886.003 70.972 886.609 71.182 887.425 71.182C888.013 71.182 888.697 71.074 889.477 70.858L889.477 72.604ZM895.393 72.82C894.889 73.024 894.349 73.126 893.773 73.126C892.153 73.126 891.343 72.22 891.343 70.408L891.343 59.68L893.971 59.68L893.971 70.192C893.971 70.528 894.025 70.768 894.133 70.912C894.253 71.044 894.445 71.11 894.709 71.11C894.877 71.11 895.105 71.092 895.393 71.056L895.393 72.82ZM898.983 69.04C899.031 69.832 899.271 70.408 899.703 70.768C900.135 71.116 900.813 71.29 901.737 71.29C902.541 71.29 903.477 71.14 904.545 70.84L904.545 72.586C904.125 72.802 903.621 72.97 903.033 73.09C902.457 73.21 901.857 73.27 901.233 73.27C899.709 73.27 898.545 72.856 897.741 72.028C896.949 71.2 896.553 69.988 896.553 68.392C896.553 66.856 896.949 65.662 897.741 64.81C898.533 63.958 899.631 63.532 901.035 63.532C902.223 63.532 903.135 63.862 903.771 64.522C904.419 65.17 904.743 66.1 904.743 67.312C904.743 67.576 904.725 67.876 904.689 68.212C904.653 68.548 904.611 68.824 904.563 69.04L898.983 69.04ZM900.945 65.35C900.357 65.35 899.889 65.53 899.541 65.89C899.205 66.238 899.013 66.748 898.965 67.42L902.493 67.42L902.493 67.114C902.493 65.938 901.977 65.35 900.945 65.35Z" fill="white"/> -<path d="M960 100L960 99L959 99L709 99L708 99L708 100L708 522C708 528.075 712.925 533 719 533L949 533C955.075 533 960 528.075 960 522L960 100Z" fill="white" stroke="#000716" stroke-width="2"/> -<rect x="739.5" y="114.5" width="190" height="47" rx="5.5" fill="white"/> -<rect x="739.5" y="114.5" width="190" height="47" rx="5.5" stroke="#1A1A1A"/> -<path d="M767.793 143.696C766.929 144.027 765.995 144.192 764.993 144.192C763.243 144.192 761.915 143.712 761.009 142.752C760.113 141.781 759.665 140.363 759.665 138.496C759.665 136.651 760.129 135.232 761.057 134.24C761.995 133.248 763.334 132.752 765.073 132.752C765.979 132.752 766.833 132.896 767.633 133.184V134.512C766.662 134.288 765.873 134.176 765.265 134.176C763.921 134.176 762.939 134.507 762.321 135.168C761.702 135.819 761.393 136.859 761.393 138.288V138.672C761.393 140.08 761.691 141.115 762.289 141.776C762.897 142.437 763.857 142.768 765.169 142.768C765.841 142.768 766.715 142.635 767.793 142.368V143.696ZM769.703 144V132.912H773.351C774.983 132.912 776.226 133.387 777.079 134.336C777.943 135.275 778.375 136.651 778.375 138.464C778.375 140.256 777.938 141.627 777.063 142.576C776.189 143.525 774.935 144 773.303 144H769.703ZM771.335 134.192V142.72H773.127C775.506 142.72 776.695 141.36 776.695 138.64V138.272C776.695 136.917 776.397 135.899 775.799 135.216C775.202 134.533 774.311 134.192 773.127 134.192H771.335ZM780.75 144V132.912H782.382V137.872L786.942 132.912H788.862L783.934 138.208L789.294 144H787.294L782.382 138.704V144H780.75ZM799.421 144L799.293 143.168C798.909 143.499 798.482 143.755 798.013 143.936C797.554 144.117 797.095 144.208 796.637 144.208C795.879 144.208 795.271 143.995 794.813 143.568C794.365 143.131 794.141 142.549 794.141 141.824C794.141 141.045 794.418 140.427 794.973 139.968C795.527 139.499 796.274 139.264 797.213 139.264C797.831 139.264 798.503 139.355 799.229 139.536V138.48C799.229 137.904 799.095 137.499 798.829 137.264C798.573 137.029 798.13 136.912 797.501 136.912C796.594 136.912 795.655 137.077 794.685 137.408V136.288C795.069 136.085 795.538 135.931 796.093 135.824C796.647 135.707 797.207 135.648 797.773 135.648C798.786 135.648 799.533 135.861 800.013 136.288C800.493 136.704 800.733 137.344 800.733 138.208V144H799.421ZM797.021 143.008C797.746 143.008 798.482 142.736 799.229 142.192V140.56C798.674 140.421 798.109 140.352 797.533 140.352C796.327 140.352 795.725 140.816 795.725 141.744C795.725 142.149 795.837 142.464 796.061 142.688C796.285 142.901 796.605 143.008 797.021 143.008ZM803.09 147.296V135.888H804.418L804.562 136.72C805.373 136.005 806.274 135.648 807.266 135.648C808.301 135.648 809.117 136.027 809.714 136.784C810.312 137.531 810.61 138.549 810.61 139.84C810.61 141.152 810.296 142.203 809.666 142.992C809.037 143.781 808.2 144.176 807.154 144.176C806.194 144.176 805.368 143.861 804.674 143.232V147.296H803.09ZM806.818 136.928C806.061 136.928 805.346 137.173 804.674 137.664V142.128C805.368 142.64 806.072 142.896 806.786 142.896C808.258 142.896 808.994 141.904 808.994 139.92C808.994 138.907 808.813 138.155 808.45 137.664C808.098 137.173 807.554 136.928 806.818 136.928ZM812.559 147.296V135.888H813.887L814.031 136.72C814.842 136.005 815.743 135.648 816.735 135.648C817.77 135.648 818.586 136.027 819.183 136.784C819.78 137.531 820.079 138.549 820.079 139.84C820.079 141.152 819.764 142.203 819.135 142.992C818.506 143.781 817.668 144.176 816.623 144.176C815.663 144.176 814.836 143.861 814.143 143.232V147.296H812.559ZM816.287 136.928C815.53 136.928 814.815 137.173 814.143 137.664V142.128C814.836 142.64 815.54 142.896 816.255 142.896C817.727 142.896 818.463 141.904 818.463 139.92C818.463 138.907 818.282 138.155 817.919 137.664C817.567 137.173 817.023 136.928 816.287 136.928ZM830.023 141.824C830.023 141.568 829.938 141.36 829.767 141.2C829.607 141.04 829.309 140.88 828.871 140.72L827.511 140.208C826.327 139.771 825.735 139.024 825.735 137.968C825.735 137.275 826.002 136.715 826.535 136.288C827.079 135.861 827.789 135.648 828.663 135.648C829.506 135.648 830.301 135.819 831.047 136.16V137.28C830.215 137.013 829.447 136.88 828.743 136.88C827.719 136.88 827.207 137.227 827.207 137.92C827.207 138.197 827.293 138.416 827.463 138.576C827.634 138.736 827.97 138.912 828.471 139.104L829.719 139.584C830.349 139.829 830.802 140.123 831.079 140.464C831.357 140.795 831.495 141.227 831.495 141.76C831.495 142.517 831.213 143.12 830.647 143.568C830.082 144.016 829.33 144.24 828.391 144.24C827.335 144.24 826.418 144.037 825.639 143.632V142.512C826.642 142.843 827.57 143.008 828.423 143.008C828.946 143.008 829.341 142.907 829.607 142.704C829.885 142.501 830.023 142.208 830.023 141.824ZM836.578 144.24C835.362 144.24 834.412 143.861 833.73 143.104C833.047 142.347 832.706 141.291 832.706 139.936C832.706 138.592 833.047 137.541 833.73 136.784C834.412 136.027 835.362 135.648 836.578 135.648C837.794 135.648 838.743 136.027 839.426 136.784C840.108 137.541 840.45 138.592 840.45 139.936C840.45 141.291 840.108 142.347 839.426 143.104C838.743 143.861 837.794 144.24 836.578 144.24ZM836.578 142.96C838.082 142.96 838.834 141.952 838.834 139.936C838.834 137.931 838.082 136.928 836.578 136.928C835.074 136.928 834.322 137.931 834.322 139.936C834.322 141.952 835.074 142.96 836.578 142.96ZM847.923 144L847.747 143.136C846.755 143.872 845.736 144.24 844.691 144.24C843.933 144.24 843.352 144.027 842.947 143.6C842.541 143.173 842.339 142.571 842.339 141.792V135.888H843.923V141.28C843.923 141.856 844.035 142.283 844.259 142.56C844.483 142.827 844.84 142.96 845.331 142.96C846.099 142.96 846.872 142.704 847.651 142.192V135.888H849.235V144H847.923ZM851.606 144V135.888H852.934L853.11 137.088C853.409 136.768 853.686 136.523 853.942 136.352C854.198 136.171 854.459 136.037 854.726 135.952C854.993 135.867 855.281 135.824 855.59 135.824C855.793 135.824 856.011 135.84 856.246 135.872V137.312C855.905 137.269 855.617 137.248 855.382 137.248C854.529 137.248 853.798 137.504 853.19 138.016V144H851.606ZM863.034 143.696C862.416 144.016 861.701 144.176 860.89 144.176C859.632 144.176 858.666 143.819 857.994 143.104C857.333 142.379 857.002 141.333 857.002 139.968C857.002 138.613 857.344 137.568 858.026 136.832C858.72 136.085 859.696 135.712 860.954 135.712C861.669 135.712 862.341 135.861 862.97 136.16V137.296C862.362 137.104 861.765 137.008 861.178 137.008C860.282 137.008 859.637 137.237 859.242 137.696C858.848 138.144 858.65 138.864 858.65 139.856V140.064C858.65 141.035 858.848 141.749 859.242 142.208C859.648 142.656 860.282 142.88 861.146 142.88C861.722 142.88 862.352 142.773 863.034 142.56V143.696ZM865.679 140.288C865.7 141.205 865.924 141.883 866.351 142.32C866.788 142.757 867.46 142.976 868.367 142.976C869.21 142.976 870.068 142.811 870.943 142.48V143.616C870.175 144.032 869.236 144.24 868.127 144.24C866.815 144.24 865.823 143.877 865.151 143.152C864.479 142.427 864.143 141.355 864.143 139.936C864.143 138.581 864.479 137.531 865.151 136.784C865.823 136.027 866.762 135.648 867.967 135.648C868.98 135.648 869.759 135.936 870.303 136.512C870.847 137.077 871.119 137.883 871.119 138.928C871.119 139.429 871.076 139.883 870.991 140.288H865.679ZM867.887 136.848C867.215 136.848 866.692 137.051 866.319 137.456C865.946 137.851 865.732 138.443 865.679 139.232H869.663C869.674 139.147 869.679 139.008 869.679 138.816C869.679 138.165 869.524 137.675 869.215 137.344C868.916 137.013 868.474 136.848 867.887 136.848ZM882.831 143.696C882.213 144.016 881.498 144.176 880.687 144.176C879.429 144.176 878.463 143.819 877.791 143.104C877.13 142.379 876.799 141.333 876.799 139.968C876.799 138.613 877.141 137.568 877.823 136.832C878.517 136.085 879.493 135.712 880.751 135.712C881.466 135.712 882.138 135.861 882.767 136.16V137.296C882.159 137.104 881.562 137.008 880.975 137.008C880.079 137.008 879.434 137.237 879.039 137.696C878.645 138.144 878.447 138.864 878.447 139.856V140.064C878.447 141.035 878.645 141.749 879.039 142.208C879.445 142.656 880.079 142.88 880.943 142.88C881.519 142.88 882.149 142.773 882.831 142.56V143.696ZM887.812 144.24C886.596 144.24 885.647 143.861 884.964 143.104C884.281 142.347 883.94 141.291 883.94 139.936C883.94 138.592 884.281 137.541 884.964 136.784C885.647 136.027 886.596 135.648 887.812 135.648C889.028 135.648 889.977 136.027 890.66 136.784C891.343 137.541 891.684 138.592 891.684 139.936C891.684 141.291 891.343 142.347 890.66 143.104C889.977 143.861 889.028 144.24 887.812 144.24ZM887.812 142.96C889.316 142.96 890.068 141.952 890.068 139.936C890.068 137.931 889.316 136.928 887.812 136.928C886.308 136.928 885.556 137.931 885.556 139.936C885.556 141.952 886.308 142.96 887.812 142.96ZM899.397 144L899.189 143.168C898.837 143.488 898.437 143.739 897.989 143.92C897.541 144.091 897.088 144.176 896.629 144.176C895.957 144.176 895.365 144.011 894.853 143.68C894.341 143.349 893.941 142.869 893.653 142.24C893.365 141.6 893.221 140.848 893.221 139.984C893.221 139.12 893.36 138.363 893.637 137.712C893.914 137.061 894.309 136.555 894.821 136.192C895.344 135.829 895.962 135.648 896.677 135.648C897.584 135.648 898.4 135.947 899.125 136.544V132.16H900.709V144H899.397ZM897.109 142.896C897.77 142.896 898.442 142.651 899.125 142.16V137.632C898.794 137.387 898.458 137.211 898.117 137.104C897.786 136.987 897.418 136.928 897.013 136.928C895.562 136.928 894.837 137.931 894.837 139.936C894.837 141.909 895.594 142.896 897.109 142.896ZM904.195 140.288C904.216 141.205 904.44 141.883 904.867 142.32C905.304 142.757 905.976 142.976 906.883 142.976C907.725 142.976 908.584 142.811 909.459 142.48V143.616C908.691 144.032 907.752 144.24 906.643 144.24C905.331 144.24 904.339 143.877 903.667 143.152C902.995 142.427 902.659 141.355 902.659 139.936C902.659 138.581 902.995 137.531 903.667 136.784C904.339 136.027 905.277 135.648 906.483 135.648C907.496 135.648 908.275 135.936 908.819 136.512C909.363 137.077 909.635 137.883 909.635 138.928C909.635 139.429 909.592 139.883 909.507 140.288H904.195ZM906.403 136.848C905.731 136.848 905.208 137.051 904.835 137.456C904.461 137.851 904.248 138.443 904.195 139.232H908.179C908.189 139.147 908.195 139.008 908.195 138.816C908.195 138.165 908.04 137.675 907.731 137.344C907.432 137.013 906.989 136.848 906.403 136.848Z" fill="#1A1A1A"/> -<rect x="737" y="204" width="193" height="46" rx="5" fill="#0972D3"/> -<rect x="737" y="204" width="193" height="46" rx="5" stroke="#000716" stroke-width="2"/> -<path d="M806.758 232.712C805.894 233.043 804.928 233.208 803.862 233.208C802.059 233.208 800.694 232.728 799.766 231.768C798.838 230.797 798.374 229.379 798.374 227.512C798.374 225.667 798.859 224.237 799.83 223.224C800.8 222.211 802.166 221.704 803.926 221.704C804.864 221.704 805.755 221.853 806.598 222.152V224.04C805.627 223.827 804.832 223.72 804.214 223.72C803.104 223.72 802.272 224.013 801.718 224.6C801.174 225.187 800.902 226.083 800.902 227.288V227.656C800.902 228.851 801.168 229.741 801.702 230.328C802.235 230.904 803.051 231.192 804.15 231.192C804.768 231.192 805.638 231.069 806.758 230.824V232.712ZM811.929 233.24C810.66 233.24 809.668 232.861 808.953 232.104C808.239 231.336 807.881 230.269 807.881 228.904C807.881 227.549 808.239 226.493 808.953 225.736C809.668 224.968 810.66 224.584 811.929 224.584C813.199 224.584 814.191 224.968 814.905 225.736C815.62 226.493 815.977 227.549 815.977 228.904C815.977 230.269 815.62 231.336 814.905 232.104C814.191 232.861 813.199 233.24 811.929 233.24ZM811.929 231.448C813.049 231.448 813.609 230.6 813.609 228.904C813.609 227.219 813.049 226.376 811.929 226.376C810.809 226.376 810.249 227.219 810.249 228.904C810.249 230.6 810.809 231.448 811.929 231.448ZM822.966 233V227.64C822.966 227.203 822.87 226.883 822.678 226.68C822.486 226.477 822.192 226.376 821.798 226.376C821.211 226.376 820.63 226.557 820.054 226.92V233H817.718V224.824H819.638L819.862 225.704C820.822 224.957 821.846 224.584 822.934 224.584C823.691 224.584 824.272 224.792 824.678 225.208C825.094 225.613 825.302 226.195 825.302 226.952V233H822.966ZM830.906 230.744C830.906 230.531 830.842 230.365 830.714 230.248C830.597 230.131 830.352 230.003 829.978 229.864L828.73 229.368C828.08 229.112 827.61 228.797 827.322 228.424C827.034 228.051 826.89 227.576 826.89 227C826.89 226.275 827.178 225.693 827.754 225.256C828.341 224.808 829.12 224.584 830.09 224.584C830.986 224.584 831.813 224.76 832.57 225.112V226.664C831.76 226.419 831.002 226.296 830.298 226.296C829.861 226.296 829.541 226.349 829.338 226.456C829.136 226.563 829.034 226.733 829.034 226.968C829.034 227.149 829.093 227.299 829.21 227.416C829.338 227.523 829.6 227.656 829.994 227.816L831.21 228.312C831.872 228.579 832.341 228.888 832.618 229.24C832.906 229.592 833.05 230.051 833.05 230.616C833.05 231.405 832.746 232.045 832.138 232.536C831.541 233.016 830.752 233.256 829.77 233.256C828.672 233.256 827.701 233.037 826.858 232.6V231.048C827.914 231.379 828.88 231.544 829.754 231.544C830.522 231.544 830.906 231.277 830.906 230.744ZM839.343 232.792C838.767 233.016 838.122 233.128 837.407 233.128C836.501 233.128 835.829 232.915 835.391 232.488C834.965 232.061 834.751 231.4 834.751 230.504V226.552H833.519V225.112L834.815 224.856L835.167 222.616H837.087V224.824H839.295V226.552H837.087V230.392C837.087 230.733 837.173 230.973 837.343 231.112C837.514 231.251 837.802 231.32 838.207 231.32C838.538 231.32 838.917 231.288 839.343 231.224V232.792ZM840.696 233V224.824H842.616L842.904 226.04C843.331 225.571 843.731 225.24 844.104 225.048C844.488 224.845 844.894 224.744 845.32 224.744C845.523 224.744 845.736 224.76 845.96 224.792V226.952C845.662 226.888 845.331 226.856 844.968 226.856C844.275 226.856 843.63 226.979 843.032 227.224V233H840.696ZM852.541 233L852.317 232.136C851.367 232.872 850.375 233.24 849.341 233.24C848.615 233.24 848.05 233.027 847.645 232.6C847.239 232.163 847.037 231.565 847.037 230.808V224.824H849.373V230.152C849.373 231.016 849.746 231.448 850.493 231.448C851.047 231.448 851.591 231.277 852.125 230.936V224.824H854.461V233H852.541ZM862.518 232.648C862.23 232.819 861.884 232.947 861.478 233.032C861.073 233.128 860.652 233.176 860.214 233.176C858.913 233.176 857.916 232.813 857.222 232.088C856.54 231.363 856.198 230.317 856.198 228.952C856.198 227.597 856.561 226.541 857.286 225.784C858.012 225.027 859.02 224.648 860.31 224.648C861.089 224.648 861.809 224.819 862.47 225.16V226.712C861.841 226.531 861.265 226.44 860.742 226.44C859.996 226.44 859.446 226.632 859.094 227.016C858.742 227.389 858.566 227.987 858.566 228.808V229.032C858.566 229.843 858.737 230.44 859.078 230.824C859.43 231.197 859.969 231.384 860.694 231.384C861.217 231.384 861.825 231.288 862.518 231.096V232.648ZM869.273 232.792C868.697 233.016 868.052 233.128 867.337 233.128C866.431 233.128 865.759 232.915 865.321 232.488C864.895 232.061 864.681 231.4 864.681 230.504V226.552H863.449V225.112L864.745 224.856L865.097 222.616H867.017V224.824H869.225V226.552H867.017V230.392C867.017 230.733 867.103 230.973 867.273 231.112C867.444 231.251 867.732 231.32 868.137 231.32C868.468 231.32 868.847 231.288 869.273 231.224V232.792Z" fill="white"/> -<rect x="737" y="293" width="193" height="46" rx="5" fill="#0972D3"/> -<rect x="737" y="293" width="193" height="46" rx="5" stroke="#000716" stroke-width="2"/> -<path d="M807.973 317.952V322H805.637V310.912H809.877C811.029 310.912 811.941 311.227 812.613 311.856C813.285 312.485 813.621 313.344 813.621 314.432C813.621 315.52 813.285 316.379 812.613 317.008C811.941 317.637 811.029 317.952 809.877 317.952H807.973ZM807.973 316.16H809.605C810.139 316.16 810.544 316.016 810.821 315.728C811.109 315.429 811.253 314.997 811.253 314.432C811.253 313.867 811.109 313.44 810.821 313.152C810.544 312.853 810.139 312.704 809.605 312.704H807.973V316.16ZM815.303 322V313.824H817.223L817.511 315.04C817.938 314.571 818.338 314.24 818.711 314.048C819.095 313.845 819.501 313.744 819.927 313.744C820.13 313.744 820.343 313.76 820.567 313.792V315.952C820.269 315.888 819.938 315.856 819.575 315.856C818.882 315.856 818.237 315.979 817.639 316.224V322H815.303ZM823.452 318.48C823.494 319.184 823.708 319.696 824.092 320.016C824.476 320.325 825.078 320.48 825.9 320.48C826.614 320.48 827.446 320.347 828.396 320.08V321.632C828.022 321.824 827.574 321.973 827.052 322.08C826.54 322.187 826.006 322.24 825.452 322.24C824.097 322.24 823.062 321.872 822.348 321.136C821.644 320.4 821.292 319.323 821.292 317.904C821.292 316.539 821.644 315.477 822.348 314.72C823.052 313.963 824.028 313.584 825.276 313.584C826.332 313.584 827.142 313.877 827.708 314.464C828.284 315.04 828.572 315.867 828.572 316.944C828.572 317.179 828.556 317.445 828.524 317.744C828.492 318.043 828.454 318.288 828.412 318.48H823.452ZM825.196 315.2C824.673 315.2 824.257 315.36 823.948 315.68C823.649 315.989 823.478 316.443 823.436 317.04H826.572V316.768C826.572 315.723 826.113 315.2 825.196 315.2ZM830.284 325.296V313.824H832.204L832.396 314.592C832.716 314.283 833.1 314.037 833.548 313.856C834.007 313.675 834.471 313.584 834.94 313.584C835.975 313.584 836.791 313.963 837.388 314.72C837.996 315.477 838.3 316.501 838.3 317.792C838.3 318.635 838.161 319.387 837.884 320.048C837.607 320.709 837.207 321.232 836.684 321.616C836.161 321.989 835.559 322.176 834.876 322.176C834.439 322.176 834.023 322.107 833.628 321.968C833.233 321.829 832.897 321.637 832.62 321.392V325.296H830.284ZM834.188 315.344C833.633 315.344 833.111 315.488 832.62 315.776V319.984C833.089 320.272 833.612 320.416 834.188 320.416C834.785 320.416 835.223 320.213 835.5 319.808C835.788 319.403 835.932 318.763 835.932 317.888C835.932 317.003 835.793 316.357 835.516 315.952C835.239 315.547 834.796 315.344 834.188 315.344ZM844.736 322L844.544 321.28C844.213 321.579 843.829 321.819 843.392 322C842.965 322.171 842.549 322.256 842.144 322.256C841.354 322.256 840.72 322.032 840.24 321.584C839.77 321.136 839.536 320.539 839.536 319.792C839.536 319.28 839.664 318.832 839.92 318.448C840.176 318.053 840.544 317.744 841.024 317.52C841.504 317.296 842.069 317.184 842.72 317.184C843.232 317.184 843.797 317.253 844.416 317.392V316.592C844.416 316.101 844.314 315.765 844.112 315.584C843.909 315.403 843.536 315.312 842.992 315.312C842.117 315.312 841.152 315.477 840.096 315.808V314.256C840.49 314.053 840.986 313.893 841.584 313.776C842.181 313.648 842.789 313.584 843.408 313.584C844.506 313.584 845.306 313.808 845.808 314.256C846.32 314.693 846.576 315.387 846.576 316.336V322H844.736ZM842.8 320.688C843.066 320.688 843.338 320.629 843.616 320.512C843.904 320.395 844.17 320.235 844.416 320.032V318.64C843.946 318.565 843.525 318.528 843.152 318.528C842.224 318.528 841.76 318.901 841.76 319.648C841.76 319.979 841.85 320.235 842.032 320.416C842.213 320.597 842.469 320.688 842.8 320.688ZM848.702 322V313.824H850.622L850.91 315.04C851.337 314.571 851.737 314.24 852.11 314.048C852.494 313.845 852.9 313.744 853.326 313.744C853.529 313.744 853.742 313.76 853.966 313.792V315.952C853.668 315.888 853.337 315.856 852.974 315.856C852.281 315.856 851.636 315.979 851.038 316.224V322H848.702ZM856.851 318.48C856.893 319.184 857.107 319.696 857.491 320.016C857.875 320.325 858.477 320.48 859.299 320.48C860.013 320.48 860.845 320.347 861.795 320.08V321.632C861.421 321.824 860.973 321.973 860.451 322.08C859.939 322.187 859.405 322.24 858.851 322.24C857.496 322.24 856.461 321.872 855.747 321.136C855.043 320.4 854.691 319.323 854.691 317.904C854.691 316.539 855.043 315.477 855.747 314.72C856.451 313.963 857.427 313.584 858.675 313.584C859.731 313.584 860.541 313.877 861.107 314.464C861.683 315.04 861.971 315.867 861.971 316.944C861.971 317.179 861.955 317.445 861.923 317.744C861.891 318.043 861.853 318.288 861.811 318.48H856.851ZM858.595 315.2C858.072 315.2 857.656 315.36 857.347 315.68C857.048 315.989 856.877 316.443 856.835 317.04H859.971V316.768C859.971 315.723 859.512 315.2 858.595 315.2Z" fill="white"/> -<rect x="737" y="382" width="193" height="46" rx="5" fill="#0972D3"/> -<rect x="737" y="382" width="193" height="46" rx="5" stroke="#000716" stroke-width="2"/> -<path d="M806.687 411L802.751 399.912H805.407L807.999 408.648L810.575 399.912H813.167L809.231 411H806.687ZM818.508 411L818.316 410.28C817.985 410.579 817.601 410.819 817.164 411C816.737 411.171 816.321 411.256 815.916 411.256C815.127 411.256 814.492 411.032 814.012 410.584C813.543 410.136 813.308 409.539 813.308 408.792C813.308 408.28 813.436 407.832 813.692 407.448C813.948 407.053 814.316 406.744 814.796 406.52C815.276 406.296 815.841 406.184 816.492 406.184C817.004 406.184 817.569 406.253 818.188 406.392V405.592C818.188 405.101 818.087 404.765 817.884 404.584C817.681 404.403 817.308 404.312 816.764 404.312C815.889 404.312 814.924 404.477 813.868 404.808V403.256C814.263 403.053 814.759 402.893 815.356 402.776C815.953 402.648 816.561 402.584 817.18 402.584C818.279 402.584 819.079 402.808 819.58 403.256C820.092 403.693 820.348 404.387 820.348 405.336V411H818.508ZM816.572 409.688C816.839 409.688 817.111 409.629 817.388 409.512C817.676 409.395 817.943 409.235 818.188 409.032V407.64C817.719 407.565 817.297 407.528 816.924 407.528C815.996 407.528 815.532 407.901 815.532 408.648C815.532 408.979 815.623 409.235 815.804 409.416C815.985 409.597 816.241 409.688 816.572 409.688ZM826.074 410.84C825.626 411.021 825.146 411.112 824.634 411.112C823.194 411.112 822.474 410.307 822.474 408.696V399.16H824.81V408.504C824.81 408.803 824.858 409.016 824.954 409.144C825.061 409.261 825.232 409.32 825.466 409.32C825.616 409.32 825.818 409.304 826.074 409.272V410.84ZM827.662 411V402.824H829.998V411H827.662ZM828.83 401.56C828.424 401.56 828.099 401.448 827.854 401.224C827.608 401 827.486 400.696 827.486 400.312C827.486 399.928 827.608 399.624 827.854 399.4C828.099 399.176 828.424 399.064 828.83 399.064C829.235 399.064 829.56 399.176 829.806 399.4C830.051 399.624 830.174 399.928 830.174 400.312C830.174 400.696 830.051 401 829.806 401.224C829.56 401.448 829.235 401.56 828.83 401.56ZM837.741 411L837.549 410.28C836.887 410.877 836.103 411.176 835.197 411.176C834.525 411.176 833.933 411.011 833.421 410.68C832.909 410.339 832.509 409.848 832.221 409.208C831.943 408.568 831.805 407.816 831.805 406.952C831.805 405.629 832.119 404.573 832.749 403.784C833.378 402.984 834.21 402.584 835.245 402.584C836.087 402.584 836.818 402.824 837.437 403.304V399.16H839.773V411H837.741ZM835.965 409.416C836.477 409.416 836.967 409.267 837.437 408.968V404.744C836.978 404.477 836.45 404.344 835.853 404.344C835.287 404.344 834.866 404.557 834.589 404.984C834.311 405.4 834.173 406.035 834.173 406.888C834.173 407.741 834.317 408.376 834.605 408.792C834.903 409.208 835.357 409.416 835.965 409.416ZM846.625 411L846.433 410.28C846.103 410.579 845.719 410.819 845.281 411C844.855 411.171 844.439 411.256 844.033 411.256C843.244 411.256 842.609 411.032 842.129 410.584C841.66 410.136 841.425 409.539 841.425 408.792C841.425 408.28 841.553 407.832 841.809 407.448C842.065 407.053 842.433 406.744 842.913 406.52C843.393 406.296 843.959 406.184 844.609 406.184C845.121 406.184 845.687 406.253 846.305 406.392V405.592C846.305 405.101 846.204 404.765 846.001 404.584C845.799 404.403 845.425 404.312 844.881 404.312C844.007 404.312 843.041 404.477 841.985 404.808V403.256C842.38 403.053 842.876 402.893 843.473 402.776C844.071 402.648 844.679 402.584 845.297 402.584C846.396 402.584 847.196 402.808 847.697 403.256C848.209 403.693 848.465 404.387 848.465 405.336V411H846.625ZM844.689 409.688C844.956 409.688 845.228 409.629 845.505 409.512C845.793 409.395 846.06 409.235 846.305 409.032V407.64C845.836 407.565 845.415 407.528 845.041 407.528C844.113 407.528 843.649 407.901 843.649 408.648C843.649 408.979 843.74 409.235 843.921 409.416C844.103 409.597 844.359 409.688 844.689 409.688ZM855.456 410.792C854.88 411.016 854.235 411.128 853.52 411.128C852.613 411.128 851.941 410.915 851.504 410.488C851.077 410.061 850.864 409.4 850.864 408.504V404.552H849.632V403.112L850.928 402.856L851.28 400.616H853.2V402.824H855.408V404.552H853.2V408.392C853.2 408.733 853.285 408.973 853.456 409.112C853.627 409.251 853.915 409.32 854.32 409.32C854.651 409.32 855.029 409.288 855.456 409.224V410.792ZM858.553 407.48C858.595 408.184 858.809 408.696 859.193 409.016C859.577 409.325 860.179 409.48 861.001 409.48C861.715 409.48 862.547 409.347 863.497 409.08V410.632C863.123 410.824 862.675 410.973 862.153 411.08C861.641 411.187 861.107 411.24 860.553 411.24C859.198 411.24 858.163 410.872 857.449 410.136C856.745 409.4 856.393 408.323 856.393 406.904C856.393 405.539 856.745 404.477 857.449 403.72C858.153 402.963 859.129 402.584 860.377 402.584C861.433 402.584 862.243 402.877 862.809 403.464C863.385 404.04 863.673 404.867 863.673 405.944C863.673 406.179 863.657 406.445 863.625 406.744C863.593 407.043 863.555 407.288 863.513 407.48H858.553ZM860.297 404.2C859.774 404.2 859.358 404.36 859.049 404.68C858.75 404.989 858.579 405.443 858.537 406.04H861.673V405.768C861.673 404.723 861.214 404.2 860.297 404.2Z" fill="white"/> -<rect x="737" y="471" width="193" height="46" rx="5" fill="#0972D3"/> -<rect x="737" y="471" width="193" height="46" rx="5" stroke="#000716" stroke-width="2"/> -<path d="M796.948 495.152C795.999 494.8 795.316 494.373 794.9 493.872C794.484 493.36 794.276 492.715 794.276 491.936C794.276 490.933 794.644 490.133 795.38 489.536C796.127 488.939 797.124 488.64 798.372 488.64C799.418 488.64 800.442 488.832 801.444 489.216V491.04C800.41 490.72 799.45 490.56 798.564 490.56C797.306 490.56 796.676 490.965 796.676 491.776C796.676 492.075 796.783 492.32 796.996 492.512C797.22 492.704 797.631 492.907 798.228 493.12L799.412 493.552C800.404 493.915 801.108 494.341 801.524 494.832C801.951 495.312 802.164 495.941 802.164 496.72C802.164 497.819 801.77 498.688 800.98 499.328C800.191 499.957 799.108 500.272 797.732 500.272C797.135 500.272 796.538 500.213 795.94 500.096C795.343 499.989 794.831 499.84 794.404 499.648V497.824C794.938 497.984 795.508 498.112 796.116 498.208C796.724 498.304 797.274 498.352 797.764 498.352C798.394 498.352 798.879 498.24 799.22 498.016C799.562 497.781 799.732 497.451 799.732 497.024C799.732 496.693 799.626 496.432 799.412 496.24C799.21 496.048 798.794 495.835 798.164 495.6L796.948 495.152ZM806.084 500.128L802.852 491.824H805.332L807.156 497.936L808.884 491.824H811.3L807.844 501.104C807.534 501.947 807.156 502.555 806.708 502.928C806.26 503.301 805.694 503.488 805.012 503.488C804.478 503.488 803.961 503.403 803.46 503.232V501.648C803.801 501.68 804.105 501.696 804.372 501.696C804.82 501.696 805.166 501.589 805.412 501.376C805.657 501.173 805.865 500.816 806.036 500.304L806.084 500.128ZM817.654 500V494.64C817.654 494.203 817.558 493.883 817.366 493.68C817.174 493.477 816.881 493.376 816.486 493.376C815.899 493.376 815.318 493.557 814.742 493.92V500H812.406V491.824H814.326L814.55 492.704C815.51 491.957 816.534 491.584 817.622 491.584C818.379 491.584 818.961 491.792 819.366 492.208C819.782 492.613 819.99 493.195 819.99 493.952V500H817.654ZM826.987 499.792C826.411 500.016 825.765 500.128 825.051 500.128C824.144 500.128 823.472 499.915 823.035 499.488C822.608 499.061 822.395 498.4 822.395 497.504V493.552H821.163V492.112L822.459 491.856L822.811 489.616H824.731V491.824H826.939V493.552H824.731V497.392C824.731 497.733 824.816 497.973 824.987 498.112C825.157 498.251 825.445 498.32 825.851 498.32C826.181 498.32 826.56 498.288 826.987 498.224V499.792ZM833.588 500V494.64C833.588 494.203 833.492 493.883 833.3 493.68C833.108 493.477 832.814 493.376 832.42 493.376C831.833 493.376 831.252 493.557 830.676 493.92V500H828.34V488.16H830.676V492.56C831.593 491.909 832.553 491.584 833.556 491.584C834.313 491.584 834.894 491.792 835.3 492.208C835.716 492.613 835.924 493.195 835.924 493.952V500H833.588ZM839.801 496.48C839.843 497.184 840.057 497.696 840.441 498.016C840.825 498.325 841.427 498.48 842.249 498.48C842.963 498.48 843.795 498.347 844.745 498.08V499.632C844.371 499.824 843.923 499.973 843.401 500.08C842.889 500.187 842.355 500.24 841.801 500.24C840.446 500.24 839.411 499.872 838.697 499.136C837.993 498.4 837.641 497.323 837.641 495.904C837.641 494.539 837.993 493.477 838.697 492.72C839.401 491.963 840.377 491.584 841.625 491.584C842.681 491.584 843.491 491.877 844.057 492.464C844.633 493.04 844.921 493.867 844.921 494.944C844.921 495.179 844.905 495.445 844.873 495.744C844.841 496.043 844.803 496.288 844.761 496.48H839.801ZM841.545 493.2C841.022 493.2 840.606 493.36 840.297 493.68C839.998 493.989 839.827 494.443 839.785 495.04H842.921V494.768C842.921 493.723 842.462 493.2 841.545 493.2ZM850.105 497.744C850.105 497.531 850.041 497.365 849.913 497.248C849.795 497.131 849.55 497.003 849.177 496.864L847.929 496.368C847.278 496.112 846.809 495.797 846.521 495.424C846.233 495.051 846.089 494.576 846.089 494C846.089 493.275 846.377 492.693 846.953 492.256C847.539 491.808 848.318 491.584 849.289 491.584C850.185 491.584 851.011 491.76 851.769 492.112V493.664C850.958 493.419 850.201 493.296 849.497 493.296C849.059 493.296 848.739 493.349 848.537 493.456C848.334 493.563 848.233 493.733 848.233 493.968C848.233 494.149 848.291 494.299 848.409 494.416C848.537 494.523 848.798 494.656 849.193 494.816L850.409 495.312C851.07 495.579 851.539 495.888 851.817 496.24C852.105 496.592 852.249 497.051 852.249 497.616C852.249 498.405 851.945 499.045 851.337 499.536C850.739 500.016 849.95 500.256 848.969 500.256C847.87 500.256 846.899 500.037 846.057 499.6V498.048C847.113 498.379 848.078 498.544 848.953 498.544C849.721 498.544 850.105 498.277 850.105 497.744ZM853.742 500V491.824H856.078V500H853.742ZM854.91 490.56C854.504 490.56 854.179 490.448 853.934 490.224C853.688 490 853.566 489.696 853.566 489.312C853.566 488.928 853.688 488.624 853.934 488.4C854.179 488.176 854.504 488.064 854.91 488.064C855.315 488.064 855.64 488.176 855.886 488.4C856.131 488.624 856.254 488.928 856.254 489.312C856.254 489.696 856.131 490 855.886 490.224C855.64 490.448 855.315 490.56 854.91 490.56ZM857.693 500V498.336L861.901 493.552H857.853V491.824H864.477V493.488L860.221 498.272H864.557V500H857.693ZM867.699 496.48C867.742 497.184 867.955 497.696 868.339 498.016C868.723 498.325 869.326 498.48 870.147 498.48C870.862 498.48 871.694 498.347 872.643 498.08V499.632C872.27 499.824 871.822 499.973 871.299 500.08C870.787 500.187 870.254 500.24 869.699 500.24C868.345 500.24 867.31 499.872 866.595 499.136C865.891 498.4 865.539 497.323 865.539 495.904C865.539 494.539 865.891 493.477 866.595 492.72C867.299 491.963 868.275 491.584 869.523 491.584C870.579 491.584 871.39 491.877 871.955 492.464C872.531 493.04 872.819 493.867 872.819 494.944C872.819 495.179 872.803 495.445 872.771 495.744C872.739 496.043 872.702 496.288 872.659 496.48H867.699ZM869.443 493.2C868.921 493.2 868.505 493.36 868.195 493.68C867.897 493.989 867.726 494.443 867.683 495.04H870.819V494.768C870.819 493.723 870.361 493.2 869.443 493.2Z" fill="white"/> -<path d="M833.293 202.707C833.683 203.098 834.317 203.098 834.707 202.707L841.071 196.343C841.462 195.953 841.462 195.319 841.071 194.929C840.681 194.538 840.047 194.538 839.657 194.929L834 200.586L828.343 194.929C827.953 194.538 827.319 194.538 826.929 194.929C826.538 195.319 826.538 195.953 826.929 196.343L833.293 202.707ZM833 162V202H835V162H833Z" fill="black"/> -<path d="M832.293 291.707C832.683 292.098 833.317 292.098 833.707 291.707L840.071 285.343C840.462 284.953 840.462 284.319 840.071 283.929C839.681 283.538 839.047 283.538 838.657 283.929L833 289.586L827.343 283.929C826.953 283.538 826.319 283.538 825.929 283.929C825.538 284.319 825.538 284.953 825.929 285.343L832.293 291.707ZM832 251V291H834V251H832Z" fill="black"/> -<path d="M832.293 380.707C832.683 381.098 833.317 381.098 833.707 380.707L840.071 374.343C840.462 373.953 840.462 373.319 840.071 372.929C839.681 372.538 839.047 372.538 838.657 372.929L833 378.586L827.343 372.929C826.953 372.538 826.319 372.538 825.929 372.929C825.538 373.319 825.538 373.953 825.929 374.343L832.293 380.707ZM832 340V380H834V340H832Z" fill="black"/> -<path d="M832.293 469.707C832.683 470.098 833.317 470.098 833.707 469.707L840.071 463.343C840.462 462.953 840.462 462.319 840.071 461.929C839.681 461.538 839.047 461.538 838.657 461.929L833 467.586L827.343 461.929C826.953 461.538 826.319 461.538 825.929 461.929C825.538 462.319 825.538 462.953 825.929 463.343L832.293 469.707ZM832 429V469H834V429H832Z" fill="black"/> -<path d="M1009.71 494.707C1010.1 494.317 1010.1 493.683 1009.71 493.293L1003.34 486.929C1002.95 486.538 1002.32 486.538 1001.93 486.929C1001.54 487.319 1001.54 487.953 1001.93 488.343L1007.59 494L1001.93 499.657C1001.54 500.047 1001.54 500.681 1001.93 501.071C1002.32 501.462 1002.95 501.462 1003.34 501.071L1009.71 494.707ZM929 495H1009V493H929V495Z" fill="black"/> -<rect x="14" y="16" width="1453" height="548" rx="19" stroke="black" stroke-width="2"/> -</svg> diff --git a/v2/guide/deploy/images/default-deploy-process_cdk_flowchart.png b/v2/guide/deploy/images/default-deploy-process_cdk_flowchart.png deleted file mode 100644 index a6df0d61..00000000 Binary files a/v2/guide/deploy/images/default-deploy-process_cdk_flowchart.png and /dev/null differ diff --git a/v2/guide/deploy/images/default-deploy-process_cdk_flowchart.svg b/v2/guide/deploy/images/default-deploy-process_cdk_flowchart.svg deleted file mode 100644 index b1aea874..00000000 --- a/v2/guide/deploy/images/default-deploy-process_cdk_flowchart.svg +++ /dev/null @@ -1,97 +0,0 @@ -<svg width="1761" height="452" viewBox="0 0 1761 452" fill="none" xmlns="http://www.w3.org/2000/svg"> -<rect width="1761" height="452" fill="white"/> -<rect x="11" y="11" width="1739" height="430" rx="19" stroke="black" stroke-width="2"/> -<path d="M312 111L312 110L311 110L39 110L38 110L38 111L38 405C38 411.075 42.9249 416 49 416L301 416C307.075 416 312 411.075 312 405L312 111Z" fill="white" stroke="#000716" stroke-width="2"/> -<path d="M1448 111L1448 110L1447 110L313 110L312 110L312 111L312 405C312 411.075 316.925 416 323 416L1437 416C1443.08 416 1448 411.075 1448 405L1448 111Z" fill="white" stroke="#000716" stroke-width="2"/> -<path d="M1725 109L1725 108L1724 108L1449 108L1448 108L1448 109L1448 405C1448 411.075 1452.92 416 1459 416L1714 416C1720.08 416 1725 411.075 1725 405L1725 109Z" fill="white" stroke="#000716" stroke-width="2"/> -<mask id="path-5-outside-1_11_373" maskUnits="userSpaceOnUse" x="310" y="37" width="1139" height="74" fill="black"> -<rect fill="white" x="310" y="37" width="1139" height="74"/> -<path d="M312 49C312 43.4772 316.477 39 322 39L1437 39C1442.52 39 1447 43.4771 1447 49L1447 109L312 109L312 49Z"/> -</mask> -<path d="M312 49C312 43.4772 316.477 39 322 39L1437 39C1442.52 39 1447 43.4771 1447 49L1447 109L312 109L312 49Z" fill="#033160"/> -<path d="M1447 109L1447 111L1449 111L1449 109L1447 109ZM312 109L310 109L310 111L312 111L312 109ZM322 41L1437 41L1437 37L322 37L322 41ZM1445 49L1445 109L1449 109L1449 49L1445 49ZM1447 107L312 107L312 111L1447 111L1447 107ZM314 109L314 49L310 49L310 109L314 109ZM1437 41C1441.42 41 1445 44.5817 1445 49L1449 49C1449 42.3726 1443.63 37 1437 37L1437 41ZM322 37C315.373 37 310 42.3726 310 49L314 49C314 44.5817 317.582 41 322 41L322 37Z" fill="#000716" mask="url(#path-5-outside-1_11_373)"/> -<path d="M766.665 76.446L766.665 81L764.037 81L764.037 68.526L768.807 68.526C770.103 68.526 771.129 68.88 771.885 69.588C772.641 70.296 773.019 71.262 773.019 72.486C773.019 73.71 772.641 74.676 771.885 75.384C771.129 76.092 770.103 76.446 768.807 76.446L766.665 76.446ZM766.665 74.43L768.501 74.43C769.101 74.43 769.557 74.268 769.869 73.944C770.193 73.608 770.355 73.122 770.355 72.486C770.355 71.85 770.193 71.37 769.869 71.046C769.557 70.71 769.101 70.542 768.501 70.542L766.665 70.542L766.665 74.43ZM776.787 77.04C776.835 77.832 777.075 78.408 777.507 78.768C777.939 79.116 778.617 79.29 779.541 79.29C780.345 79.29 781.281 79.14 782.349 78.84L782.349 80.586C781.929 80.802 781.425 80.97 780.837 81.09C780.261 81.21 779.661 81.27 779.037 81.27C777.513 81.27 776.349 80.856 775.545 80.028C774.753 79.2 774.357 77.988 774.357 76.392C774.357 74.856 774.753 73.662 775.545 72.81C776.337 71.958 777.435 71.532 778.839 71.532C780.027 71.532 780.939 71.862 781.575 72.522C782.223 73.17 782.547 74.1 782.547 75.312C782.547 75.576 782.529 75.876 782.493 76.212C782.457 76.548 782.415 76.824 782.367 77.04L776.787 77.04ZM778.749 73.35C778.161 73.35 777.693 73.53 777.345 73.89C777.009 74.238 776.817 74.748 776.769 75.42L780.297 75.42L780.297 75.114C780.297 73.938 779.781 73.35 778.749 73.35ZM784.564 81L784.564 71.802L786.724 71.802L787.048 73.17C787.528 72.642 787.978 72.27 788.398 72.054C788.83 71.826 789.286 71.712 789.766 71.712C789.994 71.712 790.234 71.73 790.486 71.766L790.486 74.196C790.15 74.124 789.778 74.088 789.37 74.088C788.59 74.088 787.864 74.226 787.192 74.502L787.192 81L784.564 81ZM803.253 81L803.253 74.772C803.253 73.956 802.887 73.548 802.155 73.548C801.507 73.548 800.853 73.704 800.193 74.016L800.193 74.196L800.193 81L797.565 81L797.565 74.772C797.565 73.956 797.199 73.548 796.467 73.548C795.795 73.548 795.135 73.71 794.487 74.034L794.487 81L791.859 81L791.859 71.802L794.019 71.802L794.253 72.684C794.889 72.264 795.459 71.97 795.963 71.802C796.479 71.622 797.007 71.532 797.547 71.532C798.627 71.532 799.389 71.916 799.833 72.684C800.445 72.276 801.021 71.982 801.561 71.802C802.101 71.622 802.659 71.532 803.235 71.532C804.075 71.532 804.723 71.766 805.179 72.234C805.647 72.702 805.881 73.356 805.881 74.196L805.881 81L803.253 81ZM808.436 81L808.436 71.802L811.064 71.802L811.064 81L808.436 81ZM809.75 70.38C809.294 70.38 808.928 70.254 808.652 70.002C808.376 69.75 808.238 69.408 808.238 68.976C808.238 68.544 808.376 68.202 808.652 67.95C808.928 67.698 809.294 67.572 809.75 67.572C810.206 67.572 810.572 67.698 810.848 67.95C811.124 68.202 811.262 68.544 811.262 68.976C811.262 69.408 811.124 69.75 810.848 70.002C810.572 70.254 810.206 70.38 809.75 70.38ZM817.562 78.462C817.562 78.222 817.49 78.036 817.346 77.904C817.214 77.772 816.938 77.628 816.518 77.472L815.114 76.914C814.382 76.626 813.854 76.272 813.53 75.852C813.206 75.432 813.044 74.898 813.044 74.25C813.044 73.434 813.368 72.78 814.016 72.288C814.676 71.784 815.552 71.532 816.644 71.532C817.652 71.532 818.582 71.73 819.434 72.126L819.434 73.872C818.522 73.596 817.67 73.458 816.878 73.458C816.386 73.458 816.026 73.518 815.798 73.638C815.57 73.758 815.456 73.95 815.456 74.214C815.456 74.418 815.522 74.586 815.654 74.718C815.798 74.838 816.092 74.988 816.536 75.168L817.904 75.726C818.648 76.026 819.176 76.374 819.488 76.77C819.812 77.166 819.974 77.682 819.974 78.318C819.974 79.206 819.632 79.926 818.948 80.478C818.276 81.018 817.388 81.288 816.284 81.288C815.048 81.288 813.956 81.042 813.008 80.55L813.008 78.804C814.196 79.176 815.282 79.362 816.266 79.362C817.13 79.362 817.562 79.062 817.562 78.462ZM825.577 78.462C825.577 78.222 825.505 78.036 825.361 77.904C825.229 77.772 824.953 77.628 824.533 77.472L823.129 76.914C822.397 76.626 821.869 76.272 821.545 75.852C821.221 75.432 821.059 74.898 821.059 74.25C821.059 73.434 821.383 72.78 822.031 72.288C822.691 71.784 823.567 71.532 824.659 71.532C825.667 71.532 826.597 71.73 827.449 72.126L827.449 73.872C826.537 73.596 825.685 73.458 824.893 73.458C824.401 73.458 824.041 73.518 823.813 73.638C823.585 73.758 823.471 73.95 823.471 74.214C823.471 74.418 823.537 74.586 823.669 74.718C823.813 74.838 824.107 74.988 824.551 75.168L825.919 75.726C826.663 76.026 827.191 76.374 827.503 76.77C827.827 77.166 827.989 77.682 827.989 78.318C827.989 79.206 827.647 79.926 826.963 80.478C826.291 81.018 825.403 81.288 824.299 81.288C823.063 81.288 821.971 81.042 821.023 80.55L821.023 78.804C822.211 79.176 823.297 79.362 824.281 79.362C825.145 79.362 825.577 79.062 825.577 78.462ZM829.759 81L829.759 71.802L832.387 71.802L832.387 81L829.759 81ZM831.073 70.38C830.617 70.38 830.251 70.254 829.975 70.002C829.699 69.75 829.561 69.408 829.561 68.976C829.561 68.544 829.699 68.202 829.975 67.95C830.251 67.698 830.617 67.572 831.073 67.572C831.529 67.572 831.895 67.698 832.171 67.95C832.447 68.202 832.585 68.544 832.585 68.976C832.585 69.408 832.447 69.75 832.171 70.002C831.895 70.254 831.529 70.38 831.073 70.38ZM839.064 81.27C837.636 81.27 836.52 80.844 835.716 79.992C834.912 79.128 834.51 77.928 834.51 76.392C834.51 74.868 834.912 73.68 835.716 72.828C836.52 71.964 837.636 71.532 839.064 71.532C840.492 71.532 841.608 71.964 842.412 72.828C843.216 73.68 843.618 74.868 843.618 76.392C843.618 77.928 843.216 79.128 842.412 79.992C841.608 80.844 840.492 81.27 839.064 81.27ZM839.064 79.254C840.324 79.254 840.954 78.3 840.954 76.392C840.954 74.496 840.324 73.548 839.064 73.548C837.804 73.548 837.174 74.496 837.174 76.392C837.174 78.3 837.804 79.254 839.064 79.254ZM851.569 81L851.569 74.97C851.569 74.478 851.461 74.118 851.245 73.89C851.029 73.662 850.699 73.548 850.255 73.548C849.595 73.548 848.941 73.752 848.293 74.16L848.293 81L845.665 81L845.665 71.802L847.825 71.802L848.077 72.792C849.157 71.952 850.309 71.532 851.533 71.532C852.385 71.532 853.039 71.766 853.495 72.234C853.963 72.69 854.197 73.344 854.197 74.196L854.197 81L851.569 81ZM860.593 78.462C860.593 78.222 860.521 78.036 860.377 77.904C860.245 77.772 859.969 77.628 859.549 77.472L858.145 76.914C857.413 76.626 856.885 76.272 856.561 75.852C856.237 75.432 856.075 74.898 856.075 74.25C856.075 73.434 856.399 72.78 857.047 72.288C857.707 71.784 858.583 71.532 859.675 71.532C860.683 71.532 861.613 71.73 862.465 72.126L862.465 73.872C861.553 73.596 860.701 73.458 859.909 73.458C859.417 73.458 859.057 73.518 858.829 73.638C858.601 73.758 858.487 73.95 858.487 74.214C858.487 74.418 858.553 74.586 858.685 74.718C858.829 74.838 859.123 74.988 859.567 75.168L860.935 75.726C861.679 76.026 862.207 76.374 862.519 76.77C862.843 77.166 863.005 77.682 863.005 78.318C863.005 79.206 862.663 79.926 861.979 80.478C861.307 81.018 860.419 81.288 859.315 81.288C858.079 81.288 856.987 81.042 856.039 80.55L856.039 78.804C857.227 79.176 858.313 79.362 859.297 79.362C860.161 79.362 860.593 79.062 860.593 78.462ZM874.687 81L874.471 80.19C874.099 80.526 873.667 80.796 873.175 81C872.695 81.192 872.227 81.288 871.771 81.288C870.883 81.288 870.169 81.036 869.629 80.532C869.101 80.028 868.837 79.356 868.837 78.516C868.837 77.94 868.981 77.436 869.269 77.004C869.557 76.56 869.971 76.212 870.511 75.96C871.051 75.708 871.687 75.582 872.419 75.582C872.995 75.582 873.631 75.66 874.327 75.816L874.327 74.916C874.327 74.364 874.213 73.986 873.985 73.782C873.757 73.578 873.337 73.476 872.725 73.476C871.741 73.476 870.655 73.662 869.467 74.034L869.467 72.288C869.911 72.06 870.469 71.88 871.141 71.748C871.813 71.604 872.497 71.532 873.193 71.532C874.429 71.532 875.329 71.784 875.893 72.288C876.469 72.78 876.757 73.56 876.757 74.628L876.757 81L874.687 81ZM872.509 79.524C872.809 79.524 873.115 79.458 873.427 79.326C873.751 79.194 874.051 79.014 874.327 78.786L874.327 77.22C873.799 77.136 873.325 77.094 872.905 77.094C871.861 77.094 871.339 77.514 871.339 78.354C871.339 78.726 871.441 79.014 871.645 79.218C871.849 79.422 872.137 79.524 872.509 79.524ZM879.239 81L879.239 71.802L881.399 71.802L881.723 73.17C882.203 72.642 882.653 72.27 883.073 72.054C883.505 71.826 883.961 71.712 884.441 71.712C884.669 71.712 884.909 71.73 885.161 71.766L885.161 74.196C884.825 74.124 884.453 74.088 884.045 74.088C883.265 74.088 882.539 74.226 881.867 74.502L881.867 81L879.239 81ZM888.496 77.04C888.544 77.832 888.784 78.408 889.216 78.768C889.648 79.116 890.326 79.29 891.25 79.29C892.054 79.29 892.99 79.14 894.058 78.84L894.058 80.586C893.638 80.802 893.134 80.97 892.546 81.09C891.97 81.21 891.37 81.27 890.746 81.27C889.222 81.27 888.058 80.856 887.254 80.028C886.462 79.2 886.066 77.988 886.066 76.392C886.066 74.856 886.462 73.662 887.254 72.81C888.046 71.958 889.144 71.532 890.548 71.532C891.736 71.532 892.648 71.862 893.284 72.522C893.932 73.17 894.256 74.1 894.256 75.312C894.256 75.576 894.238 75.876 894.202 76.212C894.166 76.548 894.124 76.824 894.076 77.04L888.496 77.04ZM890.458 73.35C889.87 73.35 889.402 73.53 889.054 73.89C888.718 74.238 888.526 74.748 888.478 75.42L892.006 75.42L892.006 75.114C892.006 73.938 891.49 73.35 890.458 73.35ZM902.946 77.04C902.994 77.832 903.234 78.408 903.666 78.768C904.098 79.116 904.776 79.29 905.7 79.29C906.504 79.29 907.44 79.14 908.508 78.84L908.508 80.586C908.088 80.802 907.584 80.97 906.996 81.09C906.42 81.21 905.82 81.27 905.196 81.27C903.672 81.27 902.508 80.856 901.704 80.028C900.912 79.2 900.516 77.988 900.516 76.392C900.516 74.856 900.912 73.662 901.704 72.81C902.496 71.958 903.594 71.532 904.998 71.532C906.186 71.532 907.098 71.862 907.734 72.522C908.382 73.17 908.706 74.1 908.706 75.312C908.706 75.576 908.688 75.876 908.652 76.212C908.616 76.548 908.574 76.824 908.526 77.04L902.946 77.04ZM904.908 73.35C904.32 73.35 903.852 73.53 903.504 73.89C903.168 74.238 902.976 74.748 902.928 75.42L906.456 75.42L906.456 75.114C906.456 73.938 905.94 73.35 904.908 73.35ZM914.628 78.462C914.628 78.222 914.556 78.036 914.412 77.904C914.28 77.772 914.004 77.628 913.584 77.472L912.18 76.914C911.448 76.626 910.92 76.272 910.596 75.852C910.272 75.432 910.11 74.898 910.11 74.25C910.11 73.434 910.434 72.78 911.082 72.288C911.742 71.784 912.618 71.532 913.71 71.532C914.718 71.532 915.648 71.73 916.5 72.126L916.5 73.872C915.588 73.596 914.736 73.458 913.944 73.458C913.452 73.458 913.092 73.518 912.864 73.638C912.636 73.758 912.522 73.95 912.522 74.214C912.522 74.418 912.588 74.586 912.72 74.718C912.864 74.838 913.158 74.988 913.602 75.168L914.97 75.726C915.714 76.026 916.242 76.374 916.554 76.77C916.878 77.166 917.04 77.682 917.04 78.318C917.04 79.206 916.698 79.926 916.014 80.478C915.342 81.018 914.454 81.288 913.35 81.288C912.114 81.288 911.022 81.042 910.074 80.55L910.074 78.804C911.262 79.176 912.348 79.362 913.332 79.362C914.196 79.362 914.628 79.062 914.628 78.462ZM924.21 80.766C923.562 81.018 922.836 81.144 922.032 81.144C921.012 81.144 920.256 80.904 919.764 80.424C919.284 79.944 919.044 79.2 919.044 78.192L919.044 73.746L917.658 73.746L917.658 72.126L919.116 71.838L919.512 69.318L921.672 69.318L921.672 71.802L924.156 71.802L924.156 73.746L921.672 73.746L921.672 78.066C921.672 78.45 921.768 78.72 921.96 78.876C922.152 79.032 922.476 79.11 922.932 79.11C923.304 79.11 923.73 79.074 924.21 79.002L924.21 80.766ZM931.096 81L930.88 80.19C930.508 80.526 930.076 80.796 929.584 81C929.104 81.192 928.636 81.288 928.18 81.288C927.292 81.288 926.578 81.036 926.038 80.532C925.51 80.028 925.246 79.356 925.246 78.516C925.246 77.94 925.39 77.436 925.678 77.004C925.966 76.56 926.38 76.212 926.92 75.96C927.46 75.708 928.096 75.582 928.828 75.582C929.404 75.582 930.04 75.66 930.736 75.816L930.736 74.916C930.736 74.364 930.622 73.986 930.394 73.782C930.166 73.578 929.746 73.476 929.134 73.476C928.15 73.476 927.064 73.662 925.876 74.034L925.876 72.288C926.32 72.06 926.878 71.88 927.55 71.748C928.222 71.604 928.906 71.532 929.602 71.532C930.838 71.532 931.738 71.784 932.302 72.288C932.878 72.78 933.166 73.56 933.166 74.628L933.166 81L931.096 81ZM928.918 79.524C929.218 79.524 929.524 79.458 929.836 79.326C930.16 79.194 930.46 79.014 930.736 78.786L930.736 77.22C930.208 77.136 929.734 77.094 929.314 77.094C928.27 77.094 927.748 77.514 927.748 78.354C927.748 78.726 927.85 79.014 928.054 79.218C928.258 79.422 928.546 79.524 928.918 79.524ZM935.648 81L935.648 67.68L938.276 67.68L938.276 72.504C938.624 72.204 939.032 71.97 939.5 71.802C939.968 71.622 940.43 71.532 940.886 71.532C942.05 71.532 942.968 71.958 943.64 72.81C944.324 73.662 944.666 74.814 944.666 76.266C944.666 77.214 944.51 78.06 944.198 78.804C943.886 79.548 943.436 80.136 942.848 80.568C942.26 80.988 941.582 81.198 940.814 81.198C940.262 81.198 939.746 81.102 939.266 80.91C938.786 80.718 938.384 80.448 938.06 80.1L937.826 81L935.648 81ZM940.04 73.512C939.416 73.512 938.828 73.674 938.276 73.998L938.276 78.732C938.804 79.056 939.392 79.218 940.04 79.218C940.712 79.218 941.204 78.99 941.516 78.534C941.84 78.078 942.002 77.358 942.002 76.374C942.002 75.378 941.846 74.652 941.534 74.196C941.222 73.74 940.724 73.512 940.04 73.512ZM950.772 80.82C950.268 81.024 949.728 81.126 949.152 81.126C947.532 81.126 946.722 80.22 946.722 78.408L946.722 67.68L949.35 67.68L949.35 78.192C949.35 78.528 949.404 78.768 949.512 78.912C949.632 79.044 949.824 79.11 950.088 79.11C950.256 79.11 950.484 79.092 950.772 79.056L950.772 80.82ZM952.647 81L952.647 71.802L955.275 71.802L955.275 81L952.647 81ZM953.961 70.38C953.505 70.38 953.139 70.254 952.863 70.002C952.587 69.75 952.449 69.408 952.449 68.976C952.449 68.544 952.587 68.202 952.863 67.95C953.139 67.698 953.505 67.572 953.961 67.572C954.417 67.572 954.783 67.698 955.059 67.95C955.335 68.202 955.473 68.544 955.473 68.976C955.473 69.408 955.335 69.75 955.059 70.002C954.783 70.254 954.417 70.38 953.961 70.38ZM961.772 78.462C961.772 78.222 961.7 78.036 961.556 77.904C961.424 77.772 961.148 77.628 960.728 77.472L959.324 76.914C958.592 76.626 958.064 76.272 957.74 75.852C957.416 75.432 957.254 74.898 957.254 74.25C957.254 73.434 957.578 72.78 958.226 72.288C958.886 71.784 959.762 71.532 960.854 71.532C961.862 71.532 962.792 71.73 963.644 72.126L963.644 73.872C962.732 73.596 961.88 73.458 961.088 73.458C960.596 73.458 960.236 73.518 960.008 73.638C959.78 73.758 959.666 73.95 959.666 74.214C959.666 74.418 959.732 74.586 959.864 74.718C960.008 74.838 960.302 74.988 960.746 75.168L962.114 75.726C962.858 76.026 963.386 76.374 963.698 76.77C964.022 77.166 964.184 77.682 964.184 78.318C964.184 79.206 963.842 79.926 963.158 80.478C962.486 81.018 961.598 81.288 960.494 81.288C959.258 81.288 958.166 81.042 957.218 80.55L957.218 78.804C958.406 79.176 959.492 79.362 960.476 79.362C961.34 79.362 961.772 79.062 961.772 78.462ZM971.786 81L971.786 74.97C971.786 74.478 971.678 74.118 971.462 73.89C971.246 73.662 970.916 73.548 970.472 73.548C969.812 73.548 969.158 73.752 968.51 74.16L968.51 81L965.882 81L965.882 67.68L968.51 67.68L968.51 72.63C969.542 71.898 970.622 71.532 971.75 71.532C972.602 71.532 973.256 71.766 973.712 72.234C974.18 72.69 974.414 73.344 974.414 74.196L974.414 81L971.786 81ZM978.866 77.04C978.914 77.832 979.154 78.408 979.586 78.768C980.018 79.116 980.696 79.29 981.62 79.29C982.424 79.29 983.36 79.14 984.428 78.84L984.428 80.586C984.008 80.802 983.504 80.97 982.916 81.09C982.34 81.21 981.74 81.27 981.116 81.27C979.592 81.27 978.428 80.856 977.624 80.028C976.832 79.2 976.436 77.988 976.436 76.392C976.436 74.856 976.832 73.662 977.624 72.81C978.416 71.958 979.514 71.532 980.918 71.532C982.106 71.532 983.018 71.862 983.654 72.522C984.302 73.17 984.626 74.1 984.626 75.312C984.626 75.576 984.608 75.876 984.572 76.212C984.536 76.548 984.494 76.824 984.446 77.04L978.866 77.04ZM980.828 73.35C980.24 73.35 979.772 73.53 979.424 73.89C979.088 74.238 978.896 74.748 978.848 75.42L982.376 75.42L982.376 75.114C982.376 73.938 981.86 73.35 980.828 73.35ZM992.852 81L992.636 80.19C991.892 80.862 991.01 81.198 989.99 81.198C989.234 81.198 988.568 81.012 987.992 80.64C987.416 80.256 986.966 79.704 986.642 78.984C986.33 78.264 986.174 77.418 986.174 76.446C986.174 74.958 986.528 73.77 987.236 72.882C987.944 71.982 988.88 71.532 990.044 71.532C990.992 71.532 991.814 71.802 992.51 72.342L992.51 67.68L995.138 67.68L995.138 81L992.852 81ZM990.854 79.218C991.43 79.218 991.982 79.05 992.51 78.714L992.51 73.962C991.994 73.662 991.4 73.512 990.728 73.512C990.092 73.512 989.618 73.752 989.306 74.232C988.994 74.7 988.838 75.414 988.838 76.374C988.838 77.334 989 78.048 989.324 78.516C989.66 78.984 990.17 79.218 990.854 79.218Z" fill="white"/> -<mask id="path-8-outside-2_11_373" maskUnits="userSpaceOnUse" x="1447" y="37" width="279" height="74" fill="black"> -<rect fill="white" x="1447" y="37" width="279" height="74"/> -<path d="M1449 49C1449 43.4772 1453.48 39 1459 39L1714 39C1719.52 39 1724 43.4771 1724 49L1724 109L1449 109L1449 49Z"/> -</mask> -<path d="M1449 49C1449 43.4772 1453.48 39 1459 39L1714 39C1719.52 39 1724 43.4771 1724 49L1724 109L1449 109L1449 49Z" fill="#033160"/> -<path d="M1724 109L1724 111L1726 111L1726 109L1724 109ZM1449 109L1447 109L1447 111L1449 111L1449 109ZM1459 41L1714 41L1714 37L1459 37L1459 41ZM1722 49L1722 109L1726 109L1726 49L1722 49ZM1724 107L1449 107L1449 111L1724 111L1724 107ZM1451 109L1451 49L1447 49L1447 109L1451 109ZM1714 41C1718.42 41 1722 44.5817 1722 49L1726 49C1726 42.3726 1720.63 37 1714 37L1714 41ZM1459 37C1452.37 37 1447 42.3726 1447 49L1451 49C1451 44.5817 1454.58 41 1459 41L1459 37Z" fill="#000716" mask="url(#path-8-outside-2_11_373)"/> -<path d="M1479.15 81L1479.15 68.526L1483.63 68.526C1485.49 68.526 1486.92 69.066 1487.91 70.146C1488.92 71.214 1489.43 72.75 1489.43 74.754C1489.43 76.746 1488.92 78.288 1487.91 79.38C1486.92 80.46 1485.51 81 1483.68 81L1479.15 81ZM1481.85 70.614L1481.85 78.912L1483.4 78.912C1485.57 78.912 1486.65 77.586 1486.65 74.934L1486.65 74.574C1486.65 71.934 1485.56 70.614 1483.38 70.614L1481.85 70.614ZM1493.73 77.04C1493.78 77.832 1494.02 78.408 1494.45 78.768C1494.88 79.116 1495.56 79.29 1496.48 79.29C1497.29 79.29 1498.22 79.14 1499.29 78.84L1499.29 80.586C1498.87 80.802 1498.37 80.97 1497.78 81.09C1497.2 81.21 1496.6 81.27 1495.98 81.27C1494.45 81.27 1493.29 80.856 1492.49 80.028C1491.69 79.2 1491.3 77.988 1491.3 76.392C1491.3 74.856 1491.69 73.662 1492.49 72.81C1493.28 71.958 1494.38 71.532 1495.78 71.532C1496.97 71.532 1497.88 71.862 1498.52 72.522C1499.16 73.17 1499.49 74.1 1499.49 75.312C1499.49 75.576 1499.47 75.876 1499.43 76.212C1499.4 76.548 1499.36 76.824 1499.31 77.04L1493.73 77.04ZM1495.69 73.35C1495.1 73.35 1494.63 73.53 1494.29 73.89C1493.95 74.238 1493.76 74.748 1493.71 75.42L1497.24 75.42L1497.24 75.114C1497.24 73.938 1496.72 73.35 1495.69 73.35ZM1501.5 84.708L1501.5 71.802L1503.66 71.802L1503.88 72.666C1504.24 72.318 1504.67 72.042 1505.18 71.838C1505.69 71.634 1506.21 71.532 1506.74 71.532C1507.91 71.532 1508.82 71.958 1509.5 72.81C1510.18 73.662 1510.52 74.814 1510.52 76.266C1510.52 77.214 1510.37 78.06 1510.05 78.804C1509.74 79.548 1509.29 80.136 1508.7 80.568C1508.12 80.988 1507.44 81.198 1506.67 81.198C1506.18 81.198 1505.71 81.12 1505.27 80.964C1504.82 80.808 1504.44 80.592 1504.13 80.316L1504.13 84.708L1501.5 84.708ZM1505.9 73.512C1505.27 73.512 1504.68 73.674 1504.13 73.998L1504.13 78.732C1504.66 79.056 1505.25 79.218 1505.9 79.218C1506.57 79.218 1507.06 78.99 1507.37 78.534C1507.7 78.078 1507.86 77.358 1507.86 76.374C1507.86 75.378 1507.7 74.652 1507.39 74.196C1507.08 73.74 1506.58 73.512 1505.9 73.512ZM1516.63 80.82C1516.12 81.024 1515.58 81.126 1515.01 81.126C1513.39 81.126 1512.58 80.22 1512.58 78.408L1512.58 67.68L1515.21 67.68L1515.21 78.192C1515.21 78.528 1515.26 78.768 1515.37 78.912C1515.49 79.044 1515.68 79.11 1515.94 79.11C1516.11 79.11 1516.34 79.092 1516.63 79.056L1516.63 80.82ZM1522.34 81.27C1520.91 81.27 1519.8 80.844 1518.99 79.992C1518.19 79.128 1517.79 77.928 1517.79 76.392C1517.79 74.868 1518.19 73.68 1518.99 72.828C1519.8 71.964 1520.91 71.532 1522.34 71.532C1523.77 71.532 1524.89 71.964 1525.69 72.828C1526.49 73.68 1526.9 74.868 1526.9 76.392C1526.9 77.928 1526.49 79.128 1525.69 79.992C1524.89 80.844 1523.77 81.27 1522.34 81.27ZM1522.34 79.254C1523.6 79.254 1524.23 78.3 1524.23 76.392C1524.23 74.496 1523.6 73.548 1522.34 73.548C1521.08 73.548 1520.45 74.496 1520.45 76.392C1520.45 78.3 1521.08 79.254 1522.34 79.254ZM1531.22 81.144L1527.58 71.802L1530.37 71.802L1532.42 78.678L1534.37 71.802L1537.08 71.802L1533.2 82.242C1532.85 83.19 1532.42 83.874 1531.92 84.294C1531.41 84.714 1530.78 84.924 1530.01 84.924C1529.41 84.924 1528.83 84.828 1528.26 84.636L1528.26 82.854C1528.65 82.89 1528.99 82.908 1529.29 82.908C1529.79 82.908 1530.18 82.788 1530.46 82.548C1530.74 82.32 1530.97 81.918 1531.16 81.342L1531.22 81.144ZM1549.81 81L1549.81 74.772C1549.81 73.956 1549.45 73.548 1548.71 73.548C1548.07 73.548 1547.41 73.704 1546.75 74.016L1546.75 74.196L1546.75 81L1544.12 81L1544.12 74.772C1544.12 73.956 1543.76 73.548 1543.03 73.548C1542.35 73.548 1541.69 73.71 1541.05 74.034L1541.05 81L1538.42 81L1538.42 71.802L1540.58 71.802L1540.81 72.684C1541.45 72.264 1542.02 71.97 1542.52 71.802C1543.04 71.622 1543.57 71.532 1544.11 71.532C1545.19 71.532 1545.95 71.916 1546.39 72.684C1547 72.276 1547.58 71.982 1548.12 71.802C1548.66 71.622 1549.22 71.532 1549.79 71.532C1550.63 71.532 1551.28 71.766 1551.74 72.234C1552.21 72.702 1552.44 73.356 1552.44 74.196L1552.44 81L1549.81 81ZM1556.89 77.04C1556.93 77.832 1557.17 78.408 1557.61 78.768C1558.04 79.116 1558.72 79.29 1559.64 79.29C1560.44 79.29 1561.38 79.14 1562.45 78.84L1562.45 80.586C1562.03 80.802 1561.52 80.97 1560.94 81.09C1560.36 81.21 1559.76 81.27 1559.14 81.27C1557.61 81.27 1556.45 80.856 1555.64 80.028C1554.85 79.2 1554.46 77.988 1554.46 76.392C1554.46 74.856 1554.85 73.662 1555.64 72.81C1556.44 71.958 1557.53 71.532 1558.94 71.532C1560.13 71.532 1561.04 71.862 1561.67 72.522C1562.32 73.17 1562.65 74.1 1562.65 75.312C1562.65 75.576 1562.63 75.876 1562.59 76.212C1562.56 76.548 1562.51 76.824 1562.47 77.04L1556.89 77.04ZM1558.85 73.35C1558.26 73.35 1557.79 73.53 1557.44 73.89C1557.11 74.238 1556.92 74.748 1556.87 75.42L1560.4 75.42L1560.4 75.114C1560.4 73.938 1559.88 73.35 1558.85 73.35ZM1570.57 81L1570.57 74.97C1570.57 74.478 1570.46 74.118 1570.24 73.89C1570.03 73.662 1569.7 73.548 1569.25 73.548C1568.59 73.548 1567.94 73.752 1567.29 74.16L1567.29 81L1564.66 81L1564.66 71.802L1566.82 71.802L1567.07 72.792C1568.15 71.952 1569.31 71.532 1570.53 71.532C1571.38 71.532 1572.04 71.766 1572.49 72.234C1572.96 72.69 1573.19 73.344 1573.19 74.196L1573.19 81L1570.57 81ZM1581.16 80.766C1580.51 81.018 1579.78 81.144 1578.98 81.144C1577.96 81.144 1577.2 80.904 1576.71 80.424C1576.23 79.944 1575.99 79.2 1575.99 78.192L1575.99 73.746L1574.6 73.746L1574.6 72.126L1576.06 71.838L1576.46 69.318L1578.62 69.318L1578.62 71.802L1581.1 71.802L1581.1 73.746L1578.62 73.746L1578.62 78.066C1578.62 78.45 1578.71 78.72 1578.91 78.876C1579.1 79.032 1579.42 79.11 1579.88 79.11C1580.25 79.11 1580.68 79.074 1581.16 79.002L1581.16 80.766ZM1587.55 81L1587.55 71.802L1590.18 71.802L1590.18 81L1587.55 81ZM1588.86 70.38C1588.41 70.38 1588.04 70.254 1587.77 70.002C1587.49 69.75 1587.35 69.408 1587.35 68.976C1587.35 68.544 1587.49 68.202 1587.77 67.95C1588.04 67.698 1588.41 67.572 1588.86 67.572C1589.32 67.572 1589.69 67.698 1589.96 67.95C1590.24 68.202 1590.38 68.544 1590.38 68.976C1590.38 69.408 1590.24 69.75 1589.96 70.002C1589.69 70.254 1589.32 70.38 1588.86 70.38ZM1596.68 78.462C1596.68 78.222 1596.6 78.036 1596.46 77.904C1596.33 77.772 1596.05 77.628 1595.63 77.472L1594.23 76.914C1593.5 76.626 1592.97 76.272 1592.64 75.852C1592.32 75.432 1592.16 74.898 1592.16 74.25C1592.16 73.434 1592.48 72.78 1593.13 72.288C1593.79 71.784 1594.67 71.532 1595.76 71.532C1596.77 71.532 1597.7 71.73 1598.55 72.126L1598.55 73.872C1597.64 73.596 1596.78 73.458 1595.99 73.458C1595.5 73.458 1595.14 73.518 1594.91 73.638C1594.68 73.758 1594.57 73.95 1594.57 74.214C1594.57 74.418 1594.64 74.586 1594.77 74.718C1594.91 74.838 1595.21 74.988 1595.65 75.168L1597.02 75.726C1597.76 76.026 1598.29 76.374 1598.6 76.77C1598.93 77.166 1599.09 77.682 1599.09 78.318C1599.09 79.206 1598.75 79.926 1598.06 80.478C1597.39 81.018 1596.5 81.288 1595.4 81.288C1594.16 81.288 1593.07 81.042 1592.12 80.55L1592.12 78.804C1593.31 79.176 1594.4 79.362 1595.38 79.362C1596.24 79.362 1596.68 79.062 1596.68 78.462ZM1605.5 84.708L1605.5 71.802L1607.66 71.802L1607.87 72.666C1608.23 72.318 1608.66 72.042 1609.17 71.838C1609.68 71.634 1610.21 71.532 1610.73 71.532C1611.9 71.532 1612.82 71.958 1613.49 72.81C1614.17 73.662 1614.51 74.814 1614.51 76.266C1614.51 77.214 1614.36 78.06 1614.05 78.804C1613.73 79.548 1613.28 80.136 1612.7 80.568C1612.11 80.988 1611.43 81.198 1610.66 81.198C1610.17 81.198 1609.7 81.12 1609.26 80.964C1608.81 80.808 1608.44 80.592 1608.12 80.316L1608.12 84.708L1605.5 84.708ZM1609.89 73.512C1609.26 73.512 1608.68 73.674 1608.12 73.998L1608.12 78.732C1608.65 79.056 1609.24 79.218 1609.89 79.218C1610.56 79.218 1611.05 78.99 1611.36 78.534C1611.69 78.078 1611.85 77.358 1611.85 76.374C1611.85 75.378 1611.69 74.652 1611.38 74.196C1611.07 73.74 1610.57 73.512 1609.89 73.512ZM1618.53 77.04C1618.58 77.832 1618.82 78.408 1619.25 78.768C1619.68 79.116 1620.36 79.29 1621.29 79.29C1622.09 79.29 1623.03 79.14 1624.09 78.84L1624.09 80.586C1623.67 80.802 1623.17 80.97 1622.58 81.09C1622.01 81.21 1621.41 81.27 1620.78 81.27C1619.26 81.27 1618.09 80.856 1617.29 80.028C1616.5 79.2 1616.1 77.988 1616.1 76.392C1616.1 74.856 1616.5 73.662 1617.29 72.81C1618.08 71.958 1619.18 71.532 1620.58 71.532C1621.77 71.532 1622.68 71.862 1623.32 72.522C1623.97 73.17 1624.29 74.1 1624.29 75.312C1624.29 75.576 1624.27 75.876 1624.24 76.212C1624.2 76.548 1624.16 76.824 1624.11 77.04L1618.53 77.04ZM1620.49 73.35C1619.91 73.35 1619.44 73.53 1619.09 73.89C1618.75 74.238 1618.56 74.748 1618.51 75.42L1622.04 75.42L1622.04 75.114C1622.04 73.938 1621.53 73.35 1620.49 73.35ZM1626.31 81L1626.31 71.802L1628.47 71.802L1628.79 73.17C1629.27 72.642 1629.72 72.27 1630.14 72.054C1630.57 71.826 1631.03 71.712 1631.51 71.712C1631.74 71.712 1631.98 71.73 1632.23 71.766L1632.23 74.196C1631.89 74.124 1631.52 74.088 1631.11 74.088C1630.33 74.088 1629.61 74.226 1628.94 74.502L1628.94 81L1626.31 81ZM1634.77 81L1634.77 73.746L1633.32 73.746L1633.32 72.126L1634.77 71.856L1634.77 71.028C1634.77 69.816 1635.05 68.916 1635.6 68.328C1636.17 67.728 1637.02 67.428 1638.16 67.428C1638.48 67.428 1638.82 67.464 1639.17 67.536C1639.51 67.596 1639.82 67.68 1640.08 67.788L1640.08 69.57C1639.6 69.498 1639.2 69.462 1638.86 69.462C1638.31 69.462 1637.92 69.552 1637.71 69.732C1637.5 69.912 1637.4 70.23 1637.4 70.686L1637.4 71.802L1639.98 71.802L1639.98 73.746L1637.4 73.746L1637.4 81L1634.77 81ZM1645.39 81.27C1643.96 81.27 1642.84 80.844 1642.04 79.992C1641.24 79.128 1640.83 77.928 1640.83 76.392C1640.83 74.868 1641.24 73.68 1642.04 72.828C1642.84 71.964 1643.96 71.532 1645.39 71.532C1646.82 71.532 1647.93 71.964 1648.74 72.828C1649.54 73.68 1649.94 74.868 1649.94 76.392C1649.94 77.928 1649.54 79.128 1648.74 79.992C1647.93 80.844 1646.82 81.27 1645.39 81.27ZM1645.39 79.254C1646.65 79.254 1647.28 78.3 1647.28 76.392C1647.28 74.496 1646.65 73.548 1645.39 73.548C1644.13 73.548 1643.5 74.496 1643.5 76.392C1643.5 78.3 1644.13 79.254 1645.39 79.254ZM1651.99 81L1651.99 71.802L1654.15 71.802L1654.47 73.17C1654.95 72.642 1655.4 72.27 1655.82 72.054C1656.26 71.826 1656.71 71.712 1657.19 71.712C1657.42 71.712 1657.66 71.73 1657.91 71.766L1657.91 74.196C1657.58 74.124 1657.2 74.088 1656.8 74.088C1656.02 74.088 1655.29 74.226 1654.62 74.502L1654.62 81L1651.99 81ZM1670.68 81L1670.68 74.772C1670.68 73.956 1670.31 73.548 1669.58 73.548C1668.93 73.548 1668.28 73.704 1667.62 74.016L1667.62 74.196L1667.62 81L1664.99 81L1664.99 74.772C1664.99 73.956 1664.63 73.548 1663.89 73.548C1663.22 73.548 1662.56 73.71 1661.91 74.034L1661.91 81L1659.29 81L1659.29 71.802L1661.45 71.802L1661.68 72.684C1662.32 72.264 1662.89 71.97 1663.39 71.802C1663.91 71.622 1664.43 71.532 1664.97 71.532C1666.05 71.532 1666.82 71.916 1667.26 72.684C1667.87 72.276 1668.45 71.982 1668.99 71.802C1669.53 71.622 1670.09 71.532 1670.66 71.532C1671.5 71.532 1672.15 71.766 1672.61 72.234C1673.07 72.702 1673.31 73.356 1673.31 74.196L1673.31 81L1670.68 81ZM1677.75 77.04C1677.8 77.832 1678.04 78.408 1678.47 78.768C1678.91 79.116 1679.58 79.29 1680.51 79.29C1681.31 79.29 1682.25 79.14 1683.32 78.84L1683.32 80.586C1682.9 80.802 1682.39 80.97 1681.8 81.09C1681.23 81.21 1680.63 81.27 1680 81.27C1678.48 81.27 1677.32 80.856 1676.51 80.028C1675.72 79.2 1675.32 77.988 1675.32 76.392C1675.32 74.856 1675.72 73.662 1676.51 72.81C1677.3 71.958 1678.4 71.532 1679.81 71.532C1680.99 71.532 1681.91 71.862 1682.54 72.522C1683.19 73.17 1683.51 74.1 1683.51 75.312C1683.51 75.576 1683.5 75.876 1683.46 76.212C1683.42 76.548 1683.38 76.824 1683.33 77.04L1677.75 77.04ZM1679.72 73.35C1679.13 73.35 1678.66 73.53 1678.31 73.89C1677.98 74.238 1677.78 74.748 1677.74 75.42L1681.26 75.42L1681.26 75.114C1681.26 73.938 1680.75 73.35 1679.72 73.35ZM1691.74 81L1691.52 80.19C1690.78 80.862 1689.9 81.198 1688.88 81.198C1688.12 81.198 1687.46 81.012 1686.88 80.64C1686.3 80.256 1685.85 79.704 1685.53 78.984C1685.22 78.264 1685.06 77.418 1685.06 76.446C1685.06 74.958 1685.42 73.77 1686.12 72.882C1686.83 71.982 1687.77 71.532 1688.93 71.532C1689.88 71.532 1690.7 71.802 1691.4 72.342L1691.4 67.68L1694.03 67.68L1694.03 81L1691.74 81ZM1689.74 79.218C1690.32 79.218 1690.87 79.05 1691.4 78.714L1691.4 73.962C1690.88 73.662 1690.29 73.512 1689.62 73.512C1688.98 73.512 1688.51 73.752 1688.19 74.232C1687.88 74.7 1687.73 75.414 1687.73 76.374C1687.73 77.334 1687.89 78.048 1688.21 78.516C1688.55 78.984 1689.06 79.218 1689.74 79.218Z" fill="white"/> -<mask id="path-11-outside-3_11_373" maskUnits="userSpaceOnUse" x="37" y="37" width="276" height="74" fill="black"> -<rect fill="white" x="37" y="37" width="276" height="74"/> -<path d="M39 49C39 43.4772 43.4772 39 49 39L301 39C306.523 39 311 43.4771 311 49L311 109L39 109L39 49Z"/> -</mask> -<path d="M39 49C39 43.4772 43.4772 39 49 39L301 39C306.523 39 311 43.4771 311 49L311 109L39 109L39 49Z" fill="#033160"/> -<path d="M311 109L311 111L313 111L313 109L311 109ZM39 109L37 109L37 111L39 111L39 109ZM49 41L301 41L301 37L49 37L49 41ZM309 49L309 109L313 109L313 49L309 49ZM311 107L39 107L39 111L311 111L311 107ZM41 109L41 49L37 49L37 109L41 109ZM301 41C305.418 41 309 44.5817 309 49L313 49C313 42.3726 307.627 37 301 37L301 41ZM49 37C42.3726 37 37 42.3726 37 49L41 49C41 44.5817 44.5817 41 49 41L49 37Z" fill="#000716" mask="url(#path-11-outside-3_11_373)"/> -<path d="M70.9358 81L70.0538 78.156L65.7878 78.156L64.9418 81L62.1158 81L66.5078 68.526L69.4778 68.526L73.8698 81L70.9358 81ZM66.3638 76.212L69.4958 76.212L67.9118 70.992L66.3638 76.212ZM81.8805 80.604C81.5565 80.796 81.1665 80.94 80.7105 81.036C80.2545 81.144 79.7805 81.198 79.2885 81.198C77.8245 81.198 76.7025 80.79 75.9225 79.974C75.1545 79.158 74.7705 77.982 74.7705 76.446C74.7705 74.922 75.1785 73.734 75.9945 72.882C76.8105 72.03 77.9445 71.604 79.3965 71.604C80.2725 71.604 81.0825 71.796 81.8265 72.18L81.8265 73.926C81.1185 73.722 80.4705 73.62 79.8825 73.62C79.0425 73.62 78.4245 73.836 78.0285 74.268C77.6325 74.688 77.4345 75.36 77.4345 76.284L77.4345 76.536C77.4345 77.448 77.6265 78.12 78.0105 78.552C78.4065 78.972 79.0125 79.182 79.8285 79.182C80.4165 79.182 81.1005 79.074 81.8805 78.858L81.8805 80.604ZM89.5699 80.766C88.9219 81.018 88.1959 81.144 87.3919 81.144C86.3719 81.144 85.6159 80.904 85.1239 80.424C84.6439 79.944 84.4039 79.2 84.4039 78.192L84.4039 73.746L83.0179 73.746L83.0179 72.126L84.4759 71.838L84.8719 69.318L87.0319 69.318L87.0319 71.802L89.5159 71.802L89.5159 73.746L87.0319 73.746L87.0319 78.066C87.0319 78.45 87.1279 78.72 87.3199 78.876C87.5119 79.032 87.8359 79.11 88.2919 79.11C88.6639 79.11 89.0899 79.074 89.5699 79.002L89.5699 80.766ZM95.2679 81.27C93.8399 81.27 92.7239 80.844 91.9199 79.992C91.1159 79.128 90.7139 77.928 90.7139 76.392C90.7139 74.868 91.1159 73.68 91.9199 72.828C92.7239 71.964 93.8399 71.532 95.2679 71.532C96.6959 71.532 97.8119 71.964 98.6159 72.828C99.4199 73.68 99.8219 74.868 99.8219 76.392C99.8219 77.928 99.4199 79.128 98.6159 79.992C97.8119 80.844 96.6959 81.27 95.2679 81.27ZM95.2679 79.254C96.5279 79.254 97.1579 78.3 97.1579 76.392C97.1579 74.496 96.5279 73.548 95.2679 73.548C94.0079 73.548 93.3779 74.496 93.3779 76.392C93.3779 78.3 94.0079 79.254 95.2679 79.254ZM101.869 81L101.869 71.802L104.029 71.802L104.353 73.17C104.833 72.642 105.283 72.27 105.703 72.054C106.135 71.826 106.591 71.712 107.071 71.712C107.299 71.712 107.539 71.73 107.791 71.766L107.791 74.196C107.455 74.124 107.083 74.088 106.675 74.088C105.895 74.088 105.169 74.226 104.497 74.502L104.497 81L101.869 81ZM113.947 81L113.947 71.802L116.575 71.802L116.575 81L113.947 81ZM115.261 70.38C114.805 70.38 114.439 70.254 114.163 70.002C113.887 69.75 113.749 69.408 113.749 68.976C113.749 68.544 113.887 68.202 114.163 67.95C114.439 67.698 114.805 67.572 115.261 67.572C115.717 67.572 116.083 67.698 116.359 67.95C116.635 68.202 116.773 68.544 116.773 68.976C116.773 69.408 116.635 69.75 116.359 70.002C116.083 70.254 115.717 70.38 115.261 70.38ZM125.07 81L125.07 74.97C125.07 74.478 124.962 74.118 124.746 73.89C124.53 73.662 124.2 73.548 123.756 73.548C123.096 73.548 122.442 73.752 121.794 74.16L121.794 81L119.166 81L119.166 71.802L121.326 71.802L121.578 72.792C122.658 71.952 123.81 71.532 125.034 71.532C125.886 71.532 126.54 71.766 126.996 72.234C127.464 72.69 127.698 73.344 127.698 74.196L127.698 81L125.07 81ZM130.26 81L130.26 71.802L132.888 71.802L132.888 81L130.26 81ZM131.574 70.38C131.118 70.38 130.752 70.254 130.476 70.002C130.2 69.75 130.062 69.408 130.062 68.976C130.062 68.544 130.2 68.202 130.476 67.95C130.752 67.698 131.118 67.572 131.574 67.572C132.03 67.572 132.396 67.698 132.672 67.95C132.948 68.202 133.086 68.544 133.086 68.976C133.086 69.408 132.948 69.75 132.672 70.002C132.396 70.254 132.03 70.38 131.574 70.38ZM140.951 80.766C140.303 81.018 139.577 81.144 138.773 81.144C137.753 81.144 136.997 80.904 136.505 80.424C136.025 79.944 135.785 79.2 135.785 78.192L135.785 73.746L134.399 73.746L134.399 72.126L135.857 71.838L136.253 69.318L138.413 69.318L138.413 71.802L140.897 71.802L140.897 73.746L138.413 73.746L138.413 78.066C138.413 78.45 138.509 78.72 138.701 78.876C138.893 79.032 139.217 79.11 139.673 79.11C140.045 79.11 140.471 79.074 140.951 79.002L140.951 80.766ZM142.635 81L142.635 71.802L145.263 71.802L145.263 81L142.635 81ZM143.949 70.38C143.493 70.38 143.127 70.254 142.851 70.002C142.575 69.75 142.437 69.408 142.437 68.976C142.437 68.544 142.575 68.202 142.851 67.95C143.127 67.698 143.493 67.572 143.949 67.572C144.405 67.572 144.771 67.698 145.047 67.95C145.323 68.202 145.461 68.544 145.461 68.976C145.461 69.408 145.323 69.75 145.047 70.002C144.771 70.254 144.405 70.38 143.949 70.38ZM153.128 81L152.912 80.19C152.54 80.526 152.108 80.796 151.616 81C151.136 81.192 150.668 81.288 150.212 81.288C149.324 81.288 148.61 81.036 148.07 80.532C147.542 80.028 147.278 79.356 147.278 78.516C147.278 77.94 147.422 77.436 147.71 77.004C147.998 76.56 148.412 76.212 148.952 75.96C149.492 75.708 150.128 75.582 150.86 75.582C151.436 75.582 152.072 75.66 152.768 75.816L152.768 74.916C152.768 74.364 152.654 73.986 152.426 73.782C152.198 73.578 151.778 73.476 151.166 73.476C150.182 73.476 149.096 73.662 147.908 74.034L147.908 72.288C148.352 72.06 148.91 71.88 149.582 71.748C150.254 71.604 150.938 71.532 151.634 71.532C152.87 71.532 153.77 71.784 154.334 72.288C154.91 72.78 155.198 73.56 155.198 74.628L155.198 81L153.128 81ZM150.95 79.524C151.25 79.524 151.556 79.458 151.868 79.326C152.192 79.194 152.492 79.014 152.768 78.786L152.768 77.22C152.24 77.136 151.766 77.094 151.346 77.094C150.302 77.094 149.78 77.514 149.78 78.354C149.78 78.726 149.882 79.014 150.086 79.218C150.29 79.422 150.578 79.524 150.95 79.524ZM163.152 80.766C162.504 81.018 161.778 81.144 160.974 81.144C159.954 81.144 159.198 80.904 158.706 80.424C158.226 79.944 157.986 79.2 157.986 78.192L157.986 73.746L156.6 73.746L156.6 72.126L158.058 71.838L158.454 69.318L160.614 69.318L160.614 71.802L163.098 71.802L163.098 73.746L160.614 73.746L160.614 78.066C160.614 78.45 160.71 78.72 160.902 78.876C161.094 79.032 161.418 79.11 161.874 79.11C162.246 79.11 162.672 79.074 163.152 79.002L163.152 80.766ZM166.726 77.04C166.774 77.832 167.014 78.408 167.446 78.768C167.878 79.116 168.556 79.29 169.48 79.29C170.284 79.29 171.22 79.14 172.288 78.84L172.288 80.586C171.868 80.802 171.364 80.97 170.776 81.09C170.2 81.21 169.6 81.27 168.976 81.27C167.452 81.27 166.288 80.856 165.484 80.028C164.692 79.2 164.296 77.988 164.296 76.392C164.296 74.856 164.692 73.662 165.484 72.81C166.276 71.958 167.374 71.532 168.778 71.532C169.966 71.532 170.878 71.862 171.514 72.522C172.162 73.17 172.486 74.1 172.486 75.312C172.486 75.576 172.468 75.876 172.432 76.212C172.396 76.548 172.354 76.824 172.306 77.04L166.726 77.04ZM168.688 73.35C168.1 73.35 167.632 73.53 167.284 73.89C166.948 74.238 166.756 74.748 166.708 75.42L170.236 75.42L170.236 75.114C170.236 73.938 169.72 73.35 168.688 73.35ZM178.408 78.462C178.408 78.222 178.336 78.036 178.192 77.904C178.06 77.772 177.784 77.628 177.364 77.472L175.96 76.914C175.228 76.626 174.7 76.272 174.376 75.852C174.052 75.432 173.89 74.898 173.89 74.25C173.89 73.434 174.214 72.78 174.862 72.288C175.522 71.784 176.398 71.532 177.49 71.532C178.498 71.532 179.428 71.73 180.28 72.126L180.28 73.872C179.368 73.596 178.516 73.458 177.724 73.458C177.232 73.458 176.872 73.518 176.644 73.638C176.416 73.758 176.302 73.95 176.302 74.214C176.302 74.418 176.368 74.586 176.5 74.718C176.644 74.838 176.938 74.988 177.382 75.168L178.75 75.726C179.494 76.026 180.022 76.374 180.334 76.77C180.658 77.166 180.82 77.682 180.82 78.318C180.82 79.206 180.478 79.926 179.794 80.478C179.122 81.018 178.234 81.288 177.13 81.288C175.894 81.288 174.802 81.042 173.854 80.55L173.854 78.804C175.042 79.176 176.128 79.362 177.112 79.362C177.976 79.362 178.408 79.062 178.408 78.462ZM193.439 81L193.223 80.19C192.479 80.862 191.597 81.198 190.577 81.198C189.821 81.198 189.155 81.012 188.579 80.64C188.003 80.256 187.553 79.704 187.229 78.984C186.917 78.264 186.761 77.418 186.761 76.446C186.761 74.958 187.115 73.77 187.823 72.882C188.531 71.982 189.467 71.532 190.631 71.532C191.579 71.532 192.401 71.802 193.097 72.342L193.097 67.68L195.725 67.68L195.725 81L193.439 81ZM191.441 79.218C192.017 79.218 192.569 79.05 193.097 78.714L193.097 73.962C192.581 73.662 191.987 73.512 191.315 73.512C190.679 73.512 190.205 73.752 189.893 74.232C189.581 74.7 189.425 75.414 189.425 76.374C189.425 77.334 189.587 78.048 189.911 78.516C190.247 78.984 190.757 79.218 191.441 79.218ZM200.212 77.04C200.26 77.832 200.5 78.408 200.932 78.768C201.364 79.116 202.042 79.29 202.966 79.29C203.77 79.29 204.706 79.14 205.774 78.84L205.774 80.586C205.354 80.802 204.85 80.97 204.262 81.09C203.686 81.21 203.086 81.27 202.462 81.27C200.938 81.27 199.774 80.856 198.97 80.028C198.178 79.2 197.782 77.988 197.782 76.392C197.782 74.856 198.178 73.662 198.97 72.81C199.762 71.958 200.86 71.532 202.264 71.532C203.452 71.532 204.364 71.862 205 72.522C205.648 73.17 205.972 74.1 205.972 75.312C205.972 75.576 205.954 75.876 205.918 76.212C205.882 76.548 205.84 76.824 205.792 77.04L200.212 77.04ZM202.174 73.35C201.586 73.35 201.118 73.53 200.77 73.89C200.434 74.238 200.242 74.748 200.194 75.42L203.722 75.42L203.722 75.114C203.722 73.938 203.206 73.35 202.174 73.35ZM207.989 84.708L207.989 71.802L210.149 71.802L210.365 72.666C210.725 72.318 211.157 72.042 211.661 71.838C212.177 71.634 212.699 71.532 213.227 71.532C214.391 71.532 215.309 71.958 215.981 72.81C216.665 73.662 217.007 74.814 217.007 76.266C217.007 77.214 216.851 78.06 216.539 78.804C216.227 79.548 215.777 80.136 215.189 80.568C214.601 80.988 213.923 81.198 213.155 81.198C212.663 81.198 212.195 81.12 211.751 80.964C211.307 80.808 210.929 80.592 210.617 80.316L210.617 84.708L207.989 84.708ZM212.381 73.512C211.757 73.512 211.169 73.674 210.617 73.998L210.617 78.732C211.145 79.056 211.733 79.218 212.381 79.218C213.053 79.218 213.545 78.99 213.857 78.534C214.181 78.078 214.343 77.358 214.343 76.374C214.343 75.378 214.187 74.652 213.875 74.196C213.563 73.74 213.065 73.512 212.381 73.512ZM223.113 80.82C222.609 81.024 222.069 81.126 221.493 81.126C219.873 81.126 219.063 80.22 219.063 78.408L219.063 67.68L221.691 67.68L221.691 78.192C221.691 78.528 221.745 78.768 221.853 78.912C221.973 79.044 222.165 79.11 222.429 79.11C222.597 79.11 222.825 79.092 223.113 79.056L223.113 80.82ZM228.826 81.27C227.398 81.27 226.282 80.844 225.478 79.992C224.674 79.128 224.272 77.928 224.272 76.392C224.272 74.868 224.674 73.68 225.478 72.828C226.282 71.964 227.398 71.532 228.826 71.532C230.254 71.532 231.37 71.964 232.174 72.828C232.978 73.68 233.38 74.868 233.38 76.392C233.38 77.928 232.978 79.128 232.174 79.992C231.37 80.844 230.254 81.27 228.826 81.27ZM228.826 79.254C230.086 79.254 230.716 78.3 230.716 76.392C230.716 74.496 230.086 73.548 228.826 73.548C227.566 73.548 226.936 74.496 226.936 76.392C226.936 78.3 227.566 79.254 228.826 79.254ZM237.7 81.144L234.064 71.802L236.854 71.802L238.906 78.678L240.85 71.802L243.568 71.802L239.68 82.242C239.332 83.19 238.906 83.874 238.402 84.294C237.898 84.714 237.262 84.924 236.494 84.924C235.894 84.924 235.312 84.828 234.748 84.636L234.748 82.854C235.132 82.89 235.474 82.908 235.774 82.908C236.278 82.908 236.668 82.788 236.944 82.548C237.22 82.32 237.454 81.918 237.646 81.342L237.7 81.144ZM256.297 81L256.297 74.772C256.297 73.956 255.931 73.548 255.199 73.548C254.551 73.548 253.897 73.704 253.237 74.016L253.237 74.196L253.237 81L250.609 81L250.609 74.772C250.609 73.956 250.243 73.548 249.511 73.548C248.839 73.548 248.179 73.71 247.531 74.034L247.531 81L244.903 81L244.903 71.802L247.063 71.802L247.297 72.684C247.933 72.264 248.503 71.97 249.007 71.802C249.523 71.622 250.051 71.532 250.591 71.532C251.671 71.532 252.433 71.916 252.877 72.684C253.489 72.276 254.065 71.982 254.605 71.802C255.145 71.622 255.703 71.532 256.279 71.532C257.119 71.532 257.767 71.766 258.223 72.234C258.691 72.702 258.925 73.356 258.925 74.196L258.925 81L256.297 81ZM263.37 77.04C263.418 77.832 263.658 78.408 264.09 78.768C264.522 79.116 265.2 79.29 266.124 79.29C266.928 79.29 267.864 79.14 268.932 78.84L268.932 80.586C268.512 80.802 268.008 80.97 267.42 81.09C266.844 81.21 266.244 81.27 265.62 81.27C264.096 81.27 262.932 80.856 262.128 80.028C261.336 79.2 260.94 77.988 260.94 76.392C260.94 74.856 261.336 73.662 262.128 72.81C262.92 71.958 264.018 71.532 265.422 71.532C266.61 71.532 267.522 71.862 268.158 72.522C268.806 73.17 269.13 74.1 269.13 75.312C269.13 75.576 269.112 75.876 269.076 76.212C269.04 76.548 268.998 76.824 268.95 77.04L263.37 77.04ZM265.332 73.35C264.744 73.35 264.276 73.53 263.928 73.89C263.592 74.238 263.4 74.748 263.352 75.42L266.88 75.42L266.88 75.114C266.88 73.938 266.364 73.35 265.332 73.35ZM277.051 81L277.051 74.97C277.051 74.478 276.943 74.118 276.727 73.89C276.511 73.662 276.181 73.548 275.737 73.548C275.077 73.548 274.423 73.752 273.775 74.16L273.775 81L271.147 81L271.147 71.802L273.307 71.802L273.559 72.792C274.639 71.952 275.791 71.532 277.015 71.532C277.867 71.532 278.521 71.766 278.977 72.234C279.445 72.69 279.679 73.344 279.679 74.196L279.679 81L277.051 81ZM287.64 80.766C286.992 81.018 286.266 81.144 285.462 81.144C284.442 81.144 283.686 80.904 283.194 80.424C282.714 79.944 282.474 79.2 282.474 78.192L282.474 73.746L281.088 73.746L281.088 72.126L282.546 71.838L282.942 69.318L285.102 69.318L285.102 71.802L287.586 71.802L287.586 73.746L285.102 73.746L285.102 78.066C285.102 78.45 285.198 78.72 285.39 78.876C285.582 79.032 285.906 79.11 286.362 79.11C286.734 79.11 287.16 79.074 287.64 79.002L287.64 80.766Z" fill="white"/> -<rect x="340" y="243" width="223" height="46" rx="5" fill="#0972D3"/> -<rect x="340" y="243" width="223" height="46" rx="5" stroke="#000716" stroke-width="2"/> -<path d="M395.021 272V260.912H397.421V272H395.021ZM406.627 272L405.843 269.472H402.051L401.299 272H398.787L402.691 260.912H405.331L409.235 272H406.627ZM402.563 267.744H405.347L403.939 263.104L402.563 267.744ZM419.684 272V264.32L417.236 269.296H415.092L412.644 264.32V272H410.532V260.912H413.156L416.18 267.216L419.22 260.912H421.796V272H419.684ZM434.131 271.648C433.843 271.819 433.497 271.947 433.091 272.032C432.686 272.128 432.265 272.176 431.827 272.176C430.526 272.176 429.529 271.813 428.835 271.088C428.153 270.363 427.811 269.317 427.811 267.952C427.811 266.597 428.174 265.541 428.899 264.784C429.625 264.027 430.633 263.648 431.923 263.648C432.702 263.648 433.422 263.819 434.083 264.16V265.712C433.454 265.531 432.878 265.44 432.355 265.44C431.609 265.44 431.059 265.632 430.707 266.016C430.355 266.389 430.179 266.987 430.179 267.808V268.032C430.179 268.843 430.35 269.44 430.691 269.824C431.043 270.197 431.582 270.384 432.307 270.384C432.83 270.384 433.438 270.288 434.131 270.096V271.648ZM435.71 272V263.824H437.63L437.918 265.04C438.344 264.571 438.744 264.24 439.118 264.048C439.502 263.845 439.907 263.744 440.334 263.744C440.536 263.744 440.75 263.76 440.974 263.792V265.952C440.675 265.888 440.344 265.856 439.982 265.856C439.288 265.856 438.643 265.979 438.046 266.224V272H435.71ZM443.858 268.48C443.901 269.184 444.114 269.696 444.498 270.016C444.882 270.325 445.485 270.48 446.306 270.48C447.021 270.48 447.853 270.347 448.802 270.08V271.632C448.429 271.824 447.981 271.973 447.458 272.08C446.946 272.187 446.413 272.24 445.858 272.24C444.503 272.24 443.469 271.872 442.754 271.136C442.05 270.4 441.698 269.323 441.698 267.904C441.698 266.539 442.05 265.477 442.754 264.72C443.458 263.963 444.434 263.584 445.682 263.584C446.738 263.584 447.549 263.877 448.114 264.464C448.69 265.04 448.978 265.867 448.978 266.944C448.978 267.179 448.962 267.445 448.93 267.744C448.898 268.043 448.861 268.288 448.818 268.48H443.858ZM445.602 265.2C445.079 265.2 444.663 265.36 444.354 265.68C444.055 265.989 443.885 266.443 443.842 267.04H446.978V266.768C446.978 265.723 446.519 265.2 445.602 265.2ZM456.21 272L456.018 271.28C455.357 271.877 454.573 272.176 453.666 272.176C452.994 272.176 452.402 272.011 451.89 271.68C451.378 271.339 450.978 270.848 450.69 270.208C450.413 269.568 450.274 268.816 450.274 267.952C450.274 266.629 450.589 265.573 451.218 264.784C451.848 263.984 452.68 263.584 453.714 263.584C454.557 263.584 455.288 263.824 455.906 264.304V260.16H458.242V272H456.21ZM454.434 270.416C454.946 270.416 455.437 270.267 455.906 269.968V265.744C455.448 265.477 454.92 265.344 454.322 265.344C453.757 265.344 453.336 265.557 453.058 265.984C452.781 266.4 452.642 267.035 452.642 267.888C452.642 268.741 452.786 269.376 453.074 269.792C453.373 270.208 453.826 270.416 454.434 270.416ZM462.151 268.48C462.194 269.184 462.407 269.696 462.791 270.016C463.175 270.325 463.778 270.48 464.599 270.48C465.314 270.48 466.146 270.347 467.095 270.08V271.632C466.722 271.824 466.274 271.973 465.751 272.08C465.239 272.187 464.706 272.24 464.151 272.24C462.797 272.24 461.762 271.872 461.047 271.136C460.343 270.4 459.991 269.323 459.991 267.904C459.991 266.539 460.343 265.477 461.047 264.72C461.751 263.963 462.727 263.584 463.975 263.584C465.031 263.584 465.842 263.877 466.407 264.464C466.983 265.04 467.271 265.867 467.271 266.944C467.271 267.179 467.255 267.445 467.223 267.744C467.191 268.043 467.154 268.288 467.111 268.48H462.151ZM463.895 265.2C463.373 265.2 462.957 265.36 462.647 265.68C462.349 265.989 462.178 266.443 462.135 267.04H465.271V266.768C465.271 265.723 464.813 265.2 463.895 265.2ZM474.231 272V266.64C474.231 266.203 474.135 265.883 473.943 265.68C473.751 265.477 473.458 265.376 473.063 265.376C472.477 265.376 471.895 265.557 471.319 265.92V272H468.983V263.824H470.903L471.127 264.704C472.087 263.957 473.111 263.584 474.199 263.584C474.957 263.584 475.538 263.792 475.943 264.208C476.359 264.613 476.567 265.195 476.567 265.952V272H474.231ZM483.564 271.792C482.988 272.016 482.343 272.128 481.628 272.128C480.722 272.128 480.05 271.915 479.612 271.488C479.186 271.061 478.972 270.4 478.972 269.504V265.552H477.74V264.112L479.036 263.856L479.388 261.616H481.308V263.824H483.516V265.552H481.308V269.392C481.308 269.733 481.394 269.973 481.564 270.112C481.735 270.251 482.023 270.32 482.428 270.32C482.759 270.32 483.138 270.288 483.564 270.224V271.792ZM484.981 272V263.824H487.317V272H484.981ZM486.149 262.56C485.744 262.56 485.419 262.448 485.173 262.224C484.928 262 484.805 261.696 484.805 261.312C484.805 260.928 484.928 260.624 485.173 260.4C485.419 260.176 485.744 260.064 486.149 260.064C486.555 260.064 486.88 260.176 487.125 260.4C487.371 260.624 487.493 260.928 487.493 261.312C487.493 261.696 487.371 262 487.125 262.224C486.88 262.448 486.555 262.56 486.149 262.56ZM494.228 272L494.036 271.28C493.706 271.579 493.322 271.819 492.884 272C492.458 272.171 492.042 272.256 491.636 272.256C490.847 272.256 490.212 272.032 489.732 271.584C489.263 271.136 489.028 270.539 489.028 269.792C489.028 269.28 489.156 268.832 489.412 268.448C489.668 268.053 490.036 267.744 490.516 267.52C490.996 267.296 491.562 267.184 492.212 267.184C492.724 267.184 493.29 267.253 493.908 267.392V266.592C493.908 266.101 493.807 265.765 493.604 265.584C493.402 265.403 493.028 265.312 492.484 265.312C491.61 265.312 490.644 265.477 489.588 265.808V264.256C489.983 264.053 490.479 263.893 491.076 263.776C491.674 263.648 492.282 263.584 492.9 263.584C493.999 263.584 494.799 263.808 495.3 264.256C495.812 264.693 496.068 265.387 496.068 266.336V272H494.228ZM492.292 270.688C492.559 270.688 492.831 270.629 493.108 270.512C493.396 270.395 493.663 270.235 493.908 270.032V268.64C493.439 268.565 493.018 268.528 492.644 268.528C491.716 268.528 491.252 268.901 491.252 269.648C491.252 269.979 491.343 270.235 491.524 270.416C491.706 270.597 491.962 270.688 492.292 270.688ZM501.795 271.84C501.347 272.021 500.867 272.112 500.355 272.112C498.915 272.112 498.195 271.307 498.195 269.696V260.16H500.531V269.504C500.531 269.803 500.579 270.016 500.675 270.144C500.781 270.261 500.952 270.32 501.187 270.32C501.336 270.32 501.539 270.304 501.795 270.272V271.84ZM506.79 269.744C506.79 269.531 506.726 269.365 506.598 269.248C506.48 269.131 506.235 269.003 505.862 268.864L504.614 268.368C503.963 268.112 503.494 267.797 503.206 267.424C502.918 267.051 502.774 266.576 502.774 266C502.774 265.275 503.062 264.693 503.638 264.256C504.224 263.808 505.003 263.584 505.974 263.584C506.87 263.584 507.696 263.76 508.454 264.112V265.664C507.643 265.419 506.886 265.296 506.182 265.296C505.744 265.296 505.424 265.349 505.222 265.456C505.019 265.563 504.918 265.733 504.918 265.968C504.918 266.149 504.976 266.299 505.094 266.416C505.222 266.523 505.483 266.656 505.878 266.816L507.094 267.312C507.755 267.579 508.224 267.888 508.502 268.24C508.79 268.592 508.934 269.051 508.934 269.616C508.934 270.405 508.63 271.045 508.022 271.536C507.424 272.016 506.635 272.256 505.654 272.256C504.555 272.256 503.584 272.037 502.742 271.6V270.048C503.798 270.379 504.763 270.544 505.638 270.544C506.406 270.544 506.79 270.277 506.79 269.744Z" fill="white"/> -<path d="M338.707 173.707C339.098 173.317 339.098 172.683 338.707 172.293L332.343 165.929C331.953 165.538 331.319 165.538 330.929 165.929C330.538 166.319 330.538 166.953 330.929 167.343L336.586 173L330.929 178.657C330.538 179.047 330.538 179.681 330.929 180.071C331.319 180.462 331.953 180.462 332.343 180.071L338.707 173.707ZM288 174H338V172H288V174Z" fill="black"/> -<path d="M338.707 266.707C339.098 266.317 339.098 265.683 338.707 265.293L332.343 258.929C331.953 258.538 331.319 258.538 330.929 258.929C330.538 259.319 330.538 259.953 330.929 260.343L336.586 266L330.929 271.657C330.538 272.047 330.538 272.681 330.929 273.071C331.319 273.462 331.953 273.462 332.343 273.071L338.707 266.707ZM287 267H338V265H287V267Z" fill="black"/> -<rect x="65" y="137" width="222" height="71" stroke="#7D8998" stroke-width="2"/> -<path fill-rule="evenodd" clip-rule="evenodd" d="M109.025 193C109.524 183.085 117.395 175.178 127 175.178C130.248 175.178 133.43 176.092 136.205 177.822C141.354 181.033 144.653 186.783 144.974 193H109.025ZM117.192 162.878C117.192 157.432 121.592 153 127.001 153C132.408 153 136.807 157.432 136.807 162.878C136.807 168.325 132.408 172.757 127.001 172.757C121.592 172.757 117.192 168.325 117.192 162.878ZM137.263 176.125C135.53 175.044 133.65 174.26 131.698 173.771C135.877 171.939 138.807 167.749 138.807 162.878C138.807 156.329 133.51 151 127.001 151C120.489 151 115.192 156.329 115.192 162.878C115.192 167.755 118.13 171.95 122.317 173.778C113.545 175.981 107 184.2 107 194C107 194.552 107.447 195 108 195H146C146.552 195 147 194.552 147 194C147 186.719 143.269 179.87 137.263 176.125Z" fill="#000716"/> -<path d="M163.28 179V167.912H167.264C168.917 167.912 170.187 168.392 171.072 169.352C171.968 170.301 172.416 171.667 172.416 173.448C172.416 175.219 171.968 176.589 171.072 177.56C170.187 178.52 168.933 179 167.312 179H163.28ZM165.68 169.768V177.144H167.056C168.987 177.144 169.952 175.965 169.952 173.608V173.288C169.952 170.941 168.981 169.768 167.04 169.768H165.68ZM176.239 175.48C176.282 176.184 176.495 176.696 176.879 177.016C177.263 177.325 177.866 177.48 178.687 177.48C179.402 177.48 180.234 177.347 181.183 177.08V178.632C180.81 178.824 180.362 178.973 179.839 179.08C179.327 179.187 178.794 179.24 178.239 179.24C176.884 179.24 175.85 178.872 175.135 178.136C174.431 177.4 174.079 176.323 174.079 174.904C174.079 173.539 174.431 172.477 175.135 171.72C175.839 170.963 176.815 170.584 178.063 170.584C179.119 170.584 179.93 170.877 180.495 171.464C181.071 172.04 181.359 172.867 181.359 173.944C181.359 174.179 181.343 174.445 181.311 174.744C181.279 175.043 181.242 175.288 181.199 175.48H176.239ZM177.983 172.2C177.46 172.2 177.044 172.36 176.735 172.68C176.436 172.989 176.266 173.443 176.223 174.04H179.359V173.768C179.359 172.723 178.9 172.2 177.983 172.2ZM185.199 179L182.095 170.824H184.575L186.319 176.904L188.095 170.824H190.511L187.423 179H185.199ZM193.286 175.48C193.329 176.184 193.542 176.696 193.926 177.016C194.31 177.325 194.913 177.48 195.734 177.48C196.449 177.48 197.281 177.347 198.23 177.08V178.632C197.857 178.824 197.409 178.973 196.886 179.08C196.374 179.187 195.841 179.24 195.286 179.24C193.931 179.24 192.897 178.872 192.182 178.136C191.478 177.4 191.126 176.323 191.126 174.904C191.126 173.539 191.478 172.477 192.182 171.72C192.886 170.963 193.862 170.584 195.11 170.584C196.166 170.584 196.977 170.877 197.542 171.464C198.118 172.04 198.406 172.867 198.406 173.944C198.406 174.179 198.39 174.445 198.358 174.744C198.326 175.043 198.289 175.288 198.246 175.48H193.286ZM195.03 172.2C194.507 172.2 194.091 172.36 193.782 172.68C193.483 172.989 193.313 173.443 193.27 174.04H196.406V173.768C196.406 172.723 195.947 172.2 195.03 172.2ZM203.798 178.84C203.35 179.021 202.87 179.112 202.358 179.112C200.918 179.112 200.198 178.307 200.198 176.696V167.16H202.534V176.504C202.534 176.803 202.582 177.016 202.678 177.144C202.785 177.261 202.955 177.32 203.19 177.32C203.339 177.32 203.542 177.304 203.798 177.272V178.84ZM208.877 179.24C207.608 179.24 206.616 178.861 205.901 178.104C205.186 177.336 204.829 176.269 204.829 174.904C204.829 173.549 205.186 172.493 205.901 171.736C206.616 170.968 207.608 170.584 208.877 170.584C210.146 170.584 211.138 170.968 211.853 171.736C212.568 172.493 212.925 173.549 212.925 174.904C212.925 176.269 212.568 177.336 211.853 178.104C211.138 178.861 210.146 179.24 208.877 179.24ZM208.877 177.448C209.997 177.448 210.557 176.6 210.557 174.904C210.557 173.219 209.997 172.376 208.877 172.376C207.757 172.376 207.197 173.219 207.197 174.904C207.197 176.6 207.757 177.448 208.877 177.448ZM214.745 182.296V170.824H216.665L216.857 171.592C217.177 171.283 217.561 171.037 218.009 170.856C218.468 170.675 218.932 170.584 219.401 170.584C220.436 170.584 221.252 170.963 221.849 171.72C222.457 172.477 222.761 173.501 222.761 174.792C222.761 175.635 222.622 176.387 222.345 177.048C222.068 177.709 221.668 178.232 221.145 178.616C220.622 178.989 220.02 179.176 219.337 179.176C218.9 179.176 218.484 179.107 218.089 178.968C217.694 178.829 217.358 178.637 217.081 178.392V182.296H214.745ZM218.649 172.344C218.094 172.344 217.572 172.488 217.081 172.776V176.984C217.55 177.272 218.073 177.416 218.649 177.416C219.246 177.416 219.684 177.213 219.961 176.808C220.249 176.403 220.393 175.763 220.393 174.888C220.393 174.003 220.254 173.357 219.977 172.952C219.7 172.547 219.257 172.344 218.649 172.344ZM226.333 175.48C226.375 176.184 226.589 176.696 226.973 177.016C227.357 177.325 227.959 177.48 228.781 177.48C229.495 177.48 230.327 177.347 231.277 177.08V178.632C230.903 178.824 230.455 178.973 229.933 179.08C229.421 179.187 228.887 179.24 228.333 179.24C226.978 179.24 225.943 178.872 225.229 178.136C224.525 177.4 224.173 176.323 224.173 174.904C224.173 173.539 224.525 172.477 225.229 171.72C225.933 170.963 226.909 170.584 228.157 170.584C229.213 170.584 230.023 170.877 230.589 171.464C231.165 172.04 231.453 172.867 231.453 173.944C231.453 174.179 231.437 174.445 231.405 174.744C231.373 175.043 231.335 175.288 231.293 175.48H226.333ZM228.077 172.2C227.554 172.2 227.138 172.36 226.829 172.68C226.53 172.989 226.359 173.443 226.317 174.04H229.453V173.768C229.453 172.723 228.994 172.2 228.077 172.2ZM233.245 179V170.824H235.165L235.453 172.04C235.88 171.571 236.28 171.24 236.653 171.048C237.037 170.845 237.442 170.744 237.869 170.744C238.072 170.744 238.285 170.76 238.509 170.792V172.952C238.21 172.888 237.88 172.856 237.517 172.856C236.824 172.856 236.178 172.979 235.581 173.224V179H233.245Z" fill="#414D5C"/> -<rect x="368" y="147" width="48" height="48" fill="#DD344C"/> -<path fill-rule="evenodd" clip-rule="evenodd" d="M408.463 184.395L399.536 175.468C399.351 175.283 399.307 174.999 399.427 174.768C400.674 172.366 400.195 169.339 398.263 167.407C396.886 166.029 394.983 165.375 393.049 165.608C391.111 165.842 389.402 166.961 388.362 168.677C387.139 170.693 387.193 173.278 388.5 175.265C390.312 178.022 393.846 178.975 396.718 177.485C396.951 177.365 397.233 177.408 397.419 177.594L398.9 179.075C399.012 179.187 399.075 179.34 399.075 179.499V181.445H401.021C401.179 181.445 401.332 181.508 401.445 181.62L402.294 182.468C402.406 182.581 402.47 182.733 402.47 182.893V184.838H404.415C404.575 184.838 404.727 184.902 404.839 185.014L405.952 186.128L408.318 186.285L408.463 184.395ZM409.68 184.212L409.468 186.969C409.444 187.284 409.182 187.523 408.871 187.523C408.857 187.523 408.844 187.523 408.83 187.522L405.648 187.31C405.502 187.3 405.366 187.238 405.264 187.136L404.167 186.038H401.87C401.538 186.038 401.27 185.77 401.27 185.438V183.141L400.773 182.645H398.475C398.144 182.645 397.875 182.376 397.875 182.045V179.747L396.872 178.743C393.528 180.235 389.565 179.07 387.496 175.924C385.938 173.553 385.875 170.464 387.335 168.055C388.569 166.021 390.599 164.695 392.904 164.417C395.209 164.139 397.472 164.919 399.112 166.559C401.304 168.75 401.922 172.13 400.685 174.92L409.506 183.741C409.63 183.866 409.694 184.037 409.68 184.212V184.212ZM395.254 171.807C395.254 171.407 395.098 171.03 394.814 170.747C394.53 170.463 394.153 170.307 393.753 170.307C393.353 170.307 392.976 170.463 392.693 170.746C392.108 171.331 392.108 172.283 392.693 172.868C393.277 173.453 394.229 173.453 394.814 172.868V172.868C395.098 172.584 395.254 172.208 395.254 171.807V171.807ZM395.662 169.898C396.173 170.408 396.454 171.086 396.454 171.807C396.454 172.528 396.173 173.206 395.662 173.716V173.717C395.136 174.243 394.445 174.506 393.753 174.506C393.062 174.506 392.371 174.243 391.845 173.716C390.792 172.663 390.792 170.95 391.845 169.898C392.354 169.388 393.032 169.107 393.753 169.107C394.475 169.107 395.152 169.388 395.662 169.898V169.898ZM381.201 173.953H384.8V175.153H381.2C377.688 175.145 374.796 172.654 374.614 169.481C374.607 169.331 374.6 169.192 374.6 169.053C374.6 165.138 377.376 163.683 379.011 163.167C379 162.994 378.994 162.819 378.994 162.642C378.994 159.432 381.249 156.109 384.238 154.913C387.722 153.507 391.417 154.206 394.116 156.784C394.828 157.456 395.739 158.46 396.377 159.685C397.059 159.086 397.828 158.793 398.71 158.793C400.452 158.793 402.404 160.194 402.759 163.258C406.37 164.083 408.2 166.065 408.2 169.153C408.2 172.409 406.267 174.594 402.897 175.145L402.703 173.961C404.663 173.64 407 172.545 407 169.153C407 166.524 405.438 164.996 402.085 164.342C401.817 164.289 401.617 164.062 401.601 163.789C401.466 161.554 400.277 159.993 398.71 159.993C397.909 159.993 397.281 160.341 396.673 161.121C396.54 161.293 396.325 161.378 396.109 161.346C395.895 161.313 395.714 161.167 395.638 160.964C395.115 159.566 394.072 158.393 393.29 157.655C390.939 155.409 387.723 154.802 384.685 156.027C382.166 157.034 380.194 159.94 380.194 162.642C380.194 162.945 380.212 163.236 380.25 163.533C380.253 163.555 380.254 163.578 380.254 163.601V163.602V163.603V163.604V163.605V163.605V163.607V163.607V163.607V163.608V163.609C380.254 163.912 380.03 164.165 379.738 164.207C378.239 164.587 375.8 165.719 375.8 169.053C375.8 169.171 375.806 169.289 375.812 169.403C375.957 171.952 378.325 173.947 381.201 173.953V173.953Z" fill="white"/> -<path d="M428.344 167V155.912H430.744V167H428.344ZM440.03 167L439.246 164.472H435.454L434.702 167H432.19L436.094 155.912H438.734L442.638 167H440.03ZM435.966 162.744H438.75L437.342 158.104L435.966 162.744ZM453.166 167V159.32L450.718 164.296H448.574L446.126 159.32V167H444.014V155.912H446.638L449.662 162.216L452.702 155.912H455.278V167H453.166ZM428.344 186V174.912H430.744V186H428.344ZM438.734 186L438.542 185.28C437.88 185.877 437.096 186.176 436.19 186.176C435.518 186.176 434.926 186.011 434.414 185.68C433.902 185.339 433.502 184.848 433.214 184.208C432.936 183.568 432.798 182.816 432.798 181.952C432.798 180.629 433.112 179.573 433.742 178.784C434.371 177.984 435.203 177.584 436.238 177.584C437.08 177.584 437.811 177.824 438.43 178.304V174.16H440.766V186H438.734ZM436.958 184.416C437.47 184.416 437.96 184.267 438.43 183.968V179.744C437.971 179.477 437.443 179.344 436.846 179.344C436.28 179.344 435.859 179.557 435.582 179.984C435.304 180.4 435.166 181.035 435.166 181.888C435.166 182.741 435.31 183.376 435.598 183.792C435.896 184.208 436.35 184.416 436.958 184.416ZM444.755 182.48C444.797 183.184 445.011 183.696 445.395 184.016C445.779 184.325 446.381 184.48 447.203 184.48C447.917 184.48 448.749 184.347 449.699 184.08V185.632C449.325 185.824 448.877 185.973 448.355 186.08C447.843 186.187 447.309 186.24 446.755 186.24C445.4 186.24 444.365 185.872 443.651 185.136C442.947 184.4 442.595 183.323 442.595 181.904C442.595 180.539 442.947 179.477 443.651 178.72C444.355 177.963 445.331 177.584 446.579 177.584C447.635 177.584 448.445 177.877 449.011 178.464C449.587 179.04 449.875 179.867 449.875 180.944C449.875 181.179 449.859 181.445 449.827 181.744C449.795 182.043 449.757 182.288 449.715 182.48H444.755ZM446.499 179.2C445.976 179.2 445.56 179.36 445.251 179.68C444.952 179.989 444.781 180.443 444.739 181.04H447.875V180.768C447.875 179.723 447.416 179.2 446.499 179.2ZM456.915 186V180.64C456.915 180.203 456.819 179.883 456.627 179.68C456.435 179.477 456.142 179.376 455.747 179.376C455.16 179.376 454.579 179.557 454.003 179.92V186H451.667V177.824H453.587L453.811 178.704C454.771 177.957 455.795 177.584 456.883 177.584C457.64 177.584 458.222 177.792 458.627 178.208C459.043 178.613 459.251 179.195 459.251 179.952V186H456.915ZM466.328 185.792C465.752 186.016 465.106 186.128 464.392 186.128C463.485 186.128 462.813 185.915 462.376 185.488C461.949 185.061 461.736 184.4 461.736 183.504V179.552H460.504V178.112L461.8 177.856L462.152 175.616H464.072V177.824H466.28V179.552H464.072V183.392C464.072 183.733 464.157 183.973 464.328 184.112C464.498 184.251 464.786 184.32 465.192 184.32C465.522 184.32 465.901 184.288 466.328 184.224V185.792ZM467.825 186V177.824H470.161V186H467.825ZM468.993 176.56C468.587 176.56 468.262 176.448 468.017 176.224C467.771 176 467.649 175.696 467.649 175.312C467.649 174.928 467.771 174.624 468.017 174.4C468.262 174.176 468.587 174.064 468.993 174.064C469.398 174.064 469.723 174.176 469.969 174.4C470.214 174.624 470.337 174.928 470.337 175.312C470.337 175.696 470.214 176 469.969 176.224C469.723 176.448 469.398 176.56 468.993 176.56ZM477.328 185.792C476.752 186.016 476.106 186.128 475.392 186.128C474.485 186.128 473.813 185.915 473.376 185.488C472.949 185.061 472.736 184.4 472.736 183.504V179.552H471.504V178.112L472.8 177.856L473.152 175.616H475.072V177.824H477.28V179.552H475.072V183.392C475.072 183.733 475.157 183.973 475.328 184.112C475.498 184.251 475.786 184.32 476.192 184.32C476.522 184.32 476.901 184.288 477.328 184.224V185.792ZM481.421 186.128L478.189 177.824H480.669L482.493 183.936L484.221 177.824H486.637L483.181 187.104C482.872 187.947 482.493 188.555 482.045 188.928C481.597 189.301 481.032 189.488 480.349 189.488C479.816 189.488 479.298 189.403 478.797 189.232V187.648C479.138 187.68 479.442 187.696 479.709 187.696C480.157 187.696 480.504 187.589 480.749 187.376C480.994 187.173 481.202 186.816 481.373 186.304L481.421 186.128ZM500.235 185.712C499.371 186.043 498.405 186.208 497.339 186.208C495.536 186.208 494.171 185.728 493.243 184.768C492.315 183.797 491.851 182.379 491.851 180.512C491.851 178.667 492.336 177.237 493.307 176.224C494.277 175.211 495.643 174.704 497.403 174.704C498.341 174.704 499.232 174.853 500.075 175.152V177.04C499.104 176.827 498.309 176.72 497.691 176.72C496.581 176.72 495.749 177.013 495.195 177.6C494.651 178.187 494.379 179.083 494.379 180.288V180.656C494.379 181.851 494.645 182.741 495.179 183.328C495.712 183.904 496.528 184.192 497.627 184.192C498.245 184.192 499.115 184.069 500.235 183.824V185.712ZM503.598 182.48C503.641 183.184 503.854 183.696 504.238 184.016C504.622 184.325 505.225 184.48 506.046 184.48C506.761 184.48 507.593 184.347 508.542 184.08V185.632C508.169 185.824 507.721 185.973 507.198 186.08C506.686 186.187 506.153 186.24 505.598 186.24C504.244 186.24 503.209 185.872 502.494 185.136C501.79 184.4 501.438 183.323 501.438 181.904C501.438 180.539 501.79 179.477 502.494 178.72C503.198 177.963 504.174 177.584 505.422 177.584C506.478 177.584 507.289 177.877 507.854 178.464C508.43 179.04 508.718 179.867 508.718 180.944C508.718 181.179 508.702 181.445 508.67 181.744C508.638 182.043 508.601 182.288 508.558 182.48H503.598ZM505.342 179.2C504.82 179.2 504.404 179.36 504.094 179.68C503.796 179.989 503.625 180.443 503.582 181.04H506.718V180.768C506.718 179.723 506.26 179.2 505.342 179.2ZM515.759 186V180.64C515.759 180.203 515.663 179.883 515.471 179.68C515.279 179.477 514.985 179.376 514.591 179.376C514.004 179.376 513.423 179.557 512.847 179.92V186H510.511V177.824H512.431L512.655 178.704C513.615 177.957 514.639 177.584 515.727 177.584C516.484 177.584 517.065 177.792 517.471 178.208C517.887 178.613 518.095 179.195 518.095 179.952V186H515.759ZM525.172 185.792C524.596 186.016 523.95 186.128 523.236 186.128C522.329 186.128 521.657 185.915 521.22 185.488C520.793 185.061 520.58 184.4 520.58 183.504V179.552H519.348V178.112L520.644 177.856L520.996 175.616H522.916V177.824H525.124V179.552H522.916V183.392C522.916 183.733 523.001 183.973 523.172 184.112C523.342 184.251 523.63 184.32 524.036 184.32C524.366 184.32 524.745 184.288 525.172 184.224V185.792ZM528.348 182.48C528.391 183.184 528.604 183.696 528.988 184.016C529.372 184.325 529.975 184.48 530.796 184.48C531.511 184.48 532.343 184.347 533.292 184.08V185.632C532.919 185.824 532.471 185.973 531.948 186.08C531.436 186.187 530.903 186.24 530.348 186.24C528.994 186.24 527.959 185.872 527.244 185.136C526.54 184.4 526.188 183.323 526.188 181.904C526.188 180.539 526.54 179.477 527.244 178.72C527.948 177.963 528.924 177.584 530.172 177.584C531.228 177.584 532.039 177.877 532.604 178.464C533.18 179.04 533.468 179.867 533.468 180.944C533.468 181.179 533.452 181.445 533.42 181.744C533.388 182.043 533.351 182.288 533.308 182.48H528.348ZM530.092 179.2C529.57 179.2 529.154 179.36 528.844 179.68C528.546 179.989 528.375 180.443 528.332 181.04H531.468V180.768C531.468 179.723 531.01 179.2 530.092 179.2ZM535.261 186V177.824H537.181L537.469 179.04C537.895 178.571 538.295 178.24 538.669 178.048C539.053 177.845 539.458 177.744 539.885 177.744C540.087 177.744 540.301 177.76 540.525 177.792V179.952C540.226 179.888 539.895 179.856 539.533 179.856C538.839 179.856 538.194 179.979 537.597 180.224V186H535.261Z" fill="#414D5C"/> -<rect x="341" y="137" width="222" height="71" stroke="#7D8998" stroke-width="2"/> -<path d="M289.5 173L313 173C318.523 173 323 177.477 323 183L323 256C323 261.523 327.477 266 333 266L338.5 266" stroke="black" stroke-width="2"/> -<rect x="591" y="154" width="127" height="38" rx="19" fill="#F2FCF3"/> -<rect x="591" y="154" width="127" height="38" rx="19" stroke="#037F0C" stroke-width="2"/> -<path fill-rule="evenodd" clip-rule="evenodd" d="M610 181C605.582 181 602 177.418 602 173C602 168.582 605.582 165 610 165C614.418 165 618 168.582 618 173C618 177.418 614.418 181 610 181ZM610 179C613.314 179 616 176.314 616 173C616 169.686 613.314 167 610 167C606.686 167 604 169.686 604 173C604 176.314 606.686 179 610 179ZM605.586 173L607 171.586L609 173.586L612.52 170.066L613.934 171.48L609 176.414L605.586 173Z" fill="#037F0C"/> -<path d="M633.331 178L632.645 175.788H629.327L628.669 178H626.471L629.887 168.298H632.197L635.613 178H633.331ZM629.775 174.276H632.211L630.979 170.216L629.775 174.276ZM639.715 176.026C639.715 175.839 639.659 175.695 639.547 175.592C639.445 175.489 639.23 175.377 638.903 175.256L637.811 174.822C637.242 174.598 636.831 174.323 636.579 173.996C636.327 173.669 636.201 173.254 636.201 172.75C636.201 172.115 636.453 171.607 636.957 171.224C637.471 170.832 638.152 170.636 639.001 170.636C639.785 170.636 640.509 170.79 641.171 171.098V172.456C640.462 172.241 639.799 172.134 639.183 172.134C638.801 172.134 638.521 172.181 638.343 172.274C638.166 172.367 638.077 172.517 638.077 172.722C638.077 172.881 638.129 173.011 638.231 173.114C638.343 173.207 638.572 173.324 638.917 173.464L639.981 173.898C640.56 174.131 640.971 174.402 641.213 174.71C641.465 175.018 641.591 175.419 641.591 175.914C641.591 176.605 641.325 177.165 640.793 177.594C640.271 178.014 639.58 178.224 638.721 178.224C637.76 178.224 636.911 178.033 636.173 177.65V176.292C637.097 176.581 637.942 176.726 638.707 176.726C639.379 176.726 639.715 176.493 639.715 176.026ZM645.95 176.026C645.95 175.839 645.894 175.695 645.782 175.592C645.679 175.489 645.464 175.377 645.138 175.256L644.046 174.822C643.476 174.598 643.066 174.323 642.814 173.996C642.562 173.669 642.436 173.254 642.436 172.75C642.436 172.115 642.688 171.607 643.192 171.224C643.705 170.832 644.386 170.636 645.236 170.636C646.02 170.636 646.743 170.79 647.406 171.098V172.456C646.696 172.241 646.034 172.134 645.418 172.134C645.035 172.134 644.755 172.181 644.578 172.274C644.4 172.367 644.312 172.517 644.312 172.722C644.312 172.881 644.363 173.011 644.466 173.114C644.578 173.207 644.806 173.324 645.152 173.464L646.216 173.898C646.794 174.131 647.205 174.402 647.448 174.71C647.7 175.018 647.826 175.419 647.826 175.914C647.826 176.605 647.56 177.165 647.028 177.594C646.505 178.014 645.814 178.224 644.956 178.224C643.994 178.224 643.145 178.033 642.408 177.65V176.292C643.332 176.581 644.176 176.726 644.942 176.726C645.614 176.726 645.95 176.493 645.95 176.026ZM653.906 178L653.71 177.244C652.879 177.888 652.011 178.21 651.106 178.21C650.471 178.21 649.977 178.023 649.622 177.65C649.267 177.267 649.09 176.745 649.09 176.082V170.846H651.134V175.508C651.134 176.264 651.461 176.642 652.114 176.642C652.599 176.642 653.075 176.493 653.542 176.194V170.846H655.586V178H653.906ZM666.403 178V173.156C666.403 172.521 666.118 172.204 665.549 172.204C665.045 172.204 664.536 172.325 664.023 172.568V172.708V178H661.979V173.156C661.979 172.521 661.694 172.204 661.125 172.204C660.602 172.204 660.089 172.33 659.585 172.582V178H657.541V170.846H659.221L659.403 171.532C659.897 171.205 660.341 170.977 660.733 170.846C661.134 170.706 661.545 170.636 661.965 170.636C662.805 170.636 663.397 170.935 663.743 171.532C664.219 171.215 664.667 170.986 665.087 170.846C665.507 170.706 665.941 170.636 666.389 170.636C667.042 170.636 667.546 170.818 667.901 171.182C668.265 171.546 668.447 172.055 668.447 172.708V178H666.403ZM671.904 174.92C671.942 175.536 672.128 175.984 672.464 176.264C672.8 176.535 673.328 176.67 674.046 176.67C674.672 176.67 675.4 176.553 676.23 176.32V177.678C675.904 177.846 675.512 177.977 675.054 178.07C674.606 178.163 674.14 178.21 673.654 178.21C672.469 178.21 671.564 177.888 670.938 177.244C670.322 176.6 670.014 175.657 670.014 174.416C670.014 173.221 670.322 172.293 670.938 171.63C671.554 170.967 672.408 170.636 673.5 170.636C674.424 170.636 675.134 170.893 675.628 171.406C676.132 171.91 676.384 172.633 676.384 173.576C676.384 173.781 676.37 174.015 676.342 174.276C676.314 174.537 676.282 174.752 676.244 174.92H671.904ZM673.43 172.05C672.973 172.05 672.609 172.19 672.338 172.47C672.077 172.741 671.928 173.137 671.89 173.66H674.634V173.422C674.634 172.507 674.233 172.05 673.43 172.05ZM681.617 178V170.846H683.297L683.549 171.91C683.922 171.499 684.272 171.21 684.599 171.042C684.935 170.865 685.289 170.776 685.663 170.776C685.84 170.776 686.027 170.79 686.223 170.818V172.708C685.961 172.652 685.672 172.624 685.355 172.624C684.748 172.624 684.183 172.731 683.661 172.946V178H681.617ZM690.469 178.21C689.358 178.21 688.49 177.879 687.865 177.216C687.239 176.544 686.927 175.611 686.927 174.416C686.927 173.231 687.239 172.307 687.865 171.644C688.49 170.972 689.358 170.636 690.469 170.636C691.579 170.636 692.447 170.972 693.073 171.644C693.698 172.307 694.011 173.231 694.011 174.416C694.011 175.611 693.698 176.544 693.073 177.216C692.447 177.879 691.579 178.21 690.469 178.21ZM690.469 176.642C691.449 176.642 691.939 175.9 691.939 174.416C691.939 172.941 691.449 172.204 690.469 172.204C689.489 172.204 688.999 172.941 688.999 174.416C688.999 175.9 689.489 176.642 690.469 176.642ZM698.753 177.86C698.361 178.019 697.941 178.098 697.493 178.098C696.233 178.098 695.603 177.393 695.603 175.984V167.64H697.647V175.816C697.647 176.077 697.689 176.264 697.773 176.376C697.866 176.479 698.016 176.53 698.221 176.53C698.352 176.53 698.529 176.516 698.753 176.488V177.86ZM701.545 174.92C701.582 175.536 701.769 175.984 702.105 176.264C702.441 176.535 702.968 176.67 703.687 176.67C704.312 176.67 705.04 176.553 705.871 176.32V177.678C705.544 177.846 705.152 177.977 704.695 178.07C704.247 178.163 703.78 178.21 703.295 178.21C702.11 178.21 701.204 177.888 700.579 177.244C699.963 176.6 699.655 175.657 699.655 174.416C699.655 173.221 699.963 172.293 700.579 171.63C701.195 170.967 702.049 170.636 703.141 170.636C704.065 170.636 704.774 170.893 705.269 171.406C705.773 171.91 706.025 172.633 706.025 173.576C706.025 173.781 706.011 174.015 705.983 174.276C705.955 174.537 705.922 174.752 705.885 174.92H701.545ZM703.071 172.05C702.614 172.05 702.25 172.19 701.979 172.47C701.718 172.741 701.568 173.137 701.531 173.66H704.275V173.422C704.275 172.507 703.874 172.05 703.071 172.05Z" fill="#037F0C"/> -<rect x="591" y="247" width="127" height="38" rx="19" fill="#F2FCF3"/> -<rect x="591" y="247" width="127" height="38" rx="19" stroke="#037F0C" stroke-width="2"/> -<path fill-rule="evenodd" clip-rule="evenodd" d="M610 274C605.582 274 602 270.418 602 266C602 261.582 605.582 258 610 258C614.418 258 618 261.582 618 266C618 270.418 614.418 274 610 274ZM610 272C613.314 272 616 269.314 616 266C616 262.686 613.314 260 610 260C606.686 260 604 262.686 604 266C604 269.314 606.686 272 610 272ZM605.586 266L607 264.586L609 266.586L612.52 263.066L613.934 264.48L609 269.414L605.586 266Z" fill="#037F0C"/> -<path d="M633.331 271L632.645 268.788H629.327L628.669 271H626.471L629.887 261.298H632.197L635.613 271H633.331ZM629.775 267.276H632.211L630.979 263.216L629.775 267.276ZM639.715 269.026C639.715 268.839 639.659 268.695 639.547 268.592C639.445 268.489 639.23 268.377 638.903 268.256L637.811 267.822C637.242 267.598 636.831 267.323 636.579 266.996C636.327 266.669 636.201 266.254 636.201 265.75C636.201 265.115 636.453 264.607 636.957 264.224C637.471 263.832 638.152 263.636 639.001 263.636C639.785 263.636 640.509 263.79 641.171 264.098V265.456C640.462 265.241 639.799 265.134 639.183 265.134C638.801 265.134 638.521 265.181 638.343 265.274C638.166 265.367 638.077 265.517 638.077 265.722C638.077 265.881 638.129 266.011 638.231 266.114C638.343 266.207 638.572 266.324 638.917 266.464L639.981 266.898C640.56 267.131 640.971 267.402 641.213 267.71C641.465 268.018 641.591 268.419 641.591 268.914C641.591 269.605 641.325 270.165 640.793 270.594C640.271 271.014 639.58 271.224 638.721 271.224C637.76 271.224 636.911 271.033 636.173 270.65V269.292C637.097 269.581 637.942 269.726 638.707 269.726C639.379 269.726 639.715 269.493 639.715 269.026ZM645.95 269.026C645.95 268.839 645.894 268.695 645.782 268.592C645.679 268.489 645.464 268.377 645.138 268.256L644.046 267.822C643.476 267.598 643.066 267.323 642.814 266.996C642.562 266.669 642.436 266.254 642.436 265.75C642.436 265.115 642.688 264.607 643.192 264.224C643.705 263.832 644.386 263.636 645.236 263.636C646.02 263.636 646.743 263.79 647.406 264.098V265.456C646.696 265.241 646.034 265.134 645.418 265.134C645.035 265.134 644.755 265.181 644.578 265.274C644.4 265.367 644.312 265.517 644.312 265.722C644.312 265.881 644.363 266.011 644.466 266.114C644.578 266.207 644.806 266.324 645.152 266.464L646.216 266.898C646.794 267.131 647.205 267.402 647.448 267.71C647.7 268.018 647.826 268.419 647.826 268.914C647.826 269.605 647.56 270.165 647.028 270.594C646.505 271.014 645.814 271.224 644.956 271.224C643.994 271.224 643.145 271.033 642.408 270.65V269.292C643.332 269.581 644.176 269.726 644.942 269.726C645.614 269.726 645.95 269.493 645.95 269.026ZM653.906 271L653.71 270.244C652.879 270.888 652.011 271.21 651.106 271.21C650.471 271.21 649.977 271.023 649.622 270.65C649.267 270.267 649.09 269.745 649.09 269.082V263.846H651.134V268.508C651.134 269.264 651.461 269.642 652.114 269.642C652.599 269.642 653.075 269.493 653.542 269.194V263.846H655.586V271H653.906ZM666.403 271V266.156C666.403 265.521 666.118 265.204 665.549 265.204C665.045 265.204 664.536 265.325 664.023 265.568V265.708V271H661.979V266.156C661.979 265.521 661.694 265.204 661.125 265.204C660.602 265.204 660.089 265.33 659.585 265.582V271H657.541V263.846H659.221L659.403 264.532C659.897 264.205 660.341 263.977 660.733 263.846C661.134 263.706 661.545 263.636 661.965 263.636C662.805 263.636 663.397 263.935 663.743 264.532C664.219 264.215 664.667 263.986 665.087 263.846C665.507 263.706 665.941 263.636 666.389 263.636C667.042 263.636 667.546 263.818 667.901 264.182C668.265 264.546 668.447 265.055 668.447 265.708V271H666.403ZM671.904 267.92C671.942 268.536 672.128 268.984 672.464 269.264C672.8 269.535 673.328 269.67 674.046 269.67C674.672 269.67 675.4 269.553 676.23 269.32V270.678C675.904 270.846 675.512 270.977 675.054 271.07C674.606 271.163 674.14 271.21 673.654 271.21C672.469 271.21 671.564 270.888 670.938 270.244C670.322 269.6 670.014 268.657 670.014 267.416C670.014 266.221 670.322 265.293 670.938 264.63C671.554 263.967 672.408 263.636 673.5 263.636C674.424 263.636 675.134 263.893 675.628 264.406C676.132 264.91 676.384 265.633 676.384 266.576C676.384 266.781 676.37 267.015 676.342 267.276C676.314 267.537 676.282 267.752 676.244 267.92H671.904ZM673.43 265.05C672.973 265.05 672.609 265.19 672.338 265.47C672.077 265.741 671.928 266.137 671.89 266.66H674.634V266.422C674.634 265.507 674.233 265.05 673.43 265.05ZM681.617 271V263.846H683.297L683.549 264.91C683.922 264.499 684.272 264.21 684.599 264.042C684.935 263.865 685.289 263.776 685.663 263.776C685.84 263.776 686.027 263.79 686.223 263.818V265.708C685.961 265.652 685.672 265.624 685.355 265.624C684.748 265.624 684.183 265.731 683.661 265.946V271H681.617ZM690.469 271.21C689.358 271.21 688.49 270.879 687.865 270.216C687.239 269.544 686.927 268.611 686.927 267.416C686.927 266.231 687.239 265.307 687.865 264.644C688.49 263.972 689.358 263.636 690.469 263.636C691.579 263.636 692.447 263.972 693.073 264.644C693.698 265.307 694.011 266.231 694.011 267.416C694.011 268.611 693.698 269.544 693.073 270.216C692.447 270.879 691.579 271.21 690.469 271.21ZM690.469 269.642C691.449 269.642 691.939 268.9 691.939 267.416C691.939 265.941 691.449 265.204 690.469 265.204C689.489 265.204 688.999 265.941 688.999 267.416C688.999 268.9 689.489 269.642 690.469 269.642ZM698.753 270.86C698.361 271.019 697.941 271.098 697.493 271.098C696.233 271.098 695.603 270.393 695.603 268.984V260.64H697.647V268.816C697.647 269.077 697.689 269.264 697.773 269.376C697.866 269.479 698.016 269.53 698.221 269.53C698.352 269.53 698.529 269.516 698.753 269.488V270.86ZM701.545 267.92C701.582 268.536 701.769 268.984 702.105 269.264C702.441 269.535 702.968 269.67 703.687 269.67C704.312 269.67 705.04 269.553 705.871 269.32V270.678C705.544 270.846 705.152 270.977 704.695 271.07C704.247 271.163 703.78 271.21 703.295 271.21C702.11 271.21 701.204 270.888 700.579 270.244C699.963 269.6 699.655 268.657 699.655 267.416C699.655 266.221 699.963 265.293 700.579 264.63C701.195 263.967 702.049 263.636 703.141 263.636C704.065 263.636 704.774 263.893 705.269 264.406C705.773 264.91 706.025 265.633 706.025 266.576C706.025 266.781 706.011 267.015 705.983 267.276C705.955 267.537 705.922 267.752 705.885 267.92H701.545ZM703.071 265.05C702.614 265.05 702.25 265.19 701.979 265.47C701.718 265.741 701.568 266.137 701.531 266.66H704.275V266.422C704.275 265.507 703.874 265.05 703.071 265.05Z" fill="#037F0C"/> -<rect x="591" y="335" width="127" height="38" rx="19" fill="#F2FCF3"/> -<rect x="591" y="335" width="127" height="38" rx="19" stroke="#037F0C" stroke-width="2"/> -<path fill-rule="evenodd" clip-rule="evenodd" d="M610 362C605.582 362 602 358.418 602 354C602 349.582 605.582 346 610 346C614.418 346 618 349.582 618 354C618 358.418 614.418 362 610 362ZM610 360C613.314 360 616 357.314 616 354C616 350.686 613.314 348 610 348C606.686 348 604 350.686 604 354C604 357.314 606.686 360 610 360ZM605.586 354L607 352.586L609 354.586L612.52 351.066L613.934 352.48L609 357.414L605.586 354Z" fill="#037F0C"/> -<path d="M633.331 359L632.645 356.788H629.327L628.669 359H626.471L629.887 349.298H632.197L635.613 359H633.331ZM629.775 355.276H632.211L630.979 351.216L629.775 355.276ZM639.715 357.026C639.715 356.839 639.659 356.695 639.547 356.592C639.445 356.489 639.23 356.377 638.903 356.256L637.811 355.822C637.242 355.598 636.831 355.323 636.579 354.996C636.327 354.669 636.201 354.254 636.201 353.75C636.201 353.115 636.453 352.607 636.957 352.224C637.471 351.832 638.152 351.636 639.001 351.636C639.785 351.636 640.509 351.79 641.171 352.098V353.456C640.462 353.241 639.799 353.134 639.183 353.134C638.801 353.134 638.521 353.181 638.343 353.274C638.166 353.367 638.077 353.517 638.077 353.722C638.077 353.881 638.129 354.011 638.231 354.114C638.343 354.207 638.572 354.324 638.917 354.464L639.981 354.898C640.56 355.131 640.971 355.402 641.213 355.71C641.465 356.018 641.591 356.419 641.591 356.914C641.591 357.605 641.325 358.165 640.793 358.594C640.271 359.014 639.58 359.224 638.721 359.224C637.76 359.224 636.911 359.033 636.173 358.65V357.292C637.097 357.581 637.942 357.726 638.707 357.726C639.379 357.726 639.715 357.493 639.715 357.026ZM645.95 357.026C645.95 356.839 645.894 356.695 645.782 356.592C645.679 356.489 645.464 356.377 645.138 356.256L644.046 355.822C643.476 355.598 643.066 355.323 642.814 354.996C642.562 354.669 642.436 354.254 642.436 353.75C642.436 353.115 642.688 352.607 643.192 352.224C643.705 351.832 644.386 351.636 645.236 351.636C646.02 351.636 646.743 351.79 647.406 352.098V353.456C646.696 353.241 646.034 353.134 645.418 353.134C645.035 353.134 644.755 353.181 644.578 353.274C644.4 353.367 644.312 353.517 644.312 353.722C644.312 353.881 644.363 354.011 644.466 354.114C644.578 354.207 644.806 354.324 645.152 354.464L646.216 354.898C646.794 355.131 647.205 355.402 647.448 355.71C647.7 356.018 647.826 356.419 647.826 356.914C647.826 357.605 647.56 358.165 647.028 358.594C646.505 359.014 645.814 359.224 644.956 359.224C643.994 359.224 643.145 359.033 642.408 358.65V357.292C643.332 357.581 644.176 357.726 644.942 357.726C645.614 357.726 645.95 357.493 645.95 357.026ZM653.906 359L653.71 358.244C652.879 358.888 652.011 359.21 651.106 359.21C650.471 359.21 649.977 359.023 649.622 358.65C649.267 358.267 649.09 357.745 649.09 357.082V351.846H651.134V356.508C651.134 357.264 651.461 357.642 652.114 357.642C652.599 357.642 653.075 357.493 653.542 357.194V351.846H655.586V359H653.906ZM666.403 359V354.156C666.403 353.521 666.118 353.204 665.549 353.204C665.045 353.204 664.536 353.325 664.023 353.568V353.708V359H661.979V354.156C661.979 353.521 661.694 353.204 661.125 353.204C660.602 353.204 660.089 353.33 659.585 353.582V359H657.541V351.846H659.221L659.403 352.532C659.897 352.205 660.341 351.977 660.733 351.846C661.134 351.706 661.545 351.636 661.965 351.636C662.805 351.636 663.397 351.935 663.743 352.532C664.219 352.215 664.667 351.986 665.087 351.846C665.507 351.706 665.941 351.636 666.389 351.636C667.042 351.636 667.546 351.818 667.901 352.182C668.265 352.546 668.447 353.055 668.447 353.708V359H666.403ZM671.904 355.92C671.942 356.536 672.128 356.984 672.464 357.264C672.8 357.535 673.328 357.67 674.046 357.67C674.672 357.67 675.4 357.553 676.23 357.32V358.678C675.904 358.846 675.512 358.977 675.054 359.07C674.606 359.163 674.14 359.21 673.654 359.21C672.469 359.21 671.564 358.888 670.938 358.244C670.322 357.6 670.014 356.657 670.014 355.416C670.014 354.221 670.322 353.293 670.938 352.63C671.554 351.967 672.408 351.636 673.5 351.636C674.424 351.636 675.134 351.893 675.628 352.406C676.132 352.91 676.384 353.633 676.384 354.576C676.384 354.781 676.37 355.015 676.342 355.276C676.314 355.537 676.282 355.752 676.244 355.92H671.904ZM673.43 353.05C672.973 353.05 672.609 353.19 672.338 353.47C672.077 353.741 671.928 354.137 671.89 354.66H674.634V354.422C674.634 353.507 674.233 353.05 673.43 353.05ZM681.617 359V351.846H683.297L683.549 352.91C683.922 352.499 684.272 352.21 684.599 352.042C684.935 351.865 685.289 351.776 685.663 351.776C685.84 351.776 686.027 351.79 686.223 351.818V353.708C685.961 353.652 685.672 353.624 685.355 353.624C684.748 353.624 684.183 353.731 683.661 353.946V359H681.617ZM690.469 359.21C689.358 359.21 688.49 358.879 687.865 358.216C687.239 357.544 686.927 356.611 686.927 355.416C686.927 354.231 687.239 353.307 687.865 352.644C688.49 351.972 689.358 351.636 690.469 351.636C691.579 351.636 692.447 351.972 693.073 352.644C693.698 353.307 694.011 354.231 694.011 355.416C694.011 356.611 693.698 357.544 693.073 358.216C692.447 358.879 691.579 359.21 690.469 359.21ZM690.469 357.642C691.449 357.642 691.939 356.9 691.939 355.416C691.939 353.941 691.449 353.204 690.469 353.204C689.489 353.204 688.999 353.941 688.999 355.416C688.999 356.9 689.489 357.642 690.469 357.642ZM698.753 358.86C698.361 359.019 697.941 359.098 697.493 359.098C696.233 359.098 695.603 358.393 695.603 356.984V348.64H697.647V356.816C697.647 357.077 697.689 357.264 697.773 357.376C697.866 357.479 698.016 357.53 698.221 357.53C698.352 357.53 698.529 357.516 698.753 357.488V358.86ZM701.545 355.92C701.582 356.536 701.769 356.984 702.105 357.264C702.441 357.535 702.968 357.67 703.687 357.67C704.312 357.67 705.04 357.553 705.871 357.32V358.678C705.544 358.846 705.152 358.977 704.695 359.07C704.247 359.163 703.78 359.21 703.295 359.21C702.11 359.21 701.204 358.888 700.579 358.244C699.963 357.6 699.655 356.657 699.655 355.416C699.655 354.221 699.963 353.293 700.579 352.63C701.195 351.967 702.049 351.636 703.141 351.636C704.065 351.636 704.774 351.893 705.269 352.406C705.773 352.91 706.025 353.633 706.025 354.576C706.025 354.781 706.011 355.015 705.983 355.276C705.955 355.537 705.922 355.752 705.885 355.92H701.545ZM703.071 353.05C702.614 353.05 702.25 353.19 701.979 353.47C701.718 353.741 701.568 354.137 701.531 354.66H704.275V354.422C704.275 353.507 703.874 353.05 703.071 353.05Z" fill="#037F0C"/> -<rect x="746" y="243" width="257" height="46" rx="5" fill="#0972D3"/> -<rect x="746" y="243" width="257" height="46" rx="5" stroke="#000716" stroke-width="2"/> -<path d="M789.384 272V260.912H793.368C795.021 260.912 796.29 261.392 797.176 262.352C798.072 263.301 798.52 264.667 798.52 266.448C798.52 268.219 798.072 269.589 797.176 270.56C796.29 271.52 795.037 272 793.416 272H789.384ZM791.784 262.768V270.144H793.16C795.09 270.144 796.056 268.965 796.056 266.608V266.288C796.056 263.941 795.085 262.768 793.144 262.768H791.784ZM802.263 268.48C802.305 269.184 802.519 269.696 802.903 270.016C803.287 270.325 803.889 270.48 804.711 270.48C805.425 270.48 806.257 270.347 807.207 270.08V271.632C806.833 271.824 806.385 271.973 805.863 272.08C805.351 272.187 804.817 272.24 804.263 272.24C802.908 272.24 801.873 271.872 801.159 271.136C800.455 270.4 800.103 269.323 800.103 267.904C800.103 266.539 800.455 265.477 801.159 264.72C801.863 263.963 802.839 263.584 804.087 263.584C805.143 263.584 805.953 263.877 806.519 264.464C807.095 265.04 807.383 265.867 807.383 266.944C807.383 267.179 807.367 267.445 807.335 267.744C807.303 268.043 807.265 268.288 807.223 268.48H802.263ZM804.007 265.2C803.484 265.2 803.068 265.36 802.759 265.68C802.46 265.989 802.289 266.443 802.247 267.04H805.383V266.768C805.383 265.723 804.924 265.2 804.007 265.2ZM809.095 275.296V263.824H811.015L811.207 264.592C811.527 264.283 811.911 264.037 812.359 263.856C812.818 263.675 813.282 263.584 813.751 263.584C814.786 263.584 815.602 263.963 816.199 264.72C816.807 265.477 817.111 266.501 817.111 267.792C817.111 268.635 816.972 269.387 816.695 270.048C816.418 270.709 816.018 271.232 815.495 271.616C814.972 271.989 814.37 272.176 813.687 272.176C813.25 272.176 812.834 272.107 812.439 271.968C812.044 271.829 811.708 271.637 811.431 271.392V275.296H809.095ZM812.999 265.344C812.444 265.344 811.922 265.488 811.431 265.776V269.984C811.9 270.272 812.423 270.416 812.999 270.416C813.596 270.416 814.034 270.213 814.311 269.808C814.599 269.403 814.743 268.763 814.743 267.888C814.743 267.003 814.604 266.357 814.327 265.952C814.05 265.547 813.607 265.344 812.999 265.344ZM822.459 271.84C822.011 272.021 821.531 272.112 821.019 272.112C819.579 272.112 818.859 271.307 818.859 269.696V260.16H821.195V269.504C821.195 269.803 821.243 270.016 821.339 270.144C821.445 270.261 821.616 270.32 821.851 270.32C822 270.32 822.203 270.304 822.459 270.272V271.84ZM827.458 272.24C826.188 272.24 825.196 271.861 824.482 271.104C823.767 270.336 823.41 269.269 823.41 267.904C823.41 266.549 823.767 265.493 824.482 264.736C825.196 263.968 826.188 263.584 827.458 263.584C828.727 263.584 829.719 263.968 830.434 264.736C831.148 265.493 831.506 266.549 831.506 267.904C831.506 269.269 831.148 270.336 830.434 271.104C829.719 271.861 828.727 272.24 827.458 272.24ZM827.458 270.448C828.578 270.448 829.138 269.6 829.138 267.904C829.138 266.219 828.578 265.376 827.458 265.376C826.338 265.376 825.778 266.219 825.778 267.904C825.778 269.6 826.338 270.448 827.458 270.448ZM835.265 272.128L832.033 263.824H834.513L836.337 269.936L838.065 263.824H840.481L837.025 273.104C836.716 273.947 836.337 274.555 835.889 274.928C835.441 275.301 834.876 275.488 834.193 275.488C833.66 275.488 833.143 275.403 832.641 275.232V273.648C832.983 273.68 833.287 273.696 833.553 273.696C834.001 273.696 834.348 273.589 834.593 273.376C834.839 273.173 835.047 272.816 835.217 272.304L835.265 272.128ZM851.715 272V266.464C851.715 265.739 851.39 265.376 850.739 265.376C850.163 265.376 849.582 265.515 848.995 265.792V265.952V272H846.659V266.464C846.659 265.739 846.334 265.376 845.683 265.376C845.086 265.376 844.499 265.52 843.923 265.808V272H841.587V263.824H843.507L843.715 264.608C844.281 264.235 844.787 263.973 845.235 263.824C845.694 263.664 846.163 263.584 846.643 263.584C847.603 263.584 848.281 263.925 848.675 264.608C849.219 264.245 849.731 263.984 850.211 263.824C850.691 263.664 851.187 263.584 851.699 263.584C852.446 263.584 853.022 263.792 853.427 264.208C853.843 264.624 854.051 265.205 854.051 265.952V272H851.715ZM857.923 268.48C857.966 269.184 858.179 269.696 858.563 270.016C858.947 270.325 859.55 270.48 860.371 270.48C861.086 270.48 861.918 270.347 862.867 270.08V271.632C862.494 271.824 862.046 271.973 861.523 272.08C861.011 272.187 860.478 272.24 859.923 272.24C858.569 272.24 857.534 271.872 856.819 271.136C856.115 270.4 855.763 269.323 855.763 267.904C855.763 266.539 856.115 265.477 856.819 264.72C857.523 263.963 858.499 263.584 859.747 263.584C860.803 263.584 861.614 263.877 862.179 264.464C862.755 265.04 863.043 265.867 863.043 266.944C863.043 267.179 863.027 267.445 862.995 267.744C862.963 268.043 862.926 268.288 862.883 268.48H857.923ZM859.667 265.2C859.145 265.2 858.729 265.36 858.419 265.68C858.121 265.989 857.95 266.443 857.907 267.04H861.043V266.768C861.043 265.723 860.585 265.2 859.667 265.2ZM870.004 272V266.64C870.004 266.203 869.908 265.883 869.716 265.68C869.524 265.477 869.23 265.376 868.836 265.376C868.249 265.376 867.668 265.557 867.092 265.92V272H864.756V263.824H866.676L866.9 264.704C867.86 263.957 868.884 263.584 869.972 263.584C870.729 263.584 871.31 263.792 871.716 264.208C872.132 264.613 872.34 265.195 872.34 265.952V272H870.004ZM879.337 271.792C878.761 272.016 878.115 272.128 877.401 272.128C876.494 272.128 875.822 271.915 875.385 271.488C874.958 271.061 874.745 270.4 874.745 269.504V265.552H873.513V264.112L874.809 263.856L875.161 261.616H877.081V263.824H879.289V265.552H877.081V269.392C877.081 269.733 877.166 269.973 877.337 270.112C877.507 270.251 877.795 270.32 878.201 270.32C878.531 270.32 878.91 270.288 879.337 270.224V271.792ZM887.505 272L886.721 269.472H882.929L882.177 272H879.665L883.569 260.912H886.209L890.113 272H887.505ZM883.441 267.744H886.225L884.817 263.104L883.441 267.744ZM897.154 271.648C896.866 271.819 896.519 271.947 896.114 272.032C895.709 272.128 895.287 272.176 894.85 272.176C893.549 272.176 892.551 271.813 891.858 271.088C891.175 270.363 890.834 269.317 890.834 267.952C890.834 266.597 891.197 265.541 891.922 264.784C892.647 264.027 893.655 263.648 894.946 263.648C895.725 263.648 896.445 263.819 897.106 264.16V265.712C896.477 265.531 895.901 265.44 895.378 265.44C894.631 265.44 894.082 265.632 893.73 266.016C893.378 266.389 893.202 266.987 893.202 267.808V268.032C893.202 268.843 893.373 269.44 893.714 269.824C894.066 270.197 894.605 270.384 895.33 270.384C895.853 270.384 896.461 270.288 897.154 270.096V271.648ZM903.909 271.792C903.333 272.016 902.688 272.128 901.973 272.128C901.066 272.128 900.394 271.915 899.957 271.488C899.53 271.061 899.317 270.4 899.317 269.504V265.552H898.085V264.112L899.381 263.856L899.733 261.616H901.653V263.824H903.861V265.552H901.653V269.392C901.653 269.733 901.738 269.973 901.909 270.112C902.08 270.251 902.368 270.32 902.773 270.32C903.104 270.32 903.482 270.288 903.909 270.224V271.792ZM905.326 272V263.824H907.662V272H905.326ZM906.494 262.56C906.089 262.56 905.763 262.448 905.518 262.224C905.273 262 905.15 261.696 905.15 261.312C905.15 260.928 905.273 260.624 905.518 260.4C905.763 260.176 906.089 260.064 906.494 260.064C906.899 260.064 907.225 260.176 907.47 260.4C907.715 260.624 907.838 260.928 907.838 261.312C907.838 261.696 907.715 262 907.47 262.224C907.225 262.448 906.899 262.56 906.494 262.56ZM913.517 272.24C912.248 272.24 911.256 271.861 910.541 271.104C909.826 270.336 909.469 269.269 909.469 267.904C909.469 266.549 909.826 265.493 910.541 264.736C911.256 263.968 912.248 263.584 913.517 263.584C914.786 263.584 915.778 263.968 916.493 264.736C917.208 265.493 917.565 266.549 917.565 267.904C917.565 269.269 917.208 270.336 916.493 271.104C915.778 271.861 914.786 272.24 913.517 272.24ZM913.517 270.448C914.637 270.448 915.197 269.6 915.197 267.904C915.197 266.219 914.637 265.376 913.517 265.376C912.397 265.376 911.837 266.219 911.837 267.904C911.837 269.6 912.397 270.448 913.517 270.448ZM924.553 272V266.64C924.553 266.203 924.457 265.883 924.265 265.68C924.073 265.477 923.78 265.376 923.385 265.376C922.798 265.376 922.217 265.557 921.641 265.92V272H919.305V263.824H921.225L921.449 264.704C922.409 263.957 923.433 263.584 924.521 263.584C925.278 263.584 925.86 263.792 926.265 264.208C926.681 264.613 926.889 265.195 926.889 265.952V272H924.553ZM929.182 272V260.912H933.454C934.606 260.912 935.518 261.216 936.19 261.824C936.862 262.432 937.198 263.259 937.198 264.304C937.198 264.944 937.022 265.52 936.67 266.032C936.318 266.544 935.822 266.944 935.182 267.232L937.934 272H935.454L933.054 267.696H931.486V272H929.182ZM931.486 266.032H933.15C934.27 266.032 934.83 265.467 934.83 264.336C934.83 263.227 934.281 262.672 933.182 262.672H931.486V266.032ZM942.605 272.24C941.336 272.24 940.344 271.861 939.629 271.104C938.914 270.336 938.557 269.269 938.557 267.904C938.557 266.549 938.914 265.493 939.629 264.736C940.344 263.968 941.336 263.584 942.605 263.584C943.874 263.584 944.866 263.968 945.581 264.736C946.296 265.493 946.653 266.549 946.653 267.904C946.653 269.269 946.296 270.336 945.581 271.104C944.866 271.861 943.874 272.24 942.605 272.24ZM942.605 270.448C943.725 270.448 944.285 269.6 944.285 267.904C944.285 266.219 943.725 265.376 942.605 265.376C941.485 265.376 940.925 266.219 940.925 267.904C940.925 269.6 941.485 270.448 942.605 270.448ZM951.993 271.84C951.545 272.021 951.065 272.112 950.553 272.112C949.113 272.112 948.393 271.307 948.393 269.696V260.16H950.729V269.504C950.729 269.803 950.777 270.016 950.873 270.144C950.98 270.261 951.15 270.32 951.385 270.32C951.534 270.32 951.737 270.304 951.993 270.272V271.84ZM955.104 268.48C955.147 269.184 955.36 269.696 955.744 270.016C956.128 270.325 956.731 270.48 957.552 270.48C958.267 270.48 959.099 270.347 960.048 270.08V271.632C959.675 271.824 959.227 271.973 958.704 272.08C958.192 272.187 957.659 272.24 957.104 272.24C955.749 272.24 954.715 271.872 954 271.136C953.296 270.4 952.944 269.323 952.944 267.904C952.944 266.539 953.296 265.477 954 264.72C954.704 263.963 955.68 263.584 956.928 263.584C957.984 263.584 958.795 263.877 959.36 264.464C959.936 265.04 960.224 265.867 960.224 266.944C960.224 267.179 960.208 267.445 960.176 267.744C960.144 268.043 960.107 268.288 960.064 268.48H955.104ZM956.848 265.2C956.325 265.2 955.909 265.36 955.6 265.68C955.301 265.989 955.131 266.443 955.088 267.04H958.224V266.768C958.224 265.723 957.765 265.2 956.848 265.2Z" fill="white"/> -<rect x="1164" y="243" width="257" height="46" rx="5" fill="#0972D3"/> -<rect x="1164" y="243" width="257" height="46" rx="5" stroke="#000716" stroke-width="2"/> -<path d="M1188.64 271.712C1187.78 272.043 1186.81 272.208 1185.75 272.208C1183.94 272.208 1182.58 271.728 1181.65 270.768C1180.72 269.797 1180.26 268.379 1180.26 266.512C1180.26 264.667 1180.74 263.237 1181.71 262.224C1182.68 261.211 1184.05 260.704 1185.81 260.704C1186.75 260.704 1187.64 260.853 1188.48 261.152V263.04C1187.51 262.827 1186.72 262.72 1186.1 262.72C1184.99 262.72 1184.16 263.013 1183.6 263.6C1183.06 264.187 1182.79 265.083 1182.79 266.288V266.656C1182.79 267.851 1183.05 268.741 1183.59 269.328C1184.12 269.904 1184.94 270.192 1186.03 270.192C1186.65 270.192 1187.52 270.069 1188.64 269.824V271.712ZM1193.78 271.84C1193.33 272.021 1192.85 272.112 1192.34 272.112C1190.9 272.112 1190.18 271.307 1190.18 269.696V260.16H1192.52V269.504C1192.52 269.803 1192.57 270.016 1192.66 270.144C1192.77 270.261 1192.94 270.32 1193.17 270.32C1193.32 270.32 1193.53 270.304 1193.78 270.272V271.84ZM1198.78 272.24C1197.51 272.24 1196.52 271.861 1195.8 271.104C1195.09 270.336 1194.73 269.269 1194.73 267.904C1194.73 266.549 1195.09 265.493 1195.8 264.736C1196.52 263.968 1197.51 263.584 1198.78 263.584C1200.05 263.584 1201.04 263.968 1201.76 264.736C1202.47 265.493 1202.83 266.549 1202.83 267.904C1202.83 269.269 1202.47 270.336 1201.76 271.104C1201.04 271.861 1200.05 272.24 1198.78 272.24ZM1198.78 270.448C1199.9 270.448 1200.46 269.6 1200.46 267.904C1200.46 266.219 1199.9 265.376 1198.78 265.376C1197.66 265.376 1197.1 266.219 1197.1 267.904C1197.1 269.6 1197.66 270.448 1198.78 270.448ZM1210.01 272L1209.78 271.136C1208.84 271.872 1207.84 272.24 1206.81 272.24C1206.08 272.24 1205.52 272.027 1205.11 271.6C1204.71 271.163 1204.5 270.565 1204.5 269.808V263.824H1206.84V269.152C1206.84 270.016 1207.21 270.448 1207.96 270.448C1208.52 270.448 1209.06 270.277 1209.59 269.936V263.824H1211.93V272H1210.01ZM1219.6 272L1219.41 271.28C1218.75 271.877 1217.96 272.176 1217.06 272.176C1216.39 272.176 1215.79 272.011 1215.28 271.68C1214.77 271.339 1214.37 270.848 1214.08 270.208C1213.8 269.568 1213.67 268.816 1213.67 267.952C1213.67 266.629 1213.98 265.573 1214.61 264.784C1215.24 263.984 1216.07 263.584 1217.11 263.584C1217.95 263.584 1218.68 263.824 1219.3 264.304V260.16H1221.63V272H1219.6ZM1217.83 270.416C1218.34 270.416 1218.83 270.267 1219.3 269.968V265.744C1218.84 265.477 1218.31 265.344 1217.71 265.344C1217.15 265.344 1216.73 265.557 1216.45 265.984C1216.17 266.4 1216.03 267.035 1216.03 267.888C1216.03 268.741 1216.18 269.376 1216.47 269.792C1216.76 270.208 1217.22 270.416 1217.83 270.416ZM1223.96 272V260.912H1230.94V262.768H1226.36V265.552H1230.01V267.408H1226.36V272H1223.96ZM1235.84 272.24C1234.57 272.24 1233.57 271.861 1232.86 271.104C1232.14 270.336 1231.79 269.269 1231.79 267.904C1231.79 266.549 1232.14 265.493 1232.86 264.736C1233.57 263.968 1234.57 263.584 1235.84 263.584C1237.1 263.584 1238.1 263.968 1238.81 264.736C1239.53 265.493 1239.88 266.549 1239.88 267.904C1239.88 269.269 1239.53 270.336 1238.81 271.104C1238.1 271.861 1237.1 272.24 1235.84 272.24ZM1235.84 270.448C1236.96 270.448 1237.52 269.6 1237.52 267.904C1237.52 266.219 1236.96 265.376 1235.84 265.376C1234.72 265.376 1234.16 266.219 1234.16 267.904C1234.16 269.6 1234.72 270.448 1235.84 270.448ZM1241.62 272V263.824H1243.54L1243.83 265.04C1244.26 264.571 1244.66 264.24 1245.03 264.048C1245.42 263.845 1245.82 263.744 1246.25 263.744C1246.45 263.744 1246.66 263.76 1246.89 263.792V265.952C1246.59 265.888 1246.26 265.856 1245.9 265.856C1245.2 265.856 1244.56 265.979 1243.96 266.224V272H1241.62ZM1258.16 272V266.464C1258.16 265.739 1257.83 265.376 1257.18 265.376C1256.6 265.376 1256.02 265.515 1255.44 265.792V265.952V272H1253.1V266.464C1253.1 265.739 1252.77 265.376 1252.12 265.376C1251.53 265.376 1250.94 265.52 1250.36 265.808V272H1248.03V263.824H1249.95L1250.16 264.608C1250.72 264.235 1251.23 263.973 1251.68 263.824C1252.13 263.664 1252.6 263.584 1253.08 263.584C1254.04 263.584 1254.72 263.925 1255.12 264.608C1255.66 264.245 1256.17 263.984 1256.65 263.824C1257.13 263.664 1257.63 263.584 1258.14 263.584C1258.89 263.584 1259.46 263.792 1259.87 264.208C1260.28 264.624 1260.49 265.205 1260.49 265.952V272H1258.16ZM1267.31 272L1267.12 271.28C1266.79 271.579 1266.4 271.819 1265.96 272C1265.54 272.171 1265.12 272.256 1264.72 272.256C1263.93 272.256 1263.29 272.032 1262.81 271.584C1262.34 271.136 1262.11 270.539 1262.11 269.792C1262.11 269.28 1262.24 268.832 1262.49 268.448C1262.75 268.053 1263.12 267.744 1263.6 267.52C1264.08 267.296 1264.64 267.184 1265.29 267.184C1265.8 267.184 1266.37 267.253 1266.99 267.392V266.592C1266.99 266.101 1266.89 265.765 1266.68 265.584C1266.48 265.403 1266.11 265.312 1265.56 265.312C1264.69 265.312 1263.72 265.477 1262.67 265.808V264.256C1263.06 264.053 1263.56 263.893 1264.16 263.776C1264.75 263.648 1265.36 263.584 1265.98 263.584C1267.08 263.584 1267.88 263.808 1268.38 264.256C1268.89 264.693 1269.15 265.387 1269.15 266.336V272H1267.31ZM1265.37 270.688C1265.64 270.688 1265.91 270.629 1266.19 270.512C1266.48 270.395 1266.74 270.235 1266.99 270.032V268.64C1266.52 268.565 1266.1 268.528 1265.72 268.528C1264.8 268.528 1264.33 268.901 1264.33 269.648C1264.33 269.979 1264.42 270.235 1264.6 270.416C1264.79 270.597 1265.04 270.688 1265.37 270.688ZM1276.14 271.792C1275.56 272.016 1274.92 272.128 1274.2 272.128C1273.3 272.128 1272.62 271.915 1272.19 271.488C1271.76 271.061 1271.55 270.4 1271.55 269.504V265.552H1270.31V264.112L1271.61 263.856L1271.96 261.616H1273.88V263.824H1276.09V265.552H1273.88V269.392C1273.88 269.733 1273.97 269.973 1274.14 270.112C1274.31 270.251 1274.6 270.32 1275 270.32C1275.33 270.32 1275.71 270.288 1276.14 270.224V271.792ZM1277.55 272V263.824H1279.89V272H1277.55ZM1278.72 262.56C1278.32 262.56 1277.99 262.448 1277.75 262.224C1277.5 262 1277.38 261.696 1277.38 261.312C1277.38 260.928 1277.5 260.624 1277.75 260.4C1277.99 260.176 1278.32 260.064 1278.72 260.064C1279.13 260.064 1279.45 260.176 1279.7 260.4C1279.94 260.624 1280.07 260.928 1280.07 261.312C1280.07 261.696 1279.94 262 1279.7 262.224C1279.45 262.448 1279.13 262.56 1278.72 262.56ZM1285.75 272.24C1284.48 272.24 1283.48 271.861 1282.77 271.104C1282.06 270.336 1281.7 269.269 1281.7 267.904C1281.7 266.549 1282.06 265.493 1282.77 264.736C1283.48 263.968 1284.48 263.584 1285.75 263.584C1287.02 263.584 1288.01 263.968 1288.72 264.736C1289.44 265.493 1289.79 266.549 1289.79 267.904C1289.79 269.269 1289.44 270.336 1288.72 271.104C1288.01 271.861 1287.02 272.24 1285.75 272.24ZM1285.75 270.448C1286.87 270.448 1287.43 269.6 1287.43 267.904C1287.43 266.219 1286.87 265.376 1285.75 265.376C1284.63 265.376 1284.07 266.219 1284.07 267.904C1284.07 269.6 1284.63 270.448 1285.75 270.448ZM1296.78 272V266.64C1296.78 266.203 1296.69 265.883 1296.49 265.68C1296.3 265.477 1296.01 265.376 1295.61 265.376C1295.03 265.376 1294.45 265.557 1293.87 265.92V272H1291.53V263.824H1293.45L1293.68 264.704C1294.64 263.957 1295.66 263.584 1296.75 263.584C1297.51 263.584 1298.09 263.792 1298.49 264.208C1298.91 264.613 1299.12 265.195 1299.12 265.952V272H1296.78ZM1301.41 272V260.912H1308.71V262.768H1303.81V265.392H1307.79V267.248H1303.81V270.144H1308.71V272H1301.41ZM1314.82 272L1313.27 269.408L1311.78 272H1309.36L1312.1 267.872L1309.4 263.824H1311.91L1313.4 266.304L1314.79 263.824H1317.2L1314.53 267.744L1317.33 272H1314.82ZM1320.02 268.48C1320.07 269.184 1320.28 269.696 1320.66 270.016C1321.05 270.325 1321.65 270.48 1322.47 270.48C1323.19 270.48 1324.02 270.347 1324.97 270.08V271.632C1324.59 271.824 1324.15 271.973 1323.62 272.08C1323.11 272.187 1322.58 272.24 1322.02 272.24C1320.67 272.24 1319.63 271.872 1318.92 271.136C1318.21 270.4 1317.86 269.323 1317.86 267.904C1317.86 266.539 1318.21 265.477 1318.92 264.72C1319.62 263.963 1320.6 263.584 1321.85 263.584C1322.9 263.584 1323.71 263.877 1324.28 264.464C1324.85 265.04 1325.14 265.867 1325.14 266.944C1325.14 267.179 1325.13 267.445 1325.09 267.744C1325.06 268.043 1325.03 268.288 1324.98 268.48H1320.02ZM1321.77 265.2C1321.24 265.2 1320.83 265.36 1320.52 265.68C1320.22 265.989 1320.05 266.443 1320.01 267.04H1323.14V266.768C1323.14 265.723 1322.68 265.2 1321.77 265.2ZM1332.76 271.648C1332.47 271.819 1332.12 271.947 1331.72 272.032C1331.31 272.128 1330.89 272.176 1330.45 272.176C1329.15 272.176 1328.16 271.813 1327.46 271.088C1326.78 270.363 1326.44 269.317 1326.44 267.952C1326.44 266.597 1326.8 265.541 1327.53 264.784C1328.25 264.027 1329.26 263.648 1330.55 263.648C1331.33 263.648 1332.05 263.819 1332.71 264.16V265.712C1332.08 265.531 1331.51 265.44 1330.98 265.44C1330.24 265.44 1329.69 265.632 1329.33 266.016C1328.98 266.389 1328.81 266.987 1328.81 267.808V268.032C1328.81 268.843 1328.98 269.44 1329.32 269.824C1329.67 270.197 1330.21 270.384 1330.93 270.384C1331.46 270.384 1332.07 270.288 1332.76 270.096V271.648ZM1339.78 272L1339.55 271.136C1338.6 271.872 1337.61 272.24 1336.58 272.24C1335.85 272.24 1335.29 272.027 1334.88 271.6C1334.48 271.163 1334.27 270.565 1334.27 269.808V263.824H1336.61V269.152C1336.61 270.016 1336.98 270.448 1337.73 270.448C1338.28 270.448 1338.83 270.277 1339.36 269.936V263.824H1341.7V272H1339.78ZM1348.71 271.792C1348.14 272.016 1347.49 272.128 1346.78 272.128C1345.87 272.128 1345.2 271.915 1344.76 271.488C1344.34 271.061 1344.12 270.4 1344.12 269.504V265.552H1342.89V264.112L1344.19 263.856L1344.54 261.616H1346.46V263.824H1348.67V265.552H1346.46V269.392C1346.46 269.733 1346.54 269.973 1346.71 270.112C1346.89 270.251 1347.17 270.32 1347.58 270.32C1347.91 270.32 1348.29 270.288 1348.71 270.224V271.792ZM1350.13 272V263.824H1352.47V272H1350.13ZM1351.3 262.56C1350.89 262.56 1350.57 262.448 1350.32 262.224C1350.08 262 1349.96 261.696 1349.96 261.312C1349.96 260.928 1350.08 260.624 1350.32 260.4C1350.57 260.176 1350.89 260.064 1351.3 260.064C1351.71 260.064 1352.03 260.176 1352.28 260.4C1352.52 260.624 1352.64 260.928 1352.64 261.312C1352.64 261.696 1352.52 262 1352.28 262.224C1352.03 262.448 1351.71 262.56 1351.3 262.56ZM1358.32 272.24C1357.05 272.24 1356.06 271.861 1355.35 271.104C1354.63 270.336 1354.27 269.269 1354.27 267.904C1354.27 266.549 1354.63 265.493 1355.35 264.736C1356.06 263.968 1357.05 263.584 1358.32 263.584C1359.59 263.584 1360.58 263.968 1361.3 264.736C1362.01 265.493 1362.37 266.549 1362.37 267.904C1362.37 269.269 1362.01 270.336 1361.3 271.104C1360.58 271.861 1359.59 272.24 1358.32 272.24ZM1358.32 270.448C1359.44 270.448 1360 269.6 1360 267.904C1360 266.219 1359.44 265.376 1358.32 265.376C1357.2 265.376 1356.64 266.219 1356.64 267.904C1356.64 269.6 1357.2 270.448 1358.32 270.448ZM1369.36 272V266.64C1369.36 266.203 1369.26 265.883 1369.07 265.68C1368.88 265.477 1368.59 265.376 1368.19 265.376C1367.6 265.376 1367.02 265.557 1366.45 265.92V272H1364.11V263.824H1366.03L1366.25 264.704C1367.21 263.957 1368.24 263.584 1369.33 263.584C1370.08 263.584 1370.67 263.792 1371.07 264.208C1371.49 264.613 1371.69 265.195 1371.69 265.952V272H1369.36ZM1373.99 272V260.912H1378.26C1379.41 260.912 1380.32 261.216 1381 261.824C1381.67 262.432 1382 263.259 1382 264.304C1382 264.944 1381.83 265.52 1381.48 266.032C1381.12 266.544 1380.63 266.944 1379.99 267.232L1382.74 272H1380.26L1377.86 267.696H1376.29V272H1373.99ZM1376.29 266.032H1377.96C1379.08 266.032 1379.64 265.467 1379.64 264.336C1379.64 263.227 1379.09 262.672 1377.99 262.672H1376.29V266.032ZM1387.41 272.24C1386.14 272.24 1385.15 271.861 1384.44 271.104C1383.72 270.336 1383.36 269.269 1383.36 267.904C1383.36 266.549 1383.72 265.493 1384.44 264.736C1385.15 263.968 1386.14 263.584 1387.41 263.584C1388.68 263.584 1389.67 263.968 1390.39 264.736C1391.1 265.493 1391.46 266.549 1391.46 267.904C1391.46 269.269 1391.1 270.336 1390.39 271.104C1389.67 271.861 1388.68 272.24 1387.41 272.24ZM1387.41 270.448C1388.53 270.448 1389.09 269.6 1389.09 267.904C1389.09 266.219 1388.53 265.376 1387.41 265.376C1386.29 265.376 1385.73 266.219 1385.73 267.904C1385.73 269.6 1386.29 270.448 1387.41 270.448ZM1396.8 271.84C1396.35 272.021 1395.87 272.112 1395.36 272.112C1393.92 272.112 1393.2 271.307 1393.2 269.696V260.16H1395.54V269.504C1395.54 269.803 1395.58 270.016 1395.68 270.144C1395.79 270.261 1395.96 270.32 1396.19 270.32C1396.34 270.32 1396.54 270.304 1396.8 270.272V271.84ZM1399.91 268.48C1399.95 269.184 1400.17 269.696 1400.55 270.016C1400.93 270.325 1401.54 270.48 1402.36 270.48C1403.07 270.48 1403.9 270.347 1404.85 270.08V271.632C1404.48 271.824 1404.03 271.973 1403.51 272.08C1403 272.187 1402.46 272.24 1401.91 272.24C1400.56 272.24 1399.52 271.872 1398.81 271.136C1398.1 270.4 1397.75 269.323 1397.75 267.904C1397.75 266.539 1398.1 265.477 1398.81 264.72C1399.51 263.963 1400.49 263.584 1401.73 263.584C1402.79 263.584 1403.6 263.877 1404.17 264.464C1404.74 265.04 1405.03 265.867 1405.03 266.944C1405.03 267.179 1405.01 267.445 1404.98 267.744C1404.95 268.043 1404.91 268.288 1404.87 268.48H1399.91ZM1401.65 265.2C1401.13 265.2 1400.72 265.36 1400.41 265.68C1400.11 265.989 1399.94 266.443 1399.89 267.04H1403.03V266.768C1403.03 265.723 1402.57 265.2 1401.65 265.2Z" fill="white"/> -<rect x="746" y="332" width="257" height="46" rx="5" fill="#0972D3"/> -<rect x="746" y="332" width="257" height="46" rx="5" stroke="#000716" stroke-width="2"/> -<path d="M806.218 361V349.912H813.194V351.768H808.618V354.552H812.266V356.408H808.618V361H806.218ZM814.682 361V352.824H817.018V361H814.682ZM815.85 351.56C815.445 351.56 815.12 351.448 814.874 351.224C814.629 351 814.506 350.696 814.506 350.312C814.506 349.928 814.629 349.624 814.874 349.4C815.12 349.176 815.445 349.064 815.85 349.064C816.256 349.064 816.581 349.176 816.826 349.4C817.072 349.624 817.194 349.928 817.194 350.312C817.194 350.696 817.072 351 816.826 351.224C816.581 351.448 816.256 351.56 815.85 351.56ZM822.842 360.84C822.394 361.021 821.914 361.112 821.402 361.112C819.962 361.112 819.242 360.307 819.242 358.696V349.16H821.578V358.504C821.578 358.803 821.626 359.016 821.722 359.144C821.828 359.261 821.999 359.32 822.234 359.32C822.383 359.32 822.586 359.304 822.842 359.272V360.84ZM825.952 357.48C825.995 358.184 826.208 358.696 826.592 359.016C826.976 359.325 827.579 359.48 828.4 359.48C829.115 359.48 829.947 359.347 830.896 359.08V360.632C830.523 360.824 830.075 360.973 829.552 361.08C829.04 361.187 828.507 361.24 827.952 361.24C826.598 361.24 825.563 360.872 824.848 360.136C824.144 359.4 823.792 358.323 823.792 356.904C823.792 355.539 824.144 354.477 824.848 353.72C825.552 352.963 826.528 352.584 827.776 352.584C828.832 352.584 829.643 352.877 830.208 353.464C830.784 354.04 831.072 354.867 831.072 355.944C831.072 356.179 831.056 356.445 831.024 356.744C830.992 357.043 830.955 357.288 830.912 357.48H825.952ZM827.696 354.2C827.174 354.2 826.758 354.36 826.448 354.68C826.15 354.989 825.979 355.443 825.936 356.04H829.072V355.768C829.072 354.723 828.614 354.2 827.696 354.2ZM835.281 356.952V361H832.945V349.912H837.185C838.337 349.912 839.249 350.227 839.921 350.856C840.593 351.485 840.929 352.344 840.929 353.432C840.929 354.52 840.593 355.379 839.921 356.008C839.249 356.637 838.337 356.952 837.185 356.952H835.281ZM835.281 355.16H836.913C837.446 355.16 837.851 355.016 838.129 354.728C838.417 354.429 838.561 353.997 838.561 353.432C838.561 352.867 838.417 352.44 838.129 352.152C837.851 351.853 837.446 351.704 836.913 351.704H835.281V355.16ZM848.051 361L847.827 360.136C846.878 360.872 845.886 361.24 844.851 361.24C844.126 361.24 843.56 361.027 843.155 360.6C842.75 360.163 842.547 359.565 842.547 358.808V352.824H844.883V358.152C844.883 359.016 845.256 359.448 846.003 359.448C846.558 359.448 847.102 359.277 847.635 358.936V352.824H849.971V361H848.051ZM852.125 361V349.16H854.461V353.448C854.77 353.181 855.133 352.973 855.549 352.824C855.965 352.664 856.375 352.584 856.781 352.584C857.815 352.584 858.631 352.963 859.229 353.72C859.837 354.477 860.141 355.501 860.141 356.792C860.141 357.635 860.002 358.387 859.725 359.048C859.447 359.709 859.047 360.232 858.525 360.616C858.002 360.989 857.399 361.176 856.717 361.176C856.226 361.176 855.767 361.091 855.341 360.92C854.914 360.749 854.557 360.509 854.269 360.2L854.061 361H852.125ZM856.029 354.344C855.474 354.344 854.951 354.488 854.461 354.776V358.984C854.93 359.272 855.453 359.416 856.029 359.416C856.626 359.416 857.063 359.213 857.341 358.808C857.629 358.403 857.773 357.763 857.773 356.888C857.773 356.003 857.634 355.357 857.357 354.952C857.079 354.547 856.637 354.344 856.029 354.344ZM865.488 360.84C865.04 361.021 864.56 361.112 864.048 361.112C862.608 361.112 861.888 360.307 861.888 358.696V349.16H864.224V358.504C864.224 358.803 864.272 359.016 864.368 359.144C864.475 359.261 864.646 359.32 864.88 359.32C865.03 359.32 865.232 359.304 865.488 359.272V360.84ZM867.076 361V352.824H869.412V361H867.076ZM868.244 351.56C867.838 351.56 867.513 351.448 867.268 351.224C867.022 351 866.9 350.696 866.9 350.312C866.9 349.928 867.022 349.624 867.268 349.4C867.513 349.176 867.838 349.064 868.244 349.064C868.649 349.064 868.974 349.176 869.22 349.4C869.465 349.624 869.588 349.928 869.588 350.312C869.588 350.696 869.465 351 869.22 351.224C868.974 351.448 868.649 351.56 868.244 351.56ZM875.107 358.744C875.107 358.531 875.043 358.365 874.915 358.248C874.797 358.131 874.552 358.003 874.179 357.864L872.931 357.368C872.28 357.112 871.811 356.797 871.523 356.424C871.235 356.051 871.091 355.576 871.091 355C871.091 354.275 871.379 353.693 871.955 353.256C872.541 352.808 873.32 352.584 874.291 352.584C875.187 352.584 876.013 352.76 876.771 353.112V354.664C875.96 354.419 875.203 354.296 874.499 354.296C874.061 354.296 873.741 354.349 873.539 354.456C873.336 354.563 873.235 354.733 873.235 354.968C873.235 355.149 873.293 355.299 873.411 355.416C873.539 355.523 873.8 355.656 874.195 355.816L875.411 356.312C876.072 356.579 876.541 356.888 876.819 357.24C877.107 357.592 877.251 358.051 877.251 358.616C877.251 359.405 876.947 360.045 876.339 360.536C875.741 361.016 874.952 361.256 873.971 361.256C872.872 361.256 871.901 361.037 871.059 360.6V359.048C872.115 359.379 873.08 359.544 873.955 359.544C874.723 359.544 875.107 359.277 875.107 358.744ZM883.928 361V355.64C883.928 355.203 883.832 354.883 883.64 354.68C883.448 354.477 883.154 354.376 882.76 354.376C882.173 354.376 881.592 354.557 881.016 354.92V361H878.68V349.16H881.016V353.56C881.933 352.909 882.893 352.584 883.896 352.584C884.653 352.584 885.234 352.792 885.64 353.208C886.056 353.613 886.264 354.195 886.264 354.952V361H883.928ZM888.461 361V352.824H890.797V361H888.461ZM889.629 351.56C889.223 351.56 888.898 351.448 888.653 351.224C888.407 351 888.285 350.696 888.285 350.312C888.285 349.928 888.407 349.624 888.653 349.4C888.898 349.176 889.223 349.064 889.629 349.064C890.034 349.064 890.359 349.176 890.605 349.4C890.85 349.624 890.973 349.928 890.973 350.312C890.973 350.696 890.85 351 890.605 351.224C890.359 351.448 890.034 351.56 889.629 351.56ZM898.268 361V355.64C898.268 355.203 898.172 354.883 897.98 354.68C897.788 354.477 897.494 354.376 897.1 354.376C896.513 354.376 895.932 354.557 895.356 354.92V361H893.02V352.824H894.94L895.164 353.704C896.124 352.957 897.148 352.584 898.236 352.584C898.993 352.584 899.574 352.792 899.98 353.208C900.396 353.613 900.604 354.195 900.604 354.952V361H898.268ZM907.729 360.008C907.121 360.552 906.406 360.824 905.585 360.824C904.593 360.824 903.798 360.456 903.201 359.72C902.614 358.973 902.321 357.981 902.321 356.744C902.321 355.485 902.619 354.477 903.217 353.72C903.814 352.963 904.614 352.584 905.617 352.584C906.065 352.584 906.486 352.664 906.881 352.824C907.275 352.984 907.627 353.219 907.937 353.528L908.113 352.824H910.033V360.36C910.033 361.661 909.67 362.675 908.945 363.4C908.219 364.125 907.217 364.488 905.937 364.488C904.902 364.488 903.921 364.259 902.993 363.8V362.232C904.049 362.563 904.961 362.728 905.729 362.728C906.433 362.728 906.939 362.563 907.249 362.232C907.569 361.912 907.729 361.384 907.729 360.648V360.008ZM906.305 359.096C906.55 359.096 906.795 359.059 907.041 358.984C907.297 358.899 907.526 358.787 907.729 358.648V354.712C907.291 354.445 906.779 354.312 906.193 354.312C905.169 354.312 904.657 355.101 904.657 356.68C904.657 357.501 904.79 358.109 905.057 358.504C905.323 358.899 905.739 359.096 906.305 359.096ZM912.348 361V349.912H916.62C917.772 349.912 918.684 350.216 919.356 350.824C920.028 351.432 920.364 352.259 920.364 353.304C920.364 353.944 920.188 354.52 919.836 355.032C919.484 355.544 918.988 355.944 918.348 356.232L921.1 361H918.62L916.22 356.696H914.652V361H912.348ZM914.652 355.032H916.316C917.436 355.032 917.996 354.467 917.996 353.336C917.996 352.227 917.446 351.672 916.348 351.672H914.652V355.032ZM925.771 361.24C924.502 361.24 923.51 360.861 922.795 360.104C922.08 359.336 921.723 358.269 921.723 356.904C921.723 355.549 922.08 354.493 922.795 353.736C923.51 352.968 924.502 352.584 925.771 352.584C927.04 352.584 928.032 352.968 928.747 353.736C929.462 354.493 929.819 355.549 929.819 356.904C929.819 358.269 929.462 359.336 928.747 360.104C928.032 360.861 927.04 361.24 925.771 361.24ZM925.771 359.448C926.891 359.448 927.451 358.6 927.451 356.904C927.451 355.219 926.891 354.376 925.771 354.376C924.651 354.376 924.091 355.219 924.091 356.904C924.091 358.6 924.651 359.448 925.771 359.448ZM935.159 360.84C934.711 361.021 934.231 361.112 933.719 361.112C932.279 361.112 931.559 360.307 931.559 358.696V349.16H933.895V358.504C933.895 358.803 933.943 359.016 934.039 359.144C934.146 359.261 934.316 359.32 934.551 359.32C934.7 359.32 934.903 359.304 935.159 359.272V360.84ZM938.27 357.48C938.313 358.184 938.526 358.696 938.91 359.016C939.294 359.325 939.897 359.48 940.718 359.48C941.433 359.48 942.265 359.347 943.214 359.08V360.632C942.841 360.824 942.393 360.973 941.87 361.08C941.358 361.187 940.825 361.24 940.27 361.24C938.915 361.24 937.881 360.872 937.166 360.136C936.462 359.4 936.11 358.323 936.11 356.904C936.11 355.539 936.462 354.477 937.166 353.72C937.87 352.963 938.846 352.584 940.094 352.584C941.15 352.584 941.961 352.877 942.526 353.464C943.102 354.04 943.39 354.867 943.39 355.944C943.39 356.179 943.374 356.445 943.342 356.744C943.31 357.043 943.273 357.288 943.23 357.48H938.27ZM940.014 354.2C939.491 354.2 939.075 354.36 938.766 354.68C938.467 354.989 938.297 355.443 938.254 356.04H941.39V355.768C941.39 354.723 940.931 354.2 940.014 354.2Z" fill="white"/> -<rect x="745" y="150" width="257" height="46" rx="5" fill="#0972D3"/> -<rect x="745" y="150" width="257" height="46" rx="5" stroke="#000716" stroke-width="2"/> -<path d="M795.502 179V167.912H797.902V179H795.502ZM810.419 179V173.464C810.419 172.739 810.094 172.376 809.443 172.376C808.867 172.376 808.286 172.515 807.699 172.792V172.952V179H805.363V173.464C805.363 172.739 805.038 172.376 804.387 172.376C803.79 172.376 803.203 172.52 802.627 172.808V179H800.291V170.824H802.211L802.419 171.608C802.985 171.235 803.491 170.973 803.939 170.824C804.398 170.664 804.867 170.584 805.347 170.584C806.307 170.584 806.985 170.925 807.379 171.608C807.923 171.245 808.435 170.984 808.915 170.824C809.395 170.664 809.891 170.584 810.403 170.584C811.15 170.584 811.726 170.792 812.131 171.208C812.547 171.624 812.755 172.205 812.755 172.952V179H810.419ZM819.571 179L819.379 178.28C819.048 178.579 818.664 178.819 818.227 179C817.8 179.171 817.384 179.256 816.979 179.256C816.19 179.256 815.555 179.032 815.075 178.584C814.606 178.136 814.371 177.539 814.371 176.792C814.371 176.28 814.499 175.832 814.755 175.448C815.011 175.053 815.379 174.744 815.859 174.52C816.339 174.296 816.904 174.184 817.555 174.184C818.067 174.184 818.632 174.253 819.251 174.392V173.592C819.251 173.101 819.15 172.765 818.947 172.584C818.744 172.403 818.371 172.312 817.827 172.312C816.952 172.312 815.987 172.477 814.931 172.808V171.256C815.326 171.053 815.822 170.893 816.419 170.776C817.016 170.648 817.624 170.584 818.243 170.584C819.342 170.584 820.142 170.808 820.643 171.256C821.155 171.693 821.411 172.387 821.411 173.336V179H819.571ZM817.635 177.688C817.902 177.688 818.174 177.629 818.451 177.512C818.739 177.395 819.006 177.235 819.251 177.032V175.64C818.782 175.565 818.36 175.528 817.987 175.528C817.059 175.528 816.595 175.901 816.595 176.648C816.595 176.979 816.686 177.235 816.867 177.416C817.048 177.597 817.304 177.688 817.635 177.688ZM828.53 178.008C827.922 178.552 827.207 178.824 826.386 178.824C825.394 178.824 824.599 178.456 824.002 177.72C823.415 176.973 823.122 175.981 823.122 174.744C823.122 173.485 823.42 172.477 824.018 171.72C824.615 170.963 825.415 170.584 826.418 170.584C826.866 170.584 827.287 170.664 827.682 170.824C828.076 170.984 828.428 171.219 828.738 171.528L828.914 170.824H830.834V178.36C830.834 179.661 830.471 180.675 829.746 181.4C829.02 182.125 828.018 182.488 826.738 182.488C825.703 182.488 824.722 182.259 823.794 181.8V180.232C824.85 180.563 825.762 180.728 826.53 180.728C827.234 180.728 827.74 180.563 828.05 180.232C828.37 179.912 828.53 179.384 828.53 178.648V178.008ZM827.106 177.096C827.351 177.096 827.596 177.059 827.842 176.984C828.098 176.899 828.327 176.787 828.53 176.648V172.712C828.092 172.445 827.58 172.312 826.994 172.312C825.97 172.312 825.458 173.101 825.458 174.68C825.458 175.501 825.591 176.109 825.858 176.504C826.124 176.899 826.54 177.096 827.106 177.096ZM834.733 175.48C834.775 176.184 834.989 176.696 835.373 177.016C835.757 177.325 836.359 177.48 837.181 177.48C837.895 177.48 838.727 177.347 839.677 177.08V178.632C839.303 178.824 838.855 178.973 838.333 179.08C837.821 179.187 837.287 179.24 836.733 179.24C835.378 179.24 834.343 178.872 833.629 178.136C832.925 177.4 832.573 176.323 832.573 174.904C832.573 173.539 832.925 172.477 833.629 171.72C834.333 170.963 835.309 170.584 836.557 170.584C837.613 170.584 838.423 170.877 838.989 171.464C839.565 172.04 839.853 172.867 839.853 173.944C839.853 174.179 839.837 174.445 839.805 174.744C839.773 175.043 839.735 175.288 839.693 175.48H834.733ZM836.477 172.2C835.954 172.2 835.538 172.36 835.229 172.68C834.93 172.989 834.759 173.443 834.717 174.04H837.853V173.768C837.853 172.723 837.394 172.2 836.477 172.2ZM844.061 174.952V179H841.725V167.912H845.965C847.117 167.912 848.029 168.227 848.701 168.856C849.373 169.485 849.709 170.344 849.709 171.432C849.709 172.52 849.373 173.379 848.701 174.008C848.029 174.637 847.117 174.952 845.965 174.952H844.061ZM844.061 173.16H845.693C846.226 173.16 846.632 173.016 846.909 172.728C847.197 172.429 847.341 171.997 847.341 171.432C847.341 170.867 847.197 170.44 846.909 170.152C846.632 169.853 846.226 169.704 845.693 169.704H844.061V173.16ZM856.831 179L856.607 178.136C855.658 178.872 854.666 179.24 853.631 179.24C852.906 179.24 852.341 179.027 851.935 178.6C851.53 178.163 851.327 177.565 851.327 176.808V170.824H853.663V176.152C853.663 177.016 854.037 177.448 854.783 177.448C855.338 177.448 855.882 177.277 856.415 176.936V170.824H858.751V179H856.831ZM860.905 179V167.16H863.241V171.448C863.55 171.181 863.913 170.973 864.329 170.824C864.745 170.664 865.156 170.584 865.561 170.584C866.596 170.584 867.412 170.963 868.009 171.72C868.617 172.477 868.921 173.501 868.921 174.792C868.921 175.635 868.782 176.387 868.505 177.048C868.228 177.709 867.828 178.232 867.305 178.616C866.782 178.989 866.18 179.176 865.497 179.176C865.006 179.176 864.548 179.091 864.121 178.92C863.694 178.749 863.337 178.509 863.049 178.2L862.841 179H860.905ZM864.809 172.344C864.254 172.344 863.732 172.488 863.241 172.776V176.984C863.71 177.272 864.233 177.416 864.809 177.416C865.406 177.416 865.844 177.213 866.121 176.808C866.409 176.403 866.553 175.763 866.553 174.888C866.553 174.003 866.414 173.357 866.137 172.952C865.86 172.547 865.417 172.344 864.809 172.344ZM874.269 178.84C873.821 179.021 873.341 179.112 872.829 179.112C871.389 179.112 870.669 178.307 870.669 176.696V167.16H873.005V176.504C873.005 176.803 873.053 177.016 873.149 177.144C873.255 177.261 873.426 177.32 873.661 177.32C873.81 177.32 874.013 177.304 874.269 177.272V178.84ZM875.856 179V170.824H878.192V179H875.856ZM877.024 169.56C876.619 169.56 876.293 169.448 876.048 169.224C875.803 169 875.68 168.696 875.68 168.312C875.68 167.928 875.803 167.624 876.048 167.4C876.293 167.176 876.619 167.064 877.024 167.064C877.429 167.064 877.755 167.176 878 167.4C878.245 167.624 878.368 167.928 878.368 168.312C878.368 168.696 878.245 169 878 169.224C877.755 169.448 877.429 169.56 877.024 169.56ZM883.887 176.744C883.887 176.531 883.823 176.365 883.695 176.248C883.578 176.131 883.332 176.003 882.959 175.864L881.711 175.368C881.06 175.112 880.591 174.797 880.303 174.424C880.015 174.051 879.871 173.576 879.871 173C879.871 172.275 880.159 171.693 880.735 171.256C881.322 170.808 882.1 170.584 883.071 170.584C883.967 170.584 884.794 170.76 885.551 171.112V172.664C884.74 172.419 883.983 172.296 883.279 172.296C882.842 172.296 882.522 172.349 882.319 172.456C882.116 172.563 882.015 172.733 882.015 172.968C882.015 173.149 882.074 173.299 882.191 173.416C882.319 173.523 882.58 173.656 882.975 173.816L884.191 174.312C884.852 174.579 885.322 174.888 885.599 175.24C885.887 175.592 886.031 176.051 886.031 176.616C886.031 177.405 885.727 178.045 885.119 178.536C884.522 179.016 883.732 179.256 882.751 179.256C881.652 179.256 880.682 179.037 879.839 178.6V177.048C880.895 177.379 881.86 177.544 882.735 177.544C883.503 177.544 883.887 177.277 883.887 176.744ZM892.708 179V173.64C892.708 173.203 892.612 172.883 892.42 172.68C892.228 172.477 891.935 172.376 891.54 172.376C890.953 172.376 890.372 172.557 889.796 172.92V179H887.46V167.16H889.796V171.56C890.713 170.909 891.673 170.584 892.676 170.584C893.433 170.584 894.015 170.792 894.42 171.208C894.836 171.613 895.044 172.195 895.044 172.952V179H892.708ZM897.241 179V170.824H899.577V179H897.241ZM898.409 169.56C898.004 169.56 897.678 169.448 897.433 169.224C897.188 169 897.065 168.696 897.065 168.312C897.065 167.928 897.188 167.624 897.433 167.4C897.678 167.176 898.004 167.064 898.409 167.064C898.814 167.064 899.14 167.176 899.385 167.4C899.63 167.624 899.753 167.928 899.753 168.312C899.753 168.696 899.63 169 899.385 169.224C899.14 169.448 898.814 169.56 898.409 169.56ZM907.048 179V173.64C907.048 173.203 906.952 172.883 906.76 172.68C906.568 172.477 906.275 172.376 905.88 172.376C905.293 172.376 904.712 172.557 904.136 172.92V179H901.8V170.824H903.72L903.944 171.704C904.904 170.957 905.928 170.584 907.016 170.584C907.773 170.584 908.355 170.792 908.76 171.208C909.176 171.613 909.384 172.195 909.384 172.952V179H907.048ZM916.509 178.008C915.901 178.552 915.186 178.824 914.365 178.824C913.373 178.824 912.578 178.456 911.981 177.72C911.394 176.973 911.101 175.981 911.101 174.744C911.101 173.485 911.4 172.477 911.997 171.72C912.594 170.963 913.394 170.584 914.397 170.584C914.845 170.584 915.266 170.664 915.661 170.824C916.056 170.984 916.408 171.219 916.717 171.528L916.893 170.824H918.813V178.36C918.813 179.661 918.45 180.675 917.725 181.4C917 182.125 915.997 182.488 914.717 182.488C913.682 182.488 912.701 182.259 911.773 181.8V180.232C912.829 180.563 913.741 180.728 914.509 180.728C915.213 180.728 915.72 180.563 916.029 180.232C916.349 179.912 916.509 179.384 916.509 178.648V178.008ZM915.085 177.096C915.33 177.096 915.576 177.059 915.821 176.984C916.077 176.899 916.306 176.787 916.509 176.648V172.712C916.072 172.445 915.56 172.312 914.973 172.312C913.949 172.312 913.437 173.101 913.437 174.68C913.437 175.501 913.57 176.109 913.837 176.504C914.104 176.899 914.52 177.096 915.085 177.096ZM921.128 179V167.912H925.4C926.552 167.912 927.464 168.216 928.136 168.824C928.808 169.432 929.144 170.259 929.144 171.304C929.144 171.944 928.968 172.52 928.616 173.032C928.264 173.544 927.768 173.944 927.128 174.232L929.88 179H927.4L925 174.696H923.432V179H921.128ZM923.432 173.032H925.096C926.216 173.032 926.776 172.467 926.776 171.336C926.776 170.227 926.227 169.672 925.128 169.672H923.432V173.032ZM934.551 179.24C933.282 179.24 932.29 178.861 931.575 178.104C930.861 177.336 930.503 176.269 930.503 174.904C930.503 173.549 930.861 172.493 931.575 171.736C932.29 170.968 933.282 170.584 934.551 170.584C935.821 170.584 936.813 170.968 937.527 171.736C938.242 172.493 938.599 173.549 938.599 174.904C938.599 176.269 938.242 177.336 937.527 178.104C936.813 178.861 935.821 179.24 934.551 179.24ZM934.551 177.448C935.671 177.448 936.231 176.6 936.231 174.904C936.231 173.219 935.671 172.376 934.551 172.376C933.431 172.376 932.871 173.219 932.871 174.904C932.871 176.6 933.431 177.448 934.551 177.448ZM943.939 178.84C943.491 179.021 943.011 179.112 942.499 179.112C941.059 179.112 940.339 178.307 940.339 176.696V167.16H942.675V176.504C942.675 176.803 942.723 177.016 942.819 177.144C942.926 177.261 943.097 177.32 943.331 177.32C943.481 177.32 943.683 177.304 943.939 177.272V178.84ZM947.05 175.48C947.093 176.184 947.306 176.696 947.69 177.016C948.074 177.325 948.677 177.48 949.498 177.48C950.213 177.48 951.045 177.347 951.994 177.08V178.632C951.621 178.824 951.173 178.973 950.65 179.08C950.138 179.187 949.605 179.24 949.05 179.24C947.696 179.24 946.661 178.872 945.946 178.136C945.242 177.4 944.89 176.323 944.89 174.904C944.89 173.539 945.242 172.477 945.946 171.72C946.65 170.963 947.626 170.584 948.874 170.584C949.93 170.584 950.741 170.877 951.306 171.464C951.882 172.04 952.17 172.867 952.17 173.944C952.17 174.179 952.154 174.445 952.122 174.744C952.09 175.043 952.053 175.288 952.01 175.48H947.05ZM948.794 172.2C948.272 172.2 947.856 172.36 947.546 172.68C947.248 172.989 947.077 173.443 947.034 174.04H950.17V173.768C950.17 172.723 949.712 172.2 948.794 172.2Z" fill="white"/> -<path d="M589.707 266.707C590.098 266.317 590.098 265.683 589.707 265.293L583.343 258.929C582.953 258.538 582.319 258.538 581.929 258.929C581.538 259.319 581.538 259.953 581.929 260.343L587.586 266L581.929 271.657C581.538 272.047 581.538 272.681 581.929 273.071C582.319 273.462 582.953 273.462 583.343 273.071L589.707 266.707ZM564 267H589V265H564V267Z" fill="black"/> -<path d="M589.707 355.707C590.098 355.317 590.098 354.683 589.707 354.293L583.343 347.929C582.953 347.538 582.319 347.538 581.929 347.929C581.538 348.319 581.538 348.953 581.929 349.343L587.586 355L581.929 360.657C581.538 361.047 581.538 361.681 581.929 362.071C582.319 362.462 582.953 362.462 583.343 362.071L589.707 355.707ZM572 275V345H574V275H572ZM583 356H589V354H583V356ZM572 345C572 351.075 576.925 356 583 356V354C578.029 354 574 349.971 574 345H572ZM564 267C568.418 267 572 270.582 572 275H574C574 269.477 569.523 265 564 265V267Z" fill="black"/> -<path d="M589.707 173.707C590.098 173.317 590.098 172.683 589.707 172.293L583.343 165.929C582.953 165.538 582.319 165.538 581.929 165.929C581.538 166.319 581.538 166.953 581.929 167.343L587.586 173L581.929 178.657C581.538 179.047 581.538 179.681 581.929 180.071C582.319 180.462 582.953 180.462 583.343 180.071L589.707 173.707ZM573.5 257.5V183H571.5V257.5H573.5ZM582.5 174H589V172H582.5V174ZM573.5 183C573.5 178.029 577.529 174 582.5 174V172C576.425 172 571.5 176.925 571.5 183H573.5ZM564 267C569.247 267 573.5 262.747 573.5 257.5H571.5C571.5 261.642 568.142 265 564 265V267Z" fill="black"/> -<path d="M744.707 266.707C745.098 266.317 745.098 265.683 744.707 265.293L738.343 258.929C737.953 258.538 737.319 258.538 736.929 258.929C736.538 259.319 736.538 259.953 736.929 260.343L742.586 266L736.929 271.657C736.538 272.047 736.538 272.681 736.929 273.071C737.319 273.462 737.953 273.462 738.343 273.071L744.707 266.707ZM719 267H744V265H719V267Z" fill="black"/> -<path d="M744.707 173.707C745.098 173.317 745.098 172.683 744.707 172.293L738.343 165.929C737.953 165.538 737.319 165.538 736.929 165.929C736.538 166.319 736.538 166.953 736.929 167.343L742.586 173L736.929 178.657C736.538 179.047 736.538 179.681 736.929 180.071C737.319 180.462 737.953 180.462 738.343 180.071L744.707 173.707ZM719 174H744V172H719V174Z" fill="black"/> -<path d="M744.707 355.707C745.098 355.317 745.098 354.683 744.707 354.293L738.343 347.929C737.953 347.538 737.319 347.538 736.929 347.929C736.538 348.319 736.538 348.953 736.929 349.343L742.586 355L736.929 360.657C736.538 361.047 736.538 361.681 736.929 362.071C737.319 362.462 737.953 362.462 738.343 362.071L744.707 355.707ZM719 356H744V354H719V356Z" fill="black"/> -<rect x="1031" y="247" width="105" height="38" rx="19" fill="#F2FCF3"/> -<rect x="1031" y="247" width="105" height="38" rx="19" stroke="#037F0C" stroke-width="2"/> -<path fill-rule="evenodd" clip-rule="evenodd" d="M1050 274C1045.58 274 1042 270.418 1042 266C1042 261.582 1045.58 258 1050 258C1054.42 258 1058 261.582 1058 266C1058 270.418 1054.42 274 1050 274ZM1050 272C1053.31 272 1056 269.314 1056 266C1056 262.686 1053.31 260 1050 260C1046.69 260 1044 262.686 1044 266C1044 269.314 1046.69 272 1050 272ZM1045.59 266L1047 264.586L1049 266.586L1052.52 263.066L1053.93 264.48L1049 269.414L1045.59 266Z" fill="#037F0C"/> -<path d="M1069.52 267.458V271H1067.48V261.298H1071.19C1072.2 261.298 1072.99 261.573 1073.58 262.124C1074.17 262.675 1074.46 263.426 1074.46 264.378C1074.46 265.33 1074.17 266.081 1073.58 266.632C1072.99 267.183 1072.2 267.458 1071.19 267.458H1069.52ZM1069.52 265.89H1070.95C1071.42 265.89 1071.77 265.764 1072.01 265.512C1072.27 265.251 1072.39 264.873 1072.39 264.378C1072.39 263.883 1072.27 263.51 1072.01 263.258C1071.77 262.997 1071.42 262.866 1070.95 262.866H1069.52V265.89ZM1079.97 271L1079.8 270.37C1079.51 270.631 1079.18 270.841 1078.8 271C1078.42 271.149 1078.06 271.224 1077.7 271.224C1077.01 271.224 1076.46 271.028 1076.04 270.636C1075.63 270.244 1075.42 269.721 1075.42 269.068C1075.42 268.62 1075.53 268.228 1075.76 267.892C1075.98 267.547 1076.3 267.276 1076.72 267.08C1077.14 266.884 1077.64 266.786 1078.21 266.786C1078.66 266.786 1079.15 266.847 1079.69 266.968V266.268C1079.69 265.839 1079.6 265.545 1079.43 265.386C1079.25 265.227 1078.92 265.148 1078.45 265.148C1077.68 265.148 1076.84 265.293 1075.91 265.582V264.224C1076.26 264.047 1076.69 263.907 1077.21 263.804C1077.74 263.692 1078.27 263.636 1078.81 263.636C1079.77 263.636 1080.47 263.832 1080.91 264.224C1081.36 264.607 1081.58 265.213 1081.58 266.044V271H1079.97ZM1078.28 269.852C1078.51 269.852 1078.75 269.801 1078.99 269.698C1079.24 269.595 1079.48 269.455 1079.69 269.278V268.06C1079.28 267.995 1078.91 267.962 1078.59 267.962C1077.77 267.962 1077.37 268.289 1077.37 268.942C1077.37 269.231 1077.45 269.455 1077.61 269.614C1077.76 269.773 1077.99 269.852 1078.28 269.852ZM1086.55 269.026C1086.55 268.839 1086.49 268.695 1086.38 268.592C1086.28 268.489 1086.06 268.377 1085.74 268.256L1084.65 267.822C1084.08 267.598 1083.67 267.323 1083.41 266.996C1083.16 266.669 1083.04 266.254 1083.04 265.75C1083.04 265.115 1083.29 264.607 1083.79 264.224C1084.31 263.832 1084.99 263.636 1085.84 263.636C1086.62 263.636 1087.34 263.79 1088.01 264.098V265.456C1087.3 265.241 1086.63 265.134 1086.02 265.134C1085.64 265.134 1085.36 265.181 1085.18 265.274C1085 265.367 1084.91 265.517 1084.91 265.722C1084.91 265.881 1084.96 266.011 1085.07 266.114C1085.18 266.207 1085.41 266.324 1085.75 266.464L1086.82 266.898C1087.39 267.131 1087.81 267.402 1088.05 267.71C1088.3 268.018 1088.43 268.419 1088.43 268.914C1088.43 269.605 1088.16 270.165 1087.63 270.594C1087.11 271.014 1086.41 271.224 1085.56 271.224C1084.59 271.224 1083.75 271.033 1083.01 270.65V269.292C1083.93 269.581 1084.78 269.726 1085.54 269.726C1086.21 269.726 1086.55 269.493 1086.55 269.026ZM1092.78 269.026C1092.78 268.839 1092.73 268.695 1092.62 268.592C1092.51 268.489 1092.3 268.377 1091.97 268.256L1090.88 267.822C1090.31 267.598 1089.9 267.323 1089.65 266.996C1089.4 266.669 1089.27 266.254 1089.27 265.75C1089.27 265.115 1089.52 264.607 1090.03 264.224C1090.54 263.832 1091.22 263.636 1092.07 263.636C1092.85 263.636 1093.58 263.79 1094.24 264.098V265.456C1093.53 265.241 1092.87 265.134 1092.25 265.134C1091.87 265.134 1091.59 265.181 1091.41 265.274C1091.24 265.367 1091.15 265.517 1091.15 265.722C1091.15 265.881 1091.2 266.011 1091.3 266.114C1091.41 266.207 1091.64 266.324 1091.99 266.464L1093.05 266.898C1093.63 267.131 1094.04 267.402 1094.28 267.71C1094.53 268.018 1094.66 268.419 1094.66 268.914C1094.66 269.605 1094.39 270.165 1093.86 270.594C1093.34 271.014 1092.65 271.224 1091.79 271.224C1090.83 271.224 1089.98 271.033 1089.24 270.65V269.292C1090.17 269.581 1091.01 269.726 1091.78 269.726C1092.45 269.726 1092.78 269.493 1092.78 269.026ZM1099.65 271V263.846H1101.33L1101.58 264.91C1101.95 264.499 1102.3 264.21 1102.63 264.042C1102.96 263.865 1103.32 263.776 1103.69 263.776C1103.87 263.776 1104.06 263.79 1104.25 263.818V265.708C1103.99 265.652 1103.7 265.624 1103.38 265.624C1102.78 265.624 1102.21 265.731 1101.69 265.946V271H1099.65ZM1108.5 271.21C1107.39 271.21 1106.52 270.879 1105.89 270.216C1105.27 269.544 1104.95 268.611 1104.95 267.416C1104.95 266.231 1105.27 265.307 1105.89 264.644C1106.52 263.972 1107.39 263.636 1108.5 263.636C1109.61 263.636 1110.48 263.972 1111.1 264.644C1111.73 265.307 1112.04 266.231 1112.04 267.416C1112.04 268.611 1111.73 269.544 1111.1 270.216C1110.48 270.879 1109.61 271.21 1108.5 271.21ZM1108.5 269.642C1109.48 269.642 1109.97 268.9 1109.97 267.416C1109.97 265.941 1109.48 265.204 1108.5 265.204C1107.52 265.204 1107.03 265.941 1107.03 267.416C1107.03 268.9 1107.52 269.642 1108.5 269.642ZM1116.78 270.86C1116.39 271.019 1115.97 271.098 1115.52 271.098C1114.26 271.098 1113.63 270.393 1113.63 268.984V260.64H1115.68V268.816C1115.68 269.077 1115.72 269.264 1115.8 269.376C1115.89 269.479 1116.04 269.53 1116.25 269.53C1116.38 269.53 1116.56 269.516 1116.78 269.488V270.86ZM1119.57 267.92C1119.61 268.536 1119.8 268.984 1120.13 269.264C1120.47 269.535 1121 269.67 1121.72 269.67C1122.34 269.67 1123.07 269.553 1123.9 269.32V270.678C1123.57 270.846 1123.18 270.977 1122.72 271.07C1122.28 271.163 1121.81 271.21 1121.32 271.21C1120.14 271.21 1119.23 270.888 1118.61 270.244C1117.99 269.6 1117.68 268.657 1117.68 267.416C1117.68 266.221 1117.99 265.293 1118.61 264.63C1119.22 263.967 1120.08 263.636 1121.17 263.636C1122.09 263.636 1122.8 263.893 1123.3 264.406C1123.8 264.91 1124.05 265.633 1124.05 266.576C1124.05 266.781 1124.04 267.015 1124.01 267.276C1123.98 267.537 1123.95 267.752 1123.91 267.92H1119.57ZM1121.1 265.05C1120.64 265.05 1120.28 265.19 1120.01 265.47C1119.75 265.741 1119.6 266.137 1119.56 266.66H1122.3V266.422C1122.3 265.507 1121.9 265.05 1121.1 265.05Z" fill="#037F0C"/> -<path d="M1029.71 266.707C1030.1 266.317 1030.1 265.683 1029.71 265.293L1023.34 258.929C1022.95 258.538 1022.32 258.538 1021.93 258.929C1021.54 259.319 1021.54 259.953 1021.93 260.343L1027.59 266L1021.93 271.657C1021.54 272.047 1021.54 272.681 1021.93 273.071C1022.32 273.462 1022.95 273.462 1023.34 273.071L1029.71 266.707ZM1004 267H1029V265H1004V267Z" fill="black"/> -<path d="M1162.71 266.707C1163.1 266.317 1163.1 265.683 1162.71 265.293L1156.34 258.929C1155.95 258.538 1155.32 258.538 1154.93 258.929C1154.54 259.319 1154.54 259.953 1154.93 260.343L1160.59 266L1154.93 271.657C1154.54 272.047 1154.54 272.681 1154.93 273.071C1155.32 273.462 1155.95 273.462 1156.34 273.071L1162.71 266.707ZM1137 267H1162V265H1137V267Z" fill="black"/> -<path d="M1474.71 174.709C1475.1 174.319 1475.1 173.686 1474.71 173.294L1468.36 166.917C1467.97 166.526 1467.34 166.524 1466.94 166.914C1466.55 167.304 1466.55 167.937 1466.94 168.328L1472.59 173.997L1466.92 179.642C1466.53 180.032 1466.52 180.665 1466.91 181.056C1467.3 181.447 1467.94 181.449 1468.33 181.059L1474.71 174.709ZM1002 174L1474 175L1474 173L1002 172L1002 174Z" fill="black"/> -<path d="M1474.71 354.707C1475.1 354.317 1475.1 353.683 1474.71 353.293L1468.34 346.929C1467.95 346.538 1467.32 346.538 1466.93 346.929C1466.54 347.319 1466.54 347.953 1466.93 348.343L1472.59 354L1466.93 359.657C1466.54 360.047 1466.54 360.681 1466.93 361.071C1467.32 361.462 1467.95 361.462 1468.34 361.071L1474.71 354.707ZM1004 355H1474V353H1004V355Z" fill="black"/> -<path d="M1474.71 266.707C1475.1 266.317 1475.1 265.683 1474.71 265.293L1468.34 258.929C1467.95 258.538 1467.32 258.538 1466.93 258.929C1466.54 259.319 1466.54 259.953 1466.93 260.343L1472.59 266L1466.93 271.657C1466.54 272.047 1466.54 272.681 1466.93 273.071C1467.32 273.462 1467.95 273.462 1468.34 273.071L1474.71 266.707ZM1422 267H1474V265H1422V267Z" fill="black"/> -<path d="M451.293 241.707C451.683 242.098 452.317 242.098 452.707 241.707L459.071 235.343C459.462 234.953 459.462 234.319 459.071 233.929C458.681 233.538 458.047 233.538 457.657 233.929L452 239.586L446.343 233.929C445.953 233.538 445.319 233.538 444.929 233.929C444.538 234.319 444.538 234.953 444.929 235.343L451.293 241.707ZM451 209V241H453V209H451Z" fill="black"/> -<rect x="1476" y="230" width="222" height="71" stroke="#7D8998" stroke-width="2"/> -<rect x="1503" y="240" width="48" height="48" fill="#E7157B"/> -<path fill-rule="evenodd" clip-rule="evenodd" d="M1534.8 263.978H1537.8V262.776H1534.8V263.978ZM1519.8 271.189H1522.8V269.987H1519.8V271.189ZM1513.8 271.189H1518V269.987H1513.8V271.189ZM1513.8 267.583H1521V266.382H1513.8V267.583ZM1513.8 260.372H1519.2V259.171H1513.8V260.372ZM1513.8 263.978H1533.6V262.776H1513.8V263.978ZM1525.2 277.198H1511.4V256.767H1525.2V261.574H1526.4V256.166C1526.4 255.834 1526.13 255.565 1525.8 255.565H1510.8C1510.47 255.565 1510.2 255.834 1510.2 256.166V277.799C1510.2 278.131 1510.47 278.4 1510.8 278.4H1525.8C1526.13 278.4 1526.4 278.131 1526.4 277.799V265.781H1525.2V277.198ZM1543.8 262.175C1543.8 266.058 1540.3 267.409 1538.46 267.581L1528.8 267.583V266.382H1538.4C1538.52 266.368 1542.6 265.927 1542.6 262.175C1542.6 258.758 1539.52 258.065 1538.9 257.96C1538.59 257.908 1538.38 257.629 1538.4 257.318C1538.4 257.306 1538.4 257.296 1538.41 257.285C1538.37 255.354 1537.19 254.751 1536.68 254.58C1535.72 254.262 1534.65 254.566 1534.09 255.323C1533.95 255.501 1533.74 255.592 1533.52 255.558C1533.3 255.525 1533.12 255.375 1533.04 255.166C1532.67 254.122 1532.13 253.445 1531.38 252.692C1529.5 250.823 1526.94 250.307 1524.56 251.312C1523.3 251.84 1522.21 253.037 1521.55 254.596L1520.45 254.13C1521.22 252.285 1522.55 250.853 1524.09 250.204C1526.94 249.003 1529.98 249.615 1532.22 251.841C1532.86 252.484 1533.4 253.111 1533.81 253.922C1534.71 253.259 1535.91 253.06 1537.05 253.44C1538.51 253.925 1539.44 255.192 1539.59 256.877C1541.63 257.393 1543.8 259.027 1543.8 262.175V262.175Z" fill="white"/> -<path d="M1571.34 269.712C1570.48 270.043 1569.51 270.208 1568.45 270.208C1566.65 270.208 1565.28 269.728 1564.35 268.768C1563.42 267.797 1562.96 266.379 1562.96 264.512C1562.96 262.667 1563.45 261.237 1564.42 260.224C1565.39 259.211 1566.75 258.704 1568.51 258.704C1569.45 258.704 1570.34 258.853 1571.18 259.152V261.04C1570.21 260.827 1569.42 260.72 1568.8 260.72C1567.69 260.72 1566.86 261.013 1566.3 261.6C1565.76 262.187 1565.49 263.083 1565.49 264.288V264.656C1565.49 265.851 1565.75 266.741 1566.29 267.328C1566.82 267.904 1567.64 268.192 1568.74 268.192C1569.35 268.192 1570.22 268.069 1571.34 267.824V269.712ZM1576.56 269.84C1576.12 270.021 1575.64 270.112 1575.12 270.112C1573.68 270.112 1572.96 269.307 1572.96 267.696V258.16H1575.3V267.504C1575.3 267.803 1575.35 268.016 1575.44 268.144C1575.55 268.261 1575.72 268.32 1575.96 268.32C1576.11 268.32 1576.31 268.304 1576.56 268.272V269.84ZM1581.64 270.24C1580.37 270.24 1579.38 269.861 1578.67 269.104C1577.95 268.336 1577.59 267.269 1577.59 265.904C1577.59 264.549 1577.95 263.493 1578.67 262.736C1579.38 261.968 1580.37 261.584 1581.64 261.584C1582.91 261.584 1583.9 261.968 1584.62 262.736C1585.33 263.493 1585.69 264.549 1585.69 265.904C1585.69 267.269 1585.33 268.336 1584.62 269.104C1583.9 269.861 1582.91 270.24 1581.64 270.24ZM1581.64 268.448C1582.76 268.448 1583.32 267.6 1583.32 265.904C1583.32 264.219 1582.76 263.376 1581.64 263.376C1580.52 263.376 1579.96 264.219 1579.96 265.904C1579.96 267.6 1580.52 268.448 1581.64 268.448ZM1592.95 270L1592.73 269.136C1591.78 269.872 1590.79 270.24 1589.75 270.24C1589.03 270.24 1588.46 270.027 1588.05 269.6C1587.65 269.163 1587.45 268.565 1587.45 267.808V261.824H1589.78V267.152C1589.78 268.016 1590.16 268.448 1590.9 268.448C1591.46 268.448 1592 268.277 1592.53 267.936V261.824H1594.87V270H1592.95ZM1602.62 270L1602.43 269.28C1601.77 269.877 1600.99 270.176 1600.08 270.176C1599.41 270.176 1598.82 270.011 1598.3 269.68C1597.79 269.339 1597.39 268.848 1597.1 268.208C1596.83 267.568 1596.69 266.816 1596.69 265.952C1596.69 264.629 1597 263.573 1597.63 262.784C1598.26 261.984 1599.09 261.584 1600.13 261.584C1600.97 261.584 1601.7 261.824 1602.32 262.304V258.16H1604.66V270H1602.62ZM1600.85 268.416C1601.36 268.416 1601.85 268.267 1602.32 267.968V263.744C1601.86 263.477 1601.33 263.344 1600.74 263.344C1600.17 263.344 1599.75 263.557 1599.47 263.984C1599.2 264.4 1599.06 265.035 1599.06 265.888C1599.06 266.741 1599.2 267.376 1599.49 267.792C1599.79 268.208 1600.24 268.416 1600.85 268.416ZM1607.06 270V258.912H1614.04V260.768H1609.46V263.552H1613.11V265.408H1609.46V270H1607.06ZM1619.02 270.24C1617.75 270.24 1616.76 269.861 1616.04 269.104C1615.33 268.336 1614.97 267.269 1614.97 265.904C1614.97 264.549 1615.33 263.493 1616.04 262.736C1616.76 261.968 1617.75 261.584 1619.02 261.584C1620.29 261.584 1621.28 261.968 1621.99 262.736C1622.71 263.493 1623.07 264.549 1623.07 265.904C1623.07 267.269 1622.71 268.336 1621.99 269.104C1621.28 269.861 1620.29 270.24 1619.02 270.24ZM1619.02 268.448C1620.14 268.448 1620.7 267.6 1620.7 265.904C1620.7 264.219 1620.14 263.376 1619.02 263.376C1617.9 263.376 1617.34 264.219 1617.34 265.904C1617.34 267.6 1617.9 268.448 1619.02 268.448ZM1624.89 270V261.824H1626.81L1627.09 263.04C1627.52 262.571 1627.92 262.24 1628.29 262.048C1628.68 261.845 1629.08 261.744 1629.51 261.744C1629.71 261.744 1629.93 261.76 1630.15 261.792V263.952C1629.85 263.888 1629.52 263.856 1629.16 263.856C1628.46 263.856 1627.82 263.979 1627.22 264.224V270H1624.89ZM1641.5 270V264.464C1641.5 263.739 1641.17 263.376 1640.52 263.376C1639.95 263.376 1639.36 263.515 1638.78 263.792V263.952V270H1636.44V264.464C1636.44 263.739 1636.12 263.376 1635.47 263.376C1634.87 263.376 1634.28 263.52 1633.71 263.808V270H1631.37V261.824H1633.29L1633.5 262.608C1634.06 262.235 1634.57 261.973 1635.02 261.824C1635.48 261.664 1635.95 261.584 1636.43 261.584C1637.39 261.584 1638.06 261.925 1638.46 262.608C1639 262.245 1639.51 261.984 1639.99 261.824C1640.47 261.664 1640.97 261.584 1641.48 261.584C1642.23 261.584 1642.8 261.792 1643.21 262.208C1643.63 262.624 1643.83 263.205 1643.83 263.952V270H1641.5ZM1650.73 270L1650.54 269.28C1650.21 269.579 1649.82 269.819 1649.39 270C1648.96 270.171 1648.54 270.256 1648.14 270.256C1647.35 270.256 1646.71 270.032 1646.23 269.584C1645.76 269.136 1645.53 268.539 1645.53 267.792C1645.53 267.28 1645.66 266.832 1645.91 266.448C1646.17 266.053 1646.54 265.744 1647.02 265.52C1647.5 265.296 1648.06 265.184 1648.71 265.184C1649.23 265.184 1649.79 265.253 1650.41 265.392V264.592C1650.41 264.101 1650.31 263.765 1650.11 263.584C1649.9 263.403 1649.53 263.312 1648.99 263.312C1648.11 263.312 1647.15 263.477 1646.09 263.808V262.256C1646.48 262.053 1646.98 261.893 1647.58 261.776C1648.18 261.648 1648.78 261.584 1649.4 261.584C1650.5 261.584 1651.3 261.808 1651.8 262.256C1652.31 262.693 1652.57 263.387 1652.57 264.336V270H1650.73ZM1648.79 268.688C1649.06 268.688 1649.33 268.629 1649.61 268.512C1649.9 268.395 1650.16 268.235 1650.41 268.032V266.64C1649.94 266.565 1649.52 266.528 1649.15 266.528C1648.22 266.528 1647.75 266.901 1647.75 267.648C1647.75 267.979 1647.84 268.235 1648.03 268.416C1648.21 268.597 1648.46 268.688 1648.79 268.688ZM1659.64 269.792C1659.06 270.016 1658.42 270.128 1657.7 270.128C1656.8 270.128 1656.13 269.915 1655.69 269.488C1655.26 269.061 1655.05 268.4 1655.05 267.504V263.552H1653.82V262.112L1655.11 261.856L1655.46 259.616H1657.38V261.824H1659.59V263.552H1657.38V267.392C1657.38 267.733 1657.47 267.973 1657.64 268.112C1657.81 268.251 1658.1 268.32 1658.5 268.32C1658.83 268.32 1659.21 268.288 1659.64 268.224V269.792ZM1661.14 270V261.824H1663.47V270H1661.14ZM1662.31 260.56C1661.9 260.56 1661.57 260.448 1661.33 260.224C1661.08 260 1660.96 259.696 1660.96 259.312C1660.96 258.928 1661.08 258.624 1661.33 258.4C1661.57 258.176 1661.9 258.064 1662.31 258.064C1662.71 258.064 1663.04 258.176 1663.28 258.4C1663.53 258.624 1663.65 258.928 1663.65 259.312C1663.65 259.696 1663.53 260 1663.28 260.224C1663.04 260.448 1662.71 260.56 1662.31 260.56ZM1669.41 270.24C1668.14 270.24 1667.15 269.861 1666.43 269.104C1665.72 268.336 1665.36 267.269 1665.36 265.904C1665.36 264.549 1665.72 263.493 1666.43 262.736C1667.15 261.968 1668.14 261.584 1669.41 261.584C1670.68 261.584 1671.67 261.968 1672.38 262.736C1673.1 263.493 1673.46 264.549 1673.46 265.904C1673.46 267.269 1673.1 268.336 1672.38 269.104C1671.67 269.861 1670.68 270.24 1669.41 270.24ZM1669.41 268.448C1670.53 268.448 1671.09 267.6 1671.09 265.904C1671.09 264.219 1670.53 263.376 1669.41 263.376C1668.29 263.376 1667.73 264.219 1667.73 265.904C1667.73 267.6 1668.29 268.448 1669.41 268.448ZM1680.52 270V264.64C1680.52 264.203 1680.43 263.883 1680.24 263.68C1680.04 263.477 1679.75 263.376 1679.36 263.376C1678.77 263.376 1678.19 263.557 1677.61 263.92V270H1675.28V261.824H1677.2L1677.42 262.704C1678.38 261.957 1679.4 261.584 1680.49 261.584C1681.25 261.584 1681.83 261.792 1682.24 262.208C1682.65 262.613 1682.86 263.195 1682.86 263.952V270H1680.52Z" fill="#414D5C"/> -<rect x="1476" y="138" width="222" height="71" stroke="#7D8998" stroke-width="2"/> -<rect x="1503" y="150" width="48" height="48" fill="#ED7100"/> -<path fill-rule="evenodd" clip-rule="evenodd" d="M1526.27 172.547C1525.98 172.719 1525.79 173.04 1525.79 173.384V190.032L1513.2 182.991V166.625L1527.33 158.435L1539.89 164.657L1526.27 172.547ZM1541.35 164.641C1541.35 164.297 1541.17 163.975 1540.84 163.785L1527.81 157.329C1527.51 157.157 1527.14 157.157 1526.84 157.329L1512.48 165.65C1512.18 165.823 1512 166.144 1512 166.488V183.13C1512 183.474 1512.18 183.794 1512.49 183.972L1525.54 191.271C1525.69 191.357 1525.86 191.4 1526.03 191.4C1526.19 191.4 1526.36 191.357 1526.51 191.271C1526.81 191.099 1526.99 190.778 1526.99 190.434V173.521L1540.87 165.479C1541.17 165.307 1541.35 164.986 1541.35 164.641V164.641ZM1541.38 183.028L1529.99 189.997V183.757L1535.93 179.924L1535.97 179.655C1535.98 179.584 1535.98 179.584 1535.98 179.26L1536 171.816L1541.4 168.689L1541.38 183.028ZM1542.12 167.443C1541.82 167.269 1541.45 167.27 1541.15 167.443L1535.41 170.771C1535.23 170.869 1534.8 171.1 1534.8 171.575L1534.79 179.23L1529.31 182.764C1528.98 182.959 1528.79 183.267 1528.79 183.593V190.385C1528.79 190.725 1528.97 191.035 1529.28 191.212C1529.44 191.304 1529.62 191.351 1529.79 191.351C1529.97 191.351 1530.14 191.307 1530.3 191.215L1542.1 183.998C1542.4 183.826 1542.58 183.505 1542.58 183.163L1542.6 168.28C1542.6 167.936 1542.42 167.615 1542.12 167.443V167.443Z" fill="white"/> -<path d="M1560.28 179V167.912H1567.58V169.768H1562.68V172.392H1566.66V174.248H1562.68V177.144H1567.58V179H1560.28ZM1577.28 178.712C1576.42 179.043 1575.45 179.208 1574.39 179.208C1572.58 179.208 1571.22 178.728 1570.29 177.768C1569.36 176.797 1568.9 175.379 1568.9 173.512C1568.9 171.667 1569.38 170.237 1570.35 169.224C1571.32 168.211 1572.69 167.704 1574.45 167.704C1575.39 167.704 1576.28 167.853 1577.12 168.152V170.04C1576.15 169.827 1575.36 169.72 1574.74 169.72C1573.63 169.72 1572.8 170.013 1572.24 170.6C1571.7 171.187 1571.43 172.083 1571.43 173.288V173.656C1571.43 174.851 1571.69 175.741 1572.23 176.328C1572.76 176.904 1573.57 177.192 1574.67 177.192C1575.29 177.192 1576.16 177.069 1577.28 176.824V178.712ZM1579.06 179V167.912H1583.33C1584.49 167.912 1585.4 168.216 1586.07 168.824C1586.74 169.432 1587.08 170.259 1587.08 171.304C1587.08 171.944 1586.9 172.52 1586.55 173.032C1586.2 173.544 1585.7 173.944 1585.06 174.232L1587.81 179H1585.33L1582.93 174.696H1581.37V179H1579.06ZM1581.37 173.032H1583.03C1584.15 173.032 1584.71 172.467 1584.71 171.336C1584.71 170.227 1584.16 169.672 1583.06 169.672H1581.37V173.032Z" fill="#414D5C"/> -<rect x="1476" y="318" width="222" height="71" stroke="#7D8998" stroke-width="2"/> -<rect x="1503" y="330" width="48" height="48" fill="#7AA116"/> -<path fill-rule="evenodd" clip-rule="evenodd" d="M1539.5 355.736L1539.73 354.113C1541.86 355.386 1541.88 355.911 1541.88 355.926C1541.88 355.929 1541.52 356.231 1539.5 355.736V355.736ZM1538.34 355.412C1534.66 354.3 1529.55 351.954 1527.48 350.976C1527.48 350.968 1527.48 350.96 1527.48 350.952C1527.48 350.157 1526.84 349.51 1526.04 349.51C1525.25 349.51 1524.6 350.157 1524.6 350.952C1524.6 351.747 1525.25 352.394 1526.04 352.394C1526.39 352.394 1526.71 352.263 1526.96 352.056C1529.39 353.209 1534.47 355.521 1538.16 356.613L1536.7 366.936C1536.7 366.965 1536.7 366.993 1536.7 367.021C1536.7 367.93 1532.67 369.6 1526.1 369.6C1519.45 369.6 1515.38 367.93 1515.38 367.021C1515.38 366.993 1515.38 366.966 1515.38 366.939L1512.32 344.615C1514.97 346.436 1520.66 347.4 1526.1 347.4C1531.53 347.4 1537.21 346.44 1539.86 344.624L1538.34 355.412ZM1512 342.287C1512.04 341.497 1516.58 338.4 1526.1 338.4C1535.62 338.4 1540.16 341.496 1540.2 342.287V342.556C1539.68 344.327 1533.8 346.2 1526.1 346.2C1518.39 346.2 1512.51 344.321 1512 342.548V342.287ZM1541.4 342.3C1541.4 340.221 1535.44 337.2 1526.1 337.2C1516.76 337.2 1510.8 340.221 1510.8 342.3L1510.86 342.752L1514.19 367.067C1514.26 369.786 1521.52 370.8 1526.1 370.8C1531.78 370.8 1537.82 369.493 1537.9 367.068L1539.33 356.93C1540.13 357.122 1540.79 357.219 1541.32 357.219C1542.03 357.219 1542.51 357.046 1542.8 356.699C1543.04 356.415 1543.13 356.07 1543.06 355.704C1542.91 354.873 1541.92 353.978 1539.91 352.833L1541.34 342.776L1541.4 342.3Z" fill="white"/> -<path d="M1565.44 354.152C1564.49 353.8 1563.81 353.373 1563.39 352.872C1562.98 352.36 1562.77 351.715 1562.77 350.936C1562.77 349.933 1563.14 349.133 1563.87 348.536C1564.62 347.939 1565.62 347.64 1566.86 347.64C1567.91 347.64 1568.93 347.832 1569.94 348.216V350.04C1568.9 349.72 1567.94 349.56 1567.06 349.56C1565.8 349.56 1565.17 349.965 1565.17 350.776C1565.17 351.075 1565.27 351.32 1565.49 351.512C1565.71 351.704 1566.12 351.907 1566.72 352.12L1567.9 352.552C1568.9 352.915 1569.6 353.341 1570.02 353.832C1570.44 354.312 1570.66 354.941 1570.66 355.72C1570.66 356.819 1570.26 357.688 1569.47 358.328C1568.68 358.957 1567.6 359.272 1566.22 359.272C1565.63 359.272 1565.03 359.213 1564.43 359.096C1563.83 358.989 1563.32 358.84 1562.9 358.648V356.824C1563.43 356.984 1564 357.112 1564.61 357.208C1565.22 357.304 1565.77 357.352 1566.26 357.352C1566.89 357.352 1567.37 357.24 1567.71 357.016C1568.05 356.781 1568.22 356.451 1568.22 356.024C1568.22 355.693 1568.12 355.432 1567.9 355.24C1567.7 355.048 1567.29 354.835 1566.66 354.6L1565.44 354.152ZM1576.42 352.536C1577.44 352.589 1578.24 352.893 1578.83 353.448C1579.42 354.003 1579.71 354.733 1579.71 355.64C1579.71 356.344 1579.54 356.968 1579.18 357.512C1578.84 358.056 1578.34 358.483 1577.68 358.792C1577.02 359.091 1576.24 359.24 1575.36 359.24C1574.36 359.24 1573.35 359.021 1572.34 358.584V356.776C1573.53 357.181 1574.51 357.384 1575.28 357.384C1575.96 357.384 1576.48 357.24 1576.83 356.952C1577.19 356.653 1577.38 356.221 1577.38 355.656C1577.38 355.155 1577.21 354.787 1576.88 354.552C1576.55 354.307 1576.04 354.184 1575.34 354.184C1575.2 354.184 1574.96 354.2 1574.62 354.232C1574.29 354.253 1574.04 354.275 1573.86 354.296V352.824L1576.72 349.736H1572.48V347.912H1579.23V349.672L1576.42 352.536Z" fill="#414D5C"/> -<rect x="65" y="230" width="222" height="71" stroke="#7D8998" stroke-width="2"/> -<rect x="103" y="242" width="48" height="48" fill="#BD41CA"/> -<path fill-rule="evenodd" clip-rule="evenodd" d="M121 260.6H124V259.4H121V260.6ZM125 278.7L123.89 278.244L128.445 267.131L129.555 267.586L125 278.7ZM130.343 275.468L133.641 272.575L130.345 269.718L131.132 268.811L134.947 272.119C135.078 272.232 135.153 272.397 135.154 272.571C135.155 272.744 135.08 272.909 134.949 273.024L131.134 276.37L130.343 275.468ZM118.305 272.629C118.304 272.455 118.378 272.29 118.508 272.176L122.31 268.815L123.105 269.714L119.817 272.62L123.087 275.438L122.303 276.347L118.513 273.079C118.382 272.967 118.307 272.802 118.305 272.629V272.629ZM140.521 263H114.079C112.933 263 112 262.068 112 260.922V260.6H119.2V259.4H112V253.078C112 251.932 112.933 251 114.079 251H140.521C141.667 251 142.6 251.932 142.6 253.078V259.4H125.8V260.6H142.6V260.922C142.6 262.068 141.667 263 140.521 263V263ZM116.2 281.6H137.8V264.2H116.2V281.6ZM140.521 249.8H114.079C112.271 249.8 110.8 251.271 110.8 253.078V260.922C110.8 262.729 112.271 264.2 114.079 264.2H115V282.2C115 282.531 115.268 282.8 115.6 282.8H138.4C138.732 282.8 139 282.531 139 282.2V264.2H140.521C142.329 264.2 143.8 262.729 143.8 260.922V253.078C143.8 251.271 142.329 249.8 140.521 249.8V249.8Z" fill="white"/> -<path d="M171.344 271.712C170.48 272.043 169.515 272.208 168.448 272.208C166.645 272.208 165.28 271.728 164.352 270.768C163.424 269.797 162.96 268.379 162.96 266.512C162.96 264.667 163.445 263.237 164.416 262.224C165.387 261.211 166.752 260.704 168.512 260.704C169.451 260.704 170.341 260.853 171.184 261.152V263.04C170.213 262.827 169.419 262.72 168.8 262.72C167.691 262.72 166.859 263.013 166.304 263.6C165.76 264.187 165.488 265.083 165.488 266.288V266.656C165.488 267.851 165.755 268.741 166.288 269.328C166.821 269.904 167.637 270.192 168.736 270.192C169.355 270.192 170.224 270.069 171.344 269.824V271.712ZM176.596 272.24C175.326 272.24 174.334 271.861 173.62 271.104C172.905 270.336 172.548 269.269 172.548 267.904C172.548 266.549 172.905 265.493 173.62 264.736C174.334 263.968 175.326 263.584 176.596 263.584C177.865 263.584 178.857 263.968 179.572 264.736C180.286 265.493 180.644 266.549 180.644 267.904C180.644 269.269 180.286 270.336 179.572 271.104C178.857 271.861 177.865 272.24 176.596 272.24ZM176.596 270.448C177.716 270.448 178.276 269.6 178.276 267.904C178.276 266.219 177.716 265.376 176.596 265.376C175.476 265.376 174.916 266.219 174.916 267.904C174.916 269.6 175.476 270.448 176.596 270.448ZM187.984 272L187.792 271.28C187.13 271.877 186.346 272.176 185.44 272.176C184.768 272.176 184.176 272.011 183.664 271.68C183.152 271.339 182.752 270.848 182.464 270.208C182.186 269.568 182.048 268.816 182.048 267.952C182.048 266.629 182.362 265.573 182.992 264.784C183.621 263.984 184.453 263.584 185.488 263.584C186.33 263.584 187.061 263.824 187.68 264.304V260.16H190.016V272H187.984ZM186.208 270.416C186.72 270.416 187.21 270.267 187.68 269.968V265.744C187.221 265.477 186.693 265.344 186.096 265.344C185.53 265.344 185.109 265.557 184.832 265.984C184.554 266.4 184.416 267.035 184.416 267.888C184.416 268.741 184.56 269.376 184.848 269.792C185.146 270.208 185.6 270.416 186.208 270.416ZM194.005 268.48C194.047 269.184 194.261 269.696 194.645 270.016C195.029 270.325 195.631 270.48 196.453 270.48C197.167 270.48 197.999 270.347 198.949 270.08V271.632C198.575 271.824 198.127 271.973 197.605 272.08C197.093 272.187 196.559 272.24 196.005 272.24C194.65 272.24 193.615 271.872 192.901 271.136C192.197 270.4 191.845 269.323 191.845 267.904C191.845 266.539 192.197 265.477 192.901 264.72C193.605 263.963 194.581 263.584 195.829 263.584C196.885 263.584 197.695 263.877 198.261 264.464C198.837 265.04 199.125 265.867 199.125 266.944C199.125 267.179 199.109 267.445 199.077 267.744C199.045 268.043 199.007 268.288 198.965 268.48H194.005ZM195.749 265.2C195.226 265.2 194.81 265.36 194.501 265.68C194.202 265.989 194.031 266.443 193.989 267.04H197.125V266.768C197.125 265.723 196.666 265.2 195.749 265.2ZM203.413 267.952V272H201.077V260.912H205.317C206.469 260.912 207.381 261.227 208.053 261.856C208.725 262.485 209.061 263.344 209.061 264.432C209.061 265.52 208.725 266.379 208.053 267.008C207.381 267.637 206.469 267.952 205.317 267.952H203.413ZM203.413 266.16H205.045C205.578 266.16 205.984 266.016 206.261 265.728C206.549 265.429 206.693 264.997 206.693 264.432C206.693 263.867 206.549 263.44 206.261 263.152C205.984 262.853 205.578 262.704 205.045 262.704H203.413V266.16ZM210.887 272V263.824H213.223V272H210.887ZM212.055 262.56C211.65 262.56 211.324 262.448 211.079 262.224C210.834 262 210.711 261.696 210.711 261.312C210.711 260.928 210.834 260.624 211.079 260.4C211.324 260.176 211.65 260.064 212.055 260.064C212.46 260.064 212.786 260.176 213.031 260.4C213.276 260.624 213.399 260.928 213.399 261.312C213.399 261.696 213.276 262 213.031 262.224C212.786 262.448 212.46 262.56 212.055 262.56ZM215.526 275.296V263.824H217.446L217.638 264.592C217.958 264.283 218.342 264.037 218.79 263.856C219.249 263.675 219.713 263.584 220.182 263.584C221.217 263.584 222.033 263.963 222.63 264.72C223.238 265.477 223.542 266.501 223.542 267.792C223.542 268.635 223.404 269.387 223.126 270.048C222.849 270.709 222.449 271.232 221.926 271.616C221.404 271.989 220.801 272.176 220.118 272.176C219.681 272.176 219.265 272.107 218.87 271.968C218.476 271.829 218.14 271.637 217.862 271.392V275.296H215.526ZM219.43 265.344C218.876 265.344 218.353 265.488 217.862 265.776V269.984C218.332 270.272 218.854 270.416 219.43 270.416C220.028 270.416 220.465 270.213 220.742 269.808C221.03 269.403 221.174 268.763 221.174 267.888C221.174 267.003 221.036 266.357 220.758 265.952C220.481 265.547 220.038 265.344 219.43 265.344ZM227.114 268.48C227.157 269.184 227.37 269.696 227.754 270.016C228.138 270.325 228.741 270.48 229.562 270.48C230.277 270.48 231.109 270.347 232.058 270.08V271.632C231.685 271.824 231.237 271.973 230.714 272.08C230.202 272.187 229.669 272.24 229.114 272.24C227.759 272.24 226.725 271.872 226.01 271.136C225.306 270.4 224.954 269.323 224.954 267.904C224.954 266.539 225.306 265.477 226.01 264.72C226.714 263.963 227.69 263.584 228.938 263.584C229.994 263.584 230.805 263.877 231.37 264.464C231.946 265.04 232.234 265.867 232.234 266.944C232.234 267.179 232.218 267.445 232.186 267.744C232.154 268.043 232.117 268.288 232.074 268.48H227.114ZM228.858 265.2C228.335 265.2 227.919 265.36 227.61 265.68C227.311 265.989 227.141 266.443 227.098 267.04H230.234V266.768C230.234 265.723 229.775 265.2 228.858 265.2ZM237.626 271.84C237.178 272.021 236.698 272.112 236.186 272.112C234.746 272.112 234.026 271.307 234.026 269.696V260.16H236.362V269.504C236.362 269.803 236.41 270.016 236.506 270.144C236.613 270.261 236.784 270.32 237.018 270.32C237.168 270.32 237.37 270.304 237.626 270.272V271.84ZM239.293 272V263.824H241.629V272H239.293ZM240.461 262.56C240.056 262.56 239.731 262.448 239.485 262.224C239.24 262 239.117 261.696 239.117 261.312C239.117 260.928 239.24 260.624 239.485 260.4C239.731 260.176 240.056 260.064 240.461 260.064C240.867 260.064 241.192 260.176 241.437 260.4C241.683 260.624 241.805 260.928 241.805 261.312C241.805 261.696 241.683 262 241.437 262.224C241.192 262.448 240.867 262.56 240.461 262.56ZM249.181 272V266.64C249.181 266.203 249.085 265.883 248.893 265.68C248.701 265.477 248.407 265.376 248.013 265.376C247.426 265.376 246.845 265.557 246.269 265.92V272H243.933V263.824H245.853L246.077 264.704C247.037 263.957 248.061 263.584 249.149 263.584C249.906 263.584 250.487 263.792 250.892 264.208C251.309 264.613 251.517 265.195 251.517 265.952V272H249.181ZM255.473 268.48C255.516 269.184 255.729 269.696 256.113 270.016C256.497 270.325 257.1 270.48 257.921 270.48C258.636 270.48 259.468 270.347 260.417 270.08V271.632C260.044 271.824 259.596 271.973 259.073 272.08C258.561 272.187 258.028 272.24 257.473 272.24C256.119 272.24 255.084 271.872 254.369 271.136C253.665 270.4 253.313 269.323 253.313 267.904C253.313 266.539 253.665 265.477 254.369 264.72C255.073 263.963 256.049 263.584 257.297 263.584C258.353 263.584 259.164 263.877 259.729 264.464C260.305 265.04 260.593 265.867 260.593 266.944C260.593 267.179 260.577 267.445 260.545 267.744C260.513 268.043 260.476 268.288 260.433 268.48H255.473ZM257.217 265.2C256.695 265.2 256.279 265.36 255.969 265.68C255.671 265.989 255.5 266.443 255.457 267.04H258.593V266.768C258.593 265.723 258.135 265.2 257.217 265.2Z" fill="#414D5C"/> -</svg> diff --git a/v2/guide/deploy/policy-validation-synthesis.adoc b/v2/guide/deploy/policy-validation-synthesis.adoc deleted file mode 100644 index 916e7143..00000000 --- a/v2/guide/deploy/policy-validation-synthesis.adoc +++ /dev/null @@ -1,186 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[#policy-validation-synthesis] -= {aws} CDK policy validation at synthesis time -:info_titleabbrev: Policy validation -:keywords: cdk, policy, validation - -[abstract] --- -By using the appropriate policy validation plugin, you can make the {aws} CDK application check the generated {aws} CloudFormation template against your policies immediately after synthesis. --- - -// Content start - -[#policy-validation] -== Policy validation at synthesis time - -If you or your organization use any policy validation tool, such as https://docs.aws.amazon.com/cfn-guard/latest/ug/what-is-guard.html[{aws} CloudFormation Guard] or https://www.openpolicyagent.org/[OPA], to define constraints on your {aws} CloudFormation template, you can integrate them with the {aws} CDK at synthesis time. By using the appropriate policy validation plugin, you can make the {aws} CDK application check the generated {aws} CloudFormation template against your policies immediately after synthesis. If there are any violations, the synthesis will fail and a report will be printed to the console. - -The validation performed by the {aws} CDK at synthesis time validate controls at one point in the deployment lifecycle, but they can't affect actions that occur outside synthesis. Examples include actions taken directly in the console or via service APIs. They aren't resistant to alteration of {aws} CloudFormation templates after synthesis. Some other mechanism to validate the same rule set more authoritatively should be set up independently, like https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/hooks.html[{aws} CloudFormation hooks] or https://docs.aws.amazon.com/config/latest/developerguide/WhatIsConfig.html[{aws} Config]. Nevertheless, the ability of the {aws} CDK to evaluate the rule set during development is still useful as it will improve detection speed and developer productivity. - -The goal of {aws} CDK policy validation is to minimize the amount of set up needed during development, and make it as easy as possible. - -[NOTE] -==== - -This feature is considered experimental, and both the plugin API and the format of the validation report are subject to change in the future. - -==== - -[#for-application-developers] -== For application developers - -To use one or more validation plugins in your application, use the `policyValidationBeta1` property of `Stage`: - -[source,javascript,subs="verbatim,attributes"] ----- -import { CfnGuardValidator } from '@cdklabs/cdk-validator-cfnguard'; -const app = new App({ - policyValidationBeta1: [ - new CfnGuardValidator() - ], -}); -// only apply to a particular stage -const prodStage = new Stage(app, 'ProdStage', { - policyValidationBeta1: [...], -}); ----- - -Immediately after synthesis, all plugins registered this way will be invoked to validate all the templates generated in the scope you defined. In particular, if you register the templates in the `App` object, all templates will be subject to validation. - -[WARNING] -==== - -Other than modifying the cloud assembly, plugins can do anything that your {aws} CDK application can. They can read data from the filesystem, access the network etc. It's your responsibility as the consumer of a plugin to verify that it's secure to use. - -==== - -[#cfnguard-plugin] -=== {aws} CloudFormation Guard plugin - -Using the link:https://github.com/cdklabs/cdk-validator-cfnguard[`CfnGuardValidator`] plugin allows you to use https://github.com/aws-cloudformation/cloudformation-guard[{aws} CloudFormation Guard] to perform policy validations. The `CfnGuardValidator` plugin comes with a select set of https://docs.aws.amazon.com/controltower/latest/userguide/proactive-controls.html[{aws} Control Tower proactive controls] built in. The current set of rules can be found in the https://github.com/cdklabs/cdk-validator-cfnguard/blob/main/README.md[project documentation]. As mentioned in xref:policy-validation[Policy validation at synthesis time], we recommend that organizations set up a more authoritative method of validation using https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/hooks.html[{aws} CloudFormation hooks]. - -For link:https://docs.aws.amazon.com/controltower/latest/userguide/what-is-control-tower.html[{aws} Control Tower] customers, these same proactive controls can be deployed across your organization. When you enable {aws} Control Tower proactive controls in your {aws} Control Tower environment, the controls can stop the deployment of non-compliant resources deployed via {aws} CloudFormation. For more information about managed proactive controls and how they work, see the https://docs.aws.amazon.com/controltower/latest/userguide/proactive-controls.html[{aws} Control Tower documentation]. - -These {aws} CDK bundled controls and managed {aws} Control Tower proactive controls are best used together. In this scenario you can configure this validation plugin with the same proactive controls that are active in your {aws} Control Tower cloud environment. You can then quickly gain confidence that your {aws} CDK application will pass the {aws} Control Tower controls by running `cdk synth` locally. - -[#validation-report] -=== Validation Report - -When you synthesize the {aws} CDK app the validator plugins will be called and the results will be printed. An example report is showing below. - -[source,none,subs="verbatim,attributes"] ----- -Validation Report (CfnGuardValidator) -------------------------------------- -(Summary) -╔═══════════╤════════════════════════╗ -║ Status │ failure ║ -╟───────────┼────────────────────────╢ -║ Plugin │ CfnGuardValidator ║ -╚═══════════╧════════════════════════╝ -(Violations) -Ensure S3 Buckets are encrypted with a KMS CMK (1 occurrences) -Severity: medium - Occurrences: - - - Construct Path: MyStack/MyCustomL3Construct/Bucket - - Stack Template Path: ./cdk.out/MyStack.template.json - - Creation Stack: - └── MyStack (MyStack) - │ Library: aws-cdk-lib.Stack - │ Library Version: 2.50.0 - │ Location: Object.<anonymous> (/home/johndoe/tmp/cdk-tmp-app/src/main.ts:25:20) - └── MyCustomL3Construct (MyStack/MyCustomL3Construct) - │ Library: N/A - (Local Construct) - │ Library Version: N/A - │ Location: new MyStack (/home/johndoe/tmp/cdk-tmp-app/src/main.ts:15:20) - └── Bucket (MyStack/MyCustomL3Construct/Bucket) - │ Library: aws-cdk-lib/aws-s3.Bucket - │ Library Version: 2.50.0 - │ Location: new MyCustomL3Construct (/home/johndoe/tmp/cdk-tmp-app/src/main.ts:9:20) - - Resource Name: amzn-s3-demo-bucket - - Locations: - > BucketEncryption/ServerSideEncryptionConfiguration/0/ServerSideEncryptionByDefault/SSEAlgorithm - Recommendation: Missing value for key `SSEAlgorithm` - must specify `aws:kms` - How to fix: - > Add to construct properties for `cdk-app/MyStack/Bucket` - `encryption: BucketEncryption.KMS` - -Validation failed. See above reports for details ----- - -By default, the report will be printed in a human readable format. If you want a report in JSON format, enable it using the `@aws-cdk/core:validationReportJson` via the CLI or passing it directly to the application: - -[source,javascript,subs="verbatim,attributes"] ----- -const app = new App({ - context: { '@aws-cdk/core:validationReportJson': true }, -}); ----- - -Alternatively, you can set this context key-value pair using the `cdk.json` or `cdk.context.json` files in your project directory (see xref:context[Context values and the {aws} CDK]). - -If you choose the JSON format, the {aws} CDK will print the policy validation report to a file called `policy-validation-report.json` in the cloud assembly directory. For the default, human-readable format, the report will be printed to the standard output. - -[#plugin-authors] -== For plugin authors - -[#plugins] -=== Plugins - -The {aws} CDK core framework is responsible for registering and invoking plugins and then displaying the formatted validation report. The responsibility of the plugin is to act as the translation layer between the {aws} CDK framework and the policy validation tool. A plugin can be created in any language supported by {aws} CDK. If you are creating a plugin that might be consumed by multiple languages then it's recommended that you create the plugin in `TypeScript` so that you can use JSII to publish the plugin in each {aws} CDK language. - -[#creating-plugins] -=== Creating plugins - -The communication protocol between the {aws} CDK core module and your policy tool is defined by the `IPolicyValidationPluginBeta1` interface. To create a new plugin you must write a class that implements this interface. There are two things you need to implement: the plugin name (by overriding the `name` property), and the `validate()` method. - -The framework will call `validate()`, passing an `IValidationContextBeta1` object. The location of the templates to be validated is given by `templatePaths`. The plugin should return an instance of `ValidationPluginReportBeta1`. This object represents the report that the user wil receive at the end of the synthesis. - -[source,javascript,subs="verbatim,attributes"] ----- -validate(context: IPolicyValidationContextBeta1): PolicyValidationReportBeta1 { - // First read the templates using context.templatePaths... - // ...then perform the validation, and then compose and return the report. - // Using hard-coded values here for better clarity: - return { - success: false, - violations: [{ - ruleName: 'CKV_AWS_117', - description: 'Ensure that {aws} Lambda function is configured inside a VPC', - fix: 'https://docs.bridgecrew.io/docs/ensure-that-aws-lambda-function-is-configured-inside-a-vpc-1', - violatingResources: [{ - resourceName: 'MyFunction3BAA72D1', - templatePath: '/home/johndoe/myapp/cdk.out/MyService.template.json', - locations: 'Properties/VpcConfig', - }], - }], - }; -} ----- - -Note that plugins aren't allowed to modify anything in the cloud assembly. Any attempt to do so will result in synthesis failure. - -If your plugin depends on an external tool, keep in mind that some developers may not have that tool installed in their workstations yet. To minimize friction, we highly recommend that you provide some installation script along with your plugin package, to automate the whole process. Better yet, run that script as part of the installation of your package. With `npm`, for example, you can add it to the `postinstall` link:https://docs.npmjs.com/cli/v9/using-npm/scripts[script] in the `package.json` file. - -[#handling-exemptions] -=== Handling Exemptions - -If your organization has a mechanism for handling exemptions, it can be implemented as part of the validator plugin. - -An example scenario to illustrate a possible exemption mechanism: - -* An organization has a rule that public Amazon S3 buckets aren't allowed, _except_ for under certain scenarios. -* A developer is creating an Amazon S3 bucket that falls under one of those scenarios and requests an exemption (create a ticket for example). -* Security tooling knows how to read from the internal system that registers exemptions - -In this scenario the developer would request an exception in the internal system and then will need some way of "registering" that exception. Adding on to the guard plugin example, you could create a plugin that handles exemptions by filtering out the violations that have a matching exemption in an internal ticketing system. - -See the existing plugins for example implementations. - -* https://github.com/cdklabs/cdk-validator-cfnguard[@cdklabs/cdk-validator-cfnguard] \ No newline at end of file diff --git a/v2/guide/develop/cfn-layer.adoc b/v2/guide/develop/cfn-layer.adoc deleted file mode 100644 index 2913e8b1..00000000 --- a/v2/guide/develop/cfn-layer.adoc +++ /dev/null @@ -1,534 +0,0 @@ -include::../attributes.txt[] - -// Attributes -[.topic] -[#cfn-layer] -= Customize constructs from the {aws} Construct Library -:info_titleabbrev: Customize constructs - -[abstract] --- -Customize constructs from the {aws} Construct Library through escape hatches, raw overrides, and custom resources. --- - -// Content start - -Customize constructs from the {aws} Construct Library through escape hatches, raw overrides, and custom resources. - -[#develop-customize-escape] -== Use escape hatches - -The {aws} Construct Library provides xref:constructs[constructs] of varying levels of abstraction. - -At the highest level, your {aws} CDK application and the stacks in it are themselves abstractions of your entire cloud infrastructure, or significant chunks of it. They can be parameterized to deploy them in different environments or for different needs. - -Abstractions are powerful tools for designing and implementing cloud applications. The {aws} CDK gives you the power not only to build with its abstractions, but also to create new abstractions. Using the existing open-source L2 and L3 constructs as guidance, you can build your own L2 and L3 constructs to reflect your own organization's best practices and opinions. - -No abstraction is perfect, and even good abstractions cannot cover every possible use case. During development, you may find a construct that almost fits your needs, requiring a small or large customization. - -For this reason, the {aws} CDK provides ways to _break out_ of the construct model. This includes moving to a lower-level abstraction or to a different model entirely. Escape hatches let you _escape_ the {aws} CDK paradigm and customize it in ways that suit your needs. Then, you can wrap your changes in a new construct to abstract away the underlying complexity and provide a clean API for other developers. - -The following are examples of situations where you can use escape hatches: - -* An {aws} service feature is available through {aws} CloudFormation, but there are no L2 constructs for it. -* An {aws} service feature is available through {aws} CloudFormation, and there are L2 constructs for the service, but these don't yet expose the feature. Because L2 constructs are curated by the CDK team, they may not be immediately available for new features. -* The feature is not yet available through {aws} CloudFormation at all. -+ -To determine whether a feature is available through {aws} CloudFormation, see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html[{aws} Resource and Property Types Reference]. - -[#develop-customize-escape-l1] -=== Develop escape hatches for L1 constructs - -If L2 constructs are not available for the service, you can use the automatically generated L1 constructs. These resources can be recognized by their name starting with `Cfn`, such as `CfnBucket` or `CfnRole`. You instantiate them exactly as you would use the equivalent {aws} CloudFormation resource. - -For example, to instantiate a low-level Amazon S3 bucket L1 with analytics enabled, you would write something like the following. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -new s3.CfnBucket(this, 'amzn-s3-demo-bucket', { - analyticsConfigurations: [ - { - id: 'Config', - // ... - } - ] -}); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -new s3.CfnBucket(this, 'amzn-s3-demo-bucket', { - analyticsConfigurations: [ - { - id: 'Config' - // ... - } - ] -}); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -s3.CfnBucket(self, "amzn-s3-demo-bucket", - analytics_configurations: [ - dict(id="Config", - # ... - ) - ] -) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -CfnBucket.Builder.create(this, "amzn-s3-demo-bucket") - .analyticsConfigurations(Arrays.asList(java.util.Map.of( // Java 9 or later - "id", "Config", // ... - ))).build(); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -new CfnBucket(this, 'amzn-s3-demo-bucket', new CfnBucketProps { - AnalyticsConfigurations = new Dictionary<string, string> - { - ["id"] = "Config", - // ... - } -}); ----- -==== - -There might be rare cases where you want to define a resource that doesn't have a corresponding `CfnXxx` class. This could be a new resource type that hasn't yet been published in the {aws} CloudFormation resource specification. In cases like this, you can instantiate the `cdk.CfnResource` directly and specify the resource type and properties. This is shown in the following example. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -new cdk.CfnResource(this, 'amzn-s3-demo-bucket', { - type: '{aws}::S3::Bucket', - properties: { - // Note the PascalCase here! These are CloudFormation identifiers. - AnalyticsConfigurations: [ - { - Id: 'Config', - // ... - } - ] - } -}); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -new cdk.CfnResource(this, 'amzn-s3-demo-bucket', { - type: '{aws}::S3::Bucket', - properties: { - // Note the PascalCase here! These are CloudFormation identifiers. - AnalyticsConfigurations: [ - { - Id: 'Config' - // ... - } - ] - } -}); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -cdk.CfnResource(self, 'amzn-s3-demo-bucket', - type="{aws}::S3::Bucket", - properties=dict( - # Note the PascalCase here! These are CloudFormation identifiers. - "AnalyticsConfigurations": [ - { - "Id": "Config", - # ... - } - ] - ) -) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -CfnResource.Builder.create(this, "amzn-s3-demo-bucket") - .type("{aws}::S3::Bucket") - .properties(java.util.Map.of( // Map.of requires Java 9 or later - // Note the PascalCase here! These are CloudFormation identifiers - "AnalyticsConfigurations", Arrays.asList( - java.util.Map.of("Id", "Config", // ... - )))) - .build(); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -new CfnResource(this, "amzn-s3-demo-bucket", new CfnResourceProps -{ - Type = "{aws}::S3::Bucket", - Properties = new Dictionary<string, object> - { // Note the PascalCase here! These are CloudFormation identifiers - ["AnalyticsConfigurations"] = new Dictionary<string, string>[] - { - new Dictionary<string, string> { - ["Id"] = "Config" - } - } - } -}); ----- -==== - -[#develop-customize-escape-l2] -=== Develop escape hatches for L2 constructs - -If an L2 construct is missing a feature or you're trying to work around an issue, you can modify the L1 construct that's encapsulated by the L2 construct. - -All L2 constructs contain within them the corresponding L1 construct. For example, the high-level `Bucket` construct wraps the low-level `CfnBucket` construct. Because the `CfnBucket` corresponds directly to the {aws} CloudFormation resource, it exposes all features that are available through {aws} CloudFormation. - -The basic approach to get access to the L1 construct is to use `construct.node.defaultChild` (Python: `default_child`), cast it to the right type (if necessary), and modify its properties. Again, let's take the example of a `Bucket`. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -// Get the CloudFormation resource -const cfnBucket = bucket.node.defaultChild as s3.CfnBucket; - -// Change its properties -cfnBucket.analyticsConfiguration = [ - { - id: 'Config', - // ... - } -]; ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -// Get the CloudFormation resource -const cfnBucket = bucket.node.defaultChild; - -// Change its properties -cfnBucket.analyticsConfiguration = [ - { - id: 'Config' - // ... - } -]; ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -# Get the CloudFormation resource -cfn_bucket = bucket.node.default_child - -# Change its properties -cfn_bucket.analytics_configuration = [ - { - "id": "Config", - # ... - } -] ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -// Get the CloudFormation resource -CfnBucket cfnBucket = (CfnBucket)bucket.getNode().getDefaultChild(); - -cfnBucket.setAnalyticsConfigurations( - Arrays.asList(java.util.Map.of( // Java 9 or later - "Id", "Config", // ... - )); -) ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -// Get the CloudFormation resource -var cfnBucket = (CfnBucket)bucket.Node.DefaultChild; - -cfnBucket.AnalyticsConfigurations = new List<object> { - new Dictionary<string, string> - { - ["Id"] = "Config", - // ... - } -}; ----- -==== - -You can also use this object to change {aws} CloudFormation options such as `Metadata` and ``UpdatePolicy``. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -cfnBucket.cfnOptions.metadata = { - MetadataKey: 'MetadataValue' -}; ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -cfnBucket.cfnOptions.metadata = { - MetadataKey: 'MetadataValue' -}; ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -cfn_bucket.cfn_options.metadata = { - "MetadataKey": "MetadataValue" -} ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -cfnBucket.getCfnOptions().setMetadata(java.util.Map.of( // Java 9+ - "MetadataKey", "Metadatavalue")); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -cfnBucket.CfnOptions.Metadata = new Dictionary<string, object> -{ - ["MetadataKey"] = "Metadatavalue" -}; ----- -==== - -[#develop-customize-unescape] -== Use un-escape hatches - -The {aws} CDK also provides the capability to go _up_ an abstraction level, which we might refer to as an "un-escape" hatch. If you have an L1 construct, such as `CfnBucket`, you can create a new L2 construct (`Bucket` in this case) to wrap the L1 construct. - -This is convenient when you create an L1 resource but want to use it with a construct that requires an L2 resource. It's also helpful when you want to use convenience methods like `.grantXxxxx()` that aren't available on the L1 construct. - -You move to the higher abstraction level using a static method on the L2 class called `.fromCfnXxxxx()`--for example, `Bucket.fromCfnBucket()` for Amazon S3 buckets. The L1 resource is the only parameter. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -b1 = new s3.CfnBucket(this, "buck09", { ... }); -b2 = s3.Bucket.fromCfnBucket(b1); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -b1 = new s3.CfnBucket(this, "buck09", { ...} ); -b2 = s3.Bucket.fromCfnBucket(b1); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -b1 = s3.CfnBucket(self, "buck09", ...) - b2 = s3.from_cfn_bucket(b1) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -CfnBucket b1 = CfnBucket.Builder.create(this, "buck09") - // .... - .build(); -IBucket b2 = Bucket.fromCfnBucket(b1); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -var b1 = new CfnBucket(this, "buck09", new CfnBucketProps { ... }); -var v2 = Bucket.FromCfnBucket(b1); ----- -==== - -L2 constructs created from L1 constructs are proxy objects that refer to the L1 resource, similar to those created from resource names, ARNs, or lookups. Modifications to these constructs do not affect the final synthesized {aws} CloudFormation template (since you have the L1 resource, however, you can modify that instead). For more information on proxy objects, see xref:resources-external[Referencing resources in your {aws} account]. - -To avoid confusion, do not create multiple L2 constructs that refer to the same L1 construct. For example, if you extract the `CfnBucket` from a `Bucket` using the technique in the xref:develop-customize-escape-l2[previous section], you shouldn't create a second `Bucket` instance by calling `Bucket.fromCfnBucket()` with that `CfnBucket`. It actually works as you'd expect (only one `{aws}::S3::Bucket` is synthesized) but it makes your code more difficult to maintain. - -[#develop-customize-override] -== Use raw overrides - -If there are properties that are missing from the L1 construct, you can bypass all typing using raw overrides. This also makes it possible to delete synthesized properties. - -Use one of the `addOverride` methods (Python: `add_override`) methods, as shown in the following example. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -// Get the CloudFormation resource -const cfnBucket = bucket.node.defaultChild as s3.CfnBucket; - -// Use dot notation to address inside the resource template fragment -cfnBucket.addOverride('Properties.VersioningConfiguration.Status', 'NewStatus'); -cfnBucket.addDeletionOverride('Properties.VersioningConfiguration.Status'); - -// use index (0 here) to address an element of a list -cfnBucket.addOverride('Properties.Tags.0.Value', 'NewValue'); -cfnBucket.addDeletionOverride('Properties.Tags.0'); - -// addPropertyOverride is a convenience function for paths starting with "Properties." -cfnBucket.addPropertyOverride('VersioningConfiguration.Status', 'NewStatus'); -cfnBucket.addPropertyDeletionOverride('VersioningConfiguration.Status'); -cfnBucket.addPropertyOverride('Tags.0.Value', 'NewValue'); -cfnBucket.addPropertyDeletionOverride('Tags.0'); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -// Get the CloudFormation resource -const cfnBucket = bucket.node.defaultChild ; - -// Use dot notation to address inside the resource template fragment -cfnBucket.addOverride('Properties.VersioningConfiguration.Status', 'NewStatus'); -cfnBucket.addDeletionOverride('Properties.VersioningConfiguration.Status'); - -// use index (0 here) to address an element of a list -cfnBucket.addOverride('Properties.Tags.0.Value', 'NewValue'); -cfnBucket.addDeletionOverride('Properties.Tags.0'); - -// addPropertyOverride is a convenience function for paths starting with "Properties." -cfnBucket.addPropertyOverride('VersioningConfiguration.Status', 'NewStatus'); -cfnBucket.addPropertyDeletionOverride('VersioningConfiguration.Status'); -cfnBucket.addPropertyOverride('Tags.0.Value', 'NewValue'); -cfnBucket.addPropertyDeletionOverride('Tags.0'); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -# Get the CloudFormation resource -cfn_bucket = bucket.node.default_child - -# Use dot notation to address inside the resource template fragment -cfn_bucket.add_override("Properties.VersioningConfiguration.Status", "NewStatus") -cfn_bucket.add_deletion_override("Properties.VersioningConfiguration.Status") - -# use index (0 here) to address an element of a list -cfn_bucket.add_override("Properties.Tags.0.Value", "NewValue") -cfn_bucket.add_deletion_override("Properties.Tags.0") - -# addPropertyOverride is a convenience function for paths starting with "Properties." -cfn_bucket.add_property_override("VersioningConfiguration.Status", "NewStatus") -cfn_bucket.add_property_deletion_override("VersioningConfiguration.Status") -cfn_bucket.add_property_override("Tags.0.Value", "NewValue") -cfn_bucket.add_property_deletion_override("Tags.0") ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -// Get the CloudFormation resource -CfnBucket cfnBucket = (CfnBucket)bucket.getNode().getDefaultChild(); - -// Use dot notation to address inside the resource template fragment -cfnBucket.addOverride("Properties.VersioningConfiguration.Status", "NewStatus"); -cfnBucket.addDeletionOverride("Properties.VersioningConfiguration.Status"); - -// use index (0 here) to address an element of a list -cfnBucket.addOverride("Properties.Tags.0.Value", "NewValue"); -cfnBucket.addDeletionOverride("Properties.Tags.0"); - -// addPropertyOverride is a convenience function for paths starting with "Properties." -cfnBucket.addPropertyOverride("VersioningConfiguration.Status", "NewStatus"); -cfnBucket.addPropertyDeletionOverride("VersioningConfiguration.Status"); -cfnBucket.addPropertyOverride("Tags.0.Value", "NewValue"); -cfnBucket.addPropertyDeletionOverride("Tags.0"); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -// Get the CloudFormation resource -var cfnBucket = (CfnBucket)bucket.node.defaultChild; - -// Use dot notation to address inside the resource template fragment -cfnBucket.AddOverride("Properties.VersioningConfiguration.Status", "NewStatus"); -cfnBucket.AddDeletionOverride("Properties.VersioningConfiguration.Status"); - -// use index (0 here) to address an element of a list -cfnBucket.AddOverride("Properties.Tags.0.Value", "NewValue"); -cfnBucket.AddDeletionOverride("Properties.Tags.0"); - -// addPropertyOverride is a convenience function for paths starting with "Properties." -cfnBucket.AddPropertyOverride("VersioningConfiguration.Status", "NewStatus"); -cfnBucket.AddPropertyDeletionOverride("VersioningConfiguration.Status"); -cfnBucket.AddPropertyOverride("Tags.0.Value", "NewValue"); -cfnBucket.AddPropertyDeletionOverride("Tags.0"); ----- -==== - -[#develop-customize-custom] -== Use custom resources - -If the feature isn't available through {aws} CloudFormation, but only through a direct API call, you must write an {aws} CloudFormation Custom Resource to make the API call you need. You can use the {aws} CDK to write custom resources and wrap them into a regular construct interface. From the perspective of a consumer of your construct, the experience will feel native. - -Building a custom resource involves writing a Lambda function that responds to a resource's `CREATE`, `UPDATE`, and `DELETE` lifecycle events. If your custom resource needs to make only a single API call, consider using the https://github.com/awslabs/aws-cdk/tree/master/packages/%40aws-cdk/custom-resources[AwsCustomResource]. This makes it possible to perform arbitrary SDK calls during an {aws} CloudFormation deployment. Otherwise, you should write your own Lambda function to perform the work you need to get done. - -The subject is too broad to cover completely here, but the following links should get you started: - -* https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-custom-resources.html[Custom Resources] -* https://github.com/aws-samples/aws-cdk-examples/tree/master/typescript/custom-resource/[Custom-Resource Example] -* For a more fully fledged example, see the https://github.com/awslabs/aws-cdk/blob/master/packages/@aws-cdk/aws-certificatemanager/lib/dns-validated-certificate.ts[DnsValidatedCertificate] class in the CDK standard library. This is implemented as a custom resource. \ No newline at end of file diff --git a/v2/guide/develop/chapter-develop.adoc b/v2/guide/develop/chapter-develop.adoc deleted file mode 100644 index 01e35bca..00000000 --- a/v2/guide/develop/chapter-develop.adoc +++ /dev/null @@ -1,68 +0,0 @@ -include::../attributes.txt[] - -// Attributes -[.topic] -[#develop] -= Develop {aws} CDK applications -:keywords: {aws} CDK, IaC, Infrastructure as code, {aws}, {aws} Cloud, serverless, modern applications - -[abstract] --- -Manage your infrastructure on {aws} by developing applications using the {aws} Cloud Development Kit ({aws} CDK). --- - -// Content start - -Manage your infrastructure on {aws} by developing applications using the {aws} Cloud Development Kit ({aws} CDK). - -[#develop-prerequisites] -== Prerequisites - -Before you can start developing applications, complete all set up steps in xref:getting-started[Getting started with the {aws} CDK]. - -[#develop-overview] -== Developing {aws} CDK applications overview - -At a high-level, developing CDK applications involves the following steps: - -. *Create a CDK project* – A CDK xref:projects[project] consists of the files and folders that store and organize your CDK code. -. *Create a CDK app* – Within a CDK project, you use the `App` construct to define a CDK xref:apps[application]. -. *Create a CDK stack* – Within the scope of your CDK app, you define one or more CDK xref:stacks[stacks]. -. *Define your infrastructure* – Within the scope of a CDK stack, you use xref:constructs[constructs] from the {aws} Construct Library to define the {aws} resources and properties that will become your infrastructure. Using a general-purpose programming xref:languages[language] of your choice, you can use logic, such as conditional statements and loops, to define your infrastructure based on certain conditions. - -[#develop-gs] -== Get started with developing CDK applications - -To get started, you can use the {aws} CDK Command Line Interface ({aws} CDK CLI) `cdk init` command. Provide the `--language` option to specify the programming language to use. This command creates a starting CDK project and imports the main {aws} Construct Library and core modules. - -[#develop-library] -== Import and use the {aws} CDK Library - -After you create a CDK project, import and use constructs from the {aws} CDK Library to begin defining your infrastructure. For instructions, see xref:work-with[Work with the {aws} CDK library]. - -[#develop-next] -== Next steps - -When ready to deploy your application, use the CDK CLI `cdk deploy` command. For instructions, see xref:deploy[Deploy {aws} CDK applications]. - -include::usage-data.adoc[leveloffset=+1] - -include::cfn-layer.adoc[leveloffset=+1] - -include::get-env-var.adoc[leveloffset=+1] - -include::get-cfn-val.adoc[leveloffset=+1] - -include::use-cfn-template.adoc[leveloffset=+1] - -include::get-ssm-val.adoc[leveloffset=+1] - -include::get-sm-val.adoc[leveloffset=+1] - -include::set-cw-alarm.adoc[leveloffset=+1] - -include::get-context-var.adoc[leveloffset=+1] - -include::use-cfn-public-registry.adoc[leveloffset=+1] - -include::define-iam-l2.adoc[leveloffset=+1] \ No newline at end of file diff --git a/v2/guide/develop/define-iam-l2.adoc b/v2/guide/develop/define-iam-l2.adoc deleted file mode 100644 index 7524b1c3..00000000 --- a/v2/guide/develop/define-iam-l2.adoc +++ /dev/null @@ -1,475 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[#define-iam-l2] -= Define permissions for L2 constructs with the {aws} CDK -:info_titleabbrev: Define permissions for L2 constructs -:keywords: {aws} CDK, {aws} Construct Library, {aws} CloudFormation, IAM, Permissions, Roles, Policies, - -[abstract] --- -Define {aws} Identity and Access Management (IAM) roles and policies for L2 constructs when using the {aws} Cloud Development Kit ({aws} CDK). --- - -// Content start - -Define {aws} Identity and Access Management (IAM) roles and policies for L2 constructs when using the {aws} Cloud Development Kit ({aws} CDK). - -[#define-iam-l2-grant] -== Use grant methods to define permissions - -When you define your infrastructure using L2 constructs from the {aws} Construct Library, you can use the provided _grant methods_ to specify the permissions your resources will require. The {aws} CDK will automatically create the IAM roles needed for all {aws} resources that require them. - -The following is an example that defines permissions between an {aws} Lambda function and Amazon Simple Storage Service (Amazon S3) bucket. Here, the `grantRead` method of the Bucket L2 construct is used to define these permissions: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -import * as cdk from 'aws-cdk-lib'; -import { Construct } from 'constructs'; -import * as s3 from 'aws-cdk-lib/aws-s3'; -import * as lambda from 'aws-cdk-lib/aws-lambda'; -import * as kms from 'aws-cdk-lib/aws-kms'; - -export class CdkDemoStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - const key = new kms.Key(this, 'BucketKey'); - const bucket = new s3.Bucket(this, 'Bucket', { - encryptionKey: key, - }); - const handler = new lambda.Function(this, 'Handler', { - runtime: lambda.Runtime.NODEJS_20_X, - handler: 'index.handler', - code: lambda.Code.fromAsset('lambda'), - }); - - // Define permissions between function and S3 bucket using grantRead method - bucket.grantRead(handler); - - } -} ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const { Stack, Duration } = require('aws-cdk-lib'); -const s3 = require('aws-cdk-lib/aws-s3'); -const lambda = require('aws-cdk-lib/aws-lambda'); -const kms = require('aws-cdk-lib/aws-kms'); - -class CdkDemoStack extends Stack { - - constructor(scope, id, props) { - super(scope, id, props); - - const key = new kms.Key(this, 'BucketKey'); - const bucket = new s3.Bucket(this, 'Bucket', { - encryptionKey: key, - }); - const handler = new lambda.Function(this, 'Handler', { - runtime: lambda.Runtime.NODEJS_20_X, - handler: 'index.handler', - code: lambda.Code.fromAsset('lambda'), - }); - - // Define permissions between function and S3 bucket using grantRead method - bucket.grantRead(handler); - - } -} - -// ... ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -from aws_cdk import ( - Stack, - aws_s3 as s3, - aws_lambda as _lambda, - aws_kms as kms, -) -from constructs import Construct - -class CdkDemoStack(Stack): - - def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: - super().__init__(scope, construct_id, **kwargs) - - key = kms.Key(self, 'BucketKey') - bucket = s3.Bucket(self, 'Bucket') - handler = _lambda.Function( - self, - 'Handler', - runtime = _lambda.Runtime.NODEJS_20_X, - handler = 'index.handler', - code = _lambda.Code.from_asset('lambda'), - ) - - # Define permissions between function and S3 bucket using grantRead method - bucket.grantRead(handler) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -package com.myorg; - -import software.amazon.awscdk.core.App; -import software.amazon.awscdk.core.Stack; -import software.amazon.awscdk.core.StackProps; -import software.amazon.awscdk.services.kms.Key; -import software.amazon.awscdk.services.kms.KeyProps; -import software.amazon.awscdk.services.s3.Bucket; -import software.amazon.awscdk.services.s3.BucketProps; -import software.amazon.awscdk.services.lambda.Function; -import software.amazon.awscdk.services.lambda.FunctionProps; -import software.amazon.awscdk.services.lambda.Runtime; -import software.amazon.awscdk.services.lambda.Code; -import software.constructs.Construct; - -public class CdkDemoStack extends Stack { - public CdkDemoStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public CdkDemoStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - Key key = new Key(this, "BucketKey", KeyProps.builder().build()); - - Bucket bucket = new Bucket(this, "Bucket", BucketProps.builder() - .encryptionKey(key) - .build()); - - Function handler = new Function(this, "Handler", FunctionProps.builder() - .runtime(Runtime.NODEJS_20_X) - .handler("index.handler") - .code(Code.fromAsset("lambda")) - .build()); - - // Define permissions between function and S3 bucket using grantRead method - bucket.grantRead(handler); - } - - public static void main(final String[] args) { - App app = new App(); - - new CdkDemoStack(app, "CdkDemoStack"); - - app.synth(); - } -} ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -using Amazon.CDK; -using Amazon.CDK.{aws}.KMS; -using Amazon.CDK.{aws}.S3; -using Amazon.CDK.{aws}.Lambda; - -namespace CdkDemo -{ - public class CdkDemoStack : Stack - { - internal CdkDemoStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) - { - var key = new Key(this, "BucketKey"); - - var bucket = new Bucket(this, "Bucket", new BucketProps - { - EncryptionKey = key - }); - - var handler = new Function(this, "Handler", new FunctionProps - { - Runtime = Runtime.NODEJS_20_X, - Handler = "index.handler", - Code = Code.FromAsset("lambda") - }); - - // Define permissions between function and S3 bucket using grantRead method - bucket.GrantRead(handler); - } - } -} ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -package main -import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/aws-cdk-go/awscdk/v2/awskms" - "github.com/aws/aws-cdk-go/awscdk/v2/awss3" - "github.com/aws/aws-cdk-go/awscdk/v2/awslambda" - "github.com/aws/constructs-go/constructs/v10" - "github.com/aws/jsii-runtime-go" -) -// ... -func NewCdkDemoStack(scope constructs.Construct, id string, props *CdkDemoStackProps) awscdk.Stack { - stack := awscdk.NewStack(scope, &id, &props.StackProps) - key := awskms.NewKey(stack, jsii.String("BucketKey"), nil) - bucket := awss3.NewBucket(stack, jsii.String("Bucket"), &awss3.BucketProps{ - EncryptionKey: key, - }) - handler := awslambda.NewFunction(stack, jsii.String("Handler"), &awslambda.FunctionProps{ - Runtime: awslambda.Runtime_NODEJS_20_X(), - Handler: jsii.String("index.handler"), - Code: awslambda.Code_FromAsset(jsii.String("lambda"), &awss3assets.AssetOptions{}), - }) - bucket.GrantRead(handler) - return stack -} -// ... ----- -==== - -When you use grant methods of L2 constructs to define permissions between resources, the {aws} CDK will create roles with least privilege policies based on the method you specify. As a security best practice, we recommend that you use the method that applies only the permissions that you require. For example, if you only need to grant permissions for a Lambda function to read from an Amazon S3 bucket, use the `grantRead` method instead of `grantReadWrite`. - -For each method that you use, the CDK creates a unique IAM role for the specified resources. If necessary, you can also directly modify the policy that will be attached to the role. The following is an example: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -import { aws_iam as iam } from 'aws-cdk-lib'; - -handler.addToRolePolicy(new iam.PolicyStatement({ - actions: ['s3:GetObject', 's3:List*'], - resources: [ - bucket.bucketArn, - bucket.arnForObjects('*'), - ] -})); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const iam = require('aws-cdk-lib/aws-iam'); - -handler.addToRolePolicy(new iam.PolicyStatement({ - actions: ['s3:GetObject', 's3:List*'], - resources: [ - bucket.bucketArn, - bucket.arnForObjects('*'), - ] -})); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -from aws_cdk import aws_iam as iam - -handler.add_to_role_policy(iam.PolicyStatement( - actions=['s3:GetObject', 's3:List*'], - resources=[ - bucket.bucket_arn, - bucket.arn_for_objects('*'), - ] -)) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -import software.amazon.awscdk.services.iam.PolicyStatement; -import software.amazon.awscdk.services.iam.PolicyStatementProps; - -handler.addToRolePolicy(PolicyStatement.Builder.create() - .actions(Arrays.asList("s3:GetObject", "s3:List*")) - .resources(Arrays.asList( - bucket.getBucketArn(), - bucket.arnForObjects("*") - )) - .build()); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -using Amazon.CDK.{aws}.IAM; -using Amazon.CDK.{aws}.S3; -using Amazon.CDK.{aws}.Lambda; - -handler.AddToRolePolicy(new PolicyStatement(new PolicyStatementProps -{ - Actions = new[] { "s3:GetObject", "s3:List*" }, - Resources = new[] { bucket.BucketArn, bucket.ArnForObjects("*") } -})); ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -package main - -import ( - // ... - "github.com/aws/aws-cdk-go/awscdk/v2/awsiam" - // ... -) - -// ... - -func NewCdkDemoStack(scope constructs.Construct, id string, props *CdkDemoStackProps) awscdk.Stack { - // ... - - handler.AddToRolePolicy(awsiam.NewPolicyStatement(&awsiam.PolicyStatementProps{ - Actions: jsii.Strings("s3:GetObject", "s3:List*"), - Resources: jsii.Strings(bucket.BucketArn(), bucket.ArnForObjects("*")), - })) - - // ... -} ----- -==== - -However, we recommend that you use the `grant` methods when available. - -[#define-iam-l2-manual] -== Manually create and use IAM roles - -If you prefer not to use the CDK `grant` methods to create and manage permissions, you must manually create and configure them. You can create IAM roles using the {aws} Management Console, {aws} CLI, or {aws} SDKs. Then, you can pass them into your CDK application manually or use the _role customization_ feature. - -[#define-iam-l2-manual-role] -=== Reference and manage all roles manually - -Constructs that require a role have an optional `role` property that you can use to pass in a role object. - -*To reference a role manually*:: -+ -. Use `Role.fromRoleName()` to reference your pre-existing role. The following is an example: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const existingRole = Role.fromRoleName(stack, 'Role', 'my-pre-existing-role', { - mutable: false // Prevent CDK from attempting to add policies to this role -}) ----- -+ -. Pass the pre-existing role when defining your resource. The following is an example: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const handler = new lambda.Function(stack, 'Handler', { runtime: lambda.Runtime.NODEJS_20_XZ, handler: - 'index.handler', code: lambda.Code.fromAsset(path.join(__dirname, 'lambda-handler')), // Pass in pre-existing role - role: existingRole, }); ----- - -[#define-iam-l2-manual-customization] -=== Use the role customization feature - -The {aws} CDK _role customization_ feature generates a report of roles and policies in your CDK app. You can use this feature to generate a report. Then you can substitute pre-created roles for them. - -*To use the role customization feature*:: -+ -. Add `Role.customizeRoles()` somewhere towards the top of your CDK application. The following is an example: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const stack = new Stack(app, 'LambdaStack'); - -// Add this to use the role customization feature -iam.Role.customizeRoles(stack); - -// Define your resources using L2 constructs -const key = new kms.Key(stack, 'BucketKey'); -const bucket = new s3.Bucket(stack, 'Bucket', { - encryptionKey: key, -}); -const handler = new lambda.Function(stack, 'Handler', { - runtime: lambda.Runtime.NODEJS_16_X, - handler: 'index.handler', - code: lambda.Code.fromAsset(path.join(__dirname, 'lambda-handler')), -}); - -// The grantRead() is still important. Even though it actually doesn't mutate -// any policies, it indicates the need for them. -bucket.grantRead(handler); ----- -+ -. When you synthesize your application, the CDK will throw an error, indicating that you need to provide the pre-created role name to `Role.customizeRoles()`. The following is an example of the generated report: -+ ----- -<missing role> (LambdaStack/Handler/ServiceRole) - -AssumeRole Policy: -[ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "lambda.amazonaws.com" - } - } -] - -Managed Policy ARNs: -[ - "arn:(PARTITION):iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" -] - -Managed Policies Statements: -NONE - -Identity Policy Statements: -[ - { - "Action": [ - "s3:GetObject*", - "s3:GetBucket*", - "s3:List*" - ], - "Effect": "Allow", - "Resource": [ - "(LambdaStack/Bucket/Resource.Arn)", - "(LambdaStack/Bucket/Resource.Arn)/*" - ] - } -] ----- -+ -. Once the role is created, you can pass it into your application for the resource that it applies to. For example, if the name of the role created for `LambdaStack/Handler/ServiceRole` is `lambda-service-role`, you would update your CDK app as follows: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const stack = new Stack(app, 'LambdaStack'); - -// Add this to pass in the role -iam.Role.customizeRoles(stack, { - usePrecreatedRoles: { - 'LambdaStack/Handler/ServiceRole': 'lambda-service-role', - }, -}); ----- -+ -The CDK will now use the pre-created role name anywhere that the role is referenced in the CDK application. It will also continue to generate the report so that any future policy changes can be referenced. -+ -You will notice that the reference to the Amazon S3 bucket ARN in the report is rendered as (`LambdaStack/Bucket/Resource.Arn`) instead of the actual ARN of the bucket. This is because the bucket ARN is a deploy time value that is not known at synthesis (the bucket hasn`'t been created yet). This is another example of why we recommend allowing CDK to manage IAM roles and permissions by using the provided `grant` methods. In order to create the role with the initial policy, the admin will have to create the policy with broader permissions (for example, `arn:aws:s3:::*`). \ No newline at end of file diff --git a/v2/guide/develop/get-cfn-val.adoc b/v2/guide/develop/get-cfn-val.adoc deleted file mode 100644 index 56ea9798..00000000 --- a/v2/guide/develop/get-cfn-val.adoc +++ /dev/null @@ -1,358 +0,0 @@ -include::../attributes.txt[] - -// Attribues -[.topic] -[#get-cfn-param] -= Use CloudFormation parameters to get a CloudFormation value -:info_titleabbrev: Use CloudFormation parameters - -// Content start - -Use {aws} CloudFormation parameters within {aws} Cloud Development Kit ({aws} CDK) applications to input custom values into your synthesized CloudFormation templates at deployment. - -For an introduction, see xref:parameters[Parameters and the {aws} CDK]. - -[#parameters-define] -== Define parameters in your CDK app - -Use the link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.CfnParameter.html[`CfnParameter`] class to define a parameter. You'll want to specify at least a type and a description for most parameters, though both are technically optional. The description appears when the user is prompted to enter the parameter's value in the {aws} CloudFormation console. For more information on the available types, see link:https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html#parameters-section-structure-properties-type[Types]. - -[NOTE] -==== - -You can define parameters in any scope. However, we recommend defining parameters at the stack level so that their logical ID doesn't change when you refactor your code. - -==== - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const uploadBucketName = new CfnParameter(this, "uploadBucketName", { - type: "String", - description: "The name of the Amazon S3 bucket where uploaded files will be stored."}); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const uploadBucketName = new CfnParameter(this, "uploadBucketName", { - type: "String", - description: "The name of the Amazon S3 bucket where uploaded files will be stored."}); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -upload_bucket_name = CfnParameter(self, "uploadBucketName", type="String", - description="The name of the Amazon S3 bucket where uploaded files will be stored.") ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -CfnParameter uploadBucketName = CfnParameter.Builder.create(this, "uploadBucketName") - .type("String") - .description("The name of the Amazon S3 bucket where uploaded files will be stored") - .build(); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -var uploadBucketName = new CfnParameter(this, "uploadBucketName", new CfnParameterProps -{ - Type = "String", - Description = "The name of the Amazon S3 bucket where uploaded files will be stored" -}); ----- -==== - - -[#parameters-use,] -== Use parameters - -A `CfnParameter` instance exposes its value to your CDK app via a xref:tokens[token]. Like all tokens, the parameter's token is resolved at synthesis time. But it resolves to a reference to the parameter defined in the {aws} CloudFormation template (which will be resolved at deploy time), rather than to a concrete value. - -You can retrieve the token as an instance of the `Token` class, or in string, string list, or numeric encoding. Your choice depends on the kind of value required by the class or method that you want to use the parameter with. - -==== -[role="tablist"] -TypeScript:: -+ -[cols="1,1", options="header"] -|=== -| Property -| kind of value - -|`value` -|`Token` class instance - -|`valueAsList` -|The token represented as a string list - -|`valueAsNumber` -|The token represented as a number - -|`valueAsString` -|The token represented as a string -|=== - -JavaScript:: -+ -[cols="1,1", options="header"] -|=== -| Property -| kind of value - -|`value` -|`Token` class instance - -|`valueAsList` -|The token represented as a string list - -|`valueAsNumber` -|The token represented as a number - -|`valueAsString` -|The token represented as a string -|=== - -Python:: -+ -[cols="1,1", options="header"] -|=== -| Property -| kind of value - -|`value` -|`Token` class instance - -|`value_as_list` -|The token represented as a string list - -|`value_as_number` -|The token represented as a number - -|`value_as_string` -|The token represented as a string -|=== - -Java:: -+ -[cols="1,1", options="header"] -|=== -| Property -| kind of value - -|`getValue()` -|`Token` class instance - -|`getValueAsList()` -|The token represented as a string list - -|`getValueAsNumber()` -|The token represented as a number - -|`getValueAsString()` -|The token represented as a string -|=== - -C#:: -+ -[cols="1,1", options="header"] -|=== -| Property -| kind of value - -|`Value` -|`Token` class instance - -|`ValueAsList` -|The token represented as a string list - -|`ValueAsNumber` -|The token represented as a number - -|`ValueAsString` -|The token represented as a string -|=== -==== - -For example, to use a parameter in a `Bucket` definition: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const bucket = new Bucket(this, "amzn-s3-demo-bucket", - { bucketName: uploadBucketName.valueAsString}); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const bucket = new Bucket(this, "amzn-s3-demo-bucket", - { bucketName: uploadBucketName.valueAsString}); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -bucket = Bucket(self, "amzn-s3-demo-bucket", - bucket_name=upload_bucket_name.value_as_string) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -Bucket bucket = Bucket.Builder.create(this, "amzn-s3-demo-bucket") - .bucketName(uploadBucketName.getValueAsString()) - .build(); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -var bucket = new Bucket(this, "amzn-s3-demo-bucket") -{ - BucketName = uploadBucketName.ValueAsString -}; ----- -==== - -[#parameters-deploy] -== Deploy CDK apps containing parameters - -When you deploy a generated {aws} CloudFormation template through the {aws} CloudFormation console, you will be prompted to provide the values for each parameter. - -You can also provide parameter values using the CDK CLI `cdk deploy` command, or by specifying parameter values in your CDK project's stack file. - -[#parameters-deploy-cli] -=== Provide parameter values with [.noloc]``cdk deploy`` - -When you deploy using the CDK CLI `cdk deploy` command, you can provide parameter values at deployment with the `--parameters` option. - -The following is an example of the `cdk deploy` command structure: - -[source,none,subs="verbatim,attributes"] ----- -$ cdk deploy <stack-logical-id> --parameters <stack-name>:<parameter-name>=<parameter-value> ----- - -If your CDK app contains a single stack, you don't have to provide the stack logical ID argument or the `stack-name` value in the `--parameters` option. The CDK CLI will automatically find and provide these values. The following is an example that specifies an `uploadbucket` value for the `uploadBucketName` parameter of the single stack in our CDK app: - -[source,none,subs="verbatim,attributes"] ----- -$ cdk deploy --parameters <uploadBucketName>=<uploadbucket> ----- - -[#parameters-deploy-cli-multi-stack] -=== Provide parameter values with cdk deploy for multi-stack applications - -The following is an example CDK application in TypeScript that contains two CDK stacks. Each stack contains an Amazon S3 bucket instance and a parameter to set the Amazon S3 bucket name: - -[source,javascript,subs="verbatim,attributes"] ----- -import * as cdk from 'aws-cdk-lib'; -import { Construct } from 'constructs'; -import * as s3 from 'aws-cdk-lib/aws-s3'; - -// Define the CDK app -const app = new cdk.App(); - -// First stack -export class MyFirstStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - // Set a default parameter name - const bucketNameParam = new cdk.CfnParameter(this, 'bucketNameParam', { - type: 'String', - default: 'myfirststackdefaultbucketname' - }); - - // Define an S3 bucket - new s3.Bucket(this, 'MyFirstBucket', { - bucketName: bucketNameParam.valueAsString - }); - } -} - -// Second stack -export class MySecondStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - // Set a default parameter name - const bucketNameParam = new cdk.CfnParameter(this, 'bucketNameParam', { - type: 'String', - default: 'mysecondstackdefaultbucketname' - }); - - // Define an S3 bucket - new s3.Bucket(this, 'MySecondBucket', { - bucketName: bucketNameParam.valueAsString - }); - } -} - -// Instantiate the stacks -new MyFirstStack(app, 'MyFirstStack', { - stackName: 'MyFirstDeployedStack', -}); - -new MySecondStack(app, 'MySecondStack', { - stackName: 'MySecondDeployedStack', -}); ----- - -For CDK apps that contain multiple stacks, you can do the following: - -* *Deploy one stack with parameters* – To deploy a single stack from a multi-stack application, provide the stack logical ID as an argument. -+ -The following is an example that deploys `MySecondStack` with `mynewbucketname` as the parameter value for `bucketNameParam`: -+ -[source,none,subs="verbatim,attributes"] ----- -$ cdk deploy <MySecondStack> --parameters <bucketNameParam>='<mynewbucketname>' ----- -* *Deploy all stacks and specify parameter values for each stack* – Provide the `'*'` wildcard or the `--all` option to deploy all stacks. Provide the `--parameters` option multiple times in a single command to specify parameter values for each stack. The following is an example: -+ -[source,none,subs="verbatim,attributes"] ----- -$ cdk deploy <'*'> --parameters <MyFirstDeployedStack>:<bucketNameParam>='<mynewfirststackbucketname>' --parameters <MySecondDeployedStack>:<bucketNameParam>='<mynewsecondstackbucketname>' ----- -* *Deploy all stacks and specify parameter values for a single stack* – Provide the `'*'` wildcard or the `--all` option to deploy all stacks. Then, specify the stack to define the parameter for in the `--parameters` option. The following are examples that deploys all stacks in a CDK app and specifies a parameter value for the `MySecondDeployedStack` {aws} CloudFormation stack. All other stacks will deploy and use the default parameter value: -+ -[source,none,subs="verbatim,attributes"] ----- -$ cdk deploy <'*'> --parameters <MySecondDeployedStack>:<bucketNameParam>='<mynewbucketname>' -$ cdk deploy <--all> --parameters <MySecondDeployedStack>:<bucketNameParam>='<mynewbucketname>' ----- - -[#parameters-deploy-cli-nested-stack] -=== Provide parameter values with `cdk deploy` for applications with nested stacks - -The CDK CLI behavior when working with applications containing nested stacks is similar to multi-stack applications. The main difference is, if you want to deploy all nested stacks, use the `'\\**'` wildcard. The `'*'` wildcard deploys all stacks but will not deploy nested stacks. The `'**'` wildcard deploys all stacks, including nested stacks. - -The following is an example that deploys nested stacks while specifying the parameter value for one nested stack: - -[source,none,subs="verbatim,attributes"] ----- -$ cdk deploy '**' --parameters <MultiStackCdkApp/SecondStack>:<bucketNameParam>='<mysecondstackbucketname>' ----- - -For more information on `cdk deploy` command options, see xref:ref-cli-cmd-deploy[cdk deploy]. \ No newline at end of file diff --git a/v2/guide/develop/get-context-var.adoc b/v2/guide/develop/get-context-var.adoc deleted file mode 100644 index 33581e8d..00000000 --- a/v2/guide/develop/get-context-var.adoc +++ /dev/null @@ -1,129 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[[get-context-var,get-context-var.title]] -= Save and retrieve context variable values -:info_titleabbrev: Get context value - -// Content start - -You can specify context variables with the {aws} Cloud Development Kit ({aws} CDK) CLI or in the `cdk.json` file. Then, use the `TryGetContext` method to retrieve values. - -[#develop-context-specify] -== Specify context variables - -You can specify a context variable either as part of an {aws} CDK CLI command, or in `cdk.json`. - -To create a command line context variable, use the `--context` (`-c`) option, as shown in the following example. - -[source,none,subs="verbatim,attributes"] ----- -cdk synth -c bucket_name=mygroovybucket ----- - -To specify the same context variable and value in the `cdk.json` file, use the following code. - -[source,json,subs="verbatim,attributes"] ----- -{ - "context": { - "bucket_name": "myotherbucket" - } -} ----- - -If you specify a context variable using both the {aws} CDK CLI and `cdk.json` file, the {aws} CDK CLI value takes precedence. - -[#develop-context-retrieve] -== Retrieve context variable values - -To get the value of a context variable in your app, use the `TryGetContext` method in the context of a construct. (That is, when `this`, or `self` in Python, is an instance of some construct.) - -In this example, we retrieve the value of the `bucket_name` context variable. If the requested value is not defined, `TryGetContext` returns `undefined` (`None` in Python; `null` in Java and C#; `nil` in Go) rather than raising an exception. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const bucket_name = this.node.tryGetContext('bucket_name'); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const bucket_name = this.node.tryGetContext('bucket_name'); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -bucket_name = self.node.try_get_context("bucket_name") ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -String bucketName = (String)this.getNode().tryGetContext("bucket_name"); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -var bucketName = this.Node.TryGetContext("bucket_name"); ----- -==== - -Outside the context of a construct, you can access the context variable from the app object, like this. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const app = new cdk.App(); -const bucket_name = app.node.tryGetContext('bucket_name') ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const app = new cdk.App(); -const bucket_name = app.node.tryGetContext('bucket_name'); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -app = cdk.App() -bucket_name = app.node.try_get_context("bucket_name") ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -App app = App(); -String bucketName = (String)app.getNode().tryGetContext("bucket_name"); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -app = App(); -var bucketName = app.Node.TryGetContext("bucket_name"); ----- -==== - -For more details on working with context variables, see xref:context[Context values and the {aws} CDK]. \ No newline at end of file diff --git a/v2/guide/develop/get-env-var.adoc b/v2/guide/develop/get-env-var.adoc deleted file mode 100644 index dec890e5..00000000 --- a/v2/guide/develop/get-env-var.adoc +++ /dev/null @@ -1,79 +0,0 @@ -include::../attributes.txt[] - -// Attributes -[.topic] -[#get-env-var] -= Get a value from an environment variable -:info_titleabbrev: Get environment value - -// Content start - -To get the value of an environment variable, use code like the following. This code gets the value of the environment variable `amzn-s3-demo-bucket`. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- - -// Sets bucket_name to undefined if environment variable not set -var bucket_name = process.env.amzn-s3-demo-bucket; - -// Sets bucket_name to a default if env var doesn't exist -var bucket_name = process.env.amzn-s3-demo-bucket || "DefaultName"; ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- - -// Sets bucket_name to undefined if environment variable not set -var bucket_name = process.env.amzn-s3-demo-bucket; - -// Sets bucket_name to a default if env var doesn't exist -var bucket_name = process.env.amzn-s3-demo-bucket || "DefaultName"; ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -import os - -# Raises KeyError if environment variable doesn't exist -bucket_name = os.environ["amzn-s3-demo-bucket"] - -# Sets bucket_name to None if environment variable doesn't exist -bucket_name = os.getenv("amzn-s3-demo-bucket") - -# Sets bucket_name to a default if env var doesn't exist -bucket_name = os.getenv("amzn-s3-demo-bucket", "DefaultName") ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -// Sets bucketName to null if environment variable doesn't exist -String bucketName = System.getenv("amzn-s3-demo-bucket"); - -// Sets bucketName to a default if env var doesn't exist -String bucketName = System.getenv("amzn-s3-demo-bucket"); -if (bucketName == null) bucketName = "DefaultName"; ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -using System; - -// Sets bucket name to null if environment variable doesn't exist -string bucketName = Environment.GetEnvironmentVariable("amzn-s3-demo-bucket"); - -// Sets bucket_name to a default if env var doesn't exist -string bucketName = Environment.GetEnvironmentVariable("amzn-s3-demo-bucket") ?? "DefaultName"; ----- -==== \ No newline at end of file diff --git a/v2/guide/develop/get-ssm-val.adoc b/v2/guide/develop/get-ssm-val.adoc deleted file mode 100644 index cab7cc4d..00000000 --- a/v2/guide/develop/get-ssm-val.adoc +++ /dev/null @@ -1,201 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[[get-ssm-value,get-ssm-value.title]] -= Get a value from the Systems Manager Parameter Store -:info_titleabbrev: Get SSM value - -// Content start - -The {aws} Cloud Development Kit ({aws} CDK) can retrieve the value of {aws} Systems Manager Parameter Store attributes. During synthesis, the {aws} CDK produces a xref:tokens[token] that is resolved by {aws} CloudFormation during deployment. - -The {aws} CDK supports retrieving both plain and secure values. You may request a specific version of either kind of value. For plain values, you may omit the version from your request to retrieve the latest version. For secure values, you must specify the version when requesting the value of the secure attribute. - -[NOTE] -==== - -This topic shows how to read attributes from the {aws} Systems Manager Parameter Store. You can also read secrets from the {aws} Secrets Manager (see xref:get-secrets-manager-value[Get a value from {aws} Secrets Manager]). - -==== - -[#ssm-read-at-deploy] -== Read Systems Manager values at deployment time - -To read values from the Systems Manager Parameter Store, use the link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ssm.StringParameter.html#static-valuewbrforwbrstringwbrparameterscope-parametername-version[`valueForStringParameter`] and link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ssm.StringParameter.html#static-valuewbrforwbrsecurewbrstringwbrparameterscope-parametername-version[`valueForSecureStringParameter`] methods. Choose a method based on whether the attribute you want is a plain string or a secure string value. These methods return xref:tokens[tokens], not the actual value. The value is resolved by {aws} CloudFormation during deployment. The following is an example: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -import * as ssm from 'aws-cdk-lib/aws-ssm'; - -// Get latest version or specified version of plain string attribute -const latestStringToken = ssm.StringParameter.valueForStringParameter( - this, 'my-plain-parameter-name'); // latest version -const versionOfStringToken = ssm.StringParameter.valueForStringParameter( - this, 'my-plain-parameter-name', 1); // version 1 - -// Get specified version of secure string attribute -const secureStringToken = ssm.StringParameter.valueForSecureStringParameter( - this, 'my-secure-parameter-name', 1); // must specify version ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const ssm = require('aws-cdk-lib/aws-ssm'); - -// Get latest version or specified version of plain string attribute -const latestStringToken = ssm.StringParameter.valueForStringParameter( - this, 'my-plain-parameter-name'); // latest version -const versionOfStringToken = ssm.StringParameter.valueForStringParameter( - this, 'my-plain-parameter-name', 1); // version 1 - -// Get specified version of secure string attribute -const secureStringToken = ssm.StringParameter.valueForSecureStringParameter( - this, 'my-secure-parameter-name', 1); // must specify version ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -import aws_cdk.aws_ssm as ssm - -# Get latest version or specified version of plain string attribute -latest_string_token = ssm.StringParameter.value_for_string_parameter( - self, "my-plain-parameter-name") -latest_string_token = ssm.StringParameter.value_for_string_parameter( - self, "my-plain-parameter-name", 1) - -# Get specified version of secure string attribute -secure_string_token = ssm.StringParameter.value_for_secure_string_parameter( - self, "my-secure-parameter-name", 1) # must specify version ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -import software.amazon.awscdk.services.ssm.StringParameter; - -//Get latest version or specified version of plain string attribute -String latestStringToken = StringParameter.valueForStringParameter( - this, "my-plain-parameter-name"); // latest version -String versionOfStringToken = StringParameter.valueForStringParameter( - this, "my-plain-parameter-name", 1); // version 1 - -//Get specified version of secure string attribute -String secureStringToken = StringParameter.valueForSecureStringParameter( - this, "my-secure-parameter-name", 1); // must specify version ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -using Amazon.CDK.{aws}.SSM; - -// Get latest version or specified version of plain string attribute -var latestStringToken = StringParameter.ValueForStringParameter( - this, "my-plain-parameter-name"); // latest version -var versionOfStringToken = StringParameter.ValueForStringParameter( - this, "my-plain-parameter-name", 1); // version 1 - -// Get specified version of secure string attribute -var secureStringToken = StringParameter.ValueForSecureStringParameter( - this, "my-secure-parameter-name", 1); // must specify version ----- -==== - -A link:https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/dynamic-references.html#template-parameters-dynamic-patterns-resources[limited number of {aws} services] currently support this feature. - -[#ssm-read-at-synth] -== Read Systems Manager values at synthesis time - -At times, it's useful to provide a parameter at synthesis time. By doing this, the {aws} CloudFormation template will always use the same value instead of resolving the value during deployment. - -To read a value from the Systems Manager Parameter Store at synthesis time, use the link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ssm.StringParameter.html#static-valuewbrfromwbrlookupscope-parametername[`valueFromLookup`] method (Python: `value_from_lookup`). This method returns the actual value of the parameter as a xref:context[Context values and the {aws} CDK] value. If the value is not already cached in `cdk.json` or passed on the command line, it is retrieved from the current {aws} account. For this reason, the stack _must_ be synthesized with explicit {aws} environment information. - -The following is an example: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -import * as ssm from 'aws-cdk-lib/aws-ssm'; - -const stringValue = ssm.StringParameter.valueFromLookup(this, 'my-plain-parameter-name'); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const ssm = require('aws-cdk-lib/aws-ssm'); - -const stringValue = ssm.StringParameter.valueFromLookup(this, 'my-plain-parameter-name'); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -import aws_cdk.aws_ssm as ssm - -string_value = ssm.StringParameter.value_from_lookup(self, "my-plain-parameter-name") ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -import software.amazon.awscdk.services.ssm.StringParameter; - -String stringValue = StringParameter.valueFromLookup(this, "my-plain-parameter-name"); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -using Amazon.CDK.{aws}.SSM; - -var stringValue = StringParameter.ValueFromLookup(this, "my-plain-parameter-name"); ----- -==== - -Only plain Systems Manager strings may be retrieved. Secure strings cannot be retrieved. The latest version will always be returned. Specific versions cannot be requested. - -[IMPORTANT] -==== - -The retrieved value will end up in your synthesized {aws} CloudFormation template. This might be a security risk, depending on who has access to your {aws} CloudFormation templates and what kind of value it is. Generally, don't use this feature for passwords, keys, or other values you want to keep private. - -==== - -[#ssm-write] -== Write values to Systems Manager - -You can use the {aws} CLI, the {aws} Management Console, or an {aws} SDK to set Systems Manager parameter values. The following examples use the link:https://docs.aws.amazon.com/cli/latest/reference/ssm/put-parameter.html[`ssm put-parameter`] CLI command. - -[source,none,subs="verbatim,attributes"] ----- -aws ssm put-parameter --name "parameter-name" --type "String" --value "parameter-value" -aws ssm put-parameter --name "secure-parameter-name" --type "SecureString" --value "secure-parameter-value" ----- - -When updating an SSM value that already exists, also include the `--overwrite` option. - -[source,none,subs="verbatim,attributes"] ----- -aws ssm put-parameter --overwrite --name "parameter-name" --type "String" --value "parameter-value" -aws ssm put-parameter --overwrite --name "secure-parameter-name" --type "SecureString" --value "secure-parameter-value" ----- \ No newline at end of file diff --git a/v2/guide/develop/images/activate-cfn-extension.png b/v2/guide/develop/images/activate-cfn-extension.png deleted file mode 100644 index 04d01e4a..00000000 Binary files a/v2/guide/develop/images/activate-cfn-extension.png and /dev/null differ diff --git a/v2/guide/develop/set-cw-alarm.adoc b/v2/guide/develop/set-cw-alarm.adoc deleted file mode 100644 index 63f0398e..00000000 --- a/v2/guide/develop/set-cw-alarm.adoc +++ /dev/null @@ -1,254 +0,0 @@ -include::../attributes.txt[] - -// Attributes -[.topic] -[#how-to-set-cw-alarm] -= Set a CloudWatch alarm -:info_titleabbrev: Set CloudWatch alarm - -// Content start - -Use the link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_cloudwatch-readme.html[`aws-cloudwatch`] package to set up Amazon CloudWatch alarms on CloudWatch metrics. You can use predefined metrics or create your own. - -[#how-to-set-cw-alarm-use-metric] -== Use an existing metric - -Many {aws} Construct Library modules let you set an alarm on an existing metric by passing the metric's name to a convenience method on an instance of an object that has metrics. For example, given an Amazon SQS queue, you can get the metric *ApproximateNumberOfMessagesVisible* from the queue's link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_sqs.Queue.html#metricmetricname-props[`metric()`] method: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const metric = queue.metric("ApproximateNumberOfMessagesVisible"); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const metric = queue.metric("ApproximateNumberOfMessagesVisible"); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -metric = queue.metric("ApproximateNumberOfMessagesVisible") ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -Metric metric = queue.metric("ApproximateNumberOfMessagesVisible"); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -var metric = queue.Metric("ApproximateNumberOfMessagesVisible"); ----- -==== - -[#how-to-set-cw-alarm-new-metric] -== Create your own metric - -Create your own link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_cloudwatch.Metric.html[metric] as follows, where the _namespace_ value should be something like *{aws}/SQS* for an Amazon SQS queue. You also need to specify your metric's name and dimension: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const metric = new cloudwatch.Metric({ - namespace: 'MyNamespace', - metricName: 'MyMetric', - dimensionsMap: { MyDimension: 'MyDimensionValue' } -}); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const metric = new cloudwatch.Metric({ - namespace: 'MyNamespace', - metricName: 'MyMetric', - dimensionsMap: { MyDimension: 'MyDimensionValue' } -}); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -metric = cloudwatch.Metric( - namespace="MyNamespace", - metric_name="MyMetric", - dimensionsMap=dict(MyDimension="MyDimensionValue") -) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -Metric metric = Metric.Builder.create() - .namespace("MyNamespace") - .metricName("MyMetric") - .dimensionsMap(java.util.Map.of( // Java 9 or later - "MyDimension", "MyDimensionValue")) - .build(); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -var metric = new Metric(this, "Metric", new MetricProps -{ - Namespace = "MyNamespace", - MetricName = "MyMetric", - Dimensions = new Dictionary<string, object> - { - { "MyDimension", "MyDimensionValue" } - } -}); ----- -==== - -[#how-to-set-cw-alarm-create] -== Create the alarm - -Once you have a metric, either an existing one or one you defined, you can create an alarm. In this example, the alarm is raised when there are more than 100 of your metric in two of the last three evaluation periods. You can use comparisons such as less-than in your alarms via the `comparisonOperator` property. Greater-than-or-equal-to is the {aws} CDK default, so we don't need to specify it. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const alarm = new cloudwatch.Alarm(this, 'Alarm', { - metric: metric, - threshold: 100, - evaluationPeriods: 3, - datapointsToAlarm: 2, -}); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const alarm = new cloudwatch.Alarm(this, 'Alarm', { - metric: metric, - threshold: 100, - evaluationPeriods: 3, - datapointsToAlarm: 2 -}); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -alarm = cloudwatch.Alarm(self, "Alarm", - metric=metric, - threshold=100, - evaluation_periods=3, - datapoints_to_alarm=2 -) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -import software.amazon.awscdk.services.cloudwatch.Alarm; -import software.amazon.awscdk.services.cloudwatch.Metric; - -Alarm alarm = Alarm.Builder.create(this, "Alarm") - .metric(metric) - .threshold(100) - .evaluationPeriods(3) - .datapointsToAlarm(2).build(); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -var alarm = new Alarm(this, "Alarm", new AlarmProps -{ - Metric = metric, - Threshold = 100, - EvaluationPeriods = 3, - DatapointsToAlarm = 2 -}); ----- -==== - -An alternative way to create an alarm is using the metric's link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_cloudwatch.Metric.html#createwbralarmscope-id-props[`createAlarm()`] method, which takes essentially the same properties as the `Alarm` constructor. You don't need to pass in the metric, because it's already known. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -metric.createAlarm(this, 'Alarm', { - threshold: 100, - evaluationPeriods: 3, - datapointsToAlarm: 2, -}); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -metric.createAlarm(this, 'Alarm', { - threshold: 100, - evaluationPeriods: 3, - datapointsToAlarm: 2, -}); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -metric.create_alarm(self, "Alarm", - threshold=100, - evaluation_periods=3, - datapoints_to_alarm=2 -) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -metric.createAlarm(this, "Alarm", new CreateAlarmOptions.Builder() - .threshold(100) - .evaluationPeriods(3) - .datapointsToAlarm(2) - .build()); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -metric.CreateAlarm(this, "Alarm", new CreateAlarmOptions -{ - Threshold = 100, - EvaluationPeriods = 3, - DatapointsToAlarm = 2 -}); ----- -==== \ No newline at end of file diff --git a/v2/guide/develop/usage-data.adoc b/v2/guide/develop/usage-data.adoc deleted file mode 100644 index 09b1a8f5..00000000 --- a/v2/guide/develop/usage-data.adoc +++ /dev/null @@ -1,278 +0,0 @@ -include::../attributes.txt[] - -// Attributes -[.topic] -[[usage-data,usage-data.title]] -= Configure {aws} CDK usage data reporting -:info_titleabbrev: Configure usage data reporting -:keywords: {aws} CDK, Reporting, Usage data, Version reporting - -[abstract] --- -The {aws} Cloud Development Kit ({aws} CDK) collects usage data from your CDK applications to gain insight into how the {aws} CDK is being used. The CDK team uses this data to do the following: --- - -// Content start - -[#usage-data-intro] -== What is CDK usage data reporting? - -{aws} Cloud Development Kit ({aws} CDK) applications are configured to collect and report on usage data to gain insight into how the {aws} CDK is being used. The CDK team uses this data to do the following: - -* *Communicate with customers* – Identify stacks using a construct with known security or reliability issues and send out communication on customer-impacting topics. -* *Inform CDK development* – Gain insight on CDK usage to better inform CDK development. -* *Investigate CDK issues* – When bugs are reported, usage data provides valuable insight to the CDK team when troubleshooting. - -[#usage-data-categories] -== What usage data is collected? - -There are two categories of usage data collected by the CDK: - -* General usage data -* Additional usage data - -[#usage-data-categories-general] -=== General usage data collection - -The CDK collects the following types of general usage data from your CDK applications: - -* Versions of CDK libraries used. -* Names of constructs used from the following `NPM` modules: -+ --- -** {aws} CDK core modules -** {aws} Construct Library modules -** {aws} Solutions Constructs module -** {aws} Render Farm Deployment Kit module --- - -[NOTE] -==== - -Before version 1.93.0, the {aws} CDK reported the names and versions of the modules loaded during synthesis, instead of the constructs used in the stack. - -==== - -[#usage-data-categories-additional] -=== Additional usage data collection - -Starting with CDK version 2.178.0, usage data collection expanded to include the following additional usage data: - -* *CDK–defined property keys* – When you use a built-in property of an L2 construct, the property key will be collected. This includes built-in property keys nested in dictionary objects. -* *Boolean and enum property values from CDK–defined property keys* – For CDK–defined property keys, property values of only Boolean and enum types will be collected. All other types, such as string values or construct references will be redacted. -* *Method name, keys, and property values of Boolean and enum types* – When you use an L2 construct method, we will collect the method name, property keys, and property values of Boolean and enum types. - -For property keys and values that you uniquely create, the entire object will be redacted. For example, if you use `link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_apigateway.InlineApiDefinition.html[InlineApiDefinition]` to define an [.noloc]`OpenAPI` specification and pass it into a `link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_apigateway.RestApi.html[RestApi]` construct, the entire `InlineApiDefinition` object will be redacted. - -For more information on additional usage data collection, including its benefits and potential concerns, see the https://github.com/aws/aws-cdk/discussions/33198[CDK Collecting Additional Metadata (under feature flag) #33198] discussion in the _aws-cdk repository_. - -[#usage-data-how] -== How the CDK collects usage data - -At synthesis, the CDK collects usage data from your application and stores it within the `{aws}::CDK::Metadata` resource. The following is an example of this on a synthesized {aws} CloudFormation template: - -[source,yaml,subs="verbatim,attributes"] ----- -CDKMetadata: - Type: "{aws}::CDK::Metadata" - Properties: - Analytics: "v2:deflate64:H4sIAND9SGAAAzXKSw5AMBAA0L1b2PdzBYnEAdio3RglglY60zQi7u6TWL/XKmNUlxeQSOKwaPTBqrNhwEWU3hGHiCzK0dWWfAxoL/Fd8mvk+QkS/0X6BdjnCdgmOOQKWz+AqqLDt2Y3YMnLYWwAAAA=" ----- - -The `Analytics` property is a gzipped, base64-encoded, prefix-encoded list of the constructs in the stack. - -[#usage-data-configure] -== How to opt out or opt in to usage data reporting - -Your options to opt out or opt in to general usage data reporting and additional usage data reporting depends on the CDK version you used to originally create your app. - -By default, CDK applications are configured to automatically opt in to usage data reporting as follows: - -* *All CDK apps* – Opted in to general usage data reporting. -* *CDK apps created with a version older than v2.178.0* – Not automatically opted in to additional usage data reporting. -* *CDK apps created with v2.178.0 or newer* – Opted in to additional usage data reporting. - -[WARNING] -==== - -If you choose to opt out, the CDK will not be able to identify if you`'ve been impacted by security issues and will not send you notifications for them. - -==== - -[#usage-data-configure-optout-all] -=== Opt out of all usage data reporting - -To opt out of all usage data reporting, you can use the {aws} Cloud Development Kit ({aws} CDK) Command Line Interface (CLI) or configure your project's `cdk.json` file. - -*To opt out of all usage data reporting using the CDK CLI*:: -+ -* Use the `--no-version-reporting` option with any CDK CLI command to opt out for a single command. The following is an example of opting out during template synthesis: -+ -[source,none,subs="verbatim,attributes"] ----- -$ cdk synth --no-version-reporting ----- -+ -Since the CDK synthesizes templates automatically when you run `cdk deploy`, you should also use `--no-version-reporting` with the `cdk deploy` command. - -*To opt out of all usage data reporting by configuring the cdk.json file*:: -+ -. Set `versionReporting` to `false` in `./cdk.json` or `~/.cdk.json`. This opts you out by default. The following is an example: -+ -[source,json,subs="verbatim,attributes"] ----- -{ - "app": "...", - "versionReporting": false -} ----- -+ -. After configuring, you can override this behavior and opt in by specifying `--version-reporting` on an individual command. - -[#usage-data-configure-optout-additiona] -=== Opt out of only the additional usage data reporting - -If your CDK app was created with a CDK version older than 2.178.0, you are automatically opted out of additional usage data reporting, even if you are opted in to general usage data reporting. You don`'t have to do anything to opt out of additional usage data reporting. - -If your CDK app was created with CDK version 2.178.0 or newer, you must opt out of all usage data reporting. You can`'t opt out of only the additional usage data reporting. - -[#usage-data-configure-optin] -=== Opt in to usage data reporting - -If your CDK app was created with CDK version 2.178.0 or newer, you can opt in to all usage data reporting by setting `versionReporting` to `true`. This is the default behavior of CDK apps. - -If your CDK app was created with a CDK version older than 2.178.0, you can opt in to general usage data reporting by setting `versionReporting` to `true`. To opt in to additional usage data reporting, you must enable a feature flag. - -NOTE: These steps are for CDK apps originally created with a version older than 2.178.0 - -. Verify that you are now using CDK version 2.178.0 or newer. -. In your CDK configuration file, specify `@aws-cdk/core:enableAdditionalMetadataCollection` as `true`. The following is an example: -+ -[source,json,subs="verbatim,attributes"] ----- -{ - "context": { - "@aws-cdk/core:enableAdditionalMetadataCollection": "true" - } -} ----- -+ -. You can also use the `ENABLE_ADDITIONAL_METADATA_COLLECTION` value with the `https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.FeatureFlags.html[FeatureFlags]` class. The following is an example: -+ -[source,javascript,subs="verbatim,attributes"] ----- -import * as cdk from 'aws-cdk-lib'; -import { FeatureFlags } from 'aws-cdk-lib'; -import * as cx_api from 'aws-cdk-lib/cx-api'; -import { Construct } from 'constructs'; - -export class MyStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - // Set the feature flag ENABLE_ADDITIONAL_METADATA_COLLECTION to true - FeatureFlags.of(this).add(cx_api.ENABLE_ADDITIONAL_METADATA_COLLECTION, true); - - // Your stack resources go here - new cdk.aws_s3.Bucket(this, 'MyBucket'); - } -} - -const app = new cdk.App(); -new MyStack(app, 'MyStack'); ----- - -[#usage-data-examples] -== Examples - -[#usage-data-examples-example1] -=== General and additional usage data collected from a CDK application - -The following is an example of a CDK app: - -[source,javascript,subs="verbatim,attributes"] ----- -import * as cdk from 'aws-cdk-lib'; -import { Construct } from 'constructs'; -import * as s3 from 'aws-cdk-lib/aws-s3'; - -class MyStack extends cdk.Stack { - constructor(scope, id, props) { - super(scope, id, props); - - // Create an S3 bucket (L2 construct) - const myBucket = new s3.Bucket(this, 'MyBucket', { - bucketName: 'my-cdk-example-bucket', // String type - versioned: true, // Boolean type - removalPolicy: cdk.RemovalPolicy.DESTROY, // ENUM type - lifecycleRules: [{ // Array of object type - expirationDate: new Date('2019-10-01'), - objectSizeLessThan: 600, - objectSizeGreaterThan: 500, - }], - }); - - // Use a method of the L2 construct to define additional properties - myBucket.addLifecycleRule({ - id: 'ExpireOldObjects', - enabled: true, // Boolean - expiration: cdk.Duration.days(90), // Expire objects after 90 days - }); - } -} - -// Define the CDK app and stack -const app = new cdk.App(); -new MyStack(app, 'MyStack'); -app.synth(); ----- - -At synthesis, usage data is collected, compressed, and stored in the `{aws}::CDK::Metadata` resource. - -The following is an example of general usage data collected with a CDK version older than 2.178.0: - -[source,json,subs="verbatim,attributes"] ----- -{ - "fqn": "aws-cdk-lib.aws-s3.Bucket", - "version": "v2.170.0" -} ----- - -The following is an example of usage data collected, including the additional usage data introduced in CDK version 2.178.0: - -[source,json,subs="verbatim,attributes"] ----- -{ - "fqn": "aws-cdk-lib.aws_s3.Bucket", - "version": "2.170.0", - "metadata": [ - { - "type": "aws:cdk:analytics:construct", - "data": { - "bucketName": "*", - "versioned": true, - "removalPolicy": "cdk.RemovalPolicy.DESTROY", - "lifecycleRules": [ - { - "expirationDate": "*", - "objectSizeLessThan": "*", - "objectSizeGreaterThan": "*" - } - ] - } - }, - { - "type": "aws:cdk:analytics:method", - "data": { - "name": "addLifecycleRule", - "prop": { - "id": "*", - "enabled": true, - "expiration": "*", - } - } - } - ] -} ----- \ No newline at end of file diff --git a/v2/guide/develop/use-cfn-public-registry.adoc b/v2/guide/develop/use-cfn-public-registry.adoc deleted file mode 100644 index 889984d1..00000000 --- a/v2/guide/develop/use-cfn-public-registry.adoc +++ /dev/null @@ -1,135 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[#use-cfn-public-registry] -= Use resources from the {aws} CloudFormation Public Registry -:info_titleabbrev: Use resources from the CloudFormation Public Registry - -// Content start - -The {aws} CloudFormation Public Registry lets you manage extensions, both public and private, such as resources, modules, and hooks that are available for use in your {aws} account. You can use public resource extensions in your {aws} Cloud Development Kit ({aws} CDK) applications with the link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.CfnResource.html[`CfnResource`] construct. - -To learn more about the {aws} CloudFormation Public Registry, see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/registry.html[Using the {aws} CloudFormation registry] in the _{aws} CloudFormation User Guide_. - -All public extensions published by {aws} are available to all accounts in all Regions without any action on your part. However, you must activate each third-party extension you want to use, in each account and Region where you want to use it. - -[NOTE] -==== - -When you use {aws} CloudFormation with third-party resource types, you will incur charges. Charges are based on the number of handler operations you run per month and handler operation duration. See https://aws.amazon.com/cloudformation/pricing/[CloudFormation pricing] for complete details. - -==== - -To learn more about public extensions, see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/registry-public.html[Using public extensions in CloudFormation] in the _{aws} CloudFormation User Guide_ - -[#use-cfn-public-registry-activate] -== Activate a third-party resource in your account and Region - -Extensions published by {aws} do not require activation. They are always available in every account and Region. You can activate a third-party extension through the {aws} Management Console, via the {aws} Command Line Interface, or by deploying a special {aws} CloudFormation resource. - -*To activate a third-party extension through the {aws} Management Console or see what resources are available*:: -+ -image::images/activate-cfn-extension.png[scaledwidth=100%] -+ -. Sign in to the {aws} account in which you want to use the extension, then switch to the Region where you want to use it. -. Navigate to the CloudFormation console via the *Services* menu. -. Choose *Public extensions* on the navigation bar, then activate the *Third party* radio button under **Publisher**. A list of the available third-party public extensions appears. (You may also choose *{aws}* to see a list of the public extensions published by {aws}, though you don't need to activate them.) -. Browse the list and find the extension you want to activate. Alternatively, search for it, then activate the radio button in the upper right corner of the extension's card. -. Choose the *Activate* button at the top of the list to activate the selected extension. The extension's *Activate* page appears. -. In the *Activate* page, you can override the extension's default name and specify an execution role and logging configuration. You can also choose whether to automatically update the extension when a new version is released. When you have set these options as you like, choose *Activate extension* at the bottom of the page. - -*To activate a third-party extension using the {aws} CLI*:: -+ -* Use the `activate-type` command. Substitute the ARN of the custom type you want to use where indicated. -+ -The following is an example: -+ -[source,none,subs="verbatim,attributes"] ----- -aws cloudformation activate-type --public-type-arn <public_extension_ARN> --auto-update-activated ----- - -*To activate a third-party extension through CloudFormation or CDK*:: -+ -. Deploy a resource of type `{aws}::CloudFormation::TypeActivation` and specify the following properties: -+ --- -.. `TypeName` - The name of the type, such as ``AWSQS::EKS::Cluster``. -.. `MajorVersion` - The major version number of the extension that you want. Omit if you want the latest version. -.. `AutoUpdate` - Whether to automatically update this extension when a new minor version is released by the publisher. (Major version updates require explicitly changing the `MajorVersion` property.) -.. `ExecutionRoleArn` - The ARN of the IAM role under which this extension will run. -.. `LoggingConfig` - The logging configuration for the extension. --- -+ -The `TypeActivation` resource can be deployed by the CDK using the link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.CfnResource.html[`CfnResource`] construct. This is shown for the actual extensions in the following section. - -[#use-cfn-public-registry-add] -== Add a resource from the {aws} CloudFormation Public Registry to your CDK app - -Use the link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.CfnResource.html[`CfnResource`] construct to include a resource from the {aws} CloudFormation Public Registry in your application. This construct is in the CDK's `aws-cdk-lib` module. - -For example, suppose that there is a public resource named `MY::S5::UltimateBucket` that you want to use in your {aws} CDK application. This resource takes one property: the bucket name. The corresponding `CfnResource` instantiation looks like this. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const ubucket = new CfnResource(this, 'MyUltimateBucket', { - type: 'MY::S5::UltimateBucket::MODULE', - properties: { - BucketName: 'UltimateBucket' - } -}); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const ubucket = new CfnResource(this, 'MyUltimateBucket', { - type: 'MY::S5::UltimateBucket::MODULE', - properties: { - BucketName: 'UltimateBucket' - } -}); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -ubucket = CfnResource(self, "MyUltimateBucket", - type="MY::S5::UltimateBucket::MODULE", - properties=dict( - BucketName="UltimateBucket")) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -CfnResource.Builder.create(this, "MyUltimateBucket") - .type("MY::S5::UltimateBucket::MODULE") - .properties(java.util.Map.of( // Map.of requires Java 9+ - "BucketName", "UltimateBucket")) - .build(); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -new CfnResource(this, "MyUltimateBucket", new CfnResourceProps -{ - Type = "MY::S5::UltimateBucket::MODULE", - Properties = new Dictionary<string, object> - { - ["BucketName"] = "UltimateBucket" - } -}); ----- -==== \ No newline at end of file diff --git a/v2/guide/develop/use-cfn-template.adoc b/v2/guide/develop/use-cfn-template.adoc deleted file mode 100644 index 80156f9e..00000000 --- a/v2/guide/develop/use-cfn-template.adoc +++ /dev/null @@ -1,701 +0,0 @@ -include::../attributes.txt[] - -// Attributes -[.topic] -[#use-cfn-template] -= Import an existing {aws} CloudFormation template -:info_titleabbrev: Import an {aws} CloudFormation template - -// Content start - -Import resources from an {aws} CloudFormation template into your {aws} Cloud Development Kit ({aws} CDK) applications by using the link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.cloudformation_include-readme.html[`cloudformation-include.CfnInclude`] construct to convert resources to L1 constructs. - -After import, you can work with these resources in your app in the same way that you would if they were originally defined in {aws} CDK code. You can also use these L1 constructs within higher-level {aws} CDK constructs. For example, this can let you use the L2 permission grant methods with the resources they define. - -The `cloudformation-include.CfnInclude` construct essentially adds an {aws} CDK API wrapper to any resource in your {aws} CloudFormation template. Use this capability to import your existing {aws} CloudFormation templates to the {aws} CDK a piece at a time. By doing this, you can manage your existing resources using {aws} CDK constructs to utilize the benefits of higher-level abstractions. You can also use this feature to vend your {aws} CloudFormation templates to {aws} CDK developers by providing an {aws} CDK construct API. - -[NOTE] -==== - -{aws} CDK v1 also included link:https://docs.aws.amazon.com/cdk/api/latest/docs/aws-cdk-lib.CfnInclude.html[`aws-cdk-lib.CfnInclude`], which was previously used for the same general purpose. However, it lacks much of the functionality of `cloudformation-include.CfnInclude`. - -==== - - - -[#use-cfn-template-import]] -== Import an {aws} CloudFormation template - -The following is a sample {aws} CloudFormation template that we will use to provide examples in this topic. Copy and save the template as `my-template.json` to follow along. After working through these examples, you can explore further by using any of your existing deployed {aws} CloudFormation templates. You can obtain them from the {aws} CloudFormation console. - -[source,json,subs="verbatim,attributes"] ----- -{ - "Resources": { - "amzn-s3-demo-bucket": { - "Type": "{aws}::S3::Bucket", - "Properties": { - "BucketName": "amzn-s3-demo-bucket", - } - } - } -} ----- - -You can work with either JSON or YAML templates. We recommend JSON if available since YAML parsers can vary slightly in what they accept. - -The following is an example of how to import the sample template into your {aws} CDK app using `cloudformation-include`. Templates are imported within the context of an CDK stack. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -import * as cdk from 'aws-cdk-lib'; -import * as cfninc from 'aws-cdk-lib/cloudformation-include'; -import { Construct } from 'constructs'; - -export class MyStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - const template = new cfninc.CfnInclude(this, 'Template', { - templateFile: 'my-template.json', - }); - } -} ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const cdk = require('aws-cdk-lib'); -const cfninc = require('aws-cdk-lib/cloudformation-include'); - -class MyStack extends cdk.Stack { - constructor(scope, id, props) { - super(scope, id, props); - - const template = new cfninc.CfnInclude(this, 'Template', { - templateFile: 'my-template.json', - }); - } -} - -module.exports = { MyStack } ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -import aws_cdk as cdk -from aws_cdk import cloudformation_include as cfn_inc -from constructs import Construct - -class MyStack(cdk.Stack): - - def __init__(self, scope: Construct, id: str, **kwargs) -> None: - super().__init__(scope, id, **kwargs) - - template = cfn_inc.CfnInclude(self, "Template", - template_file="my-template.json") ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.StackProps; -import software.amazon.awscdk.cloudformation.include.CfnInclude; -import software.constructs.Construct; - -public class MyStack extends Stack { - public MyStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public MyStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - CfnInclude template = CfnInclude.Builder.create(this, "Template") - .templateFile("my-template.json") - .build(); - } -} ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -using Amazon.CDK; -using Constructs; -using cfnInc = Amazon.CDK.CloudFormation.Include; - -namespace MyApp -{ - public class MyStack : Stack - { - internal MyStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) - { - var template = new cfnInc.CfnInclude(this, "Template", new cfnInc.CfnIncludeProps - { - TemplateFile = "my-template.json" - }); - } - } -} ----- -==== - -By default, importing a resource preserves the resource's original logical ID from the template. This behavior is suitable for importing an {aws} CloudFormation template into the {aws} CDK, where logical IDs must be retained. {aws} CloudFormation needs this information to recognize these imported resources as the same resources from the {aws} CloudFormation template. - -If you are developing an {aws} CDK construct wrapper for the template so that it can be used by other {aws} CDK developers, have the {aws} CDK generate new resource IDs instead. By doing this, the construct can be used multiple times in a stack without name conflicts. To do this, set the `preserveLogicalIds` property to `false` when importing the template. The following is an example: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const template = new cfninc.CfnInclude(this, 'MyConstruct', { - templateFile: 'my-template.json', - preserveLogicalIds: false -}); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const template = new cfninc.CfnInclude(this, 'MyConstruct', { - templateFile: 'my-template.json', - preserveLogicalIds: false -}); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -template = cfn_inc.CfnInclude(self, "Template", - template_file="my-template.json", - preserve_logical_ids=False) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -CfnInclude template = CfnInclude.Builder.create(this, "Template") - .templateFile("my-template.json") - .preserveLogicalIds(false) - .build(); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -var template = new cfnInc.CfnInclude(this, "Template", new cfn_inc.CfnIncludeProps -{ - TemplateFile = "my-template.json", - PreserveLogicalIds = false -}); ----- -==== - -To put imported resources under the control of your {aws} CDK app, add the stack to the `App`: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -import * as cdk from 'aws-cdk-lib'; -import { MyStack } from '../lib/my-stack'; - -const app = new cdk.App(); -new MyStack(app, 'MyStack'); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const cdk = require('aws-cdk-lib'); -const { MyStack } = require('../lib/my-stack'); - -const app = new cdk.App(); -new MyStack(app, 'MyStack'); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -import aws_cdk as cdk -from mystack.my_stack import MyStack - -app = cdk.App() -MyStack(app, "MyStack") ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -import software.amazon.awscdk.App; - -public class MyApp { - public static void main(final String[] args) { - App app = new App(); - - new MyStack(app, "MyStack"); - } -} ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -using Amazon.CDK; - -namespace CdkApp -{ - sealed class Program - { - public static void Main(string[] args) - { - var app = new App(); - new MyStack(app, "MyStack"); - } - } -} ----- -==== - -To verify that there won't be any unintended changes to the {aws} resources in the stack, you can perform a diff. Use the {aws} CDK CLI `cdk diff` command and omit any {aws} CDK-specific metadata. The following is an example: - -[source,none,subs="verbatim,attributes"] ----- -cdk diff --no-version-reporting --no-path-metadata --no-asset-metadata ----- - -After you import an {aws} CloudFormation template, the {aws} CDK app should become the source of truth for your imported resources. To make changes to your resources, modify them in your {aws} CDK app and deploy with the {aws} CDK CLI `cdk deploy` command. - -[#use-cfn-template-cfninclude-access] -== Access imported resources - -The name `template` in the example code represents the imported {aws} CloudFormation template. To access a resource from it, use the object's link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.cloudformation_include.CfnInclude.html#getwbrresourcelogicalid[`getResource()`] method. To access the returned resource as a specific kind of resource, cast the result to the desired type. This isn't necessary in Python or JavaScript. The following is an example: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const cfnBucket = template.getResource('amzn-s3-demo-bucket') as s3.CfnBucket; ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const cfnBucket = template.getResource('amzn-s3-demo-bucket'); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -cfn_bucket = template.get_resource("amzn-s3-demo-bucket") ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -CfnBucket cfnBucket = (CfnBucket)template.getResource("amzn-s3-demo-bucket"); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -var cfnBucket = (CfnBucket)template.GetResource("amzn-s3-demo-bucket"); ----- -==== - -From this example, `cfnBucket` is now an instance of the link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html[`aws-s3.CfnBucket`] class. This is an L1 construct that represents the corresponding {aws} CloudFormation resource. You can treat it like any other resource of its type. For example, you can get its ARN value with the `bucket.attrArn` property. - -To wrap the L1 `CfnBucket` resource in an L2 link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html[`aws-s3.CfnBucket`] instance instead, use the static methods link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html#static-fromwbrbucketwbrarnscope-id-bucketarn[`fromBucketArn()`], link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html#static-fromwbrbucketwbrattributesscope-id-attrs[`fromBucketAttributes()`], or link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html#static-fromwbrbucketwbrnamescope-id-bucketname[`fromBucketName()`]. Usually, the `fromBucketName()` method is most convenient. The following is an example: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const bucket = s3.Bucket.fromBucketName(this, 'Bucket', cfnBucket.ref); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const bucket = s3.Bucket.fromBucketName(this, 'Bucket', cfnBucket.ref); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -bucket = s3.Bucket.from_bucket_name(self, "Bucket", cfn_bucket.ref) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -Bucket bucket = (Bucket)Bucket.fromBucketName(this, "Bucket", cfnBucket.getRef()); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -var bucket = (Bucket)Bucket.FromBucketName(this, "Bucket", cfnBucket.Ref); ----- -==== - -Other L2 constructs have similar methods for creating the construct from an existing resource. - -When you wrap an L1 construct in an L2 construct, it doesn't create a new resource. From our example, we are not creating a second S3; bucket. Instead, the new `Bucket` instance encapsulates the existing `CfnBucket`. - -From the example, the `bucket` is now an L2 `Bucket` construct that behaves like any other L2 construct. For example, you can grant an {aws} Lambda function write access to the bucket by using the bucket's convenient link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html#grantwbrwriteidentity-objectskeypattern[`grantWrite()`] method. You don't have to define the necessary {aws} Identity and Access Management (IAM) policy manually. The following is an example: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -bucket.grantWrite(lambdaFunc); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -bucket.grantWrite(lambdaFunc); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -bucket.grant_write(lambda_func) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -bucket.grantWrite(lambdaFunc); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -bucket.GrantWrite(lambdaFunc); ----- -==== - -[#use-cfn-template-cfninclude-params] -== Replace parameters - -If your {aws} CloudFormation template contains parameters, you can replace them with build time values at import by using the `parameters` property. In the following example, we replace the `UploadBucket` parameter with the ARN of a bucket defined elsewhere in our {aws} CDK code. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const template = new cfninc.CfnInclude(this, 'Template', { - templateFile: 'my-template.json', - parameters: { - 'UploadBucket': bucket.bucketArn, - }, -}); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const template = new cfninc.CfnInclude(this, 'Template', { - templateFile: 'my-template.json', - parameters: { - 'UploadBucket': bucket.bucketArn, - }, -}); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -template = cfn_inc.CfnInclude(self, "Template", - template_file="my-template.json", - parameters=dict(UploadBucket=bucket.bucket_arn) -) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -CfnInclude template = CfnInclude.Builder.create(this, "Template") - .templateFile("my-template.json") - .parameters(java.util.Map.of( // Map.of requires Java 9+ - "UploadBucket", bucket.getBucketArn())) - .build(); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -var template = new cfnInc.CfnInclude(this, "Template", new cfnInc.CfnIncludeProps -{ - TemplateFile = "my-template.json", - Parameters = new Dictionary<string, string> - { - { "UploadBucket", bucket.BucketArn } - } -}); ----- -==== - -[#use-cfn-template-cfninclude-other] -== Import other template elements - -You can import any {aws} CloudFormation template element, not just resources. The imported elements become a part of the {aws} CDK stack. To import these elements, use the following methods of the `CfnInclude` object: - -* link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.cloudformation_include.CfnInclude.html#getwbrconditionconditionname[`getCondition()`] – {aws} CloudFormation https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/conditions-section-structure.html[conditions]. -* link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.cloudformation_include.CfnInclude.html#getwbrhookhooklogicalid[`getHook()`] – {aws} CloudFormation https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/blue-green.html[hooks] for blue/green deployments. -* link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.cloudformation_include.CfnInclude.html#getwbrmappingmappingname[`getMapping()`] – {aws} CloudFormation https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/mappings-section-structure.html[mappings]. -* link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.cloudformation_include.CfnInclude.html#getwbroutputlogicalid[`getOutput()`] – {aws} CloudFormation https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html[outputs]. -* link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.cloudformation_include.CfnInclude.html#getwbrparameterparametername[`getParameter()`] – {aws} CloudFormation https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html[parameters]. -* link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.cloudformation_include.CfnInclude.html#getwbrrulerulename[`getRule()`] – {aws} CloudFormation link:https://docs.aws.amazon.com/servicecatalog/latest/adminguide/reference-template_constraint_rules.html[rules] for {aws} Service Catalog templates. - -Each of these methods return an instance of a class that represents the specific type of {aws} CloudFormation element. These objects are mutable. Changes that you make to them will appear in the template that gets generated from the {aws} CDK stack. The following is an example that imports a parameter from the template and modifies its default value: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const param = template.getParameter('MyParameter'); -param.default = "{aws} CDK" ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const param = template.getParameter('MyParameter'); -param.default = "{aws} CDK" ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -param = template.get_parameter("MyParameter") -param.default = "{aws} CDK" ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -CfnParameter param = template.getParameter("MyParameter"); -param.setDefaultValue("{aws} CDK") ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -var cfnBucket = (CfnBucket)template.GetResource("amzn-s3-demo-bucket"); -var param = template.GetParameter("MyParameter"); -param.Default = "{aws} CDK"; ----- -==== - -[#use-cfn-template-cfninclude-nested] -== Import nested stacks - -You can import https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-nested-stacks.html[nested stacks] by specifying them either when you import their main template, or at some later point. The nested template must be stored in a local file, but referenced as a `NestedStack` resource in the main template. Also, the resource name used in the {aws} CDK code must match the name used for the nested stack in the main template. - -Given this resource definition in the main template, the following code shows how to import the referenced nested stack both ways. - -[source,json,subs="verbatim,attributes"] ----- -"NestedStack": { - "Type": "{aws}::CloudFormation::Stack", - "Properties": { - "TemplateURL": "https://my-s3-template-source.s3.amazonaws.com/nested-stack.json" - } -} ----- - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -// include nested stack when importing main stack -const mainTemplate = new cfninc.CfnInclude(this, 'MainStack', { - templateFile: 'main-template.json', - loadNestedStacks: { - 'NestedStack': { - templateFile: 'nested-template.json', - }, - }, -}); - -// or add it some time after importing the main stack -const nestedTemplate = mainTemplate.loadNestedStack('NestedTemplate', { - templateFile: 'nested-template.json', -}); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -// include nested stack when importing main stack -const mainTemplate = new cfninc.CfnInclude(this, 'MainStack', { - templateFile: 'main-template.json', - loadNestedStacks: { - 'NestedStack': { - templateFile: 'nested-template.json', - }, - }, -}); - -// or add it some time after importing the main stack -const nestedTemplate = mainTemplate.loadNestedStack('NestedStack', { - templateFile: 'my-nested-template.json', -}); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -# include nested stack when importing main stack -main_template = cfn_inc.CfnInclude(self, "MainStack", - template_file="main-template.json", - load_nested_stacks=dict(NestedStack= - cfn_inc.CfnIncludeProps(template_file="nested-template.json"))) - -# or add it some time after importing the main stack -nested_template = main_template.load_nested_stack("NestedStack", - template_file="nested-template.json") ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -CfnInclude mainTemplate = CfnInclude.Builder.create(this, "MainStack") - .templateFile("main-template.json") - .loadNestedStacks(java.util.Map.of( // Map.of requires Java 9+ - "NestedStack", CfnIncludeProps.builder() - .templateFile("nested-template.json").build())) - .build(); - -// or add it some time after importing the main stack -IncludedNestedStack nestedTemplate = mainTemplate.loadNestedStack("NestedTemplate", CfnIncludeProps.builder() - .templateFile("nested-template.json") - .build()); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -// include nested stack when importing main stack -var mainTemplate = new cfnInc.CfnInclude(this, "MainStack", new cfnInc.CfnIncludeProps -{ - TemplateFile = "main-template.json", - LoadNestedStacks = new Dictionary<string, cfnInc.ICfnIncludeProps> - { - { "NestedStack", new cfnInc.CfnIncludeProps { TemplateFile = "nested-template.json" } } - } -}); - -// or add it some time after importing the main stack -var nestedTemplate = mainTemplate.LoadNestedStack("NestedTemplate", new cfnInc.CfnIncludeProps { - TemplateFile = 'nested-template.json' -}); ----- -==== - -You can import multiple nested stacks with either methods. When importing the main template, you provide a mapping between the resource name of each nested stack and its template file. This mapping can contain any number of entries. To do it after the initial import, call `loadNestedStack()` once for each nested stack. - -After importing a nested stack, you can access it using the main template's link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.cloudformation_include.CfnInclude.html#getwbrnestedwbrstacklogicalid[`getNestedStack()`] method. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const nestedStack = mainTemplate.getNestedStack('NestedStack').stack; ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const nestedStack = mainTemplate.getNestedStack('NestedStack').stack; ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -nested_stack = main_template.get_nested_stack("NestedStack").stack ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -NestedStack nestedStack = mainTemplate.getNestedStack("NestedStack").getStack(); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -var nestedStack = mainTemplate.GetNestedStack("NestedStack").Stack; ----- -==== - -The `getNestedStack()` method returns an link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.cloudformation_include.CfnInclude.html#getwbrnestedwbrstacklogicalid[`IncludedNestedStack`] instance. From this instance, you can access the {aws} CDK https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.NestedStack.html[`NestedStack`] instance via the `stack` property, as shown in the example. You can also access the original {aws} CloudFormation template object via `includedTemplate`, from which you can load resources and other {aws} CloudFormation elements. \ No newline at end of file diff --git a/v2/guide/doc-history.adoc b/v2/guide/doc-history.adoc deleted file mode 100644 index 24203114..00000000 --- a/v2/guide/doc-history.adoc +++ /dev/null @@ -1,73 +0,0 @@ -include::attributes.txt[] - -[.topic] -[#doc-history] -= {aws} CDK Developer Guide history -:info_titleabbrev: Document history -:info_abstract: {aws} CDK Developer Guide history - -[abstract] --- -{aws} CDK Developer Guide history --- - -// Content start - -See link:https://github.com/awslabs/aws-cdk/releases[Releases] for information about {aws} CDK releases. The {aws} CDK is updated approximately once a week. Maintenance versions may be released between weekly releases to address critical issues. Each release includes a matched {aws} CDK Toolkit (CDK CLI), {aws} Construct Library, and API Reference. Updates to this Guide generally do not synchronize with {aws} CDK releases. - -[NOTE] -==== -The table below represents significant documentation milestones. We fix errors and improve content on an ongoing basis. -==== - -[.updates] -== Updates - -[.update,date="2025-03-27"] -=== Document bootstrap template versions v26 and v27 - -For more information, see link:https://docs.aws.amazon.com/cdk/v2/guide/bootstrapping-env.html#bootstrap-template-history[Bootstrap template version history]. - -[.update,date="2025-03-21"] -=== Add documentation for building and deploying container image assets - -When you build container image assets with the {aws} CDK, Docker is utilized by default to perform these actions. If you want to use a different container management tool, you can replace Docker. For more information, see https://docs.aws.amazon.com/cdk/v2/guide/build-containers.html[Build and deploy container image assets in CDK apps]. - -[.update,date="2024-02-02"] -=== Add documentation for CDK Migrate feature - -Use the {aws} CDK CLI `cdk migrate` command to migrate deployed {aws} resources, deployed {aws} CloudFormation stacks, and local {aws} CloudFormation templates to {aws} CDK. For more information, see https://docs.aws.amazon.com/cdk/v2/guide/migrate.html[Migrate to {aws} CDK]. - -[.update,date="2023-03-23"] -=== IAM best practices updates - -Updated guide to align with the IAM best practices. For more information, see https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html[Security best practices in IAM]. - -[.update,date="2022-04-20"] -=== Document `cdk.json` - -Add documentation of `cdk.json` configuration values. - -[.update,date="2022-04-07"] -=== Dependency management - -Add topic on managing dependencies with the {aws} CDK. - -[.update,date="2022-03-09"] -=== Remove double-braces from Java examples - -Replace this anti-pattern with Java 9 `Map.of` throughout. - -[.update,date="2021-12-04"] -=== {aws} CDK v2 release - -Version 2 of the {aws} CDK Developer Guide is released. - -See https://github.com/awslabs/aws-cdk/releases[Releases] for information about {aws} CDK releases. The {aws} CDK is updated approximately once a week. Maintenance versions may be released between weekly releases to address critical issues. Each release includes a matched {aws} CDK Toolkit (CDK CLI), {aws} Construct Library, and API Reference. Updates to this Guide generally do not synchronize with {aws} CDK releases. - -[.level] -== {blank} - -[.update-history] -|=== -|=== \ No newline at end of file diff --git a/v2/guide/getting-started/getting-started.adoc b/v2/guide/getting-started/getting-started.adoc deleted file mode 100644 index efb7b36e..00000000 --- a/v2/guide/getting-started/getting-started.adoc +++ /dev/null @@ -1,99 +0,0 @@ -include::../attributes.txt[] - -// Attributes -[.topic] -[#getting-started] -= Getting started with the {aws} CDK -:info_titleabbrev: Getting started -:info_abstract: Get started with the {aws} Cloud Development Kit ({aws} CDK) by installing and configuring the {aws} CDK Command Line Interface ({aws} CDK CLI). Then, use the CDK CLI to create your first CDK app, bootstrap your {aws} environment, and deploy your application. -:keywords: {aws} CDK, {aws} Cloud Development Kit ({aws} CDK), {aws} services, infrastructure as code, IaC - -[abstract] --- -Get started with the {aws} Cloud Development Kit ({aws} CDK) by installing and configuring the {aws} CDK Command Line Interface ({aws} CDK CLI). Then, use the CDK CLI to create your first CDK app, bootstrap your {aws} environment, and deploy your application. --- - -// Content start - -Get started with the {aws} Cloud Development Kit ({aws} CDK) by installing and configuring the {aws} CDK Command Line Interface ({aws} CDK CLI). Then, use the CDK CLI to create your first CDK app, bootstrap your {aws} environment, and deploy your application. - -[#getting-started-prerequisites] -== Prerequisites - -Before getting started with the {aws} CDK, complete all prerequisites. These prerequisites are required for those that are new to {aws} or new to programming. For instructions, see xref:prerequisites[{aws} CDK prerequisites]. - -We recommend that you have a basic understanding of what the {aws} CDK is. For more information, see xref:home[What is the {aws} CDK?] and xref:core-concepts[Learn {aws} CDK core concepts]. - -[#getting-started-install] -== Install the {aws} CDK CLI - -Use the [.noloc]`Node` Package Manager to install the CDK CLI. We recommend that you install it globally using the following command: - -[source,bash,subs="verbatim,attributes"] ----- -$ npm install -g aws-cdk ----- - -To install a specific version of the CDK CLI, use the following command structure: - -[source,bash,subs="verbatim,attributes"] ----- -$ npm install -g aws-cdk@X.YY.Z ----- - -If you want to use multiple versions of the {aws} CDK, consider installing a matching version of the CDK CLI in individual CDK projects. To do this, remove the `-g` option from the `npm install` command. Then, use `npx aws-cdk` to invoke the CDK CLI. This will run a local version if it exists. Otherwise, the globally installed version will be used. - -[#getting-started-install-troubleshoot] -*Troubleshoot a CDK CLI installation*:: -+ -If you get a permission error, and have administrator access on your system, run the following: -+ -[source,bash,subs="verbatim,attributes"] ----- -$ sudo npm install -g aws-cdk ----- -+ -If you receive an error message, try uninstalling the CDK CLI by running the following: -+ -[source,bash,subs="verbatim,attributes"] ----- -$ npm uninstall -g aws-cdk ----- -+ -Then, repeat steps to reinstall the CDK CLI. - -[#getting-started-install-verify] -== Verify a successful CDK CLI installation - -Run the following command to verify a successful installation. The {aws} CDK CLI should output the version number: - -[source,bash,subs="verbatim,attributes"] ----- -$ cdk --version ----- - -[#getting-started-configure] -== Configure the {aws} CDK CLI - -After installing the CDK CLI, you can start using it to develop applications on your local machine. To interact with {aws}, such as deploying applications, you must have security credentials configured on your local machine with permissions to perform any actions that you initiate. - -To configure security credentials on your local machine, you use the {aws} CLI. How you configure security credentials depends on how you manage users. For instructions, see https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-authentication.html[Authentication and access credentials] in the _{aws} Command Line Interface User Guide_. - -The CDK CLI will automatically use the security credentials that you configure with the {aws} CLI. For example, if you are an IAM Identity Center user, you can use the `aws configure sso` command to configure security credentials. If you are an IAM user, you can use the `aws configure` command. The {aws} CLI will guide you through configuring security credentials on your local machine and save the necessary information in your `config` and `credentials` files. Then, when you use the CDK CLI, such as deploying an application with `cdk deploy`, the CDK CLI will use your configured security credentials. - -Just like the {aws} CLI, the CDK CLI will use your `default` profile by default. You can specify a profile using the CDK CLI xref:ref-cli-cmd-options-profile[`--profile`] option. For more information on using security credentials with the CDK CLI, see xref:configure-access[Configure security credentials for the {aws} CDK CLI]. - -[#getting-started-tools] -== (Optional) Install additional {aws} CDK tools - -The https://aws.amazon.com/visualstudiocode/[{aws} Toolkit for Visual Studio Code] is an open source plug-in for [.noloc]`Visual Studio Code` that helps you create, debug, and deploy applications on {aws}. The toolkit provides an integrated experience for developing {aws} CDK applications. It includes the {aws} CDK Explorer feature to list your {aws} CDK projects and browse the various components of the CDK application. For instructions, see the following: - -* https://docs.aws.amazon.com/toolkit-for-vscode/latest/userguide/setup-toolkit.html[Installing the {aws} Toolkit for Visual Studio Code]. -* https://docs.aws.amazon.com/toolkit-for-vscode/latest/userguide/cdk-explorer.html[{aws} CDK for VS Code]. - -[#getting-started-app] -== Create your first CDK app - -You're now ready to get started with using the {aws} CDK by creating your first CDK app. For instructions, see xref:hello-world[Tutorial: Create your first {aws} CDK app]. - -include::hello-world.adoc[leveloffset=+1] \ No newline at end of file diff --git a/v2/guide/getting-started/hello-world.adoc b/v2/guide/getting-started/hello-world.adoc deleted file mode 100644 index 0489d66a..00000000 --- a/v2/guide/getting-started/hello-world.adoc +++ /dev/null @@ -1,1665 +0,0 @@ -include::../attributes.txt[] - -// Attributes -[.topic] -[#hello-world] -= Tutorial: Create your first {aws} CDK app -:info_titleabbrev: Create your first CDK app -:info_abstract: Get started with the {aws} Cloud Development Kit ({aws} CDK) by using the {aws} CDK Command Line Interface ({aws} CDK CLI) to develop your first \ - CDK app, bootstrap your {aws} environment, and deploy your application on {aws}. -:keywords: {aws} CDK, {aws} Cloud Development Kit ({aws} CDK), CDK app, {aws}, {aws} CloudFormation, Infrastructure as code, IaC - -[abstract] --- -Get started with the {aws} Cloud Development Kit ({aws} CDK) by using the {aws} CDK Command Line Interface ({aws} CDK CLI) to develop your first CDK app, bootstrap your {aws} environment, and deploy your application on {aws}. --- - -// Content start -Get started with using the {aws} Cloud Development Kit ({aws} CDK) by using the {aws} CDK Command Line Interface ({aws} CDK CLI) to develop your first CDK app, bootstrap your {aws} environment, and deploy your application on {aws}. - -[#hello-world-prerequisites] -== Prerequisites - -Before starting this tutorial, complete all set up steps in xref:getting-started[Getting started with the {aws} CDK]. - -[#hello-world-about,hello-world-about.title] -== About this tutorial - -In this tutorial, you will create and deploy a simple application on {aws} using the {aws} CDK. The application consists of an https://docs.aws.amazon.com/lambda/latest/dg/welcome.html[{aws} Lambda function] that returns a `Hello World!` message when invoked. The function will be invoked through a https://docs.aws.amazon.com/lambda/latest/dg/lambda-urls.html[Lambda function URL] that serves as a dedicated HTTP(S) endpoint for your Lambda function. - -Through this tutorial, you will perform the following: - -* *Create your project* – Create a CDK project using the CDK CLI `cdk init` command. -* *Configure your {aws} environment* – Configure the {aws} environment that you will deploy your application into. -* *Bootstrap your {aws} environment* – Prepare your {aws} environment for deployment by bootstrapping it using the CDK CLI `cdk bootstrap` command. -* *Develop your app* – Use constructs from the {aws} Construct Library to define your Lambda function and Lambda function URL resources. -* *Prepare your app for deployment* – Use the CDK CLI to build your app and synthesize an {aws} CloudFormation template. -* *Deploy your app* – Use the CDK CLI `cdk deploy` command to deploy your application and provision your {aws} resources. -* *Interact with your application* – Interact with your deployed Lambda function on {aws} by invoking it and receiving a response. -* *Modify your app* – Modify your Lambda function and deploy to implement your changes. -* *Delete your app* – Delete all resources that you created by using the CDK CLI `cdk destroy` command. - - -[#hello-world-create] -== Step 1: Create your CDK project - -In this step, you create a new CDK project. A CDK project should be in its own directory, with its own local module dependencies. - -*To create a CDK project*:: -+ -. From a starting directory of your choice, create and navigate to a directory named `hello-cdk`: -+ -[source,bash,subs="verbatim,attributes"] ----- -$ mkdir hello-cdk && cd hello-cdk ----- -+ -IMPORTANT: Be sure to name your project directory `hello-cdk`, _exactly as shown here_. The CDK CLI uses this directory name to name things within your CDK code. If you use a different directory name, you will run into issues during this tutorial. - -. From the `hello-cdk` directory, initialize a new CDK project using the CDK CLI``cdk init`` command. Specify the `app` template and your preferred programming language with the `--language` option: -+ -==== -[role="tablist"] -TypeScript:: -+ -[source,bash,subs="verbatim,attributes"] ----- -$ cdk init app --language typescript ----- - -JavaScript:: -+ -[source,bash,subs="verbatim,attributes"] ----- -$ cdk init app --language javascript ----- - -Python:: -+ -[source,bash,subs="verbatim,attributes"] ----- -$ cdk init app --language python ----- -+ -After the app has been created, also enter the following two commands. These activate the app's Python virtual environment and installs the {aws} CDK core dependencies. -+ -[source,bash,subs="verbatim,attributes"] ----- -$ source .venv/bin/activate # On Windows, run `.\venv\Scripts\activate` instead -$ python -m pip install -r requirements.txt ----- - -Java:: -+ -[source,bash,subs="verbatim,attributes"] ----- -$ cdk init app --language java ----- -+ -If you are using an IDE, you can now open or import the project. In [.noloc]``Eclipse``, for example, choose *File* > *Import* > *Maven* > **Existing Maven Projects**. Make sure that the project settings are set to use Java 8 (1.8). - -C#:: -+ -[source,bash,subs="verbatim,attributes"] ----- -$ cdk init app --language csharp ----- -+ -If you are using Visual Studio, open the solution file in the `src` directory. - -Go:: -+ -[source,bash,subs="verbatim,attributes"] ----- -$ cdk init app --language go ----- -+ -After the app has been created, also enter the following command to install the {aws} Construct Library modules that the app requires. -+ -[source,bash,subs="verbatim,attributes"] ----- -$ go get ----- -==== - -The `cdk init` command creates a structure of files and folders within the `hello-cdk` directory to help organize the source code for your CDK app. This structure of files and folders is called your CDK _project_. Take a moment to explore your CDK project. - -If you have [.noloc]`Git` installed, each project you create using `cdk init` is also initialized as a [.noloc]``Git`` repository. - -During project initialization, the CDK CLI creates a CDK app containing a single CDK stack. The CDK app instance is created using the link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.App.html[`App`] construct. The following is a portion of this code from your CDK application file: - -==== -[role="tablist"] -TypeScript:: -Located in `bin/hello-cdk.ts`: -+ -[source,javascript,subs="verbatim,attributes"] ----- -#!/usr/bin/env node -import 'source-map-support/register'; -import * as cdk from 'aws-cdk-lib'; -import { HelloCdkStack } from '../lib/hello-cdk-stack'; - -const app = new cdk.App(); -new HelloCdkStack(app, 'HelloCdkStack', { -}); ----- - -JavaScript:: -Located in `bin/hello-cdk.js`: -+ -[source,javascript,subs="verbatim,attributes"] ----- -#!/usr/bin/env node - -const cdk = require('aws-cdk-lib'); -const { HelloCdkStack } = require('../lib/hello-cdk-stack'); - -const app = new cdk.App(); -new HelloCdkStack(app, 'HelloCdkStack', { -}); ----- - -Python:: -Located in `app.py`: -+ -[source,python,subs="verbatim,attributes"] ----- -#!/usr/bin/env python3 -import os - -import aws_cdk as cdk - -from hello_cdk.hello_cdk_stack import HelloCdkStack - -app = cdk.App() -HelloCdkStack(app, "HelloCdkStack",) - -app.synth() ----- - -Java:: -Located in `src/main/java/.../HelloCdkApp.java`: -+ -[source,java,subs="verbatim,attributes"] ----- -package com.myorg; - -import software.amazon.awscdk.App; -import software.amazon.awscdk.Environment; -import software.amazon.awscdk.StackProps; - -import java.util.Arrays; - -public class HelloCdkApp { - public static void main(final String[] args) { - App app = new App(); - - new HelloCdkStack(app, "HelloCdkStack", StackProps.builder() - .build()); - - app.synth(); - } -} ----- - -C#:: -Located in `src/HelloCdk/Program.cs`: -+ -[source,csharp,subs="verbatim,attributes"] ----- -using Amazon.CDK; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace HelloCdk -{ - sealed class Program - { - public static void Main(string[] args) - { - var app = new App(); - new HelloCdkStack(app, "HelloCdkStack", new StackProps - {}); - app.Synth(); - } - } -} ----- - -Go:: -Located in `hello-cdk.go`: -+ -[source,go,subs="verbatim,attributes"] ----- -package main - -import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/constructs-go/constructs/v10" - "github.com/aws/jsii-runtime-go" -) - -// ... - -func main() { - defer jsii.Close() - - app := awscdk.NewApp(nil) - - NewHelloCdkStack(app, "HelloCdkStack", &HelloCdkStackProps{ - awscdk.StackProps{ - Env: env(), - }, - }) - - app.Synth(nil) -} - -// ... ----- -==== - -The CDK stack is created using the link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html[`Stack`] construct. The following is a portion of this code from your CDK stack file: - -==== -[role="tablist"] -TypeScript:: -Located in `lib/hello-cdk-stack.ts`: -+ -[source,javascript,subs="verbatim,attributes"] ----- -import * as cdk from 'aws-cdk-lib'; -import { Construct } from 'constructs'; - -export class HelloCdkStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - // Define your constructs here - - } -} ----- - -JavaScript:: -Located in `lib/hello-cdk-stack.js`: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const { Stack } = require('aws-cdk-lib'); - -class HelloCdkStack extends Stack { - constructor(scope, id, props) { - super(scope, id, props); - - // Define your constructs here - - } -} - -module.exports = { HelloCdkStack } ----- - -Python:: -Located in `hello_cdk/hello_cdk_stack.py`: -+ -[source,python,subs="verbatim,attributes"] ----- -from aws_cdk import ( - Stack, -) -from constructs import Construct - -class HelloCdkStack(Stack): - - def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: - super().__init__(scope, construct_id, **kwargs) - - # Define your constructs here ----- - -Java:: -Located in `src/main/java/.../HelloCdkStack.java`: -+ -[source,java,subs="verbatim,attributes"] ----- -package com.myorg; - -import software.constructs.Construct; -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.StackProps; - -public class HelloCdkStack extends Stack { - public HelloCdkStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public HelloCdkStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - // Define your constructs here - } -} ----- - -C#:: -Located in `src/HelloCdk/HelloCdkStack.cs`: -+ -[source,csharp,subs="verbatim,attributes"] ----- -using Amazon.CDK; -using Constructs; - -namespace HelloCdk -{ - public class HelloCdkStack : Stack - { - internal HelloCdkStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) - { - // Define your constructs here - } - } -} ----- - -Go:: -Located in `hello-cdk.go`: -+ -[source,go,subs="verbatim,attributes"] ----- -package main - -import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/constructs-go/constructs/v10" - "github.com/aws/jsii-runtime-go" -) - -type HelloCdkStackProps struct { - awscdk.StackProps -} - -func NewHelloCdkStack(scope constructs.Construct, id string, props *HelloCdkStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - stack := awscdk.NewStack(scope, &id, &sprops) - - return stack -} - -// ... ----- -==== - -[#hello-world-configure] -== Step 2: Configure your {aws} environment - -In this step, you configure the {aws} environment for your CDK stack. By doing this, you specify which environment your CDK stack will be deployed to. - -First, determine the {aws} environment that you want to use. An {aws} environment consists of an {aws} account and {aws} Region. - -When you use the {aws} CLI to configure security credentials on your local machine, you can then use the {aws} CLI to obtain {aws} environment information for a specific profile. - -*To use the {aws} CLI to obtain your {aws} account ID*:: -+ -. Run the following {aws} CLI command to get the {aws} account ID for your `default` profile: -+ -[source,bash,subs="verbatim,attributes"] ----- -$ aws sts get-caller-identity --query "Account" --output text ----- -+ -. If you prefer to use a named profile, provide the name of your profile using the `--profile` option: -+ -[source,bash,subs="verbatim,attributes"] ----- -$ aws sts get-caller-identity --profile your-profile-name --query "Account" --output text ----- - -*To use the {aws} CLI to obtain your {aws} Region*:: -+ -. Run the following {aws} CLI command to get the Region that you configured for your `default` profile: -+ -[source,bash,subs="verbatim,attributes"] ----- -$ aws configure get region ----- -+ -. If you prefer to use a named profile, provide the name of your profile using the `--profile` option: -+ -[source,bash,subs="verbatim,attributes"] ----- -$ aws configure get region --profile your-profile-name ----- - -Next, you will configure the {aws} environment for your CDK stack by modifying the `HelloCdkStack` instance in your __application file__. For this tutorial, you will hard code your {aws} environment information. This is recommended for production environments. For information on other ways to configure environments, see xref:configure-env[Configure environments to use with the {aws} CDK]. - -*To configure the environment for your CDK stack*:: -+ -. In your _application file_, use the `env` property of the `Stack` construct to configure your environment. The following is an example: -+ -==== -[role="tablist"] -TypeScript::: -Located in `bin/hello-cdk.ts`: -+ -[source,javascript,subs="verbatim,attributes"] ----- -#!/usr/bin/env node -import 'source-map-support/register'; -import * as cdk from 'aws-cdk-lib'; -import { HelloCdkStack } from '../lib/hello-cdk-stack'; - -const app = new cdk.App(); -new HelloCdkStack(app, 'HelloCdkStack', { - env: { account: '123456789012', region: 'us-east-1' }, -}); ----- - -JavaScript::: -Located in `bin/hello-cdk.js`: -+ -[source,javascript,subs="verbatim,attributes"] ----- -#!/usr/bin/env node - -const cdk = require('aws-cdk-lib'); -const { HelloCdkStack } = require('../lib/hello-cdk-stack'); - -const app = new cdk.App(); -new HelloCdkStack(app, 'HelloCdkStack', { - env: { account: '123456789012', region: 'us-east-1' }, -}); ----- - -Python::: -Located in `app.py`: -+ -[source,python,subs="verbatim,attributes"] ----- -#!/usr/bin/env python3 -import os - -import aws_cdk as cdk - -from hello_cdk.hello_cdk_stack import HelloCdkStack - -app = cdk.App() -HelloCdkStack(app, "HelloCdkStack", - env=cdk.Environment(account='123456789012', region='us-east-1'), - ) - -app.synth() ----- - -Java::: -Located in `src/main/java/.../HelloCdkApp.java`: -+ -[source,java,subs="verbatim,attributes"] ----- -package com.myorg; - -import software.amazon.awscdk.App; -import software.amazon.awscdk.Environment; -import software.amazon.awscdk.StackProps; - -import java.util.Arrays; - -public class HelloCdkApp { - public static void main(final String[] args) { - App app = new App(); - - new HelloCdkStack(app, "HelloCdkStack", StackProps.builder() - .env(Environment.builder() - .account("123456789012") - .region("us-east-1") - .build()) - - .build()); - - app.synth(); - } -} ----- - -C#::: -Located in `src/HelloCdk/Program.cs`: -+ -[source,csharp,subs="verbatim,attributes"] ----- -using Amazon.CDK; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace HelloCdk -{ - sealed class Program - { - public static void Main(string[] args) - { - var app = new App(); - new HelloCdkStack(app, "HelloCdkStack", new StackProps - { - Env = new Amazon.CDK.Environment - { - Account = "123456789012", - Region = "us-east-1", - } - }); - app.Synth(); - } - } -} ----- - -Go::: -Located in `hello-cdk.go`: -+ -[source,go,subs="verbatim,attributes"] ----- -package main - -import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/constructs-go/constructs/v10" - "github.com/aws/jsii-runtime-go" -) - -// ... - -func main() { - defer jsii.Close() - - app := awscdk.NewApp(nil) - - NewHelloCdkStack(app, "HelloCdkStack", &HelloCdkStackProps{ - awscdk.StackProps{ - Env: env(), - }, - }) - - app.Synth(nil) -} - -func env() *awscdk.Environment { - return &awscdk.Environment{ - Account: jsii.String("123456789012"), - Region: jsii.String("us-east-1"), - } -} ----- -==== - -[#hello-world-bootstrap] -== Step 3: Bootstrap your {aws} environment - -In this step, you bootstrap the {aws} environment that you configured in the previous step. This prepares your environment for CDK deployments. - -To bootstrap your environment, run the following from the root of your CDK project: - -[source,bash,subs="verbatim,attributes"] ----- -$ cdk bootstrap ----- - -By bootstrapping from the root of your CDK project, you don't have to provide any additional information. The CDK CLI obtains environment information from your project. When you bootstrap outside of a CDK project, you must provide environment information with the `cdk bootstrap` command. For more information, see xref:bootstrapping-env[Bootstrap your environment for use with the {aws} CDK]. - -[#hello-world-build] -== Step 4: Build your CDK app - -In most programming environments, you build or compile code after making changes. This isn't necessary with the {aws} CDK since the CDK CLI will automatically perform this step. However, you can still build manually when you want to catch syntax and type errors. The following is an example: - -==== -[role="tablist"] -TypeScript:: -+ -[source,bash,subs="verbatim,attributes"] ----- -$ npm run build - -> hello-cdk@0.1.0 build -> tsc ----- - -JavaScript:: -No build step is necessary. - -Python:: -No build step is necessary. - -Java:: -+ -[source,bash,subs="verbatim,attributes"] ----- -$ mvn compile -q ----- -+ -Or press `Control-B` in Eclipse (other Java IDEs may vary) - -C#:: -+ -[source,bash,subs="verbatim,attributes"] ----- -$ dotnet build src ----- -+ -Or press F6 in Visual Studio - -Go:: -+ -[source,bash,subs="verbatim,attributes"] ----- -$ go build ----- -==== - -[#hello-world-list] -== Step 5: List the CDK stacks in your app - -At this point, you should have a CDK app containing a single CDK stack. To verify, use the CDK CLI `cdk list` command to display your stacks. The output should display a single stack named `HelloCdkStack`: - -[source,bash,subs="verbatim,attributes"] ----- -$ cdk list -HelloCdkStack ----- - -If you don't see this output, verify that you are in the correct working directory of your project and try again. If you still don't see your stack, repeat xref:hello-world-create[Step 1: Create your CDK project] and try again. - -[#hello-world-function] -== Step 6: Define your Lambda function - -In this step, you import the link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda-readme.html[`aws_lambda`] module from the {aws} Construct Library and use the link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.Function.html[`Function`] L2 construct. - -Modify your CDK stack file as follows: - -==== -[role="tablist"] -TypeScript:: -Located in `lib/hello-cdk-stack.ts`: -+ -[source,javascript,subs="verbatim,attributes"] ----- -import * as cdk from 'aws-cdk-lib'; -import { Construct } from 'constructs'; -// Import the Lambda module -import * as lambda from 'aws-cdk-lib/aws-lambda'; - -export class HelloCdkStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - // Define the Lambda function resource - const myFunction = new lambda.Function(this, "HelloWorldFunction", { - runtime: lambda.Runtime.NODEJS_20_X, // Provide any supported Node.js runtime - handler: "index.handler", - code: lambda.Code.fromInline(` - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello World!'), - }; - }; - `), - }); - } -} ----- - -JavaScript:: -Located in `lib/hello-cdk-stack.js`: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const { Stack } = require('aws-cdk-lib'); -// Import the Lambda module -const lambda = require('aws-cdk-lib/aws-lambda'); - -class HelloCdkStack extends Stack { - constructor(scope, id, props) { - super(scope, id, props); - - // Define the Lambda function resource - const myFunction = new lambda.Function(this, "HelloWorldFunction", { - runtime: lambda.Runtime.NODEJS_20_X, // Provide any supported Node.js runtime - handler: "index.handler", - code: lambda.Code.fromInline(` - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello World!'), - }; - }; - `), - }); - - } -} - -module.exports = { HelloCdkStack } ----- - -Python:: -Located in `hello_cdk/hello_cdk_stack.py`: -+ -[source,python,subs="verbatim,attributes"] ----- -from aws_cdk import ( - Stack, - aws_lambda as _lambda, # Import the Lambda module -) -from constructs import Construct - -class HelloCdkStack(Stack): - - def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: - super().__init__(scope, construct_id, **kwargs) - - # Define the Lambda function resource - my_function = _lambda.Function( - self, "HelloWorldFunction", - runtime = _lambda.Runtime.NODEJS_20_X, # Provide any supported Node.js runtime - handler = "index.handler", - code = _lambda.Code.from_inline( - """ - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello World!'), - }; - }; - """ - ), - ) ----- - -Java:: -Located in `src/main/java/.../HelloCdkStack.java`: -+ -[source,java,subs="verbatim,attributes"] ----- -package com.myorg; - -import software.constructs.Construct; -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.StackProps; -// Import Lambda function -import software.amazon.awscdk.services.lambda.Code; -import software.amazon.awscdk.services.lambda.Function; -import software.amazon.awscdk.services.lambda.Runtime; - -public class HelloCdkStack extends Stack { - public HelloCdkStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public HelloCdkStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - // Define the Lambda function resource - Function myFunction = Function.Builder.create(this, "HelloWorldFunction") - .runtime(Runtime.NODEJS_20_X) // Provide any supported Node.js runtime - .handler("index.handler") - .code(Code.fromInline( - "exports.handler = async function(event) {" + - " return {" + - " statusCode: 200," + - " body: JSON.stringify('Hello World!')" + - " };" + - "};")) - .build(); - - } -} ----- - -C#:: -Located in `src/main/java/.../HelloCdkStack.java`: -+ -[source,csharp,subs="verbatim,attributes"] ----- -using Amazon.CDK; -using Constructs; -// Import the Lambda module -using Amazon.CDK.{aws}.Lambda; - -namespace HelloCdk -{ - public class HelloCdkStack : Stack - { - internal HelloCdkStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) - { - // Define the Lambda function resource - var myFunction = new Function(this, "HelloWorldFunction", new FunctionProps - { - Runtime = Runtime.NODEJS_20_X, // Provide any supported Node.js runtime - Handler = "index.handler", - Code = Code.FromInline(@" - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello World!'), - }; - }; - "), - }); - } - } -} ----- - -Go:: -Located in `hello-cdk.go`: -+ -[source,go,subs="verbatim,attributes"] ----- -package main - -import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/constructs-go/constructs/v10" - "github.com/aws/jsii-runtime-go" - // Import the Lambda module - "github.com/aws/aws-cdk-go/awscdk/v2/awslambda" -) - -type HelloCdkStackProps struct { - awscdk.StackProps -} - -func NewHelloCdkStack(scope constructs.Construct, id string, props *HelloCdkStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - stack := awscdk.NewStack(scope, &id, &sprops) - - // Define the Lambda function resource - myFunction := awslambda.NewFunction(stack, jsii.String("HelloWorldFunction"), &awslambda.FunctionProps{ - Runtime: awslambda.Runtime_NODEJS_20_X(), // Provide any supported Node.js runtime - Handler: jsii.String("index.handler"), - Code: awslambda.Code_FromInline(jsii.String(` - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello World!'), - }; - }; - `)), - }) - - return stack -} - -// ... ----- -==== - -Let's take a closer look at the `Function` construct. Like all constructs, the `Function` class takes three parameters: - -* *scope* – Defines your `Stack` instance as the parent of the `Function` construct. All constructs that define {aws} resources are created within the scope of a stack. You can define constructs inside of constructs, creating a hierarchy (tree). Here, and in most cases, the scope is `this` (`self` in Python). -* *Id* – The construct ID of the `Function` within your {aws} CDK app. This ID, plus a hash based on the function's location within the stack, uniquely identifies the function during deployment. The {aws} CDK also references this ID when you update the construct in your app and re-deploy to update the deployed resource. Here, your construct ID is ``HelloWorldFunction``. Functions can also have a name, specified with the `functionName` property. This is different from the construct ID. -* *props* – A bundle of values that define properties of the function. Here you define the `runtime`, `handler`, and `code` properties. -+ -Props are represented differently in the languages supported by the {aws} CDK. -+ -** In TypeScript and JavaScript, `props` is a single argument and you pass in an object containing the desired properties. -** In Python, props are passed as keyword arguments. -** In Java, a Builder is provided to pass the props. There are two: one for ``FunctionProps``, and a second for `Function` to let you build the construct and its props object in one step. This code uses the latter. -** In C#, you instantiate a `FunctionProps` object using an object initializer and pass it as the third parameter. -+ - -If a construct's props are optional, you can omit the `props` parameter entirely. - -All constructs take these same three arguments, so it's easy to stay oriented as you learn about new ones. And as you might expect, you can subclass any construct to extend it to suit your needs, or if you want to change its defaults. - -[#hello-world-url] -== Step 7: Define your Lambda function URL - -In this step, you use the `addFunctionUrl` helper method of the `Function` construct to define a Lambda function URL. To output the value of this URL at deployment, you will create an {aws} CloudFormation output using the link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.CfnOutput.html[`CfnOutput`] construct. - -Add the following to your CDK stack file: - -==== -[role="tablist"] -TypeScript:: -Located in `lib/hello-cdk-stack.ts`: -+ -[source,javascript,subs="verbatim,attributes"] ----- -// ... - -export class HelloCdkStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - // Define the Lambda function resource - // ... - - // Define the Lambda function URL resource - const myFunctionUrl = myFunction.addFunctionUrl({ - authType: lambda.FunctionUrlAuthType.NONE, - }); - - // Define a CloudFormation output for your URL - new cdk.CfnOutput(this, "myFunctionUrlOutput", { - value: myFunctionUrl.url, - }) - - } -} ----- - -JavaScript:: -Located in `lib/hello-cdk-stack.js`: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const { Stack, CfnOutput } = require('aws-cdk-lib'); // Import CfnOutput - -class HelloCdkStack extends Stack { - constructor(scope, id, props) { - super(scope, id, props); - - // Define the Lambda function resource - // ... - - // Define the Lambda function URL resource - const myFunctionUrl = myFunction.addFunctionUrl({ - authType: lambda.FunctionUrlAuthType.NONE, - }); - - // Define a CloudFormation output for your URL - new CfnOutput(this, "myFunctionUrlOutput", { - value: myFunctionUrl.url, - }) - - } -} - -module.exports = { HelloCdkStack } ----- - -Python:: -Located in `hello_cdk/hello_cdk_stack.py`: -+ -[source,python,subs="verbatim,attributes"] ----- -from aws_cdk import ( - # ... - CfnOutput # Import CfnOutput -) -from constructs import Construct - -class HelloCdkStack(Stack): - - def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: - super().__init__(scope, construct_id, **kwargs) - - # Define the Lambda function resource - # ... - - # Define the Lambda function URL resource - my_function_url = my_function.add_function_url( - auth_type = _lambda.FunctionUrlAuthType.NONE, - ) - - # Define a CloudFormation output for your URL - CfnOutput(self, "myFunctionUrlOutput", value=my_function_url.url) ----- - -Java:: -Located in `src/main/java/.../HelloCdkStack.java`: -+ -[source,java,subs="verbatim,attributes"] ----- -package com.myorg; - -// ... -// Import Lambda function URL -import software.amazon.awscdk.services.lambda.FunctionUrl; -import software.amazon.awscdk.services.lambda.FunctionUrlAuthType; -import software.amazon.awscdk.services.lambda.FunctionUrlOptions; -// Import CfnOutput -import software.amazon.awscdk.CfnOutput; - -public class HelloCdkStack extends Stack { - public HelloCdkStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public HelloCdkStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - // Define the Lambda function resource - // ... - - // Define the Lambda function URL resource - FunctionUrl myFunctionUrl = myFunction.addFunctionUrl(FunctionUrlOptions.builder() - .authType(FunctionUrlAuthType.NONE) - .build()); - - // Define a CloudFormation output for your URL - CfnOutput.Builder.create(this, "myFunctionUrlOutput") - .value(myFunctionUrl.getUrl()) - .build(); - } -} ----- - -C#:: -Located in `src/main/java/.../HelloCdkStack.java`: -+ -[source,csharp,subs="verbatim,attributes"] ----- -// ... - -namespace HelloCdk -{ - public class HelloCdkStack : Stack - { - internal HelloCdkStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) - { - // Define the Lambda function resource - // ... - - // Define the Lambda function URL resource - var myFunctionUrl = myFunction.AddFunctionUrl(new FunctionUrlOptions - { - AuthType = FunctionUrlAuthType.NONE - }); - - // Define a CloudFormation output for your URL - new CfnOutput(this, "myFunctionUrlOutput", new CfnOutputProps - { - Value = myFunctionUrl.Url - }); - } - } -} ----- - -Go:: -Located in `hello-cdk.go`: -+ -[source,go,subs="verbatim,attributes"] ----- -// ... - -func NewHelloCdkStack(scope constructs.Construct, id string, props *HelloCdkStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - stack := awscdk.NewStack(scope, &id, &sprops) - - // Define the Lambda function resource - // ... - - // Define the Lambda function URL resource - myFunctionUrl := myFunction.AddFunctionUrl(&awslambda.FunctionUrlOptions{ - AuthType: awslambda.FunctionUrlAuthType_NONE, - }) - - // Define a CloudFormation output for your URL - awscdk.NewCfnOutput(stack, jsii.String("myFunctionUrlOutput"), &awscdk.CfnOutputProps{ - Value: myFunctionUrl.Url(), - }) - - return stack -} - -// ... ----- -==== - - -[WARNING] -==== - -To keep this tutorial simple, your Lambda function URL is defined without authentication. When deployed, this creates a publicly accessible endpoint that can be used to invoke your function. When you are done with this tutorial, follow xref:hello-world-delete[Step 12: Delete your application] to delete these resources. - -==== - -[#hello-world-synth] -== Step 8: Synthesize a CloudFormation template - -In this step, you prepare for deployment by synthesizing a CloudFormation template with the CDK CLI `cdk synth` command. This command performs basic validation of your CDK code, runs your CDK app, and generates a CloudFormation template from your CDK stack. - -If your app contains more than one stack, you must specify which stacks to synthesize. Since your app contains a single stack, the CDK CLI automatically detects the stack to synthesize. - -If you don't synthesize a template, the CDK CLI will automatically perform this step when you deploy. However, we recommend that you run this step before each deployment to check for synthesis errors. - -Before synthesizing a template, you can optionally build your application to catch syntax and type errors. For instructions, see xref:hello-world-build[Step 4: Build your CDK app]. - -To synthesize a CloudFormation template, run the following from the root of your project: - -[source,bash,subs="verbatim,attributes"] ----- -$ cdk synth ----- - -[NOTE] -==== - -If you receive an error like the following, verify that you are in the `hello-cdk` directory and try again: - ----- ---app is required either in command-line, in cdk.json or in ~/.cdk.json ----- - -==== - -If successful, the CDK CLI will output a `YAML`–formatted CloudFormation template to `stdout` and save a `JSON`–formatted template in the `cdk.out` directory of your project. - -The following is an example output of the CloudFormation template: - -[#hello-world-synth-template] -.{aws} CloudFormation template -[%collapsible] -==== - -[source,yaml,subs="verbatim,attributes"] ----- -Resources: - HelloWorldFunctionServiceRole<unique-identifier>: - Type: {aws}::IAM::Role - Properties: - AssumeRolePolicyDocument: - Statement: - - Action: sts:AssumeRole - Effect: Allow - Principal: - Service: lambda.amazonaws.com - Version: "2012-10-17" - ManagedPolicyArns: - - Fn::Join: - - "" - - - "arn:" - - Ref: {aws}::Partition - - :iam::aws:policy/service-role/AWSLambdaBasicExecutionRole - Metadata: - aws:cdk:path: HelloCdkStack/HelloWorldFunction/ServiceRole/Resource - HelloWorldFunction<unique-identifier>: - Type: {aws}::Lambda::Function - Properties: - Code: - ZipFile: " - - \ exports.handler = async function(event) { - - \ return { - - \ statusCode: 200, - - \ body: JSON.stringify('Hello World!'), - - \ }; - - \ }; - - \ " - Handler: index.handler - Role: - Fn::GetAtt: - - HelloWorldFunctionServiceRole<unique-identifier> - - Arn - Runtime: nodejs20.x - DependsOn: - - HelloWorldFunctionServiceRole<unique-identifier> - Metadata: - aws:cdk:path: HelloCdkStack/HelloWorldFunction/Resource - HelloWorldFunctionFunctionUrl<unique-identifier>: - Type: {aws}::Lambda::Url - Properties: - AuthType: NONE - TargetFunctionArn: - Fn::GetAtt: - - HelloWorldFunction<unique-identifier> - - Arn - Metadata: - aws:cdk:path: HelloCdkStack/HelloWorldFunction/FunctionUrl/Resource - HelloWorldFunctioninvokefunctionurl<unique-identifier>: - Type: {aws}::Lambda::Permission - Properties: - Action: lambda:InvokeFunctionUrl - FunctionName: - Fn::GetAtt: - - HelloWorldFunction<unique-identifier> - - Arn - FunctionUrlAuthType: NONE - Principal: "*" - Metadata: - aws:cdk:path: HelloCdkStack/HelloWorldFunction/invoke-function-url - CDKMetadata: - Type: {aws}::CDK::Metadata - Properties: - Analytics: v2:deflate64:<unique-identifier> - Metadata: - aws:cdk:path: HelloCdkStack/CDKMetadata/Default - Condition: CDKMetadataAvailable -Outputs: - myFunctionUrlOutput: - Value: - Fn::GetAtt: - - HelloWorldFunctionFunctionUrl<unique-identifier> - - FunctionUrl -Parameters: - BootstrapVersion: - Type: {aws}::SSM::Parameter::Value<String> - Default: /cdk-bootstrap/<unique-identifier>/version - Description: Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip] -Rules: - CheckBootstrapVersion: - Assertions: - - Assert: - Fn::Not: - - Fn::Contains: - - - "1" - - "2" - - "3" - - "4" - - "5" - - Ref: BootstrapVersion - AssertDescription: CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI. ----- -==== - -[NOTE] -==== - -Every generated template contains an `{aws}::CDK::Metadata` resource by default. The {aws} CDK team uses this metadata to gain insight into {aws} CDK usage and find ways to improve it. For details, including how to opt out of version reporting, see xref:version-reporting[Version reporting]. - -==== - -By defining a single L2 construct, the {aws} CDK creates an extensive CloudFormation template containing your Lambda resources, along with the permissions and glue logic required for your resources to interact within your application. - -[#hello-world-deploy] -== Step 9: Deploy your CDK stack - -In this step, you use the CDK CLI `cdk deploy` command to deploy your CDK stack. This command retrieves your generated CloudFormation template and deploys it through {aws} CloudFormation, which provisions your resources as part of a CloudFormation stack. - -From the root of your project, run the following. Confirm changes if prompted: - -[source,bash,subs="verbatim,attributes"] ----- -$ cdk deploy - -✨ Synthesis time: 2.69s - -HelloCdkStack: start: Building <unique-identifier>:current_account-current_region -HelloCdkStack: success: Built <unique-identifier>:current_account-current_region -HelloCdkStack: start: Publishing <unique-identifier>:current_account-current_region -HelloCdkStack: success: Published <unique-identifier>:current_account-current_region -This deployment will make potentially sensitive changes according to your current security approval level (--require-approval broadening). -Please confirm you intend to make the following modifications: - -IAM Statement Changes -┌───┬───────────────────────────────────────┬────────┬──────────────────────────┬──────────────────────────────┬───────────┐ -│ │ Resource │ Effect │ Action │ Principal │ Condition │ -├───┼───────────────────────────────────────┼────────┼──────────────────────────┼──────────────────────────────┼───────────┤ -│ + │ ${HelloWorldFunction.Arn} │ Allow │ lambda:InvokeFunctionUrl │ * │ │ -├───┼───────────────────────────────────────┼────────┼──────────────────────────┼──────────────────────────────┼───────────┤ -│ + │ ${HelloWorldFunction/ServiceRole.Arn} │ Allow │ sts:AssumeRole │ Service:lambda.amazonaws.com │ │ -└───┴───────────────────────────────────────┴────────┴──────────────────────────┴──────────────────────────────┴───────────┘ -IAM Policy Changes -┌───┬───────────────────────────────────┬────────────────────────────────────────────────────────────────────────────────┐ -│ │ Resource │ Managed Policy ARN │ -├───┼───────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────┤ -│ + │ ${HelloWorldFunction/ServiceRole} │ arn:${{aws}::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole │ -└───┴───────────────────────────────────┴────────────────────────────────────────────────────────────────────────────────┘ -(NOTE: There may be security-related changes not in this list. See https://github.com/aws/aws-cdk/issues/1299) - -Do you wish to deploy these changes (y/n)? y ----- - -Similar to `cdk synth`, you don't have to specify the {aws} CDK stack since the app contains a single stack. - -During deployment, the CDK CLI displays progress information as your stack is deployed. When complete, you can go to the https://console.aws.amazon.com/cloudformation/home[{aws} CloudFormation console] to view your `HelloCdkStack` stack. You can also go to the Lambda console to view your `HelloWorldFunction` resource. - -When deployment completes, the CDK CLI will output your endpoint URL. Copy this URL for the next step. The following is an example: - -[source,none,subs="verbatim,attributes"] ----- -... -HelloCdkStack: deploying... [1/1] -HelloCdkStack: creating CloudFormation changeset... - - ✅ HelloCdkStack - -✨ Deployment time: 41.65s - -Outputs: -HelloCdkStack.myFunctionUrlOutput = https://<api-id>.lambda-url.<Region>.on.aws/ -Stack ARN: -arn:aws:cloudformation:<Region:account-id>:stack/HelloCdkStack/<unique-identifier> - -✨ Total time: 44.34s ----- - -[#hello-world-interact] -== Step 10: Interact with your application on {aws} - -In this step, you interact with your application on {aws} by invoking your Lambda function through the function URL. When you access the URL, your Lambda function returns the `Hello World!` message. - -To invoke your function, access the function URL through your browser or from the command line. The following is an example: - -[source,bash,subs="verbatim,attributes"] ----- -$ curl https://<api-id>.lambda-url.<Region>.on.aws/ -"Hello World!"% ----- - -[#hello-world-modify] -== Step 11: Modify your application - -In this step, you modify the message that the Lambda function returns when invoked. You perform a diff using the CDK CLI `cdk diff` command to preview your changes and deploy to update your application. You then interact with your application on {aws} to see your new message. - -Modify the `myFunction` instance in your CDK stack file as follows: - -==== -[role="tablist"] -TypeScript:: -Located in `lib/hello-cdk-stack.ts`: -+ -[source,javascript,subs="verbatim,attributes"] ----- -// ... - -export class HelloCdkStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - // Modify the Lambda function resource - const myFunction = new lambda.Function(this, "HelloWorldFunction", { - runtime: lambda.Runtime.NODEJS_20_X, // Provide any supported Node.js runtime - handler: "index.handler", - code: lambda.Code.fromInline(` - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello CDK!'), - }; - }; - `), - }); - - // ... - } -} ----- - -JavaScript:: -Located in `lib/hello-cdk-stack.js`: -+ -[source,javascript,subs="verbatim,attributes"] ----- -// ... - -class HelloCdkStack extends Stack { - constructor(scope, id, props) { - super(scope, id, props); - - // Modify the Lambda function resource - const myFunction = new lambda.Function(this, "HelloWorldFunction", { - runtime: lambda.Runtime.NODEJS_20_X, // Provide any supported Node.js runtime - handler: "index.handler", - code: lambda.Code.fromInline(` - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello CDK!'), - }; - }; - `), - }); - - // ... - - } -} - -module.exports = { HelloCdkStack } ----- - -Python:: -Located in `hello_cdk/hello_cdk_stack.py`: -+ -[source,python,subs="verbatim,attributes"] ----- -# ... - -class HelloCdkStack(Stack): - - def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: - super().__init__(scope, construct_id, **kwargs) - - # Modify the Lambda function resource - my_function = _lambda.Function( - self, "HelloWorldFunction", - runtime = _lambda.Runtime.NODEJS_20_X, # Provide any supported Node.js runtime - handler = "index.handler", - code = _lambda.Code.from_inline( - """ - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello CDK!'), - }; - }; - """ - ), - ) - - # ... ----- - -Java:: -Located in `src/main/java/.../HelloCdkStack.java`: -+ -[source,java,subs="verbatim,attributes"] ----- -// ... - -public class HelloCdkStack extends Stack { - public HelloCdkStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public HelloCdkStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - // Modify the Lambda function resource - Function myFunction = Function.Builder.create(this, "HelloWorldFunction") - .runtime(Runtime.NODEJS_20_X) // Provide any supported Node.js runtime - .handler("index.handler") - .code(Code.fromInline( - "exports.handler = async function(event) {" + - " return {" + - " statusCode: 200," + - " body: JSON.stringify('Hello CDK!')" + - " };" + - "};")) - .build(); - - // ... - } -} ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -// ... - -namespace HelloCdk -{ - public class HelloCdkStack : Stack - { - internal HelloCdkStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) - { - // Modify the Lambda function resource - var myFunction = new Function(this, "HelloWorldFunction", new FunctionProps - { - Runtime = Runtime.NODEJS_20_X, // Provide any supported Node.js runtime - Handler = "index.handler", - Code = Code.FromInline(@" - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello CDK!'), - }; - }; - "), - }); - - // ... - } - } -} ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -// ... - -type HelloCdkStackProps struct { - awscdk.StackProps -} - -func NewHelloCdkStack(scope constructs.Construct, id string, props *HelloCdkStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - stack := awscdk.NewStack(scope, &id, &sprops) - - // Modify the Lambda function resource - myFunction := awslambda.NewFunction(stack, jsii.String("HelloWorldFunction"), &awslambda.FunctionProps{ - Runtime: awslambda.Runtime_NODEJS_20_X(), // Provide any supported Node.js runtime - Handler: jsii.String("index.handler"), - Code: awslambda.Code_FromInline(jsii.String(` - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello CDK!'), - }; - }; - `)), - }) - -// ... - -} ----- -==== - -Currently, your code changes have not made any direct updates to your deployed Lambda resource. Your code defines the desired state of your resource. To modify your deployed resource, you will use the CDK CLI to synthesize the desired state into a new {aws} CloudFormation template. Then, you will deploy your new CloudFormation template as a change set. Change sets make only the necessary changes to reach your new desired state. - -To preview your changes, run the `cdk diff` command. The following is an example: - -[source,bash,subs="verbatim,attributes"] ----- -$ cdk diff -Stack HelloCdkStack -Hold on while we create a read-only change set to get a diff with accurate replacement information (use --no-change-set to use a less accurate but faster template-only diff) -Resources -[~] {aws}::Lambda::Function HelloWorldFunction HelloWorldFunction<unique-identifier> - └─ [~] Code - └─ [~] .ZipFile: - ├─ [-] - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello World!'), - }; - }; - - └─ [+] - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello CDK!'), - }; - }; - - -✨ Number of stacks with differences: 1 ----- - -To create this diff, the CDK CLI queries your {aws} account account for the latest {aws} CloudFormation template for the `HelloCdkStack` stack. Then, it compares the latest template with the template it just synthesized from your app. - -To implement your changes, run the `cdk deploy` command. The following is an example: - -[source,bash,subs="verbatim,attributes"] ----- -$ cdk deploy - -✨ Synthesis time: 2.12s - -HelloCdkStack: start: Building <unique-identifier>:current_account-current_region -HelloCdkStack: success: Built <unique-identifier>:current_account-current_region -HelloCdkStack: start: Publishing <unique-identifier>:current_account-current_region -HelloCdkStack: success: Published <unique-identifier>:current_account-current_region -HelloCdkStack: deploying... [1/1] -HelloCdkStack: creating CloudFormation changeset... - - ✅ HelloCdkStack - -✨ Deployment time: 26.96s - -Outputs: -HelloCdkStack.myFunctionUrlOutput = https://<unique-identifier>.lambda-url.<Region>.on.aws/ -Stack ARN: -arn:aws:cloudformation:<Region:account-id>:stack/HelloCdkStack/<unique-identifier> - -✨ Total time: 29.07s ----- - -To interact with your application, repeat xref:hello-world-interact[Step 10: Interact with your application on {aws}]. The following is an example: - -[source,bash,subs="verbatim,attributes"] ----- -$ curl https://<api-id>.lambda-url.<Region>.on.aws/ -"Hello CDK!"% ----- - -[#hello-world-delete] -== Step 12: Delete your application - -In this step, you use the CDK CLI `cdk destroy` command to delete your application. This command deletes the CloudFormation stack associated with your CDK stack, which includes the resources you created. - -To delete your application, run the `cdk destroy` command and confirm your request to delete the application. The following is an example: - -[source,bash,subs="verbatim,attributes"] ----- -$ cdk destroy -Are you sure you want to delete: HelloCdkStack (y/n)? y -HelloCdkStack: destroying... [1/1] - - ✅ HelloCdkStack: destroyed ----- - -[#hello-world-next-steps] -== Next steps - -Congratulations! You've completed this tutorial and have used the {aws} CDK to successfully create, modify, and delete resources in the {aws} Cloud. You're now ready to begin using the {aws} CDK. - -To learn more about using the {aws} CDK in your preferred programming language, see xref:work-with[Work with the {aws} CDK library]. - -For additional resources, see the following: - -* Try the https://cdkworkshop.com/[CDK Workshop] for a more in-depth tour involving a more complex project. -* See the https://docs.aws.amazon.com/cdk/api/v2/docs/aws-construct-library.html[API reference] to begin exploring the CDK constructs available for your favorite {aws} services. -* Visit https://constructs.dev/search?q=&cdk=aws-cdk&cdkver=2&sort=downloadsDesc&offset=0[Construct Hub] to discover constructs created by {aws} and others. -* Explore https://github.com/aws-samples/aws-cdk-examples[Examples] of using the {aws} CDK. - -The {aws} CDK is an open-source project. To contribute, see to https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md[Contributing to the {aws} Cloud Development Kit ({aws} CDK)]. \ No newline at end of file diff --git a/v2/guide/getting-started/prerequisites.adoc b/v2/guide/getting-started/prerequisites.adoc deleted file mode 100644 index cd7cc689..00000000 --- a/v2/guide/getting-started/prerequisites.adoc +++ /dev/null @@ -1,97 +0,0 @@ -include::../attributes.txt[] - -// Attributes -[.topic] -[#prerequisites] -= {aws} CDK prerequisites -:info_titleabbrev: Prerequisites -:keywords: {aws} CDK, Prerequisites, {aws} account, IAM, IAM Identity Center - -[abstract] --- -Complete prerequisites before getting started with the {aws} Cloud Development Kit ({aws} CDK). --- - -// Content start - -Complete all prerequisites before getting started with the {aws} Cloud Development Kit ({aws} CDK). - -[#prerequisites-account] -== Set up your {aws} account - -If you or your organization are new to {aws}, you must set up your {aws} account. This includes signing up for an {aws} account, securing your root user, determining your method of managing users, and creating an administrative user. To manage users, you can use {aws} Identity and Access Management (IAM) or {aws} IAM Identity Center. We recommend that you use IAM Identity Center. For more information, see the following: - -* https://docs.aws.amazon.com/IAM/latest/UserGuide/introduction.html[What is IAM?] in the _IAM User Guide_. -* https://docs.aws.amazon.com/singlesignon/latest/userguide/what-is.html[What is IAM Identity Center?] in the _{aws} IAM Identity Center User Guide_. - -After setting up an {aws} account, you should have an administrative user and the ability to create and manage additional users using IAM or IAM Identity Center. - -Before moving forward, we recommend that you take time to learn the recommended best practices in {aws} Identity and Access Management. For more information, see https://docs.aws.amazon.com/IAM/latest/UserGuide/IAMBestPracticesAndUseCases.html[Security best practices and use cases in {aws} Identity and Access Management] in the _IAM User Guide_. - -[#prerequisites-cli] -== Install and configure the {aws} CLI - -When you develop {aws} CDK applications on your local machine, you will use the {aws} Cloud Development Kit ({aws} CDK) Command Line Interface (CLI) to interact with {aws}, such as deploying applications to provision your {aws} resources. To interact with {aws} outside of the {aws} Management Console, you must configure security credentials on your local machine. To do this, we recommend that you install and use the {aws} Command Line Interface ({aws} CLI). - -For instructions on installing the {aws} CLI, see https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html[Install or update to the latest version of the {aws} CLI] in the _{aws} Command Line Interface User Guide_. - -How you configure security credentials will depend on how you or your organization manages users. For instructions, see https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-authentication.html[Authentication and access credentials] in the _{aws} Command Line Interface User Guide_. - -After installing and configuring the {aws} CLI, you should have the following: - -* The {aws} CLI installed on your local machine. -* Credentials configured in a `config` on your local machine using the {aws} CLI. - -[#prerequisites-node] -== Install [.noloc]`Node.js` and programming language prerequisites - -All {aws} CDK developers, regardless of the supported programming language that you will use, require https://nodejs.org/en/download/[Node.js] 14.15.0 or later. All supported programming languages use the same backend, which runs on [.noloc]`Node.js`. We recommend a version in https://nodejs.org/en/about/releases/[active long-term support]. If your organization has a different recommendation, follow their guidance. - -[IMPORTANT] -==== - -Node.js versions 13.0.0 through 13.6.0 are not compatible with the {aws} CDK due to compatibility issues with its dependencies. - -==== - -Other programming language prerequisites depend on the language that you will use to develop {aws} CDK applications: - -==== -[role="tablist"] -TypeScript:: -* TypeScript 3.8 or later (`npm -g install typescript`) - -JavaScript:: -* No additional requirements - -Python:: -* Python 3.7 or later including `pip` and `virtualenv` - -Java:: -* Java Development Kit (JDK) 8 (a.k.a. 1.8) or later -* Apache Maven 3.5 or later -+ -Java IDE recommended (we use [.noloc]`Eclipse`` in some examples in this guide). IDE must be able to import Maven projects. Check to make sure that your project is set to use Java 1.8. Set the JAVA_HOME environment variable to the path where you have installed the JDK. - -C#:: -.NET Core 3.1 or later, or .NET 6.0 or later. -+ -Visual Studio 2019 (any edition) or Visual Studio Code recommended. - -Go:: -Go 1.1.8 or later. - -==== - -[NOTE] -.Third-party language deprecation -==== - -Each language version is only supported until it is [.noloc]`EOL` (End Of Life) and is subject to change with prior notice. - -==== - -[#prerequisites-next] -== Next steps - -To get started with the {aws} CDK, see xref:getting-started[Getting started with the {aws} CDK]. \ No newline at end of file diff --git a/v2/guide/home.adoc b/v2/guide/home.adoc deleted file mode 100644 index f8f009cb..00000000 --- a/v2/guide/home.adoc +++ /dev/null @@ -1,377 +0,0 @@ -include::attributes.txt[] - -:https---github-com-awsdocs-aws-cdk-guide-blob-main-doc-source-my-ecs-construct-stack-yaml: https://github.com/awsdocs/aws-cdk-guide/blob/main/doc_source/my_ecs_construct-stack.yaml -[.topic] -[[home,home.title]] -= What is the {aws} CDK? -:doctype: book -:sectnums: -:toc: left -:icons: font -:experimental: -:idprefix: -:idseparator: - -:sourcedir: . -:info_titleabbrev: What is the {aws} CDK? -:keywords: {aws} CDK, Developer tool, {aws}, Infrastructure as code, IaC, constructs, {aws} CloudFormation, serverless, modern applications - -[abstract] --- -The {aws} Cloud Development Kit ({aws} CDK) is an open-source software development framework for defining cloud infrastructure in code and provisioning it through {aws} CloudFormation. --- - -The {aws} Cloud Development Kit ({aws} CDK) is an open-source software development framework for defining cloud infrastructure in code and provisioning it through {aws} CloudFormation. - -The {aws} CDK consists of two primary parts: - - - -* *xref:constructs[{aws} CDK Construct Library]* – A collection of pre-written modular and reusable pieces of code, called constructs, that you can use, modify, and integrate to develop your infrastructure quickly. The goal of the {aws} CDK Construct Library is to reduce the complexity required to define and integrate {aws} services together when building applications on {aws}. -* *xref:cli[{aws} CDK Command Line Interface ({aws} CDK CLI)]* – A command line tool for interacting with CDK apps. Use the CDK CLI to create, manage, and deploy your {aws} CDK projects. The CDK CLI is also referred to as the CDK Toolkit. - -The {aws} CDK supports [.noloc]``TypeScript``, JavaScript, Python, Java, [.noloc]``C#/.Net``, and [.noloc]``Go``. You can use any of these supported programming languages to define reusable cloud components known as xref:constructs[constructs]. You compose these together into xref:stacks[stacks] and xref:apps[apps]. Then, you deploy your CDK applications to {aws} CloudFormation to provision or update your resources. - -image::images/AppStacks.png["{aws} CDK app structure with stacks, constructs, and deployment to CloudFormation.",scaledwidth=100%] - - -[.topiclist][[Topic List]] - -[[home-benefits,home-benefits.title]] -== Benefits of the {aws} CDK - -Use the {aws} CDK to develop reliable, scalable, cost-effective applications in the cloud with the considerable expressive power of a programming language. This approach yields many benefits, including: - - - -[[home-benefits-iac]] -Develop and manage your infrastructure as code (IaC):: -Practice _infrastructure as code_ to create, deploy, and maintain infrastructure in a programmatic, descriptive, and declarative way. With IaC, you treat infrastructure the same way developers treat code. This results in a scalable and structured approach to managing infrastructure. To learn more about IaC, see https://docs.aws.amazon.com/whitepapers/latest/introduction-devops-aws/infrastructure-as-code.html[Infrastructure as code] in the __Introduction to DevOps on {aws} Whitepaper__. -+ - -With the {aws} CDK, you can put your infrastructure, application code, and configuration all in one place, ensuring that you have a complete, cloud-deployable system at every milestone. Employ software engineering best practices such as code reviews, unit tests, and source control to make your infrastructure more robust. - - -[[home-benefits-languages]] -Define your cloud infrastructure using general-purpose programming languages:: -With the {aws} CDK, you can use any of the following programming languages to define your cloud infrastructure: [.noloc]``TypeScript``, JavaScript, Python, Java, [.noloc]``C#/.Net``, and [.noloc]``Go``. Choose your preferred language and use programming elements like parameters, conditionals, loops, composition, and inheritance to define the desired outcome of your infrastructure. -+ - -Use the same programming language to define your infrastructure and your application logic. -+ - -Receive the benefits of developing infrastructure in your preferred IDE (Integrated Development Environment), such as syntax highlighting and intelligent code completion. -+ -image::images/CodeCompletion.png[Code snippet showing {aws} CDK setup for ECS cluster with VPC and Fargate service configuration.,scaledwidth=100%] - - -[[home-benefits-cfn]] -Deploy infrastructure through {aws} CloudFormation:: -{aws} CDK integrates with {aws} CloudFormation to deploy and provision your infrastructure on {aws}. {aws} CloudFormation is a managed {aws} service that offers extensive support of resource and property configurations for provisioning services on {aws}. With {aws} CloudFormation, you can perform infrastructure deployments predictably and repeatedly, with rollback on error. If you are already familiar with {aws} CloudFormation, you don`'t have to learn a new IaC management service when getting started with the {aws} CDK. - - -[[home-benefits-constructs]] -Get started developing your application quickly with constructs:: -Develop faster by using and sharing reusable components called constructs. Use low-level constructs to define individual {aws} CloudFormation resources and their properties. Use high-level constructs to quickly define larger components of your application, with sensible, secure defaults for your {aws} resources, defining more infrastructure with less code. -+ - -Create your own constructs that are customized for your unique use cases and share them across your organization or even with the public. - - -[[home-example,home-example.title]] -== Example of the {aws} CDK - -The following is an example of using the {aws} CDK Constructs Library to create an Amazon Elastic Container Service (Amazon ECS) service with {aws} Fargate launch type. For more details of this example, see xref:ecs-example[Example: Create an {aws} Fargate service using the {aws} CDK]. - - - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -export class MyEcsConstructStack extends Stack { - constructor(scope: App, id: string, props?: StackProps) { - super(scope, id, props); - - const vpc = new ec2.Vpc(this, "MyVpc", { - maxAzs: 3 // Default is all AZs in region - }); - - const cluster = new ecs.Cluster(this, "MyCluster", { - vpc: vpc - }); - - // Create a load-balanced Fargate service and make it public - new ecs_patterns.ApplicationLoadBalancedFargateService(this, "MyFargateService", { - cluster: cluster, // Required - cpu: 512, // Default is 256 - desiredCount: 6, // Default is 1 - taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample") }, - memoryLimitMiB: 2048, // Default is 512 - publicLoadBalancer: true // Default is false - }); - } -} ----- - - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -class MyEcsConstructStack extends Stack { - constructor(scope, id, props) { - super(scope, id, props); - - const vpc = new ec2.Vpc(this, "MyVpc", { - maxAzs: 3 // Default is all AZs in region - }); - - const cluster = new ecs.Cluster(this, "MyCluster", { - vpc: vpc - }); - - // Create a load-balanced Fargate service and make it public - new ecs_patterns.ApplicationLoadBalancedFargateService(this, "MyFargateService", { - cluster: cluster, // Required - cpu: 512, // Default is 256 - desiredCount: 6, // Default is 1 - taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample") }, - memoryLimitMiB: 2048, // Default is 512 - publicLoadBalancer: true // Default is false - }); - } -} - -module.exports = { MyEcsConstructStack } ----- - - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -class MyEcsConstructStack(Stack): - - def __init__(self, scope: Construct, id: str, **kwargs) -> None: - super().__init__(scope, id, **kwargs) - - vpc = ec2.Vpc(self, "MyVpc", max_azs=3) # default is all AZs in region - - cluster = ecs.Cluster(self, "MyCluster", vpc=vpc) - - ecs_patterns.ApplicationLoadBalancedFargateService(self, "MyFargateService", - cluster=cluster, # Required - cpu=512, # Default is 256 - desired_count=6, # Default is 1 - task_image_options=ecs_patterns.ApplicationLoadBalancedTaskImageOptions( - image=ecs.ContainerImage.from_registry("amazon/amazon-ecs-sample")), - memory_limit_mib=2048, # Default is 512 - public_load_balancer=True) # Default is False ----- - - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -public class MyEcsConstructStack extends Stack { - - public MyEcsConstructStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public MyEcsConstructStack(final Construct scope, final String id, - StackProps props) { - super(scope, id, props); - - Vpc vpc = Vpc.Builder.create(this, "MyVpc").maxAzs(3).build(); - - Cluster cluster = Cluster.Builder.create(this, "MyCluster") - .vpc(vpc).build(); - - ApplicationLoadBalancedFargateService.Builder.create(this, "MyFargateService") - .cluster(cluster) - .cpu(512) - .desiredCount(6) - .taskImageOptions( - ApplicationLoadBalancedTaskImageOptions.builder() - .image(ContainerImage - .fromRegistry("amazon/amazon-ecs-sample")) - .build()).memoryLimitMiB(2048) - .publicLoadBalancer(true).build(); - } -} ----- - - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -public class MyEcsConstructStack : Stack -{ - public MyEcsConstructStack(Construct scope, string id, IStackProps props=null) : base(scope, id, props) - { - var vpc = new Vpc(this, "MyVpc", new VpcProps - { - MaxAzs = 3 - }); - - var cluster = new Cluster(this, "MyCluster", new ClusterProps - { - Vpc = vpc - }); - - new ApplicationLoadBalancedFargateService(this, "MyFargateService", - new ApplicationLoadBalancedFargateServiceProps - { - Cluster = cluster, - Cpu = 512, - DesiredCount = 6, - TaskImageOptions = new ApplicationLoadBalancedTaskImageOptions - { - Image = ContainerImage.FromRegistry("amazon/amazon-ecs-sample") - }, - MemoryLimitMiB = 2048, - PublicLoadBalancer = true, - }); - } -} ----- - - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -func NewMyEcsConstructStack(scope constructs.Construct, id string, props *MyEcsConstructStackProps) awscdk.Stack { - - var sprops awscdk.StackProps - - if props != nil { - sprops = props.StackProps - } - - stack := awscdk.NewStack(scope, &id, &sprops) - - vpc := awsec2.NewVpc(stack, jsii.String("MyVpc"), &awsec2.VpcProps{ - MaxAzs: jsii.Number(3), // Default is all AZs in region - }) - - cluster := awsecs.NewCluster(stack, jsii.String("MyCluster"), &awsecs.ClusterProps{ - Vpc: vpc, - }) - - awsecspatterns.NewApplicationLoadBalancedFargateService(stack, jsii.String("MyFargateService"), - &awsecspatterns.ApplicationLoadBalancedFargateServiceProps{ - Cluster: cluster, // required - Cpu: jsii.Number(512), // default is 256 - DesiredCount: jsii.Number(5), // default is 1 - MemoryLimitMiB: jsii.Number(2048), // Default is 512 - TaskImageOptions: &awsecspatterns.ApplicationLoadBalancedTaskImageOptions{ - Image: awsecs.ContainerImage_FromRegistry(jsii.String("amazon/amazon-ecs-sample"), nil), - }, - PublicLoadBalancer: jsii.Bool(true), // Default is false - }) - - return stack - -} ----- -==== - -This class produces an {aws} CloudFormation {https---github-com-awsdocs-aws-cdk-guide-blob-main-doc-source-my-ecs-construct-stack-yaml}[template of more than 500 lines]. Deploying the {aws} CDK app produces more than 50 resources of the following types. - - - -* https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-eip.html[{aws}::EC2::EIP] -* https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-internetgateway.html[{aws}::EC2::InternetGateway] -* https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-natgateway.html[{aws}::EC2::NatGateway] -* https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-route.html[{aws}::EC2::Route] -* https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-routetable.html[{aws}::EC2::RouteTable] -* https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-security-group.html[{aws}::EC2::SecurityGroup] -* https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-subnet.html[{aws}::EC2::Subnet] -* https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-subnet-route-table-assoc.html[{aws}::EC2::SubnetRouteTableAssociation] -* https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpc-gateway-attachment.html[{aws}::EC2::VPCGatewayAttachment] -* https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpc.html[{aws}::EC2::VPC] -* https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ecs-cluster.html[{aws}::ECS::Cluster] -* https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ecs-service.html[{aws}::ECS::Service] -* https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ecs-taskdefinition.html[{aws}::ECS::TaskDefinition] -* https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticloadbalancingv2-listener.html[{aws}::ElasticLoadBalancingV2::Listener] -* https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticloadbalancingv2-loadbalancer.html[{aws}::ElasticLoadBalancingV2::LoadBalancer] -* https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticloadbalancingv2-targetgroup.html[{aws}::ElasticLoadBalancingV2::TargetGroup] -* https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-policy.html[{aws}::IAM::Policy] -* https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html[{aws}::IAM::Role] -* https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-logs-loggroup.html[{aws}::Logs::LogGroup] - - -[[home-features,home-features.title]] -== {aws} CDK features - -[[home-features-repo,home-features-repo]] -=== The {aws} CDK [.noloc]``GitHub`` repository - -For the official {aws} CDK [.noloc]``GitHub`` repository, see https://github.com/aws/aws-cdk[aws-cdk]. Here, you can submit https://github.com/aws/aws-cdk/issues[issues], view our https://github.com/aws/aws-cdk/blob/main/LICENSE[license], track https://github.com/aws/aws-cdk/releases[releases], and more. - -Because the {aws} CDK is open-source, the team encourages you to contribute to make it an even better tool. For details, see https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md[Contributing to the {aws} Cloud Development Kit ({aws} CDK)]. - -[[home-features-api,home-features-api.title]] -=== The {aws} CDK API reference - -The {aws} CDK Construct Library provides APIs to define your CDK application and add CDK constructs to the application. For more information, see the https://docs.aws.amazon.com/cdk/api/v2/docs/aws-construct-library.html[{aws} CDK API Reference]. - -[[home-features-cpm,home-features-cpm.title]] -=== The Construct Programming Model - -The Construct Programming Model (CPM) extends the concepts behind the {aws} CDK into additional domains. Other tools using the CPM include: - - - -* https://www.terraform.io/docs/cdktf/index.html[CDK for Terraform] (CDKtf) -* https://cdk8s.io/[CDK for Kubernetes] (CDK8s) -* https://github.com/projen/projen[Projen], for building project configurations - - -[[home-features-hub,home-features-hub.title]] -=== The Construct Hub - -The https://constructs.dev/[Construct Hub] is an online registry where you can find, publish, and share open-source {aws} CDK libraries. - -[[home-next,home-next.title]] -== Next steps - -To get started with using the {aws} CDK, see xref:getting-started[Getting started with the {aws} CDK]. - -[[home-learn,home-learn.title]] -== Learn more - -To continue learning about the {aws} CDK, see the following: - - - -* *xref:core-concepts[Learn {aws} CDK core concepts]* – Important concepts and terms for the {aws} CDK. -* *https://cdkworkshop.com/[{aws} CDK Workshop]* – Hands-on workshop to learn and use the {aws} CDK. -* *https://cdkpatterns.com/[{aws} CDK Patterns]* – Open-source collection of {aws} serverless architecture patterns, built for the {aws} CDK by {aws} experts. -* *https://github.com/aws-samples/aws-cdk-examples[{aws} CDK code examples]* – [.noloc]``GitHub`` repository of example {aws} CDK projects. -* *https://cdk.dev/[cdk.dev]* – Community-driven hub for the {aws} CDK, including a community [.noloc]``Slack`` workspace. -* *https://github.com/kalaiser/awesome-cdk[Awesome CDK]* – [.noloc]``GitHub`` repository containing a curated list of {aws} CDK open-source projects, guides, blogs, and other resources. -* *https://aws.amazon.com/solutions/constructs/[{aws} Solutions Constructs]* – Vetted, configuration infrastructure as code (IaC) patterns that can easily be assembled into production-ready applications. -* *https://aws.amazon.com/blogs/developer/category/developer-tools/aws-cloud-development-kit/[{aws} Developer Tools Blog]* – Blog posts filtered for the {aws} CDK. -* *https://stackoverflow.com/questions/tagged/aws-cdk[{aws} CDK on Stack Overflow]* – Questions tagged with * aws-cdk* on [.noloc]``Stack Overflow``. -* *https://docs.aws.amazon.com/cloud9/latest/user-guide/sample-cdk.html[{aws} CDK tutorial for {aws} Cloud9]* – Tutorial on using the {aws} CDK with the {aws} Cloud9 development environment. - -To learn more about related topics to the {aws} CDK, see the following: - - - -* *https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-whatis-concepts.html[{aws} CloudFormation concepts]* – Since the {aws} CDK is built to work with {aws} CloudFormation, we recommend that you learn and understand key {aws} CloudFormation concepts. -* *https://docs.aws.amazon.com/general/latest/gr/glos-chap.html[{aws} Glossary]* – Definitions of key terms used across {aws}. - -To learn more about tools related to the {aws} CDK that can be used to simplify serverless application development and deployment, see the following: - - - -* *https://aws.amazon.com/serverless/sam/[{aws} Serverless Application Model]* – An open-source developer tool that simplifies and improves the experience of building and running serverless applications on {aws}. -* *https://github.com/aws/chalice[{aws} Chalice]* – A framework for writing serverless apps in Python. diff --git a/v2/guide/how-tos/ecs_example.adoc b/v2/guide/how-tos/ecs_example.adoc deleted file mode 100644 index f08abda5..00000000 --- a/v2/guide/how-tos/ecs_example.adoc +++ /dev/null @@ -1,333 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[#ecs-example] -= Example: Create an {aws} Fargate service using the {aws} CDK -:info_titleabbrev: Example: Create a Fargate service - -[abstract] --- -Learn how to create an {aws} Fargate service. --- - -// Content start - -In this example, we show you how to create an {aws} Fargate service running on an Amazon Elastic Container Service (Amazon ECS) cluster that's fronted by an internet-facing Application Load Balancer from an image on Amazon ECR. - -Amazon ECS is a highly scalable, fast, container management service that makes it easy to run, stop, and manage Docker containers on a cluster. You can host your cluster on serverless infrastructure that's managed by Amazon ECS by launching your services or tasks using the Fargate launch type. For more control, you can host your tasks on a cluster of Amazon Elastic Compute Cloud (Amazon EC2) instances that you manage by using the Amazon EC2 launch type. - -In this example, we launch some services using the Fargate launch type. If you've used the {aws} Management Console to create a Fargate service, you know that there are many steps to follow to accomplish that task. {aws} has several tutorials and documentation topics that walk you through creating a Fargate service, including: - -* link:https://aws.amazon.com/getting-started/tutorials/deploy-docker-containers[How to Deploy Docker Containers - {aws}] -* link:https://docs.aws.amazon.com/AmazonECS/latest/developerguide/get-set-up-for-amazon-ecs.html[Setting Up with Amazon ECS] -* link:https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ECS_GetStarted.html[Getting Started with Amazon ECS Using Fargate] - -This example creates a similar Fargate service using the {aws} CDK. - -The Amazon ECS construct used in this example helps you use {aws} services by providing the following benefits: - -* Automatically configures a load balancer. -* Automatically opens a security group for load balancers. This enables load balancers to communicate with instances without having to explicitly create a security group. -* Automatically orders dependency between the service and the load balancer attaching to a target group, where the {aws} CDK enforces the correct order of creating the listener before an instance is created. -* Automatically configures user data on automatically scaling groups. This creates the correct configuration to associate a cluster to AMIs. -* Validates parameter combinations early. This exposes {aws} CloudFormation issues earlier, thus saving deployment time. For example, depending on the task, it's easy to improperly configure the memory settings. Previously, we would not encounter an error until we deployed our app. But now the {aws} CDK can detect a misconfiguration and emit an error when we synthesize our app. -* Automatically adds permissions for Amazon Elastic Container Registry (Amazon ECR) if we use an image from Amazon ECR. -* Automatically scales. The {aws} CDK supplies a method so we can auto scale instances when we use an Amazon EC2 cluster. This happens automatically when we use an instance in a Fargate cluster. -+ -In addition, the {aws} CDK prevents an instance from being deleted when automatic scaling tries to stop an instance, but either a task is running or is scheduled on that instance. -+ -Previously, we had to create a Lambda function to have this functionality. -* Provides asset support, so that we can deploy a source from our machine to Amazon ECS in one step. Previously, to use an application source, we had to perform several manual steps, such as uploading to Amazon ECR and creating a Docker image. - -[IMPORTANT] -==== - -The `ApplicationLoadBalancedFargateService` constructs we'll be using includes numerous {aws} components, some of which have non-trivial costs if left provisioned in our {aws} account, even if we don't use them. Be sure to clean up (`cdk destroy`) if you follow along with this example. - -==== - -[#ecs-example-initialize] -== Create a CDK project - -We start by creating a CDK project. This is a directory that stores our {aws} CDK code, including our CDK app. - -==== -[role="tablist"] -TypeScript:: -+ -[source,none,subs="verbatim,attributes"] ----- -mkdir MyEcsConstruct -cd MyEcsConstruct -cdk init --language typescript ----- - -JavaScript:: -+ -[source,none,subs="verbatim,attributes"] ----- -mkdir MyEcsConstruct -cd MyEcsConstruct -cdk init --language javascript ----- - -Python:: -+ -[source,none,subs="verbatim,attributes"] ----- -mkdir MyEcsConstruct -cd MyEcsConstruct -cdk init --language python -source .venv/bin/activate # On Windows, run '.\venv\Scripts\activate' instead -pip install -r requirements.txt ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -mkdir MyEcsConstruct -cd MyEcsConstruct -cdk init --language java ----- -+ -We may now import the Maven project into our IDE. - -C#:: -+ -[source,none,subs="verbatim,attributes"] ----- -mkdir MyEcsConstruct -cd MyEcsConstruct -cdk init --language csharp ----- -+ -We may now open `src/MyEcsConstruct.sln` in Visual Studio. -==== - -Next, we run the app and confirm that it creates an empty stack. - -[source,none,subs="verbatim,attributes"] ----- -cdk synth ----- - -[#ecs-example-create-fargate-service] -== Create a Fargate service - -There are two different ways that we can run our container tasks with Amazon ECS: - -* Use the `Fargate` launch type, where Amazon ECS manages the physical machines that oour containers are running on for us. -* Use the `EC2` launch type, where we do the managing, such as specifying automatic scaling. - -For this example, we'll create a Fargate service running on an Amazon ECS cluster, fronted by an internet-facing Application Load Balancer. - -We add the following {aws} Construct Library module imports to our _stack file_: - -==== -[role="tablist"] -TypeScript:: -File: `lib/my_ecs_construct-stack.ts` -+ -[source,javascript,subs="verbatim,attributes"] ----- -import * as ec2 from "aws-cdk-lib/aws-ec2"; -import * as ecs from "aws-cdk-lib/aws-ecs"; -import * as ecs_patterns from "aws-cdk-lib/aws-ecs-patterns"; ----- - -JavaScript:: -File: `lib/my_ecs_construct-stack.js` -+ -[source,javascript,subs="verbatim,attributes"] ----- -const ec2 = require("aws-cdk-lib/aws-ec2"); -const ecs = require("aws-cdk-lib/aws-ecs"); -const ecs_patterns = require("aws-cdk-lib/aws-ecs-patterns"); ----- - -Python:: -File: `my_ecs_construct/my_ecs_construct_stack.py` -+ -[source,python,subs="verbatim,attributes"] ----- -from aws_cdk import (aws_ec2 as ec2, aws_ecs as ecs, - aws_ecs_patterns as ecs_patterns) ----- - -Java:: -File: `src/main/java/com/myorg/MyEcsConstructStack.java` -+ -[source,java,subs="verbatim,attributes"] ----- -import software.amazon.awscdk.services.ec2.*; -import software.amazon.awscdk.services.ecs.*; -import software.amazon.awscdk.services.ecs.patterns.*; ----- - -C#:: -File: `src/MyEcsConstruct/MyEcsConstructStack.cs` -+ -[source,csharp,subs="verbatim,attributes"] ----- -using Amazon.CDK.{aws}.EC2; -using Amazon.CDK.{aws}.ECS; -using Amazon.CDK.{aws}.ECS.Patterns; ----- -==== - -Within our stack, we add the following code: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- - const vpc = new ec2.Vpc(this, "MyVpc", { - maxAzs: 3 // Default is all AZs in region - }); - - const cluster = new ecs.Cluster(this, "MyCluster", { - vpc: vpc - }); - - // Create a load-balanced Fargate service and make it public - new ecs_patterns.ApplicationLoadBalancedFargateService(this, "MyFargateService", { - cluster: cluster, // Required - cpu: 512, // Default is 256 - desiredCount: 6, // Default is 1 - taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample") }, - memoryLimitMiB: 2048, // Default is 512 - publicLoadBalancer: true // Default is true - }); ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- - const vpc = new ec2.Vpc(this, "MyVpc", { - maxAzs: 3 // Default is all AZs in region - }); - - const cluster = new ecs.Cluster(this, "MyCluster", { - vpc: vpc - }); - - // Create a load-balanced Fargate service and make it public - new ecs_patterns.ApplicationLoadBalancedFargateService(this, "MyFargateService", { - cluster: cluster, // Required - cpu: 512, // Default is 256 - desiredCount: 6, // Default is 1 - taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample") }, - memoryLimitMiB: 2048, // Default is 512 - publicLoadBalancer: true // Default is true - }); ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- - vpc = ec2.Vpc(self, "MyVpc", max_azs=3) # default is all AZs in region - - cluster = ecs.Cluster(self, "MyCluster", vpc=vpc) - - ecs_patterns.ApplicationLoadBalancedFargateService(self, "MyFargateService", - cluster=cluster, # Required - cpu=512, # Default is 256 - desired_count=6, # Default is 1 - task_image_options=ecs_patterns.ApplicationLoadBalancedTaskImageOptions( - image=ecs.ContainerImage.from_registry("amazon/amazon-ecs-sample")), - memory_limit_mib=2048, # Default is 512 - public_load_balancer=True) # Default is True ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- - Vpc vpc = Vpc.Builder.create(this, "MyVpc") - .maxAzs(3) // Default is all AZs in region - .build(); - - Cluster cluster = Cluster.Builder.create(this, "MyCluster") - .vpc(vpc).build(); - - // Create a load-balanced Fargate service and make it public - ApplicationLoadBalancedFargateService.Builder.create(this, "MyFargateService") - .cluster(cluster) // Required - .cpu(512) // Default is 256 - .desiredCount(6) // Default is 1 - .taskImageOptions( - ApplicationLoadBalancedTaskImageOptions.builder() - .image(ContainerImage.fromRegistry("amazon/amazon-ecs-sample")) - .build()) - .memoryLimitMiB(2048) // Default is 512 - .publicLoadBalancer(true) // Default is true - .build(); ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- - var vpc = new Vpc(this, "MyVpc", new VpcProps - { - MaxAzs = 3 // Default is all AZs in region - }); - - var cluster = new Cluster(this, "MyCluster", new ClusterProps - { - Vpc = vpc - }); - - // Create a load-balanced Fargate service and make it public - new ApplicationLoadBalancedFargateService(this, "MyFargateService", - new ApplicationLoadBalancedFargateServiceProps - { - Cluster = cluster, // Required - DesiredCount = 6, // Default is 1 - TaskImageOptions = new ApplicationLoadBalancedTaskImageOptions - { - Image = ContainerImage.FromRegistry("amazon/amazon-ecs-sample") - }, - MemoryLimitMiB = 2048, // Default is 256 - PublicLoadBalancer = true // Default is true - } - ); ----- -==== - -Next, we validate our code by running the following to synthesize our stack: - -[source,none,subs="verbatim,attributes"] ----- -cdk synth ----- - -The stack is hundreds of lines, so we won't show it here. The stack should contain one default instance, a private subnet and a public subnet for the three Availability Zones, and a security group. - -To deploy the stack, we run the following: - -[source,none,subs="verbatim,attributes"] ----- -cdk deploy ----- - -{aws} CloudFormation displays information about the dozens of steps that it takes as it deploys our app. - -Once deployment completes, we have successfully created a Fargate powered Amazon ECS service to run a Docker image. - -[#ecs-example-destroy] -== Clean up - -As a general maintenance best practice, and to minimize unnecessary costs, we delete our stack when complete: - -[source,none,subs="verbatim,attributes"] ----- -cdk destroy ----- \ No newline at end of file diff --git a/v2/guide/how-tos/how-tos.adoc b/v2/guide/how-tos/how-tos.adoc deleted file mode 100644 index 2be04cf8..00000000 --- a/v2/guide/how-tos/how-tos.adoc +++ /dev/null @@ -1,37 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[#how-tos] -= {aws} CDK tutorials and examples -:info_titleabbrev: Tutorials and examples -:keywords: {aws} CDK, {aws} Cloud Development Kit ({aws} CDK), IaC, Infrastructure as Code, serverless, serverless application, Lambda, API Gateway - -[abstract] --- -This section contains tutorials and examples for the {aws} Cloud Development Kit ({aws} CDK). --- - -// Content start - -This section contains tutorials and examples for the {aws} Cloud Development Kit ({aws} CDK). - -[#tutorials] -*Tutorials*:: -Tutorials provide you with step-by-step instructions that you can follow to implement a task using the {aws} CDK. - -[#examples] -*Examples*:: -Examples show and explain how specific tasks can be implemented using the {aws} CDK. They do not provide direct step-by-step instructions for you to follow. -+ -For more examples of {aws} CDK stacks and apps in your favorite supported programming language, see the https://github.com/aws-samples/aws-cdk-examples[{aws} CDK Examples] repository on GitHub. - - -include::serverless_example.adoc[leveloffset=+1] - - -include::create-multiple-stacks.adoc[leveloffset=+1] - - -include::ecs_example.adoc[leveloffset=+1] diff --git a/v2/guide/how-tos/images/serverless-example-01.png b/v2/guide/how-tos/images/serverless-example-01.png deleted file mode 100644 index 07758545..00000000 Binary files a/v2/guide/how-tos/images/serverless-example-01.png and /dev/null differ diff --git a/v2/guide/how-tos/serverless_example.adoc b/v2/guide/how-tos/serverless_example.adoc deleted file mode 100644 index b61ac5bd..00000000 --- a/v2/guide/how-tos/serverless_example.adoc +++ /dev/null @@ -1,1599 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -:https---docs-aws-amazon-com-cdk-api-v2-docs-aws-cdk-lib-aws-apigateway-readme-html: https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_apigateway-readme.html -:https---docs-aws-amazon-com-cdk-api-v2-docs-aws-cdk-lib-aws-lambda-readme-html: https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda-readme.html - -[.topic] -[#serverless-example] -= Tutorial: Create a serverless Hello World application -:info_titleabbrev: Tutorial: Serverless Hello World application -:info_abstract: In this tutorial, you use the {aws} CDK to create a simple serverless Hello World application that implements a basic API backend. - -[abstract] --- -In this tutorial, you use the {aws} CDK to create a simple serverless [.noloc]``Hello World`` application that implements a basic API backend. --- - -// Content start - -In this tutorial, you use the {aws} Cloud Development Kit ({aws} CDK) to create a simple serverless `Hello World` application that implements a basic API backend consisting of the following: - -* *Amazon API Gateway REST API* – Provides an HTTP endpoint that is used to invoke your function through an HTTP GET request. -* *{aws} Lambda function* – Function that returns a `Hello World!` message when invoked with the HTTP endpoint. -* *Integrations and permissions* – Configuration details and permissions for your resources to interact with one another and perform actions, such as writing logs to Amazon CloudWatch. - -The following diagram shows the components of this application: - -image::images/serverless-example-01.png[Diagram of a Lambda function that is invoked when you send a GET request to the API Gateway endpoint.,scaledwidth=100%] - -For this tutorial, you will create and interact with your application in the following steps: - -. Create an {aws} CDK project. -. Define a Lambda function and API Gateway REST API using L2 constructs from the {aws} Construct Library. -. Deploy your application to the {aws} Cloud. -. Interact with your application in the {aws} Cloud. -. Delete the sample application from the {aws} Cloud. - -[#serverless-example-pre] -== Prerequisites - -Before starting this tutorial, complete the following: - -* Create an {aws} account and have the {aws} Command Line Interface ({aws} CLI) installed and configured. -* Install Node.js and `npm`. -* Install the CDK Toolkit globally, using `npm install -g aws-cdk`. - -For more information, see xref:getting-started[Getting started with the {aws} CDK]. - -We also recommend a basic understanding of the following: - -* xref:home[What is the {aws} CDK?] for a basic introduction to the {aws} CDK. -* xref:core-concepts[Learn {aws} CDK core concepts] for an overview of core concepts of the {aws} CDK. - -[#serverless-example-project] -== Step 1: Create a CDK project - -In this step, you create a new CDK project using the {aws} CDK CLI `cdk init` command. - -*To create a CDK project*:: -+ -. From a starting directory of your choice, create and navigate to a project directory named `cdk-hello-world` on your machine: -+ -[source,none,subs="verbatim,attributes"] ----- -$ mkdir cdk-hello-world && cd cdk-hello-world ----- -+ -. Use the `cdk init` command to create a new project in your preferred programming language: -+ -==== -[role="tablist"] -TypeScript::: -+ -[source,none,subs="verbatim,attributes"] ----- -$ cdk init --language typescript ----- -+ -Install {aws} CDK libraries: -+ -[source,none,subs="verbatim,attributes"] ----- -$ npm install aws-cdk-lib constructs ----- - -JavaScript::: -+ -[source,none,subs="verbatim,attributes"] ----- -$ cdk init --language javascript ----- -+ -Install {aws} CDK libraries: -+ -[source,none,subs="verbatim,attributes"] ----- -$ npm install aws-cdk-lib constructs ----- - -Python::: -+ -[source,none,subs="verbatim,attributes"] ----- -$ cdk init --language python ----- -+ -Activate the virtual environment: -+ -[source,none,subs="verbatim,attributes"] ----- -$ source .venv/bin/activate # On Windows, run '.\venv\Scripts\activate' instead ----- -+ -Install {aws} CDK libraries and project dependencies: -+ -[source,none,subs="verbatim,attributes"] ----- -(.venv)$ python3 -m pip install -r requirements.txt ----- - -Java::: -+ -[source,none,subs="verbatim,attributes"] ----- -$ cdk init --language java ----- -+ -Install {aws} CDK libraries and project dependencies: -+ -[source,none,subs="verbatim,attributes"] ----- -$ mvn package ----- - -C#::: -+ -[source,none,subs="verbatim,attributes"] ----- -$ cdk init --language csharp ----- -+ -Install {aws} CDK libraries and project dependencies: -+ -[source,none,subs="verbatim,attributes"] ----- -$ dotnet restore src ----- - -Go::: -+ -[source,none,subs="verbatim,attributes"] ----- -$ cdk init --language go ----- -+ -Install project dependencies: -+ -[source,none,subs="verbatim,attributes"] ----- -$ go get github.com/aws/aws-cdk-go/awscdk/v2 -$ go get github.com/aws/aws-cdk-go/awscdk/v2/awslambda -$ go get github.com/aws/aws-cdk-go/awscdk/v2/awsapigateway -$ go mod tidy ----- -==== -+ - -The CDK CLI creates a project with the following structure: -+ -==== -[role="tablist"] -TypeScript::: -+ -[source,none,subs="verbatim,attributes"] ----- -cdk-hello-world -├── .git -├── .gitignore -├── .npmignore -├── README.md -├── bin -│ └── cdk-hello-world.ts -├── cdk.json -├── jest.config.js -├── lib -│ └── cdk-hello-world-stack.ts -├── node_modules -├── package-lock.json -├── package.json -├── test -│ └── cdk-hello-world.test.ts -└── tsconfig.json ----- - -JavaScript::: -+ -[source,none,subs="verbatim,attributes"] ----- -cdk-hello-world -├── .git -├── .gitignore -├── .npmignore -├── README.md -├── bin -│ └── cdk-hello-world.js -├── cdk.json -├── jest.config.js -├── lib -│ └── cdk-hello-world-stack.js -├── node_modules -├── package-lock.json -├── package.json -└── test - └── cdk-hello-world.test.js ----- - -Python::: -+ -[source,none,subs="verbatim,attributes"] ----- -cdk-hello-world -├── .git -├── .gitignore -├── .venv -├── README.md -├── app.py -├── cdk.json -├── cdk_hello_world -│ ├── __init__.py -│ └── cdk_hello_world_stack.py -├── requirements-dev.txt -├── requirements.txt -├── source.bat -└── tests ----- - -Java::: -+ -[source,none,subs="verbatim,attributes"] ----- -cdk-hello-world -├── .git -├── .gitignore -├── README.md -├── cdk.json -├── pom.xml -├── src -│ ├── main -│ │ └── java -│ │ └── com -│ │ └── myorg -│ │ ├── CdkHelloWorldApp.java -│ │ └── CdkHelloWorldStack.java -└── target ----- - -C#::: -+ -[source,none,subs="verbatim,attributes"] ----- -cdk-hello-world -├── .git -├── .gitignore -├── README.md -├── cdk.json -└── src - ├── CdkHelloWorld - │ ├── CdkHelloWorld.csproj - │ ├── CdkHelloWorldStack.cs - │ ├── GlobalSuppressions.cs - │ └── Program.cs - └── CdkHelloWorld.sln ----- - -Go::: -+ -[source,none,subs="verbatim,attributes"] ----- -cdk-hello-world -├── .git -├── .gitignore -├── README.md -├── cdk-hello-world.go -├── cdk-hello-world_test.go -├── cdk.json -├── go.mod -└── go.sum ----- -==== - -The CDK CLI automatically creates a CDK app that contains a single stack. The CDK app instance is created from the `link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.App.html[App]` class. The following is a portion of your CDK application file: - -==== -[role="tablist"] -TypeScript:: -Located in `bin/cdk-hello-world.ts`: -+ -[source,javascript,subs="verbatim,attributes"] ----- -#!/usr/bin/env node -import 'source-map-support/register'; -import * as cdk from 'aws-cdk-lib'; -import { CdkHelloWorldStack } from '../lib/cdk-hello-world-stack'; - -const app = new cdk.App(); -new CdkHelloWorldStack(app, 'CdkHelloWorldStack', { -}); ----- - -JavaScript:: -Located in `bin/cdk-hello-world.js`: -+ -[source,javascript,subs="verbatim,attributes"] ----- -#!/usr/bin/env node -const cdk = require('aws-cdk-lib'); -const { CdkHelloWorldStack } = require('../lib/cdk-hello-world-stack'); -const app = new cdk.App(); -new CdkHelloWorldStack(app, 'CdkHelloWorldStack', { -}); ----- - -Python:: -Located in `app.py`: -+ -[source,python,subs="verbatim,attributes"] ----- -#!/usr/bin/env python3 -import os -import aws_cdk as cdk -from cdk_hello_world.cdk_hello_world_stack import CdkHelloWorldStack - -app = cdk.App() -CdkHelloWorldStack(app, "CdkHelloWorldStack",) -app.synth() ----- - -Java:: -Located in `src/main/java/.../CdkHelloWorldApp.java`: -+ -[source,java,subs="verbatim,attributes"] ----- -package com.myorg; - -import software.amazon.awscdk.App; -import software.amazon.awscdk.Environment; -import software.amazon.awscdk.StackProps; - -import java.util.Arrays; - -public class JavaApp { - public static void main(final String[] args) { - App app = new App(); - - new JavaStack(app, "JavaStack", StackProps.builder() - .build()); - - app.synth(); - } -} ----- - -C#:: -Located in `src/CdkHelloWorld/Program.cs`: -+ -[source,csharp,subs="verbatim,attributes"] ----- -using Amazon.CDK; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace CdkHelloWorld -{ - sealed class Program - { - public static void Main(string[] args) - { - var app = new App(); - new CdkHelloWorldStack(app, "CdkHelloWorldStack", new StackProps - { - - }); - app.Synth(); - } - } -} ----- - -Go:: -Located in `cdk-hello-world.go`: -+ -[source,go,subs="verbatim,attributes"] ----- -package main -import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/constructs-go/constructs/v10" - "github.com/aws/jsii-runtime-go" -) - -// ... - -func main() { - defer jsii.Close() - app := awscdk.NewApp(nil) - NewCdkHelloWorldStack(app, "CdkHelloWorldStack", &CdkHelloWorldStackProps{ - awscdk.StackProps{ - Env: env(), - }, - }) - app.Synth(nil) -} - -func env() *awscdk.Environment { - return nil -} ----- -==== - -[#serverless-example-function] -== Step 2: Create your Lambda function - -Within your CDK project, create a `lambda` directory that includes a new `hello.js` file. The following is an example: - -==== -[role="tablist"] -TypeScript:: -From the root of your project, run the following: -+ -[source,none,subs="verbatim,attributes"] ----- -$ mkdir lambda && cd lambda -$ touch hello.js ----- -+ -The following should now be added to your CDK project: -+ -[source,none,subs="verbatim,attributes"] ----- -cdk-hello-world -└── lambda - └── hello.js ----- - -JavaScript:: -From the root of your project, run the following: -+ -[source,none,subs="verbatim,attributes"] ----- -$ mkdir lambda && cd lambda -$ touch hello.js ----- -+ -The following should now be added to your CDK project: -+ -[source,none,subs="verbatim,attributes"] ----- -cdk-hello-world -└── lambda - └── hello.js ----- - -Python:: -From the root of your project, run the following: -+ -[source,none,subs="verbatim,attributes"] ----- -$ mkdir lambda && cd lambda -$ touch hello.js ----- -+ -The following should now be added to your CDK project: -+ -[source,none,subs="verbatim,attributes"] ----- -cdk-hello-world -└── lambda - └── hello.js ----- - -Java:: -From the root of your project, run the following: -+ -[source,none,subs="verbatim,attributes"] ----- -$ mkdir -p src/main/resources/lambda -$ cd src/main/resources/lambda -$ touch hello.js ----- -+ -The following should now be added to your CDK project: -+ -[source,none,subs="verbatim,attributes"] ----- -cdk-hello-world -└── src - └── main - └──resources - └──lambda - └──hello.js ----- - -C#:: -From the root of your project, run the following: -+ -[source,none,subs="verbatim,attributes"] ----- -$ mkdir lambda && cd lambda -$ touch hello.js ----- -+ -The following should now be added to your CDK project: -+ -[source,none,subs="verbatim,attributes"] ----- -cdk-hello-world -└── lambda - └── hello.js ----- - -Go:: -From the root of your project, run the following: -+ -[source,none,subs="verbatim,attributes"] ----- -$ mkdir lambda && cd lambda -$ touch hello.js ----- -+ -The following should now be added to your CDK project: -+ -[source,none,subs="verbatim,attributes"] ----- -cdk-hello-world -└── lambda - └── hello.js ----- -==== - -[NOTE] -==== - -To keep this tutorial simple, we use a JavaScript Lambda function for all CDK programming languages. - -==== - -Define your Lambda function by adding the following to the newly created file: - -[source,javascript,subs="verbatim,attributes"] ----- -exports.handler = async (event) => { - return { - statusCode: 200, - headers: { "Content-Type": "text/plain" }, - body: JSON.stringify({ message: "Hello, World!" }), - }; -}; ----- - -[#serverless-example-constructs] -== Step 3: Define your constructs - -In this step, you will define your Lambda and API Gateway resources using {aws} CDK L2 constructs. - -Open the project file that defines your CDK stack. You will modify this file to define your constructs. The following is an example of your starting stack file: - -==== -[role="tablist"] -TypeScript:: -Located in `lib/cdk-hello-world-stack.ts`: -+ -[source,javascript,subs="verbatim,attributes"] ----- -import * as cdk from 'aws-cdk-lib'; -import { Construct } from 'constructs'; - -export class CdkHelloWorldStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - // Your constructs will go here - - } -} ----- - -JavaScript:: -Located in `lib/cdk-hello-world-stack.js`: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const { Stack, Duration } = require('aws-cdk-lib'); -const lambda = require('aws-cdk-lib/aws-lambda'); -const apigateway = require('aws-cdk-lib/aws-apigateway'); - -class CdkHelloWorldStack extends Stack { - - constructor(scope, id, props) { - super(scope, id, props); - - // Your constructs will go here - - } -} - -module.exports = { CdkHelloWorldStack } ----- - -Python:: -Located in `cdk_hello_world/cdk_hello_world_stack.py`: -+ -[source,python,subs="verbatim,attributes"] ----- -from aws_cdk import Stack -from constructs import Construct - -class CdkHelloWorldStack(Stack): - def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: - super().__init__(scope, construct_id, **kwargs) - - // Your constructs will go here ----- - -Java:: -Located in `src/main/java/.../CdkHelloWorldStack.java`: -+ -[source,java,subs="verbatim,attributes"] ----- -package com.myorg; - -import software.constructs.Construct; -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.StackProps; - -public class CdkHelloWorldStack extends Stack { - public CdkHelloWorldStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public CdkHelloWorldStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - // Your constructs will go here - } -} ----- - -C#:: -Located in `src/CdkHelloWorld/CdkHelloWorldStack.cs`: -+ -[source,csharp,subs="verbatim,attributes"] ----- -using Amazon.CDK; -using Constructs; - -namespace CdkHelloWorld -{ - public class CdkHelloWorldStack : Stack - { - internal CdkHelloWorldStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) - { - // Your constructs will go here - } - } -} ----- - -Go:: -Located at `cdk-hello-world.go`: -+ -[source,go,subs="verbatim,attributes"] ----- -package main - -import ( - "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/constructs-go/constructs/v10" - "github.com/aws/jsii-runtime-go" -) - -type CdkHelloWorldStackProps struct { - awscdk.StackProps -} - -func NewCdkHelloWorldStack(scope constructs.Construct, id string, props *CdkHelloWorldStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - stack := awscdk.NewStack(scope, &id, &sprops) - - // Your constructs will go here - - return stack -} - -func main() { - - // ... - -} - -func env() *awscdk.Environment { - - return nil - -} ----- -==== - -In this file, the {aws} CDK is doing the following: - -* Your CDK stack instance is instantiated from the `link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html[Stack]` class. -* The `link:https://docs.aws.amazon.com/cdk/api/v2/docs/constructs-readme.html[Constructs]` base class is imported and provided as the scope or parent of your stack instance. - -[#serverless-example-constructs-lambda] -=== Define your Lambda function resource - -To define your Lambda function resource, you import and use the `link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda-readme.html[aws-lambda]` L2 construct from the {aws} Construct Library. - -Modify your stack file as follows: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -import * as cdk from 'aws-cdk-lib'; -import { Construct } from 'constructs'; -// Import Lambda L2 construct -import * as lambda from 'aws-cdk-lib/aws-lambda'; - -export class CdkHelloWorldStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - // Define the Lambda function resource - const helloWorldFunction = new lambda.Function(this, 'HelloWorldFunction', { - runtime: lambda.Runtime.NODEJS_20_X, // Choose any supported Node.js runtime - code: lambda.Code.fromAsset('lambda'), // Points to the lambda directory - handler: 'hello.handler', // Points to the 'hello' file in the lambda directory - }); - } -} ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const { Stack, Duration } = require('aws-cdk-lib'); -// Import Lambda L2 construct -const lambda = require('aws-cdk-lib/aws-lambda'); - - -class CdkHelloWorldStack extends Stack { - constructor(scope, id, props) { - super(scope, id, props); - - // Define the Lambda function resource - const helloWorldFunction = new lambda.Function(this, 'HelloWorldFunction', { - runtime: lambda.Runtime.NODEJS_20_X, // Choose any supported Node.js runtime - code: lambda.Code.fromAsset('lambda'), // Points to the lambda directory - handler: 'hello.handler', // Points to the 'hello' file in the lambda directory - }); - } -} - -module.exports = { CdkHelloWorldStack } ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -from aws_cdk import ( - Stack, - # Import Lambda L2 construct - aws_lambda as _lambda, -) -# ... - -class CdkHelloWorldStack(Stack): - - def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: - super().__init__(scope, construct_id, **kwargs) - - # Define the Lambda function resource - hello_world_function = _lambda.Function( - self, - "HelloWorldFunction", - runtime = _lambda.Runtime.NODEJS_20_X, # Choose any supported Node.js runtime - code = _lambda.Code.from_asset("lambda"), # Points to the lambda directory - handler = "hello.handler", # Points to the 'hello' file in the lambda directory - ) ----- -+ -NOTE: We import the `aws_lambda` module as `\_lambda` because `lambda` is a build-in identifier in Python. - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -// ... -// Import Lambda L2 construct -import software.amazon.awscdk.services.lambda.Code; -import software.amazon.awscdk.services.lambda.Function; -import software.amazon.awscdk.services.lambda.Runtime; - -public class CdkHelloWorldStack extends Stack { - public CdkHelloWorldStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public CdkHelloWorldStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - // Define the Lambda function resource - Function helloWorldFunction = Function.Builder.create(this, "HelloWorldFunction") - .runtime(Runtime.NODEJS_20_X) // Choose any supported Node.js runtime - .code(Code.fromAsset("src/main/resources/lambda")) // Points to the lambda directory - .handler("hello.handler") // Points to the 'hello' file in the lambda directory - .build(); - } -} ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -// ... -// Import Lambda L2 construct -using Amazon.CDK.{aws}.Lambda; - -namespace CdkHelloWorld -{ - public class CdkHelloWorldStack : Stack - { - internal CdkHelloWorldStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) - { - // Define the Lambda function resource - var helloWorldFunction = new Function(this, "HelloWorldFunction", new FunctionProps - { - Runtime = Runtime.NODEJS_20_X, // Choose any supported Node.js runtime - Code = Code.FromAsset("lambda"), // Points to the lambda directory - Handler = "hello.handler" // Points to the 'hello' file in the lambda directory - }); - } - } -} ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -package main - -import ( - // ... - // Import Lambda L2 construct - "github.com/aws/aws-cdk-go/awscdk/v2/awslambda" - // Import S3 assets construct - "github.com/aws/aws-cdk-go/awscdk/v2/awss3assets" - // ... -) - -// ... - -func NewCdkHelloWorldStack(scope constructs.Construct, id string, props *CdkHelloWorldStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - stack := awscdk.NewStack(scope, &id, &sprops) - - // Define the Lambda function resource - helloWorldFunction := awslambda.NewFunction(stack, jsii.String("HelloWorldFunction"), &awslambda.FunctionProps{ - Runtime: awslambda.Runtime_NODEJS_20_X(), // Choose any supported Node.js runtime - Code: awslambda.Code_FromAsset(jsii.String("lambda"), &awss3assets.AssetOptions{}), // Points to the lambda directory - Handler: jsii.String("hello.handler"), // Points to the 'hello' file in the lambda directory - }) - - return stack -} - -// ... ----- -==== - -Here, you create a Lambda function resource and define the following properties: - -* `runtime` – The environment the function runs in. Here, we use Node.js version 20.x. -* `code` – The path to the function code on your local machine. -* `handler` – The name of the specific file that contains your function code. - -[#serverless-example-constructs-api] -=== Define your API Gateway REST API resource - -To define your API Gateway [.noloc]``REST API`` resource, you import and use the `link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_apigateway-readme.html[aws-apigateway]` L2 construct from the {aws} Construct Library. - -Modify your stack file as follows: - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -// ... -//Import API Gateway L2 construct -import * as apigateway from 'aws-cdk-lib/aws-apigateway'; - - -export class CdkHelloWorldStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - // ... - - // Define the API Gateway resource - const api = new apigateway.LambdaRestApi(this, 'HelloWorldApi', { - handler: helloWorldFunction, - proxy: false, - }); - - // Define the '/hello' resource with a GET method - const helloResource = api.root.addResource('hello'); - helloResource.addMethod('GET'); - } -} ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -// ... -// Import API Gateway L2 construct -const apigateway = require('aws-cdk-lib/aws-apigateway'); - - -class CdkHelloWorldStack extends Stack { - constructor(scope, id, props) { - super(scope, id, props); - - // ... - - // Define the API Gateway resource - const api = new apigateway.LambdaRestApi(this, 'HelloWorldApi', { - handler: helloWorldFunction, - proxy: false, - }); - - // Define the '/hello' resource with a GET method - const helloResource = api.root.addResource('hello'); - helloResource.addMethod('GET'); - }; -}; - -// ... ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -from aws_cdk import ( - # ... - # Import API Gateway L2 construct - aws_apigateway as apigateway, -) -from constructs import Construct - -class CdkHelloWorldStack(Stack): - - def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: - super().__init__(scope, construct_id, **kwargs) - - # ... - - # Define the API Gateway resource - api = apigateway.LambdaRestApi( - self, - "HelloWorldApi", - handler = hello_world_function, - proxy = False, - ) - - # Define the '/hello' resource with a GET method - hello_resource = api.root.add_resource("hello") - hello_resource.add_method("GET") ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -// ... -// Import API Gateway L2 construct -import software.amazon.awscdk.services.apigateway.LambdaRestApi; -import software.amazon.awscdk.services.apigateway.Resource; - -public class CdkHelloWorldStack extends Stack { - public CdkHelloWorldStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public CdkHelloWorldStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - // ... - - // Define the API Gateway resource - LambdaRestApi api = LambdaRestApi.Builder.create(this, "HelloWorldApi") - .handler(helloWorldFunction) - .proxy(false) // Turn off default proxy integration - .build(); - - // Define the '/hello' resource and its GET method - Resource helloResource = api.getRoot().addResource("hello"); - helloResource.addMethod("GET"); - } -} ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -// ... -// Import API Gateway L2 construct -using Amazon.CDK.{aws}.APIGateway; - -namespace CdkHelloWorld -{ - public class CdkHelloWorldStack : Stack - { - internal CdkHelloWorldStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) - { - // ... - - // Define the API Gateway resource - var api = new LambdaRestApi(this, "HelloWorldApi", new LambdaRestApiProps - { - Handler = helloWorldFunction, - Proxy = false - }); - - // Add a '/hello' resource with a GET method - var helloResource = api.Root.AddResource("hello"); - helloResource.AddMethod("GET"); - } - } -} ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -// ... - -import ( - // ... - // Import Api Gateway L2 construct - "github.com/aws/aws-cdk-go/awscdk/v2/awsapigateway" - // ... -) - -// ... - -func NewCdkHelloWorldStack(scope constructs.Construct, id string, props *CdkHelloWorldStackProps) awscdk.Stack { - var sprops awscdk.StackProps - if props != nil { - sprops = props.StackProps - } - stack := awscdk.NewStack(scope, &id, &sprops) - - // Define the Lambda function resource - // ... - - // Define the API Gateway resource - api := awsapigateway.NewLambdaRestApi(stack, jsii.String("HelloWorldApi"), &awsapigateway.LambdaRestApiProps{ - Handler: helloWorldFunction, - Proxy: jsii.Bool(false), - }) - - // Add a '/hello' resource with a GET method - helloResource := api.Root().AddResource(jsii.String("hello"), &awsapigateway.ResourceOptions{}) - helloResource.AddMethod(jsii.String("GET"), awsapigateway.NewLambdaIntegration(helloWorldFunction, &awsapigateway.LambdaIntegrationOptions{}), &awsapigateway.MethodOptions{}) - - return stack -} - -// ... ----- -==== - -Here, you create an API Gateway REST API resource, along with the following: - -* An integration between the REST API and your Lambda function, allowing the API to invoke your function. This includes the creation of a Lambda permission resource. -* A new resource or path named `hello` that is added to the root of the API endpoint. This creates a new endpoint that adds `/hello` to your base URL. -* A GET method for the `hello` resource. When a GET request is sent to the `/hello` endpoint, the Lambda function is invoked and its response is returned. - -[#serverless-example-deploy-prepare] -== Step 4: Prepare your application for deployment - -In this step you prepare your application for deployment by building, if necessary, and performing basic validation with the {aws} CDK CLI `cdk synth` command. - -If necessary, build your application: - -==== -[role="tablist"] -TypeScript:: -From the root of your project, run the following: -+ -[source,none,subs="verbatim,attributes"] ----- -$ npm run build ----- - -JavaScript:: -Building is not required. - -Python:: -Building is not required. - -Java:: -From the root of your project, run the following: -+ -[source,none,subs="verbatim,attributes"] ----- -$ mvn package ----- - -C#:: -From the root of your project, run the following: -+ -[source,none,subs="verbatim,attributes"] ----- -$ dotnet build src ----- - -Go:: -Building is not required. -==== - -Run `cdk synth` to synthesize an {aws} CloudFormation template from your CDK code. By using L2 constructs, many of the configuration details required by {aws} CloudFormation to facilitate the interaction between your Lambda function and REST API are provisioned for you by the {aws} CDK. - -From the root of your project, run the following: - -[source,none,subs="verbatim,attributes"] ----- -$ cdk synth ----- - -[NOTE] -==== - -If you receive an error like the following, verify that you are in the `cdk-hello-world` directory and try again: - ----- ---app is required either in command-line, in cdk.json or in ~/.cdk.json ----- - -==== - -If successful, the {aws} CDK CLI will output the {aws} CloudFormation template in `YAML` format at the command prompt. A `JSON` formatted template is also saved in the `cdk.out` directory. - -The following is an example output of the {aws} CloudFormation template: - -[#serverless-example-deploy-cfn] -.{aws} CloudFormation template -[%collapsible] -==== - -[source,yaml,subs="verbatim,attributes"] ----- -Resources: - HelloWorldFunctionServiceRoleunique-identifier: - Type: {aws}::IAM::Role - Properties: - AssumeRolePolicyDocument: - Statement: - - Action: sts:AssumeRole - Effect: Allow - Principal: - Service: lambda.amazonaws.com - Version: "2012-10-17" - ManagedPolicyArns: - - Fn::Join: - - "" - - - "arn:" - - Ref: {aws}::Partition - - :iam::aws:policy/service-role/AWSLambdaBasicExecutionRole - Metadata: - aws:cdk:path: CdkHelloWorldStack/HelloWorldFunction/ServiceRole/Resource - HelloWorldFunctionunique-identifier: - Type: {aws}::Lambda::Function - Properties: - Code: - S3Bucket: - Fn::Sub: cdk-unique-identifier-assets-${{aws}::AccountId}-${{aws}::Region} - S3Key: unique-identifier.zip - Handler: hello.handler - Role: - Fn::GetAtt: - - HelloWorldFunctionServiceRoleunique-identifier - - Arn - Runtime: nodejs20.x - DependsOn: - - HelloWorldFunctionServiceRoleunique-identifier - Metadata: - aws:cdk:path: CdkHelloWorldStack/HelloWorldFunction/Resource - aws:asset:path: asset.unique-identifier - aws:asset:is-bundled: false - aws:asset:property: Code - HelloWorldApiunique-identifier: - Type: {aws}::ApiGateway::RestApi - Properties: - Name: HelloWorldApi - Metadata: - aws:cdk:path: CdkHelloWorldStack/HelloWorldApi/Resource - HelloWorldApiDeploymentunique-identifier: - Type: {aws}::ApiGateway::Deployment - Properties: - Description: Automatically created by the RestApi construct - RestApiId: - Ref: HelloWorldApiunique-identifier - DependsOn: - - HelloWorldApihelloGETunique-identifier - - HelloWorldApihellounique-identifier - Metadata: - aws:cdk:path: CdkHelloWorldStack/HelloWorldApi/Deployment/Resource - HelloWorldApiDeploymentStageprod012345ABC: - Type: {aws}::ApiGateway::Stage - Properties: - DeploymentId: - Ref: HelloWorldApiDeploymentunique-identifier - RestApiId: - Ref: HelloWorldApiunique-identifier - StageName: prod - Metadata: - aws:cdk:path: CdkHelloWorldStack/HelloWorldApi/DeploymentStage.prod/Resource - HelloWorldApihellounique-identifier: - Type: {aws}::ApiGateway::Resource - Properties: - ParentId: - Fn::GetAtt: - - HelloWorldApiunique-identifier - - RootResourceId - PathPart: hello - RestApiId: - Ref: HelloWorldApiunique-identifier - Metadata: - aws:cdk:path: CdkHelloWorldStack/HelloWorldApi/Default/hello/Resource - HelloWorldApihelloGETApiPermissionCdkHelloWorldStackHelloWorldApiunique-identifier: - Type: {aws}::Lambda::Permission - Properties: - Action: lambda:InvokeFunction - FunctionName: - Fn::GetAtt: - - HelloWorldFunctionunique-identifier - - Arn - Principal: apigateway.amazonaws.com - SourceArn: - Fn::Join: - - "" - - - "arn:" - - Ref: {aws}::Partition - - ":execute-api:" - - Ref: {aws}::Region - - ":" - - Ref: {aws}::AccountId - - ":" - - Ref: HelloWorldApi9E278160 - - / - - Ref: HelloWorldApiDeploymentStageprodunique-identifier - - /GET/hello - Metadata: - aws:cdk:path: CdkHelloWorldStack/HelloWorldApi/Default/hello/GET/ApiPermission.CdkHelloWorldStackHelloWorldApiunique-identifier.GET..hello - HelloWorldApihelloGETApiPermissionTestCdkHelloWorldStackHelloWorldApiunique-identifier: - Type: {aws}::Lambda::Permission - Properties: - Action: lambda:InvokeFunction - FunctionName: - Fn::GetAtt: - - HelloWorldFunctionunique-identifier - - Arn - Principal: apigateway.amazonaws.com - SourceArn: - Fn::Join: - - "" - - - "arn:" - - Ref: {aws}::Partition - - ":execute-api:" - - Ref: {aws}::Region - - ":" - - Ref: {aws}::AccountId - - ":" - - Ref: HelloWorldApiunique-identifier - - /test-invoke-stage/GET/hello - Metadata: - aws:cdk:path: CdkHelloWorldStack/HelloWorldApi/Default/hello/GET/ApiPermission.Test.CdkHelloWorldStackHelloWorldApiunique-identifier.GET..hello - HelloWorldApihelloGETunique-identifier: - Type: {aws}::ApiGateway::Method - Properties: - AuthorizationType: NONE - HttpMethod: GET - Integration: - IntegrationHttpMethod: POST - Type: AWS_PROXY - Uri: - Fn::Join: - - "" - - - "arn:" - - Ref: {aws}::Partition - - ":apigateway:" - - Ref: {aws}::Region - - :lambda:path/2015-03-31/functions/ - - Fn::GetAtt: - - HelloWorldFunctionunique-identifier - - Arn - - /invocations - ResourceId: - Ref: HelloWorldApihellounique-identifier - RestApiId: - Ref: HelloWorldApiunique-identifier - Metadata: - aws:cdk:path: CdkHelloWorldStack/HelloWorldApi/Default/hello/GET/Resource - CDKMetadata: - Type: {aws}::CDK::Metadata - Properties: - Analytics: v2:deflate64:unique-identifier - Metadata: - aws:cdk:path: CdkHelloWorldStack/CDKMetadata/Default - Condition: CDKMetadataAvailable -Outputs: - HelloWorldApiEndpointunique-identifier: - Value: - Fn::Join: - - "" - - - https:// - - Ref: HelloWorldApiunique-identifier - - .execute-api. - - Ref: {aws}::Region - - "." - - Ref: {aws}::URLSuffix - - / - - Ref: HelloWorldApiDeploymentStageprodunique-identifier - - / -Conditions: - CDKMetadataAvailable: - Fn::Or: - - Fn::Or: - - Fn::Equals: - - Ref: {aws}::Region - - af-south-1 - - Fn::Equals: - - Ref: {aws}::Region - - ap-east-1 - - Fn::Equals: - - Ref: {aws}::Region - - ap-northeast-1 - - Fn::Equals: - - Ref: {aws}::Region - - ap-northeast-2 - - Fn::Equals: - - Ref: {aws}::Region - - ap-south-1 - - Fn::Equals: - - Ref: {aws}::Region - - ap-southeast-1 - - Fn::Equals: - - Ref: {aws}::Region - - ap-southeast-2 - - Fn::Equals: - - Ref: {aws}::Region - - ca-central-1 - - Fn::Equals: - - Ref: {aws}::Region - - cn-north-1 - - Fn::Equals: - - Ref: {aws}::Region - - cn-northwest-1 - - Fn::Or: - - Fn::Equals: - - Ref: {aws}::Region - - eu-central-1 - - Fn::Equals: - - Ref: {aws}::Region - - eu-north-1 - - Fn::Equals: - - Ref: {aws}::Region - - eu-south-1 - - Fn::Equals: - - Ref: {aws}::Region - - eu-west-1 - - Fn::Equals: - - Ref: {aws}::Region - - eu-west-2 - - Fn::Equals: - - Ref: {aws}::Region - - eu-west-3 - - Fn::Equals: - - Ref: {aws}::Region - - il-central-1 - - Fn::Equals: - - Ref: {aws}::Region - - me-central-1 - - Fn::Equals: - - Ref: {aws}::Region - - me-south-1 - - Fn::Equals: - - Ref: {aws}::Region - - sa-east-1 - - Fn::Or: - - Fn::Equals: - - Ref: {aws}::Region - - us-east-1 - - Fn::Equals: - - Ref: {aws}::Region - - us-east-2 - - Fn::Equals: - - Ref: {aws}::Region - - us-west-1 - - Fn::Equals: - - Ref: {aws}::Region - - us-west-2 -Parameters: - BootstrapVersion: - Type: {aws}::SSM::Parameter::Value<String> - Default: /cdk-bootstrap/hnb659fds/version - Description: Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip] -Rules: - CheckBootstrapVersion: - Assertions: - - Assert: - Fn::Not: - - Fn::Contains: - - - "1" - - "2" - - "3" - - "4" - - "5" - - Ref: BootstrapVersion - AssertDescription: CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI. ----- -==== - -By using L2 constructs, you define a few properties to configure your resources and use helper methods to integrate them together. The {aws} CDK configures the majority of your {aws} CloudFormation resources and properties required to provision your application. - -[#serverless-example-deploy] -== Step 5: Deploy your application - -In this step, you use the {aws} CDK CLI `cdk deploy` command to deploy your application. The {aws} CDK works with the {aws} CloudFormation service to provision your resources. - -[IMPORTANT] -==== - -You must perform a one-time bootstrapping of your {aws} environment before deployment. For instructions, see xref:bootstrapping-env[Bootstrap your environment for use with the {aws} CDK]. - -==== - -From the root of your project, run the following. Confirm changes if prompted: - -[source,none,subs="verbatim,attributes"] ----- -$ cdk deploy - -✨ Synthesis time: 2.44s - -... - -Do you wish to deploy these changes (y/n)? <y> ----- - -When deployment completes, the {aws} CDK CLI will output your endpoint URL. Copy this URL for the next step. The following is an example: - -[source,none,subs="verbatim,attributes"] ----- -... -✅ HelloWorldStack - -✨ Deployment time: 45.37s - -Outputs: -HelloWorldStack.HelloWorldApiEndpointunique-identifier = https://<api-id>.execute-api.<region>.amazonaws.com/prod/ -Stack ARN: -arn:aws:cloudformation:region:account-id:stack/HelloWorldStack/unique-identifier -... ----- - -[#serverless-example-interact] -== Step 6: Interact with your application - -In this step, you initiate a GET request to your API endpoint and receive your Lambda function response. - -Locate your endpoint URL from the previous step and add the `/hello` path. Then, using your browser or command prompt, send a GET request to your endpoint. The following is an example: - -[source,none,subs="verbatim,attributes"] ----- -$ curl https://<api-id>.execute-api.<region>.amazonaws.com/prod/hello -{"message":"Hello World!"}% ----- - -Congratulations, you have successfully created, deployed, and interacted with your application using the {aws} CDK! - -[#serverless-example-delete] -== Step 7: Delete your application - -In this step, you use the {aws} CDK CLI to delete your application from the {aws} Cloud. - -To delete your application, run `cdk destroy`. When prompted, confirm your request to delete the application: - -[source,none,subs="verbatim,attributes"] ----- -$ cdk destroy -Are you sure you want to delete: CdkHelloWorldStack (y/n)? y -CdkHelloWorldStack: destroying... [1/1] -... - ✅ CdkHelloWorldStack: destroyed ----- - -[#serverless-example-troubleshooting] -== Troubleshooting - -[#serverless-example-trobuleshooting-error1] -=== Error: {"`message`": "`Internal server error`"}% - -When invoking the deployed Lambda function, you receive this error. This error could occur for multiple reasons. - -*To troubleshoot further*:: -+ -Use the {aws} CLI to invoke your Lambda function. -+ -. Modify your stack file to capture the output value of your deployed Lambda function name. The following is an example: -+ -[source,javascript,subs="verbatim,attributes"] ----- -... - -class CdkHelloWorldStack extends Stack { - constructor(scope, id, props) { - super(scope, id, props); - - // Define the Lambda function resource - // ... - - new CfnOutput(this, 'HelloWorldFunctionName', { - value: helloWorldFunction.functionName, - description: 'JavaScript Lambda function' - }); - - // Define the API Gateway resource - // ... - } -} ----- -+ -. Deploy your application again. The {aws} CDK CLI will output the value of your deployed Lambda function name: -+ -[source,none,subs="verbatim,attributes"] ----- -$ cdk deploy - -✨ Synthesis time: 0.29s -... - ✅ CdkHelloWorldStack - -✨ Deployment time: 20.36s - -Outputs: -... -CdkHelloWorldStack.HelloWorldFunctionName = CdkHelloWorldStack-HelloWorldFunctionunique-identifier -... ----- -+ -. Use the {aws} CLI to invoke your Lambda function in the {aws} Cloud and output the response to a text file: -+ -[source,none,subs="verbatim,attributes"] ----- -$ aws lambda invoke --function-name CdkHelloWorldStack-HelloWorldFunctionunique-identifier output.txt ----- -+ -. Check `output.txt` to see your results. -+ - -*Possible cause: API Gateway resource is defined incorrectly in your stack file*::: -+ -If `output.txt` shows a successful Lambda function response, the issue could be with how you defined your API Gateway REST API. The {aws} CLI invokes your Lambda directly, not through your endpoint. Check your code to ensure it matches this tutorial. Then, deploy again. -+ -*Possible cause: Lambda resource is defined incorrectly in your stack file*::: -If `output.txt` returns an error, the issue could be with how you defined your Lambda function. Check your code to ensure it matches this tutorial. Then deploy again. \ No newline at end of file diff --git a/v2/guide/images/AppStacks.png b/v2/guide/images/AppStacks.png deleted file mode 100644 index 094c61db..00000000 Binary files a/v2/guide/images/AppStacks.png and /dev/null differ diff --git a/v2/guide/images/AppStacks.vsdx b/v2/guide/images/AppStacks.vsdx deleted file mode 100644 index cba88c9e..00000000 Binary files a/v2/guide/images/AppStacks.vsdx and /dev/null differ diff --git a/v2/guide/images/CodeCompletion.png b/v2/guide/images/CodeCompletion.png deleted file mode 100644 index 2006baec..00000000 Binary files a/v2/guide/images/CodeCompletion.png and /dev/null differ diff --git a/v2/guide/images/Lifecycle.png b/v2/guide/images/Lifecycle.png deleted file mode 100644 index d9108794..00000000 Binary files a/v2/guide/images/Lifecycle.png and /dev/null differ diff --git a/v2/guide/images/Lifecycle.vsdx b/v2/guide/images/Lifecycle.vsdx deleted file mode 100644 index 8e56e0e9..00000000 Binary files a/v2/guide/images/Lifecycle.vsdx and /dev/null differ diff --git a/v2/guide/images/MyEcsConstruct.png b/v2/guide/images/MyEcsConstruct.png deleted file mode 100644 index 06f8c025..00000000 Binary files a/v2/guide/images/MyEcsConstruct.png and /dev/null differ diff --git a/v2/guide/images/all-in-one.jpg b/v2/guide/images/all-in-one.jpg deleted file mode 100644 index e7011806..00000000 Binary files a/v2/guide/images/all-in-one.jpg and /dev/null differ diff --git a/v2/guide/images/aws_cover.jpg b/v2/guide/images/aws_cover.jpg deleted file mode 100644 index 42956877..00000000 Binary files a/v2/guide/images/aws_cover.jpg and /dev/null differ diff --git a/v2/guide/images/best-practice-deploy-to-multiple-accounts.png b/v2/guide/images/best-practice-deploy-to-multiple-accounts.png deleted file mode 100644 index a41e4018..00000000 Binary files a/v2/guide/images/best-practice-deploy-to-multiple-accounts.png and /dev/null differ diff --git a/v2/guide/images/code-organization.jpg b/v2/guide/images/code-organization.jpg deleted file mode 100644 index eaf846b6..00000000 Binary files a/v2/guide/images/code-organization.jpg and /dev/null differ diff --git a/v2/guide/images/eclipse-maven.png b/v2/guide/images/eclipse-maven.png deleted file mode 100644 index 2c8e6b4e..00000000 Binary files a/v2/guide/images/eclipse-maven.png and /dev/null differ diff --git a/v2/guide/images/overview-fargate.png b/v2/guide/images/overview-fargate.png deleted file mode 100644 index 5b28491d..00000000 Binary files a/v2/guide/images/overview-fargate.png and /dev/null differ diff --git a/v2/guide/images/overview-fargate.vsdx b/v2/guide/images/overview-fargate.vsdx deleted file mode 100644 index 3f0724a5..00000000 Binary files a/v2/guide/images/overview-fargate.vsdx and /dev/null differ diff --git a/v2/guide/images/pipeline.jpg b/v2/guide/images/pipeline.jpg deleted file mode 100644 index 1d8bddd6..00000000 Binary files a/v2/guide/images/pipeline.jpg and /dev/null differ diff --git a/v2/guide/images/screencast.gif b/v2/guide/images/screencast.gif deleted file mode 100644 index f84d675a..00000000 Binary files a/v2/guide/images/screencast.gif and /dev/null differ diff --git a/v2/guide/images/visual-studio-nuget.png b/v2/guide/images/visual-studio-nuget.png deleted file mode 100644 index 00db5a25..00000000 Binary files a/v2/guide/images/visual-studio-nuget.png and /dev/null differ diff --git a/v2/guide/migrate/migrate.adoc b/v2/guide/migrate/migrate.adoc deleted file mode 100644 index 21e0292d..00000000 --- a/v2/guide/migrate/migrate.adoc +++ /dev/null @@ -1,370 +0,0 @@ -include::../attributes.txt[] - -// Attributes -[.topic] -[#migrate] -= Migrate existing resources and {aws} CloudFormation templates to the {aws} CDK -:info_titleabbrev: Migrate to the {aws} CDK -:keywords: {aws} CDK, {aws} CDK CLI, {aws} CloudFormation, Migrate, {aws} resources, Infrastructure as Code, IaC - -[abstract] --- -Use the {aws} Cloud Development Kit ({aws} CDK) Command Line Interface ({aws} CDK CLI) to migrate deployed {aws} resources, deployed {aws} CloudFormation stacks, and local {aws} CloudFormation templates to {aws} CDK. --- - -// Content start - -[cols="1", frame="all"] -|=== - -|The CDK Migrate feature is in preview release for {aws} CDK and is subject to change. -|=== - -Use the {aws} Cloud Development Kit ({aws} CDK) Command Line Interface ({aws} CDK CLI) to migrate deployed {aws} resources, deployed {aws} CloudFormation stacks, and local {aws} CloudFormation templates to {aws} CDK. - - -[#migrate-intro] -== How migration works - -Use the {aws} CDK CLI `cdk migrate` command to migrate from the following sources: - --- -* Deployed {aws} resources. -* Deployed {aws} CloudFormation stacks. -* Local {aws} CloudFormation templates. --- - -*Deployed {aws} resources*:: -+ -You can migrate deployed {aws} resources from a specific environment ({aws} account and {aws} Region) that are not associated with an {aws} CloudFormation stack. -+ -The {aws} CDK CLI utilizes the _IaC generator_ service to scan for resources in your {aws} environment to gather resource details. To learn more about IaC generator, see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/generate-IaC.html[Generating templates for existing resources] in the _{aws} CloudFormation User Guide_. -+ -After gathering resource details, the {aws} CDK CLI creates a new CDK app that includes a single stack containing your migrated resources. - -*Deployed {aws} CloudFormation stacks*:: -+ -You can migrate a single {aws} CloudFormation stack into a new {aws} CDK app. The {aws} CDK CLI will retrieve the {aws} CloudFormation template of your stack and create a new CDK app. The CDK app will consist of a single stack that contains your migrated {aws} CloudFormation stack. - -*Local {aws} CloudFormation templates*:: -+ -You can migrate from a local {aws} CloudFormation template. Local templates may or may not contain deployed resources. The {aws} CDK CLI will create a new CDK app that contains a single stack with your resources. -+ -After migrating, you can manage, modify, and deploy your CDK app to {aws} CloudFormation to provision or update your resources. - -[#migrate-benefits] -== Benefits of CDK Migrate - -Migrating resources into {aws} CDK has historically been a manual process that requires time and expertise with {aws} CloudFormation and {aws} CDK to even begin. With CDK Migrate, the {aws} CDK CLI facilitates a majority of the migration effort for you in a fraction of the time. CDK Migrate will quickly get you started with using the {aws} CDK to develop and manage new and existing applications on {aws}. - -[#migrate-considerations] -== Considerations - -[#migrate-considerations-general] -=== General considerations - -*CDK Migrate vs. CDK Import*:: -+ -The `cdk import` command can import deployed resources into a new or existing CDK app. When importing, each resource will have to manually be defined as an L1 construct in your app. We recommend using `cdk import` to import one or more resources at a time into a new or existing CDK app. To learn more, see xref:cli-import[Import existing resources into a stack]. -+ -The `cdk migrate` command migrates from deployed resources, deployed {aws} CloudFormation stacks, or local {aws} CloudFormation templates into a new CDK app. During migration, the {aws} CDK CLI uses `cdk import` to import your resources into the new CDK app. The {aws} CDK CLI also generates L1 constructs for each resource for you. We recommend using `cdk migrate` when importing from a supported migration source into a new {aws} CDK app. - -*CDK Migrate creates L1 constructs only*:: -+ -The newly created CDK app will include L1 constructs only. You can add higher-level constructs to your app after migration. - -*CDK Migrate creates CDK apps that contain a single stack*:: -+ -The newly created CDK app will contain a single stack. -+ -When migrating deployed resources, all migrated resources will be contained within a single stack in the new CDK app. -+ -When migrating {aws} CloudFormation stacks, you can only migrate a single {aws} CloudFormation stack into a single stack in the new CDK app. - -*Migrating assets*:: -+ -Project assets, such as {aws} Lambda code, will not directly migrate into the new CDK app. After migration, you can specify asset values to include them in the CDK app. - -*Migrating stateful resources*:: -+ -When migrating stateful resources, such as databases and Amazon Simple Storage Service (Amazon S3) buckets, you'd most often want to migrate the existing resource instead of creating a new resource. -+ -To migrate and preserve stateful resources, do the following: -+ --- -** Verify that your stateful resource supports import. For more information, see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resource-import-supported-resources.html[Resource type support] in the _{aws} CloudFormation User Guide_. -** After migration, verify that the migrated resource`'s logical ID in the new CDK app matches the logical ID of the deployed resource. -** If migrating from an {aws} CloudFormation stack, verify that the stack name in the new CDK app matches the {aws} CloudFormation stack. -** Deploy the CDK app using the same {aws} account and {aws} Region of the migrated resource. --- - -[#migrate-considerations-template] -=== Considerations when migrating from an {aws} CloudFormation template - -*CDK Migrate supports single template migration*:: -+ -When migrating {aws} CloudFormation templates, you can select a single template to migrate. Nested templates are not supported. - -*Migrating templates with intrinsic functions*:: -+ -When migrating from an {aws} CloudFormation template that uses intrinsic functions, the {aws} CDK CLI will attempt to migrate your logic into the CDK app with the `Fn` class. To learn more, see https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Fn.html[class Fn] in the _{aws} Cloud Development Kit ({aws} CDK) API Reference_. - -[#migrate-considerations-resources] -=== Considerations when migrating from deployed resources - -*Scan limitations*:: -+ -When scanning your environment for resources, IaC generator has specific limitations on the data it can retrieve and quota limitations when scanning. To learn more, see link:https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/generate-IaC.html#generate-template-considerations[Considerations] in the _{aws} CloudFormation User Guide_. - -[#migrate-prerequisites] -== Prerequisites - -Before using the `cdk migrate` command, complete all set up steps in xref:getting-started[Getting started with the {aws} CDK]. - -[#migrate-gs] -== Get started with CDK Migrate - -To begin, run the {aws} CDK CLI `cdk migrate` command from a directory of your choice. Provide required and optional options, depending on the type of migration you are performing. - -For a full list and description of options that you can use with `cdk migrate`, see xref:ref-cli-cdk-migrate[cdk migrate]. - -The following are some important options that you may want to provide. - -*Stack name*:: -+ -The only required option is `--stack-name`. Use this option to specify a name for the stack that will be created within the {aws} CDK app after migration. The stack name will also be used as the name of your {aws} CloudFormation stack at deployment. - -*Language*:: -+ -Use `--language` to specify the programming language of the new CDK app. - -*{aws} account and {aws} Region*:: -+ -The {aws} CDK CLI retrieves {aws} account and {aws} Region information from default sources. For more information, see xref:environments[Environments for the {aws} CDK]. You can use `--account` and `--region` options with `cdk migrate` to provide other values. - -*Output directory of your new CDK project*:: -+ -By default, the {aws} CDK CLI will create a new CDK project in your working directory and use the value you provide with `--stack-name` to name the project folder. If a folder with the same name currently exists, the {aws} CDK CLI will overwrite that folder. -+ -You can specify a different output path for the new CDK project folder with the `--output-path` option. - -*Migration source*:: -+ -Provide an option to specify the source you are migrating from. -+ --- -* `--from-path` – Migrate from a local {aws} CloudFormation template. -* `--from-scan` – Migrate from deployed resources in an {aws} account and {aws} Region. -* `--from-stack` – Migrate from an {aws} CloudFormation stack. --- -+ -Depending on your migration source, you can provide additional options to customize the `cdk migrate` command. - -[#migrate-stack] -== Migrate from an {aws} CloudFormation stack - -To migrate from a deployed {aws} CloudFormation stack, provide the `--from-stack` option. Provide the name of your deployed {aws} CloudFormation stack with `--stack-name`. The following is an example: - -[source,bash,subs="verbatim,attributes"] ----- -$ cdk migrate --from-stack --stack-name "myCloudFormationStack" ----- - -The {aws} CDK CLI will do the following: - -. Retrieve the {aws} CloudFormation template of your deployed stack. -. Run `cdk init` to initialize a new CDK app. -. Create a stack within the CDK app that contains your migrated {aws} CloudFormation stack. - -When you migrate from a deployed {aws} CloudFormation stack, the {aws} CDK CLI attempts to match deployed resource logical IDs and the deployed {aws} CloudFormation stack name to the migrated resources and stack in the new CDK app. - -After migration, you can manage and modify your CDK app normally. When you deploy, {aws} CloudFormation will identify the deployment as an {aws} CloudFormation stack update due to the matching {aws} CloudFormation stack name. Resources with matching logical IDs will be updated. For more information on deploying, see xref:migrate-manage[Manage and deploy your CDK app]. - -[#migrate-template] -== Migrate from an {aws} CloudFormation template - -CDK Migrate supports migrating from {aws} CloudFormation templates formatted in `JSON` or `YAML`. - -To migrate from a local {aws} CloudFormation template, use the `--from-path` option and provide a path to the local template. You must also provide the required `--stack-name` option. The following is an example: - -[source,bash,subs="verbatim,attributes"] ----- -$ cdk migrate --from-path "./template.json" --stack-name "myCloudFormationStack" ----- - -The {aws} CDK CLI will do the following: - -. Retrieve your local {aws} CloudFormation template. -. Run `cdk init` to initialize a new CDK app. -. Create a stack within the CDK app that contains your migrated {aws} CloudFormation template. - -After migration, you can manage and modify your CDK app normally. At deployment, you have the following options: - -* *Update an {aws} CloudFormation stack* – If the local {aws} CloudFormation template was previously deployed, you can update the deployed {aws} CloudFormation stack. -* *Deploy a new {aws} CloudFormation stack* – If the local {aws} CloudFormation template was never deployed, or if you want to create a new stack from a previously deployed template, you can deploy a new {aws} CloudFormation stack. - -[#migrate-template-sam] -=== Migrate from an {aws} SAM template - -To migrate from an {aws} Serverless Application Model ({aws} SAM) template, you must first convert it to an {aws} CloudFormation template or deploy to create an {aws} CloudFormation stack. - -To convert an {aws} SAM template to {aws} CloudFormation, you can use the {aws} SAM CLI `sam validate --debug` command. You may have to set `lint` to `false` in your `samconfig.toml` file before running this command. - -To convert to an {aws} CloudFormation stack, deploy the {aws} SAM template using the {aws} SAM CLI. Then migrate from the deployed stack. - -[#migrate-resources] -== Migrate from deployed resources - -To migrate from deployed {aws} resources, provide the `--from-scan` option. You must also provide the required `--stack-name` option. The following is an example: - -[source,bash,subs="verbatim,attributes"] ----- -$ cdk migrate --from-scan --stack-name "myCloudFormationStack" ----- - -The {aws} CDK CLI will do the following: - -. *Scan your account for resource and property details* – The {aws} CDK CLI utilizes IaC generator to scan your account and gather details. -. *Generate an {aws} CloudFormation template* – After scanning, the {aws} CDK CLI utilizes IaC generator to create an {aws} CloudFormation template. -. *Initialize a new CDK app and migrate your template* – The {aws} CDK CLI runs `cdk init` to initialize a new {aws} CDK app and migrates your {aws} CloudFormation template into the CDK app as a single stack. - -[#migrate-resources-filters] -=== Use filters - -By default, the {aws} CDK CLI will scan the entire {aws} environment and migrate resources up to the maximum quota limit of IaC generator. You can provide filters with the {aws} CDK CLI to specify a criteria for which resources get migrated from your account to the new CDK app. To learn more, see `xref:ref-cli-cdk-migrate-options-filter[--filter]`. - -[#migrate-resources-scan] -=== Scanning for resources with IaC generator - -Depending on the number of resources in your account, scanning may take a few minutes. A progress bar will display during the scanning process. - -[#migrate-resources-supported] -*Supported resource types*:: -+ -The {aws} CDK CLI will migrate resources supported by the IaC generator. For a full list, see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resource-import-supported-resources.html[Resource type support] in the __{aws} CloudFormation User Guide__. - -[#migrate-resources-writeonly] -=== Resolve write-only properties - -Some supported resources contain write-only properties. These properties can be written to, to configure the property, but can't be read by IaC generator or {aws} CloudFormation to obtain the value. For example, a property used to specify a database password may be write-only for security reasons. - -When scanning resources during migration, IaC generator will detect resources that may contain write-only properties and will categorize them into any of the following types: - -* `MUTUALLY_EXCLUSIVE_PROPERTIES` – These are write-only properties for a specific resource that are interchangeable and serve a similar purpose. One of the mutually exclusive properties are required to configure your resource. For example, the `S3Bucket`, `ImageUri`, and `ZipFile` properties for an `{aws}::Lambda::Function` resource are mutually exclusive write-only properties. Any one of them can be used to specify your function assets, but you must use one. -* `MUTUALLY_EXCLUSIVE_TYPES` – These are required write-only properties that accept multiple configuration types. For example, the `Body` property of an `{aws}::ApiGateway::RestApi` resource accepts an object or string type. -* `UNSUPPORTED_PROPERTIES` – These are write-only properties that don't fall under the other two categories. They are either optional properties or required properties that accept an array of objects. - -For more information on write-only properties and how IaC generator manages them when scanning for deployed resources and creating {aws} CloudFormation templates, see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/generate-IaC-write-only-properties.html[IaC generator and write-only properties] in the _{aws} CloudFormation User Guide_. - -After migration, you must specify write-only property values in the new CDK app. The {aws} CDK CLI will append a *Warnings* section to the CDK project's `ReadMe` file to document any write-only properties that were identified by IaC generator. The following is an example: - -[source,markdown,subs="verbatim,attributes"] ----- -# Welcome to your CDK TypeScript project -... -## Warnings -### Write-only properties -Write-only properties are resource property values that can be written to but can't be read by {aws} CloudFormation or CDK Migrate. For more information, see [IaC generator and write-only properties](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/generate-IaC-write-only-properties.html). - -Write-only properties discovered during migration are organized here by resource ID and categorized by write-only property type. Resolve write-only properties by providing property values in your CDK app. For guidance, see [Resolve write-only properties](https://docs.aws.amazon.com/cdk/v2/guide/migrate.html#migrate-resources-writeonly). -### MyLambdaFunction -- **UNSUPPORTED_PROPERTIES**: - - SnapStart/ApplyOn: Applying SnapStart setting on function resource type.Possible values: [PublishedVersions, None] -This property can be replaced with other types - - Code/S3ObjectVersion: For versioned objects, the version of the deployment package object to use. -This property can be replaced with other exclusive properties -- **MUTUALLY_EXCLUSIVE_PROPERTIES**: - - Code/S3Bucket: An Amazon S3 bucket in the same {aws} Region as your function. The bucket can be in a different {aws} account. -This property can be replaced with other exclusive properties - - Code/S3Key: The Amazon S3 key of the deployment package. -This property can be replaced with other exclusive properties ----- - --- -* Warnings are organized under headings that identify the resource`'s logical ID that they are associated with. -* Warnings are categorized by type. These types come directly from IaC generator. --- - -*To resolve write-only properties*:: -+ -. Identify write-only properties to resolve from the *Warnings* section of your CDK project`'s `ReadMe` file. Here, you can take note of the resources in your CDK app that may contain write-only properties and identify the write-only property types that were discovered. -+ -.. For ``MUTUALLY_EXCLUSIVE_PROPERTIES``, determine which mutually exclusive property to configure in your {aws} CDK app. -.. For ``MUTUALLY_EXCLUSIVE_TYPES``, determine which accepted type that you will use to configure the property. -.. For ``UNSUPPORTED_PROPERTIES``, determine if the property is optional or required. Then, configure as necessary. -. Use guidance from https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/generate-IaC-write-only-properties.html[IaC generator and write-only properties] to reference what the warning types mean. -. In your CDK app, write-only property values to resolve will also be specified in the `Props` section of your app. Provide the correct values here. For property descriptions and guidance, you can reference the https://docs.aws.amazon.com/cdk/api/v2/docs/aws-construct-library.html[{aws} CDK API Reference]. -+ - -The following is an example of the `Props` section within a migrated CDK app with two write-only properties to resolve: -+ -[source,javascript,subs="verbatim,attributes"] ----- -export interface MyTestAppStackProps extends cdk.StackProps { - /** - * The Amazon S3 key of the deployment package. - */ - readonly lambdaFunction00asdfasdfsadf008grk1CodeS3Keym8P82: string; - /** - * An Amazon S3 bucket in the same {aws} Region as your function. The bucket can be in a different {aws} account. - */ - readonly lambdaFunction00asdfasdfsadf008grk1CodeS3Bucketzidw8: string; -} ----- -+ - -Once you resolve all write-only property values, you're ready to prepare for deployment. - -[#migrate-resources-file] -=== The migrate.json file - -The {aws} CDK CLI creates a `migrate.json` file in your {aws} CDK project during migration. This file contains reference information on your deployed resources. When you deploy your CDK app for the first time, the {aws} CDK CLI uses this file to reference your deployed resources, associates your resources with the new {aws} CloudFormation stack, and deletes the file. - -[#migrate-manage] -== Manage and deploy your CDK app - -When migrating to {aws} CDK, the new CDK app may not be deployment-ready immediately. This topic describes action items to consider while managing and deploying your new CDK app. - -[#migrate-manage-prepare] -=== Prepare for deployment - -Before deploying, you must prepare your CDK app. - -*Synthesize your app*:: -Use the `cdk synth` command to synthesize the stack in your CDK app into an {aws} CloudFormation template. -+ -If you migrated from a deployed {aws} CloudFormation stack or template, you can compare the synthesized template to the migrated template to verify resource and property values. -+ -To learn more about `cdk synth`, see xref:cli-synth[Synthesize stacks]. - -*Perform a diff*:: -If you migrated from a deployed {aws} CloudFormation stack, you can use the cdk diff command to compare with the stack in your new CDK app. -+ -To learn more about cdk diff, see xref:cli-diff[Compare stacks]. - -*Bootstrap your environment*:: -If you are deploying from an {aws} environment for the first time, use `cdk bootstrap` to prepare your environment. To learn more, see xref:bootstrapping[{aws} CDK bootstrapping]. - -[#migrate-manage-deploy] -=== Deploy your CDK app - -When you deploy a CDK app, the {aws} CDK CLI utilizes the {aws} CloudFormation service to provision your resources. Resources are bundled into a single stack in the CDK app and are deployed as a single {aws} CloudFormation stack. - -Depending on where you migrated from, you can deploy to create a new {aws} CloudFormation stack or update an existing {aws} CloudFormation stack. - -*Deploy to create a new {aws} CloudFormation stack*:: -If you migrated from deployed resources, the {aws} CDK CLI will automatically create a new {aws} CloudFormation stack at deployment. Your deployed resources will be included in the new {aws} CloudFormation stack. -+ -If you migrated from a local {aws} CloudFormation template that was never deployed, the {aws} CDK CLI will automatically create a new {aws} CloudFormation stack at deployment. -+ -If you migrated from a deployed {aws} CloudFormation stack or local {aws} CloudFormation template that was previously deployed, you can deploy to create a new {aws} CloudFormation stack. To create a new stack, do the following: -+ --- -* Deploy to a new {aws} environment. This consists of using a different {aws} account or deploying to a different {aws} Region. -* If you want to deploy a new stack to the same {aws} environment of the migrated stack or template, you must modify the stack name in your CDK app to a new value. You must also modify all logical IDs of resources in your CDK app. Then, you can deploy to the same environment to create a new stack and new resources. --- - -*Deploy to update an existing {aws} CloudFormation stack*:: -If you migrated from a deployed {aws} CloudFormation stack or local {aws} CloudFormation template that was previously deployed, you can deploy to update the existing {aws} CloudFormation stack. -+ -Verify that the stack name in your CDK app matches the stack name of the deployed {aws} CloudFormation stack and deploy to the same {aws} environment. \ No newline at end of file diff --git a/v2/guide/migrate/work-with-cdk-v2.adoc b/v2/guide/migrate/work-with-cdk-v2.adoc deleted file mode 100644 index 3054ec34..00000000 --- a/v2/guide/migrate/work-with-cdk-v2.adoc +++ /dev/null @@ -1,450 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[#migrating-v2] -= Migrating from {aws} CDK v1 to {aws} CDK v2 - -// Content start - -Version 2 of the {aws} Cloud Development Kit ({aws} CDK) is designed to make writing infrastructure as code in your preferred programming language easier. This topic describes the changes between v1 and v2 of the {aws} CDK. - -[TIP] -==== - -To identify stacks deployed with {aws} CDK v1, use the https://www.npmjs.com/package/awscdk-v1-stack-finder[awscdk-v1-stack-finder] utility. - -==== - -The main changes from {aws} CDK v1 to CDK v2 are as follows. - -* {aws} CDK v2 consolidates the stable parts of the {aws} Construct Library, including the core library, into a single package, `aws-cdk-lib`. Developers no longer need to install additional packages for the individual {aws} services they use. This single-package approach also means that you don't have to synchronize the versions of the various CDK library packages. -+ -L1 (CfnXXXX) constructs, which represent the exact resources available in {aws} CloudFormation, are always considered stable and so are included in `aws-cdk-lib`. - -* Experimental modules, where we're still working with the community to develop new xref:constructs-lib-levels[L2 or L3 constructs], are not included in `aws-cdk-lib`. Instead, they're distributed as individual packages. Experimental packages are named with an `alpha` suffix and a semantic version number. The semantic version number matches the first version of the {aws} Construct Library that they're compatible with, also with an `alpha` suffix. Constructs move into `aws-cdk-lib` after being designated stable, permitting the main Construct Library to adhere to strict semantic versioning. -+ -Stability is specified at the service level. For example, if we begin creating one or more xref:constructs-lib-levels[L2 constructs] for Amazon AppFlow, which at this writing has only L1 constructs, they first appear in a module named `@aws-cdk/aws-appflow-alpha`. Then, they move to `aws-cdk-lib` when we feel that the new constructs meet the fundamental needs of customers. -+ -Once a module has been designated stable and incorporated into `aws-cdk-lib`, new APIs are added using the "BetaN" convention described in the next bullet. -+ -A new version of each experimental module is released with every release of the {aws} CDK. For the most part, however, they needn't be kept in sync. You can upgrade `aws-cdk-lib` or the experimental module whenever you want. The exception is that when two or more related experimental modules depend on each other, they must be the same version. - -* For stable modules to which new functionality is being added, new APIs (whether entirely new constructs or new methods or properties on an existing construct) receive a `Beta1` suffix while work is in progress. (Followed by `Beta2`, `Beta3`, and so on when breaking changes are needed.) A version of the API without the suffix is added when the API is designated stable. All methods except the latest (whether beta or final) are then deprecated. -+ -For example, if we add a new method `grantPower()` to a construct, it initially appears as `grantPowerBeta1()`. If breaking changes are needed (for example, a new required parameter or property), the next version of the method would be named `grantPowerBeta2()`, and so on. When work is complete and the API is finalized, the method `grantPower()` (with no suffix) is added, and the BetaN methods are deprecated. -+ -All the beta APIs remain in the Construct Library until the next major version (3.0) release, and their signatures will not change. You'll see deprecation warnings if you use them, so you should move to the final version of the API at your earliest convenience. However, no future {aws} CDK 2.x releases will break your application. - -* The `Construct` class has been extracted from the {aws} CDK into a separate library, along with related types. This is done to support efforts to apply the Construct Programming Model to other domains. If you are writing your own constructs or using related APIs, you must declare the `constructs` module as a dependency and make minor changes to your imports. If you are using advanced features, such as hooking into the CDK app lifecycle, more changes may be needed. For full details, link:https://github.com/aws/aws-cdk-rfcs/blob/master/text/0192-remove-constructs-compat.md#release-notes[see the RFC]. - -* Deprecated properties, methods, and types in {aws} CDK v1.x and its Construct Library have been removed completely from the CDK v2 API. In most supported languages, these APIs produce warnings under v1.x, so you may have already migrated to the replacement APIs. A complete link:https://github.com/aws/aws-cdk/blob/master/DEPRECATED_APIs.md[list of deprecated APIs] in CDK v1.x is available on GitHub. - -* Behavior that was gated by feature flags in {aws} CDK v1.x is enabled by default in CDK v2. The earlier feature flags are no longer needed, and in most cases they're not supported. A few are still available to let you revert to CDK v1 behavior in very specific circumstances. For more information, see xref:migrating-v2-v1-upgrade-cdk-json[Updating feature flags]. - -* With CDK v2, the environments you deploy into must be bootstrapped using the modern bootstrap stack. The legacy bootstrap stack (the default under v1) is no longer supported. CDK v2 furthermore requires a new version of the modern stack. To upgrade your existing environments, re-bootstrap them. It is no longer necessary to set any feature flags or environment variables to use the modern bootstrap stack. - -[IMPORTANT] -==== - -The modern bootstrap template effectively grants the permissions implied by the `--cloudformation-execution-policies` to any {aws} account in the `--trust` list. By default, this extends permissions to read and write to any resource in the bootstrapped account. Make sure to xref:bootstrapping-customizing[configure the bootstrapping stack] with policies and trusted accounts that you are comfortable with. - -==== - -[#migrating-v2-prerequisites] -== New prerequisites - -Most requirements for {aws} CDK v2 are the same as for {aws} CDK v1.x. Additional requirements are listed here. - -* For TypeScript developers, TypeScript 3.8 or later is required. -* A new version of the CDK Toolkit is required for use with CDK v2. Now that CDK v2 is generally available, v2 is the default version when installing the CDK Toolkit. It is backward-compatible with CDK v1 projects, so you don't need to keep the earlier version installed unless you want to create CDK v1 projects. To upgrade, issue `npm install -g aws-cdk`. - -[#migrating-v2-dp-upgrade] -== Upgrading from {aws} CDK v2 Developer Preview - -If you're using the CDK v2 Developer Preview, you have dependencies in your project on a Release Candidate version of the {aws} CDK, such as `2.0.0-rc1`. Update these to `2.0.0`, then update the modules installed in your project. - -==== -[role="tablist"] -TypeScript:: -`npm install` or `yarn install` - -JavaScript:: -`npm install` or `yarn install` - -Python:: -+ -[source,none,subs="verbatim,attributes"] ----- -python -m pip install -r requirements.txt ----- - -Java:: -+ -[source,none,subs="verbatim,attributes"] ----- -mvn package ----- - -C#:: -+ -[source,none,subs="verbatim,attributes"] ----- -dotnet restore ----- - -Go:: -+ -[source,none,subs="verbatim,attributes"] ----- -go get ----- -==== - -After updating your dependencies, issue `npm update -g aws-cdk` to update the CDK Toolkit to the release version. - -[#migrating-v2-v1-uppgrade] -== Migrating from {aws} CDK v1 to CDK v2 - -To migrate your app to {aws} CDK v2, first update the feature flags in `cdk.json`. Then update your app's dependencies and imports as necessary for the programming language that it's written in. - -[#migrating-v2-v1-recent-v1] -=== Updating to a recent v1 - -We are seeing a number of customers upgrading from an old version of {aws} CDK v1 to the most recent version of v2 in one step. While it is certainly possible to do that, you would be both upgrading across multiple years of changes (that unfortunately may not all have had the same amount of evolution testing we have today), as well as upgrading across versions with new defaults and a different code organization. - -For the safest upgrade experience and to more easily diagnose the sources of any unexpected changes, we recommend you separate those two steps: first upgrade to the latest v1 version, then make the switch to v2 afterwards. - -[#migrating-v2-v1-upgrade-cdk-json] -=== Updating feature flags - -Remove the following v1 feature flags from `cdk.json` if they exist, as these are all active by default in {aws} CDK v2. If their old effect is important for your infrastructure, you will need to make source code changes. See link:https://github.com/aws/aws-cdk/blob/main/packages/%40aws-cdk/cx-api/FEATURE_FLAGS.md[the list of flags on GitHub] for more information. - -* `@aws-cdk/core:enableStackNameDuplicates` -* `aws-cdk:enableDiffNoFail` -* `@aws-cdk/aws-ecr-assets:dockerIgnoreSupport` -* `@aws-cdk/aws-secretsmanager:parseOwnedSecretName` -* `@aws-cdk/aws-kms:defaultKeyPolicies` -* `@aws-cdk/aws-s3:grantWriteWithoutAcl` -* `@aws-cdk/aws-efs:defaultEncryptionAtRest` - -A handful of v1 feature flags can be set to `false` in order to revert to specific {aws} CDK v1 behaviors; see xref:featureflags-disabling[Reverting to v1 behavior] or the list on GitHub for a complete reference. - -For both types of flags, use the `cdk diff` command to inspect the changes to your synthesized template to see if the changes to any of these flags affect your infrastructure. - -[#work-with-cdk-v2-cli] -=== CDK Toolkit compatibility - -CDK v2 requires v2 or later of the CDK Toolkit. This version is backward-compatible with CDK v1 apps. Therefore, you can use a single globally installed version of CDK Toolkit with all your {aws} CDK projects, whether they use v1 or v2. An exception is that CDK Toolkit v2 only creates CDK v2 projects. - -If you need to create both v1 and v2 CDK projects, *do not install CDK Toolkit v2 globally.* (Remove it if you already have it installed: `npm remove -g aws-cdk`.) To invoke the CDK Toolkit, use `npx` to run v1 or v2 of the CDK Toolkit as desired. - -[source,none,subs="verbatim,attributes"] ----- -npx aws-cdk@1.x init app --language typescript -npx aws-cdk@2.x init app --language typescript ----- - -[TIP] -==== - -Set up command line aliases so you can use the `cdk` and `cdk1` commands to invoke the desired version of the CDK Toolkit. - -[role="tablist"] -macOS/Linux:: -+ -[source,none,subs="verbatim,attributes"] ----- -alias cdk1="npx aws-cdk@1.x" -alias cdk="npx aws-cdk@2.x" ----- - -Windows:: -+ -[source,none,subs="verbatim,attributes"] ----- -doskey cdk1=npx aws-cdk@1.x $* -doskey cdk=npx aws-cdk@2.x $* ----- -==== - -[#migrating-v2-v1-upgrade-dependencies] -=== Updating dependencies and imports - -Update your app's dependencies, then install the new packages. Finally, update the imports in your code. - -==== -[role="tablist"] -TypeScript:: -+ -*Applications*::: -+ -For CDK apps, update `package.json` as follows. Remove dependencies on v1-style individual stable modules and establish the lowest version of `aws-cdk-lib` you require for your application (2.0.0 here). -+ -Experimental constructs are provided in separate, independently versioned packages with names that end in `alpha` and an alpha version number. The alpha version number corresponds to the first release of `aws-cdk-lib` with which they're compatible. Here, we have pinned `aws-codestar` to v2.0.0-alpha.1. -+ -[source,json,subs="verbatim,attributes"] ----- -{ - "dependencies": { - "aws-cdk-lib": "^2.0.0", - "@aws-cdk/aws-codestar-alpha": "2.0.0-alpha.1", - "constructs": "^10.0.0" - } -} ----- - -*Construct libraries*::: -+ -For construct libraries, establish the lowest version of `aws-cdk-lib` you require for your application (2.0.0 here) and update `package.json` as follows. -+ -Note that `aws-cdk-lib` appears both as a peer dependency and a dev dependency. -+ -[source,json,subs="verbatim,attributes"] ----- -{ - "peerDependencies": { - "aws-cdk-lib": "^2.0.0", - "constructs": "^10.0.0" - }, - "devDependencies": { - "aws-cdk-lib": "^2.0.0", - "constructs": "^10.0.0", - "typescript": "~3.9.0" - } -} ----- -+ -[NOTE] --- -You should perform a major version bump on your library's version number when releasing a v2-compatible library, because this is a breaking change for library consumers. It is not possible to support both CDK v1 and v2 with a single library. To continue to support customers who are still using v1, you could maintain the earlier release in parallel, or create a new package for v2. - -It's up to you how long you want to continue supporting {aws} CDK v1 customers. You might take your cue from the lifecycle of CDK v1 itself, which entered maintenance on June 1, 2022 and will reach end-of-life on June 1, 2023. For full details, see link:https://github.com/aws/aws-cdk-rfcs/blob/master/text/0079-cdk-2.0.md#aws-cdk-maintenance-policy[{aws} CDK Maintenance Policy]. --- - -*Both libraries and apps*::: -+ -Install the new dependencies by running `npm install` or `yarn install`. -+ -Change your imports to import `Construct` from the new `constructs` module, core types such as `App` and `Stack` from the top level of `aws-cdk-lib`, and stable Construct Library modules for the services you use from namespaces under `aws-cdk-lib`. -+ -[source,javascript,subs="verbatim,attributes"] ----- -import { Construct } from 'constructs'; -import { App, Stack } from 'aws-cdk-lib'; // core constructs -import { aws_s3 as s3 } from 'aws-cdk-lib'; // stable module -import * as codestar from '@aws-cdk/aws-codestar-alpha'; // experimental module ----- - -JavaScript:: -+ -Update `package.json` as follows. Remove dependencies on v1-style individual stable modules and establish the lowest version of `aws-cdk-lib` you require for your application (2.0.0 here). -+ -Experimental constructs are provided in separate, independently versioned packages with names that end in `alpha` and an alpha version number. The alpha version number corresponds to the first release of `aws-cdk-lib` with which they're compatible. Here, we have pinned `aws-codestar` to v2.0.0-alpha.1. -+ -[source,json,subs="verbatim,attributes"] ----- -{ - "dependencies": { - "aws-cdk-lib": "^2.0.0", - "@aws-cdk/aws-codestar-alpha": "2.0.0-alpha.1", - "constructs": "^10.0.0" - } -} ----- -+ -Install the new dependencies by running `npm install` or `yarn install`. -+ -Change your app's imports to do the following: -+ --- -** Import `Construct` from the new `constructs` module -** Import core types, such as `App` and ``Stack``, from the top level of `aws-cdk-lib` -** Import {aws} Construct Library modules from namespaces under `aws-cdk-lib` --- -+ -[source,javascript,subs="verbatim,attributes"] ----- -const { Construct } = require('constructs'); -const { App, Stack } = require('aws-cdk-lib'); // core constructs -const s3 = require('aws-cdk-lib').aws_s3; // stable module -const codestar = require('@aws-cdk/aws-codestar-alpha'); // experimental module ----- - -Python:: -Update `requirements.txt` or the `install_requires` definition in `setup.py` as follows. Remove dependencies on v1-style individual stable modules. -+ -Experimental constructs are provided in separate, independently versioned packages with names that end in `alpha` and an alpha version number. The alpha version number corresponds to the first release of `aws-cdk-lib` with which they're compatible. Here, we have pinned `aws-codestar` to v2.0.0alpha1. -+ -[source,python,subs="verbatim,attributes"] ----- -install_requires=[ - "aws-cdk-lib>=2.0.0", - "constructs>=10.0.0", - "aws-cdk.aws-codestar-alpha>=2.0.0alpha1", - # ... -], ----- -+ -TIP: Uninstall any other versions of {aws} CDK modules already installed in your app's virtual environment using `pip uninstall`. Then Install the new dependencies with `python -m pip install -r requirements.txt`. -+ - -Change your app's imports to do the following: -+ --- -** Import `Construct` from the new `constructs` module -** Import core types, such as `App` and ``Stack``, from the top level of `aws_cdk` -** Import {aws} Construct Library modules from namespaces under `aws_cdk` --- -+ -[source,python,subs="verbatim,attributes"] ----- -from constructs import Construct -from aws_cdk import App, Stack # core constructs -from aws_cdk import aws_s3 as s3 # stable module -import aws_cdk.aws_codestar_alpha as codestar # experimental module - -# ... - -class MyConstruct(Construct): - # ... - -class MyStack(Stack): - # ... - -s3.Bucket(...) ----- - -Java:: -In `pom.xml`, remove all `software.amazon.awscdk` dependencies for stable modules and replace them with dependencies on `software.constructs` (for `Construct`) and `software.amazon.awscdk`. -+ -Experimental constructs are provided in separate, independently versioned packages with names that end in `alpha` and an alpha version number. The alpha version number corresponds to the first release of `aws-cdk-lib` with which they're compatible. Here, we have pinned `aws-codestar` to v2.0.0-alpha.1. -+ -[source,xml,subs="verbatim,attributes"] ----- -<dependency> - <groupId>software.amazon.awscdk</groupId> - <artifactId>aws-cdk-lib</artifactId> - <version>2.0.0</version> -</dependency><dependency> - <groupId>software.amazon.awscdk</groupId> - <artifactId>code-star-alpha</artifactId> - <version>2.0.0-alpha.1</version> -</dependency> -<dependency> - <groupId>software.constructs</groupId> - <artifactId>constructs</artifactId> - <version>10.0.0</version> -</dependency> ----- -+ -Install the new dependencies by running `mvn package`. -+ -Change your code to do the following: -+ --- -** Import `Construct` from the new `software.constructs` library -** Import core classes, like `Stack` and ``App``, from `software.amazon.awscdk` -** Import service constructs from `software.amazon.awscdk.services` --- -+ -[source,java,subs="verbatim,attributes"] ----- -import software.constructs.Construct; -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.StackProps; -import software.amazon.awscdk.App; -import software.amazon.awscdk.services.s3.Bucket; -import software.amazon.awscdk.services.codestar.alpha.GitHubRepository; ----- - -C#:: -The most straightforward way to upgrade the dependencies of a C# CDK application is to edit the `.csproj` file manually. Remove all stable `Amazon.CDK.*` package references and replace them with references to the `Amazon.CDK.Lib` and `Constructs` packages. -+ -Experimental constructs are provided in separate, independently versioned packages with names that end in `alpha` and an alpha version number. The alpha version number corresponds to the first release of `aws-cdk-lib` with which they're compatible. Here, we have pinned `aws-codestar` to v2.0.0-alpha.1. -+ -[source,xml,subs="verbatim,attributes"] ----- -<PackageReference Include="Amazon.CDK.Lib" Version="2.0.0" /> -<PackageReference Include="Amazon.CDK.{aws}.Codestar.Alpha" Version="2.0.0-alpha.1" /> -<PackageReference Include="Constructs" Version="10.0.0" /> ----- -+ -Install the new dependencies by running `dotnet restore`. -+ -Change the imports in your source files as follows. -+ -[source,csharp,subs="verbatim,attributes"] ----- -using Constructs; // for Construct class -using Amazon.CDK; // for core classes like App and Stack -using Amazon.CDK.{aws}.S3; // for stable constructs like Bucket -using Amazon.CDK.Codestar.Alpha; // for experimental constructs ----- - -Go:: -Issue `go get` to update your dependencies to the latest version and update your project's `.mod` file. - -==== - -[#migrating-v2-diff.title] -== Testing your migrated app before deploying - -Before deploying your stacks, use `cdk diff` to check for unexpected changes to the resources. Changes to logical IDs (causing replacement of resources) are *not* expected. - -Expected changes include but are not limited to: - -* Changes to the `CDKMetadata` resource. -* Updated asset hashes. -* Changes related to the new-style stack synthesis. Applies if your app used the legacy stack synthesizer in v1. -* The addition of a `CheckBootstrapVersion` rule. - -Unexpected changes are typically not caused by upgrading to {aws} CDK v2 in itself. Usually, they're the result of deprecated behavior that was previously changed by feature flags. This is a symptom of upgrading from a version of CDK earlier than about 1.85.x. You would see the same changes upgrading to the latest v1.x release. You can usually resolve this by doing the following: - -. Upgrade your app to the latest v1.x release -. Remove feature flags -. Revise your code as necessary -. Deploy -. Upgrade to v2 - -[NOTE] -==== - -If your upgraded app is undeployable after the two-stage upgrade, https://github.com/aws/aws-cdk/issues/new/choose[report the issue]. - -==== - -When you are ready to deploy the stacks in your app, consider deploying a copy first so you can test it. The easiest way to do this is to deploy it into a different Region. However, you can also change the IDs of your stacks. After testing, be sure to destroy the testing copy with `cdk destroy`. - -[#migrating-v2-trouble.title] -== Troubleshooting - -*TypeScript `'from' expected` or `';' expected` error in imports*:: -+ -Upgrade to TypeScript 3.8 or later. - -*Run 'cdk bootstrap'*:: -+ -If you see an error like the following: -+ ----- -❌ MyStack failed: Error: MyStack: SSM parameter /cdk-bootstrap/hnb659fds/version not found. Has the environment been bootstrapped? Please run 'cdk bootstrap' (see https://docs.aws.amazon.com/cdk/latest/guide/bootstrapping.html) - at CloudFormationDeployments.validateBootstrapStackVersion (.../aws-cdk/lib/api/cloudformation-deployments.ts:323:13) - at processTicksAndRejections (internal/process/task_queues.js:97:5) -MyStack: SSM parameter /cdk-bootstrap/hnb659fds/version not found. Has the environment been bootstrapped? Please run 'cdk bootstrap' (see https://docs.aws.amazon.com/cdk/latest/guide/bootstrapping.html) ----- -+ -{aws} CDK v2 requires an updated bootstrap stack, and furthermore, all v2 deployments require bootstrap resources. (With v1, you could deploy simple stacks without bootstrapping.) For complete details, see xref:bootstrapping[{aws} CDK bootstrapping]. - -[#finding-v1-stacks.title] -== Finding v1 stacks - -When migrating your CDK application from v1 to v2, you might want to identify the deployed {aws} CloudFormation stacks that were created using v1. To do this, run the following command: - -[source,none,subs="verbatim,attributes"] ----- -npx awscdk-v1-stack-finder ----- - -For usage details, see the awscdk-v1-stack-finder https://github.com/cdklabs/awscdk-v1-stack-finder/blob/main/README.md[README]. \ No newline at end of file diff --git a/v2/guide/ref-cli-cmd/ref-cli-cmd-ack.adoc b/v2/guide/ref-cli-cmd/ref-cli-cmd-ack.adoc deleted file mode 100644 index 46bee0b1..00000000 --- a/v2/guide/ref-cli-cmd/ref-cli-cmd-ack.adoc +++ /dev/null @@ -1,88 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[#ref-cli-cmd-ack] -= `cdk acknowledge` -:info_titleabbrev: cdk ack -:keywords: {aws} CDK, {aws} CDK CLI, CDK Toolkit, IaC, Infrastructure as code, {aws} Cloud, {aws} CloudFormation, cdk acknowledge, cdk ack - -[abstract] --- -Acknowledge a notice by issue number and hide it from displaying again. --- - -// Content start - -Acknowledge a notice by issue number and hide it from displaying again. - -This is useful to hide notices that have been addressed or do not apply to you. - -Acknowledgements are saved at a CDK project level. If you acknowledge a notice in one CDK project, it will still display in other projects until acknowledged there. - -[#ref-cli-cmd-ack-usage] -== Usage - -[source,none,subs="verbatim,attributes"] ----- -$ cdk acknowledge <arguments> <options> ----- - -[#ref-cli-cmd-ack-args] -== Arguments - -[#ref-cli-cmd-ack-args-notice-id] -*Notice ID*:: -The ID of the notice. -+ -_Type_: String -+ -_Required_: No - -[#ref-cli-cmd-ack-options] -== Options - -For a list of global options that work with all CDK CLI commands, see xref:ref-cli-cmd-options[Global options]. - -[#ref-cli-cmd-ack-options-help] -`--help, -h <BOOLEAN>`:: -Show command reference information for the `cdk acknowledge` command. - -[#ref-cli-cmd-ack-examples] -== Examples - -[#ref-cli-cmd-ack-examples-1] -=== Acknowledge and hide a notice that displays when running another CDK CLI command - -[source,none,subs="verbatim,attributes"] ----- -$ cdk deploy -... # Normal output of the command - -NOTICES - -16603 Toggling off auto_delete_objects for Bucket empties the bucket - - Overview: If a stack is deployed with an S3 bucket with - auto_delete_objects=True, and then re-deployed with - auto_delete_objects=False, all the objects in the bucket - will be deleted. - - Affected versions: <1.126.0. - - More information at: https://github.com/aws/aws-cdk/issues/16603 - - -17061 Error when building EKS cluster with monocdk import - - Overview: When using monocdk/aws-eks to build a stack containing - an EKS cluster, error is thrown about missing - lambda-layer-node-proxy-agent/layer/package.json. - - Affected versions: >=1.126.0 <=1.130.0. - - More information at: https://github.com/aws/aws-cdk/issues/17061 - -$ cdk acknowledge 16603 ----- \ No newline at end of file diff --git a/v2/guide/ref-cli-cmd/ref-cli-cmd-bootstrap.adoc b/v2/guide/ref-cli-cmd/ref-cli-cmd-bootstrap.adoc deleted file mode 100644 index 8e22f220..00000000 --- a/v2/guide/ref-cli-cmd/ref-cli-cmd-bootstrap.adoc +++ /dev/null @@ -1,304 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[#ref-cli-cmd-bootstrap] -= `cdk bootstrap` -:keywords: {aws} CDK, {aws} CDK CLI, CDK Toolkit, IaC, Infrastructure as code, {aws} Cloud, {aws} CloudFormation, bootstrap - -[abstract] --- -Prepare an {aws} environment for CDK deployments by deploying the CDK bootstrap stack, named `CDKToolkit`, into the {aws} environment. --- - -// Content start - -Prepare an {aws} environment for CDK deployments by deploying the CDK bootstrap stack, named `CDKToolkit`, into the {aws} environment. - -The bootstrap stack is a CloudFormation stack that provisions an Amazon S3 bucket and Amazon ECR repository in the {aws} environment. The {aws} CDK CLI uses these resources to store synthesized templates and related assets during deployment. - -[#ref-cli-cmd-bootstrap-usage] -== Usage - -[source,none,subs="verbatim,attributes"] ----- -$ cdk bootstrap <arguments> <options> ----- - -[#ref-cli-cmd-bootstrap-args] -== Arguments - -[#ref-cli-cmd-bootstrap-args-env] -*{aws} environment*:: -The target {aws} environment to deploy the bootstrap stack to in the following format: `aws://<account-id>/<region>`. -+ -Example: `aws://123456789012/us-east-1` -+ -This argument can be provided multiple times in a single command to deploy the bootstrap stack to multiple environments. -+ -By default, the CDK CLI will bootstrap all environments referenced in the CDK app or will determine an environment from default sources. This could be an environment specified using the `--profile` option, from environment variables, or default {aws} CLI sources. - -[#ref-cli-cmd-bootstrap-options] -== Options - -For a list of global options that work with all CDK CLI commands, see xref:ref-cli-cmd-options[Global options]. - -[#ref-cli-cmd-bootstrap-options-bootstrap-bucket-name] -`--bootstrap-bucket-name, --toolkit-bucket-name, -b <STRING>`:: -The name of the Amazon S3 bucket that will be used by the CDK CLI. This bucket will be created and must not currently exist. -+ -Provide this option to override the default name of the Amazon S3 bucket. -+ -When you use this option, you may have to customize synthesis. To learn more, see xref:bootstrapping-custom-synth[Customize CDK stack synthesis]. -+ -_Default value_: Undefined - -[#ref-cli-cmd-bootstrap-options-bootstrap-customer-key] -`--bootstrap-customer-key <BOOLEAN>`:: -Create a Customer Master Key (CMK) for the bootstrap bucket (you will be charged but can customize permissions, modern bootstrapping only). -+ -This option is not compatible with `--bootstrap-kms-key-id`. -+ -_Default value_: Undefined - -[#ref-cli-cmd-bootstrap-options-bootstrap-kms-key-id] -`--bootstrap-kms-key-id <STRING>`:: -The {aws} KMS master key ID to use for the `SSE-KMS` encryption. -+ -Provide this option to override the default {aws} KMS key used to encrypt the Amazon S3 bucket. -+ -This option is not compatible with `--bootstrap-customer-key`. -+ -_Default value_: Undefined - -[#ref-cli-cmd-bootstrap-options-cloudformation-execution-policies] -`--cloudformation-execution-policies <ARRAY>`:: -The managed IAM policy ARNs that should be attached to the deployment role assumed by {aws} CloudFormation during deployment of your stacks. -+ -By default, stacks are deployed with full administrator permissions using the `AdministratorAccess` policy. -+ -You can provide this option multiple times in a single command. You can also provide multiple ARNs as a single string, with the individual ARNs separated by commas. The following is an example: -+ -[source,none,subs="verbatim,attributes"] ----- -$ cdk bootstrap --cloudformation-execution-policies "arn:aws:iam::aws:policy/AWSLambda_FullAccess,arn:aws:iam::aws:policy/AWSCodeDeployFullAccess" ----- -+ -To avoid deployment failures, be sure that the policies you specify are sufficient for any deployments that you will perform into the environment being bootstrapped. -+ -This option applies to modern bootstrapping only. -+ -[IMPORTANT] -==== -The modern bootstrap template effectively grants the permissions implied by the `--cloudformation-execution-policies` to any {aws} account in the `--trust` list. By default, this extends permissions to read and write to any resource in the bootstrapped account. Make sure to xref:bootstrapping-customizing[configure the bootstrapping stack] with policies and trusted accounts that you are comfortable with. -==== -+ -_Default value_: `[]` - -[#ref-cli-cmd-bootstrap-options-custom-permissions-boundary] -`--custom-permissions-boundary, -cpb <STRING>`:: -Specify the name of a permissions boundary to use. -+ -This option is not compatible with ``--example-permissions-boundary``. -+ -_Default value_: Undefined - -[#ref-cli-cmd-bootstrap-options-example-permissions-boundary] -`--example-permissions-boundary, -epb <BOOLEAN>`:: -Use the example permissions boundary, supplied by the {aws} CDK. -+ -This option is not compatible with `--custom-permissions-boundary`. -+ -The CDK supplied permissions boundary policy should be regarded as an example. Edit the content and reference the example policy if you are testing out the feature. Convert it into a new policy for actual deployments, if one does not already exist. The concern is to avoid drift. Most likely, a permissions boundary is maintained and has dedicated conventions, naming included. -+ -For more information on configuring permissions, including using permissions boundaries, see the https://github.com/aws/aws-cdk/wiki/Security-And-Safety-Dev-Guide[Security and Safety Dev Guide]. -+ -_Default value_: Undefined - -[#ref-cli-cmd-bootstrap-options-execute] -`--execute <BOOLEAN>`:: -Configure whether to execute the change set. -+ -_Default value_: `true` - -[#ref-cli-cmd-bootstrap-options-force] -`--force, -f <BOOLEAN>`:: -Always bootstrap, even if it would downgrade the bootstrap template version. -+ -_Default value_: `false` - -[#ref-cli-cmd-bootstrap-options-help] -`--help, -h <BOOLEAN>`:: -Show command reference information for the `cdk bootstrap` command. - -[#ref-cli-cmd-bootstrap-options-previous-parameters] -`--previous-parameters <BOOLEAN>`:: -Use previous values for existing parameters. -+ -Once a bootstrap template is deployed with a set of parameters, you must set this option to `false` to change any parameters on future deployments. When `false`, you must re-supply all previously supplied parameters. -+ -_Default value_: `true` - -[#ref-cli-cmd-bootstrap-options-public-access-block-configuration] -`--public-access-block-configuration <BOOLEAN>`:: -Block public access configuration on the Amazon S3 bucket that is created and used by the CDK CLI. -+ -_Default value_: `true` - -[#ref-cli-cmd-bootstrap-options-qualifier] -`--qualifier <STRING>`:: -Nine-digit string value that is unique for each bootstrap stack. This value is added to the physical ID of resources in the bootstrap stack. -+ -By providing a qualifier, you avoid resource name clashes when provisioning multiple bootstrap stacks in the same environment. -+ -When you change the qualifier, your CDK app must pass the changed value to the stack synthesizer. For more information, see xref:bootstrapping-custom-synth[Customize CDK stack synthesis]. -+ -_Default value_: `hnb659fds`. This value has no significance. - -[#ref-cli-cmd-bootstrap-options-show-template] -`--show-template <BOOLEAN>`:: -Instead of bootstrapping, print the current bootstrap template to the standard output (`stdout`). You can then copy and customize the template as necessary. -+ -_Default value_: `false` - -[#ref-cli-cmd-bootstrap-options-tags] -`--tags, -t <ARRAY>`:: -Tags to add to the bootstrap stack in the format of `KEY=VALUE`. -+ -_Default value_: `[]` - -[#ref-cli-cmd-bootstrap-options-template] -`--template <STRING>`:: -Use the template from the given file instead of the built-in one. - -[#ref-cli-cmd-bootstrap-options-termination-protection] -`--termination-protection <BOOLEAN>`:: -Toggle {aws} CloudFormation termination protection on the bootstrap stack. -+ -When `true`, termination protection is enabled. This prevents the bootstrap stack from being accidentally deleted. -+ -To learn more about termination protection, see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-protect-stacks.html[Protecting a stack from being deleted] in the _{aws} CloudFormation User Guide_. -+ -_Default value_: Undefined - -[#ref-cli-cmd-bootstrap-options-toolkit-stack-name] -`--toolkit-stack-name <STRING>`:: -The name of the bootstrap stack to create. -+ -By default, `cdk bootstrap` deploys a stack named `CDKToolkit` into the specified {aws} environment. Use this option to provide a different name for your bootstrap stack. -+ -The CDK CLI uses this value to verify your bootstrap stack version. -+ -_Default value_: `CDKToolkit` -+ -_Required_: Yes - -[#ref-cli-cmd-bootstrap-options-trust] -`--trust <ARRAY>`:: -The {aws} account IDs that should be trusted to perform deployments into this environment. -+ -The account performing the bootstrapping will always be trusted. -+ -This option requires that you also provide `--cloudformation-execution-policies`. -+ -You can provide this option multiple times in a single command. -+ -This option applies to modern bootstrapping only. -+ -To add trusted accounts to an existing bootstrap stack, you must specify all of the accounts to trust, including those that you may have previously provided. If you only provide new accounts to trust, the previously trusted accounts will be removed. -+ -The following is an example that trusts two accounts: -+ -[source,none,subs="verbatim,attributes"] ----- -$ cdk bootstrap aws://123456789012/us-west-2 --trust 234567890123 --trust 987654321098 --cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess - ⏳ Bootstrapping environment aws://123456789012/us-west-2... -Trusted accounts for deployment: 234567890123, 987654321098 -Trusted accounts for lookup: (none) -Execution policies: arn:aws:iam::aws:policy/AdministratorAccess -CDKToolkit: creating CloudFormation changeset... - ✅ Environment aws://123456789012/us-west-2 bootstrapped. ----- -+ -[IMPORTANT] -==== -The modern bootstrap template effectively grants the permissions implied by the `--cloudformation-execution-policies` to any {aws} account in the `--trust` list. By default, this extends permissions to read and write to any resource in the bootstrapped account. Make sure to xref:bootstrapping-customizing[configure the bootstrapping stack] with policies and trusted accounts that you are comfortable with. -==== -+ -_Default value_: `[]` - -[#ref-cli-cmd-bootstrap-options-trust-for-lookup] -`--trust-for-lookup <ARRAY>`:: -The {aws} account IDs that should be trusted to look up values in this environment. -+ -Use this option to give accounts permission to synthesize stacks that will be deployed into the environment, without actually giving them permission to deploy those stacks directly. -+ -You can provide this option multiple times in a single command. -+ -This option applies to modern bootstrapping only. -+ -_Default value_: `[]` - -[#ref-cli-cmd-bootstrap-examples] -== Examples - -[#ref-cli-cmd-bootstrap-examples-1] -=== Bootstrap the {aws} environment specified in the prod profile - -[source,none,subs="verbatim,attributes"] ----- -$ cdk bootstrap --profile prod ----- - -[#ref-cli-cmd-bootstrap-examples-2] -=== Deploy the bootstrap stack to environments foo and bar - -[source,none,subs="verbatim,attributes"] ----- -$ cdk bootstrap --app='node bin/main.js' foo bar ----- - -[#ref-cli-cmd-bootstrap-examples-3] -=== Export the bootstrap template to customize it - -If you have specific requirements that are not met by the bootstrap template, you can customize it to fit your needs. - -You can export the bootstrap template, modify it, and deploy it using {aws} CloudFormation. The following is an example of exporting the existing template: - -[source,none,subs="verbatim,attributes"] ----- -$ cdk bootstrap --show-template > bootstrap-template.yaml ----- - -You can also tell the CDK CLI to use a custom template. The following is an example: - -[source,none,subs="verbatim,attributes"] ----- -$ cdk bootstrap --template my-bootstrap-template.yaml ----- - -[#ref-cli-cmd-bootstrap-examples-4] -=== Bootstrap with a permissions boundary. Then, remove that permissions boundary - -To bootstrap with a custom permissions boundary, we run the following: - -[source,none,subs="verbatim,attributes"] ----- -$ cdk bootstrap --custom-permissions-boundary my-permissions-boundary ----- - -To remove the permissions boundary, we run the following: - -[source,none,subs="verbatim,attributes"] ----- -$ cdk bootstrap --no-previous-parameters ----- - -[#ref-cli-cmd-bootstrap-examples-5] -=== Use a qualifier to distinguish resources that are created for a development environment - -[source,none,subs="verbatim,attributes"] ----- -$ cdk bootstrap --qualifier dev2024 ----- \ No newline at end of file diff --git a/v2/guide/ref-cli-cmd/ref-cli-cmd-context.adoc b/v2/guide/ref-cli-cmd/ref-cli-cmd-context.adoc deleted file mode 100644 index 08773039..00000000 --- a/v2/guide/ref-cli-cmd/ref-cli-cmd-context.adoc +++ /dev/null @@ -1,55 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[#ref-cli-cmd-context] -= `cdk context` -:keywords: {aws} CDK, {aws} CDK CLI, CDK Toolkit, IaC, Infrastructure as code, {aws} Cloud, {aws} CloudFormation, cdk context - -[abstract] --- -Manage cached context values for your {aws} CDK application. --- - -// Content start - -Manage cached context values for your {aws} CDK application. - -_Context_ represents the configuration and environment information that can influence how your stacks are synthesized and deployed. Use `cdk context` to do the following: - -* View your configured context values. -* Set and manage context values. -* Remove context values. - -[#ref-cli-cmd-context-usage] -== Usage - -[source,none,subs="verbatim,attributes"] ----- -$ cdk context <options> ----- - -[#ref-cli-cmd-context-options] -== Options - -For a list of global options that work with all CDK CLI commands, see xref:ref-cli-cmd-options[Global options]. - - -[#ref-cli-cmd-context-options-clear] -`--clear <BOOLEAN>`:: -Clear all context. - -[#ref-cli-cmd-context-options-force] -`--force, -f <BOOLEAN>`:: -Ignore missing key error. -+ -_Default value_: `false` - -[#ref-cli-cmd-context-options-help] -`--help, -h <BOOLEAN>`:: -Show command reference information for the `cdk context` command. - -[#ref-cli-cmd-context-options-reset] -`--reset, -e <STRING>`:: -The context key, or its index, to reset. \ No newline at end of file diff --git a/v2/guide/ref-cli-cmd/ref-cli-cmd-deploy.adoc b/v2/guide/ref-cli-cmd/ref-cli-cmd-deploy.adoc deleted file mode 100644 index 1cd8ee35..00000000 --- a/v2/guide/ref-cli-cmd/ref-cli-cmd-deploy.adoc +++ /dev/null @@ -1,469 +0,0 @@ -include::../attributes.txt[] - -// Attributes -[.topic] -[#ref-cli-cmd-deploy] -= `cdk deploy` -:keywords: {aws} CDK, {aws} CDK CLI, CDK Toolkit, IaC, Infrastructure as code, {aws} Cloud, {aws} CloudFormation, cdk deploy - -[abstract] --- -Deploy one or more {aws} CDK stacks into your {aws} environment. --- - -// Content start - -Deploy one or more {aws} CDK stacks into your {aws} environment. - -During deployment, the CDK CLI will output progress indicators, similar to what can be observed from the {aws} CloudFormation console. - -If the {aws} environment is not bootstrapped, only stacks without assets and with synthesized templates under 51,200 bytes will successfully deploy. - -[#ref-cli-cmd-deploy-usage] -== Usage - -[source,none,subs="verbatim,attributes"] ----- -$ cdk deploy <arguments> <options> ----- - -[#ref-cli-cmd-deploy-args] -== Arguments - -[#ref-cli-cmd-deploy-args-stack-name] -*CDK stack ID*:: -The construct ID of the CDK stack from your app to deploy. -+ -_Type_: String -+ -_Required_: No - -[#ref-cli-cmd-deploy-options] -== Options - -For a list of global options that work with all CDK CLI commands, see xref:ref-cli-cmd-options[Global options]. - -[#ref-cli-cmd-deploy-options-all] -`--all <BOOLEAN>`:: -Deploy all stacks in your CDK app. -+ -_Default value_: `false` - -[#ref-cli-cmd-deploy-options-asset-parallelism] -`--asset-parallelism <BOOLEAN>`:: -Specify whether to build and publish assets in parallel. - -[#ref-cli-cmd-deploy-options-asset-prebuild] -`--asset-prebuild <BOOLEAN>`:: -Specify whether to build all assets before deploying the first stack. This option is useful for failing Docker builds. -+ -_Default value_: `true` - -[#ref-cli-cmd-deploy-options-build-exclude] -`--build-exclude, -E <ARRAY>`:: -Do not rebuild asset with the given ID. -+ -This option can be specified multiple times in a single command. -+ -_Default value_: `[]` - -[#ref-cli-cmd-deploy-options-change-set-name] -`--change-set-name <STRING>`:: -The name of the {aws} CloudFormation change set to create. -+ -This option is not compatible with `--method='direct'`. - -[#ref-cli-cmd-deploy-options-concurrency] -`--concurrency <NUMBER>`:: -Deploy multiple stacks in parallel while accounting for inter-stack dependencies. Use this option to speed up deployments. You must still factor in {aws} CloudFormation and other {aws} account rate limiting. -+ -Provide a number to specify the maximum number of simultaneous deployments (dependency permitting) to perform. -+ -_Default value_: `1` - -[#ref-cli-cmd-deploy-options-exclusively] -`--exclusively, -e <BOOLEAN>`:: -Only deploy requested stacks and don't include dependencies. - -[#ref-cli-cmd-deploy-options-force] -`--force, -f <BOOLEAN>`:: -When you deploy to update an existing stack, the CDK CLI will compare the template and tags of the deployed stack to the stack about to be deployed. If no changes are detected, the CDK CLI will skip deployment. -+ -To override this behavior and always deploy stacks, even if no changes are detected, use this option. -+ -_Default value_: `false` - -[#ref-cli-cmd-deploy-options-help] -`--help, -h <BOOLEAN>`:: -Show command reference information for the `cdk deploy` command. - -[#ref-cli-cmd-deploy-options-hotswap] -`--hotswap <BOOLEAN>`:: -Hotswap deployments for faster development. This option attempts to perform a faster, hotswap deployment if possible. For example, if you modify the code of a Lambda function in your CDK app, the CDK CLI will update the resource directly through service APIs instead of performing a CloudFormation deployment. -+ -If the CDK CLI detects changes that don't support hotswapping, those changes will be ignored and a message will display. If you prefer to perform a full CloudFormation deployment as a fall back, use `--hotswap-fallback` instead. -+ -The CDK CLI uses your current {aws} credentials to perform the API calls. It does not assume the roles from your bootstrap stack, even if the `@aws-cdk/core:newStyleStackSynthesis` feature flag is set to `true`. Those roles do not have the necessary permissions to update {aws} resources directly, without using CloudFormation. For that reason, make sure that your credentials are for the same {aws} account of the stacks that you are performing hotswap deployments against and that they have the necessary IAM permissions to update the resources. -+ -Hotswapping is currently supported for the following changes: -+ --- -* Code assets (including Docker images and inline code), tag changes, and configuration changes (only description and environment variables are supported) of Lambda functions. -* Lambda versions and alias changes. -* Definition changes of {aws} Step Functions state machines. -* Container asset changes of Amazon ECS services. -* Website asset changes of Amazon S3 bucket deployments. -* Source and environment changes of {aws} CodeBuild projects. -* VTL mapping template changes for {aws} AppSync resolvers and functions. -* Schema changes for {aws} AppSync GraphQL APIs. --- -+ -Usage of certain CloudFormation intrinsic functions are supported as part of a hotswapped deployment. These include: -+ --- -* `Ref` -* `Fn::GetAtt` – Only partially supported. Refer to link:https://github.com/aws/aws-cdk/blob/main/packages/aws-cdk/lib/api/evaluate-cloudformation-template.ts#L477-L492[this implementation] for supported resources and attributes. -* `Fn::ImportValue` -* `Fn::Join` -* `Fn::Select` -* `Fn::Split` -* `Fn::Sub` --- -+ -This option is also compatible with nested stacks. -+ -[NOTE] -==== -** This option deliberately introduces drift in CloudFormation stacks in order to speed up deployments. For this reason, only use it for development purposes. Do not use this option for your production deployments. -** This option is considered experimental and may have breaking changes in the future. -** Defaults for certain parameters may be different with the hotswap parameter. For example, an Amazon ECS service`'s minimum healthy percentage will currently be set at ``0``. Review the source accordingly if this occurs. -==== -+ -_Default value_: `false` - -[#ref-cli-cmd-deploy-options-hotswap-fallback] -`--hotswap-fallback <BOOLEAN>`:: -This option is is similar to `--hotswap`. The difference being that `--hotswap-fallback` will fall back to perform a full CloudFormation deployment if a change is detected that requires it. -+ -For more information about this option, see `--hotswap`. -+ -_Default value_: `false` - -[#ref-cli-cmd-deploy-options-ignore-no-stacks] -`--ignore-no-stacks <BOOLEAN>`:: -Perform a deployment even if your CDK app doesn't contain any stacks. -+ -This option is helpful in the following scenario: You may have an app with multiple environments, such as `dev` and `prod`. When starting development, your prod app may not have any resources, or the resources may be commented out. This will result in a deployment error with a message stating that the app has no stacks. Use `--ignore-no-stacks` to bypass this error. -+ -_Default value_: `false` - -[#ref-cli-cmd-deploy-options-import-existing-resources] -`--import-existing-resources <BOOLEAN>`:: -Import existing, unmanaged {aws} CloudFormation resources from your {aws} account. -+ -When you use this option, resources from your synthesized {aws} CloudFormation template with the same custom name as existing unmanaged resources in the same account will be imported into your stack. -+ -You can use this option to import existing resources into new or existing stacks. -+ -You can import existing resources and deploy new resources in the same `cdk deploy` command. -+ -To learn more about custom names, see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-name.html[Name type] in the _{aws} CloudFormation User Guide_. -+ -To learn more about the `ImportExistingResources` CloudFormation parameter, see https://aws.amazon.com/about-aws/whats-new/2023/11/aws-cloudformation-import-parameter-changesets/[{aws} CloudFormation simplifies resource import with a new parameter for ChangeSets]. -+ -For more information on using this option, see link:https://github.com/aws/aws-cdk-cli/tree/main/packages/aws-cdk#import-existing-resources[Import existing resources] in the _aws-cdk-cli GitHub repository_. - -[#ref-cli-cmd-deploy-options-logs] -`--logs <BOOLEAN>`:: -Show Amazon CloudWatch log in the standard output (`stdout`) for all events from all resources in the selected stacks. -+ -This option is only compatible with `--watch`. -+ -_Default value_: `true` - -[#ref-cli-cmd-deploy-options-method] -`--method, -m <STRING>`:: -Configure the method to perform a deployment. -+ --- -* `change-set` – Default method. The CDK CLI creates a CloudFormation change set with the changes that will be deployed, then performs deployment. -* `direct` – Do not create a change set. Instead, apply the change immediately. This is typically faster than creating a change set, but you lose progress information. -* `prepare-change-set` – Create change set but don't perform deployment. This is useful if you have external tools that will inspect the change set or if you have an approval process for change sets. --- -+ -_Valid values_: `change-set`, `direct`, `prepare-change-set` -+ -_Default value_: `change-set` - -[#ref-cli-cmd-deploy-options-notification-arns] -`--notification-arns <ARRAY>`:: -The ARNs of Amazon SNS topics that CloudFormation will notify for stack related events. - -[#ref-cli-cmd-deploy-options-outputs-file] -`--outputs-file, -O <STRING>`:: -The path to where stack outputs from deployments are written to. -+ -After deployment, stack outputs will be written to the specified output file in JSON format. -+ -You can configure this option in the project's `cdk.json` file or at `~/.cdk.json` on your local development machine: -+ -[source,json,subs="verbatim,attributes"] ----- -{ - "app": "npx ts-node bin/myproject.ts", - // ... - "outputsFile": "outputs.json" -} ----- -+ -If multiple stacks are deployed, outputs are written to the same output file, organized by keys representing the stack name. - -[#ref-cli-cmd-deploy-options-parameters] -`--parameters <ARRAY>`:: -Pass additional parameters to CloudFormation during deployment. -+ -This option accepts an array in the following format: `STACK:KEY=VALUE`. -+ --- -* `STACK` – The name of the stack to associate the parameter with. -* `KEY` – The name of the parameter from your stack. -* `VALUE` – The value to pass at deployment. --- -+ -If a stack name is not provided, or if `*` is provided as the stack name, parameters will be applied to all stacks being deployed. If a stack does not make use of the parameter, deployment will fail. -+ -Parameters do not propagate to nested stacks. To pass parameters to nested stacks, use the `link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.NestedStack.html[NestedStack]` construct. -+ -_Default value_: `{}` - -[#ref-cli-cmd-deploy-options-previous-parameters] -`--previous-parameters <BOOLEAN>`:: -Use previous values for existing parameters. -+ -When this option is set to `false`, you must specify all parameters on every deployment. -+ -_Default value_: `true` - -[#ref-cli-cmd-deploy-options-progress] -`--progress <STRING>`:: -Configure how the CDK CLI displays deployment progress. -+ --- -* `bar` – Display stack deployment events as a progress bar, with the events for the resource currently being deployed. -* `events` – Provide a complete history, including all CloudFormation events. --- -+ -You can also configure this option in the project's `cdk.json` file or at `~/.cdk.json` on your local development machine: -+ -[source,json,subs="verbatim,attributes"] ----- -{ - "progress": "events" -} ----- -+ -_Valid values_: `bar`, `events` -+ -_Default value_: `bar` - -[#ref-cli-cmd-deploy-options-require-approval] -`--require-approval <STRING>`:: -Specify what security-sensitive changes require manual approval. -+ --- -* `any-change` – Manual approval required for any change to the stack. -* `broadening` – Manual approval required if changes involve a broadening of permissions or security group rules. -* `never` – Approval is not required. --- -+ -_Valid values_: `any-change`, `broadening`, `never` -+ -_Default value_: `broadening` - -[#ref-cli-cmd-deploy-options-rollback] -`--rollback` | `--no-rollback`, `-R`:: -During deployment, if a resource fails to be created or updated, the deployment will roll back to the latest stable state before the CDK CLI returns. All changes made up to that point will be undone. Resources that were created will be deleted and updates that were made will be rolled back. -+ -Specify `--no-rollback` to turn off this behavior. If a resource fails to be created or updated, the CDK CLI will leave changes made up to that point in place and return. This will leave your deployment in a failed, paused state. From here, you can update your code and try the deployment again. This may be helpful in development environments where you are iterating quickly. -+ -If a deployment performed with `--no-rollback` fails, and you decide that you want to rollback the deployment, you can use the `cdk rollback` command. For more information, see xref:ref-cli-cmd-rollback[cdk rollback]. -+ -[NOTE] -==== -With `--no-rollback`, deployments that cause resource replacements will always fail. You can only use this option value for deployments that update or create new resources. -==== -+ -_Default value_: `--rollback` - -[#ref-cli-cmd-deploy-options-toolkit-stack-name] -`--toolkit-stack-name <STRING>`:: -The name of the existing CDK Toolkit stack. -+ -By default, `cdk bootstrap` deploys a stack named `CDKToolkit` into the specified {aws} environment. Use this option to provide a different name for your bootstrap stack. -+ -The CDK CLI uses this value to verify your bootstrap stack version. - -[#ref-cli-cmd-deploy-options-watch] -`--watch <BOOLEAN>`:: -Continuously observe CDK project files, and deploy the specified stacks automatically when changes are detected. -+ -This option implies `--hotswap` by default. -+ -This option has an equivalent CDK CLI command. For more information, see xref:ref-cli-cmd-watch[cdk watch]. - -[#ref-cli-cmd-deploy-examples] -== Examples - -[#ref-cli-cmd-deploy-examples-1] -=== Deploy the stack named MyStackName - -[source,none,subs="verbatim,attributes"] ----- -$ cdk deploy MyStackName --app='node bin/main.js' ----- - -[#ref-cli-cmd-deploy-examples-2] -=== Deploy multiple stacks in an app - -Use `cdk list` to list your stacks: - -[source,none,subs="verbatim,attributes"] ----- -$ cdk list -CdkHelloWorldStack -CdkStack2 -CdkStack3 ----- - -To deploy all stacks, use the `--all` option: - -[source,none,subs="verbatim,attributes"] ----- -$ cdk deploy --all ----- - -To choose which stacks to deploy, provide stack names as arguments: - -[source,none,subs="verbatim,attributes"] ----- -$ cdk deploy CdkHelloWorldStack CdkStack3 ----- - -[#ref-cli-cmd-deploy-examples-3] -=== Deploy pipeline stacks - -Use `cdk list` to show stack names as paths, showing where they are in the pipeline hierarchy: - -[source,none,subs="verbatim,attributes"] ----- -$ cdk list -PipelineStack -PiplelineStack/Prod -PipelineStack/Prod/MyService ----- - -Use the `--all` option or the wildcard `\*` to deploy all stacks. If you have a hierarchy of stacks as described above, `--all` and `*` will only match stacks on the top level. To match all stacks in the hierarchy, use ``**``. - -You can combine these patterns. The following deploys all stacks in the `Prod` stage: - -[source,none,subs="verbatim,attributes"] ----- -$ cdk deploy PipelineStack/Prod/** ----- - -[#ref-cli-cmd-deploy-examples-4] -=== Pass parameters at deployment - -Define parameters in your CDK stack. The following is an example that creates a parameter named `TopicNameParam` for an Amazon SNS topic: - -[source,javascript,subs="verbatim,attributes"] ----- -new sns.Topic(this, 'TopicParameter', { - topicName: new cdk.CfnParameter(this, 'TopicNameParam').value.toString() -}); ----- - -To provide a parameter value of `parameterized`, run the following: - -[source,none,subs="verbatim,attributes"] ----- -$ cdk deploy --parameters "MyStackName:TopicNameParam=parameterized" ----- - -You can override parameter values by using the `--force` option. The following is an example of overriding the topic name from a previous deployment: - -[source,none,subs="verbatim,attributes"] ----- -$ cdk deploy --parameters "MyStackName:TopicNameParam=parameterName" --force ----- - -[#ref-cli-cmd-deploy-examples-5] -=== Write stack outputs to a file after deployment - -Define outputs in your CDK stack file. The following is an example that creates an output for a function ARN: - -[source,javascript,subs="verbatim,attributes"] ----- -const fn = new lambda.Function(this, "fn", { - handler: "index.handler", - code: lambda.Code.fromInline(`exports.handler = \${handler.toString()}`), - runtime: lambda.Runtime.NODEJS_LATEST -}); - -new cdk.CfnOutput(this, 'FunctionArn', { - value: fn.functionArn, -}); ----- - -Deploy the stack and write outputs to `outputs.json`: - -[source,none,subs="verbatim,attributes"] ----- -$ cdk deploy --outputs-file outputs.json ----- - -The following is an example of `outputs.json` after deployment: - -[source,json,subs="verbatim,attributes"] ----- -{ - "MyStack": { - "FunctionArn": "arn:aws:lambda:us-east-1:123456789012:function:MyStack-fn5FF616E3-G632ITHSP5HK" - } -} ----- - -From this example, the key `FunctionArn` corresponds to the logical ID of the `CfnOutput` instance. - -The following is an example of `outputs.json` after deployment when multiple stacks are deployed: - -[source,json,subs="verbatim,attributes"] ----- -{ - "MyStack": { - "FunctionArn": "arn:aws:lambda:us-east-1:123456789012:function:MyStack-fn5FF616E3-G632ITHSP5HK" - }, - "AnotherStack": { - "VPCId": "vpc-z0mg270fee16693f" - } -} ----- - -[#ref-cli-cmd-deploy-examples-6] -=== Modify the deployment method - -To deploy faster, without using change sets, use `--method='direct'`: - -[source,none,subs="verbatim,attributes"] ----- -$ cdk deploy --method='direct' ----- - -To create a change set but don't deploy, use `--method='prepare-change-set'`. By default, a change set named `cdk-deploy-change-set` will be created. If a previous change set with this name exists, it will be overwritten. If no changes are detected, an empty change set is still created. - -You can also name your change set. The following is an example: - -[source,none,subs="verbatim,attributes"] ----- -$ cdk deploy --method='prepare-change-set' --change-set-name='MyChangeSetName' ----- \ No newline at end of file diff --git a/v2/guide/ref-cli-cmd/ref-cli-cmd-destroy.adoc b/v2/guide/ref-cli-cmd/ref-cli-cmd-destroy.adoc deleted file mode 100644 index 456c0e78..00000000 --- a/v2/guide/ref-cli-cmd/ref-cli-cmd-destroy.adoc +++ /dev/null @@ -1,74 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[#ref-cli-cmd-destroy] -= `cdk destroy` -:keywords: {aws} CDK, {aws} CDK CLI, CDK Toolkit, IaC, Infrastructure as code, {aws} Cloud, {aws} CloudFormation, cdk destroy - -[abstract] --- -Delete one or more {aws} CDK stacks from your {aws} environment. --- - -// Content start - -Delete one or more {aws} CDK stacks from your {aws} environment. - -When you delete a stack, resources in the stack will be destroyed, unless they were configured with a `DeletionPolicy` of `Retain`. - -During stack deletion, this command will output progress information similar to `cdk deploy` behavior. - -[#ref-cli-cmd-destroy-usage] -== Usage - -[source,none,subs="verbatim,attributes"] ----- -$ cdk destroy <arguments> <options> ----- - -[#ref-cli-cmd-destroy-args] -== Arguments - -[#ref-cli-cmd-destroy-args-stack-name] -*CDK stack ID*:: -The construct ID of the CDK stack from your app to delete. -+ -_Type_: String -+ -_Required_: No - -[#ref-cli-cmd-destroy-options] -== Options - -For a list of global options that work with all CDK CLI commands, see xref:ref-cli-cmd-options[Global options]. - -[#ref-cli-cmd-destroy-options-all] -`--all <BOOLEAN>`:: -Destroy all available stacks. -+ -_Default value_: `false` - -[#ref-cli-cmd-destroy-options-exclusively] -`--exclusively, -e <BOOLEAN>`:: -Only destroy requested stacks and don't include dependencies. - -[#ref-cli-cmd-destroy-options-force] -`--force, -f <BOOLEAN>`:: -Do not ask for confirmation before destroying the stacks. - -[#ref-cli-cmd-destroy-options-help] -`--help, -h <BOOLEAN>`:: -Show command reference information for the `cdk destroy` command. - -[#ref-cli-cmd-destroy-examples] -== Examples - -[#ref-cli-cmd-destroy-examples-1] -=== Delete a stack named MyStackName - -[source,none,subs="verbatim,attributes"] ----- -$ cdk destroy --app='node bin/main.js' <MyStackName> ----- \ No newline at end of file diff --git a/v2/guide/ref-cli-cmd/ref-cli-cmd-diff.adoc b/v2/guide/ref-cli-cmd/ref-cli-cmd-diff.adoc deleted file mode 100644 index 66258960..00000000 --- a/v2/guide/ref-cli-cmd/ref-cli-cmd-diff.adoc +++ /dev/null @@ -1,169 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[#ref-cli-cmd-diff] -= `cdk diff` -:keywords: {aws} CDK, {aws} CDK CLI, CDK Toolkit, IaC, Infrastructure as code, {aws} Cloud, {aws} CloudFormation, cdk diff - -[abstract] --- -Perform a diff to see infrastructure changes between {aws} CDK stacks. --- - -// Content start - -Perform a diff to see infrastructure changes between {aws} CDK stacks. - -This command is typically used to compare differences between the current state of stacks in your local CDK app against deployed stacks. However, you can also compare a deployed stack with any local {aws} CloudFormation template. - -[#ref-cli-cmd-diff-usage] -== Usage - -[source,none,subs="verbatim,attributes"] ----- -$ cdk diff <arguments> <options> ----- - -[#ref-cli-cmd-diff-args] -== Arguments - -[#ref-cli-cmd-diff-args-stack-name] -*CDK stack ID*:: -The construct ID of the CDK stack from your app to perform a diff. -+ -_Type_: String -+ -_Required_: No - -[#ref-cli-cmd-diff-options] -== Options - -For a list of global options that work with all CDK CLI commands, see xref:ref-cli-cmd-options[Global options]. - - -[#ref-cli-cmd-diff-options-change-set] -`--change-set <BOOLEAN>`:: -Specify whether to create a change set to analyze resource replacements. -+ -When `true`, the CDK CLI will create an {aws} CloudFormation change set to display the exact changes that will be made to your stack. This output includes whether resources will be updated or replaced. The CDK CLI uses the deploy role instead of the lookup role to perform this action. -+ -When `false`, a quicker, but less-accurate diff is performed by comparing CloudFormation templates. Any change detected to properties that require resource replacement will be displayed as a resource replacement, even if the change is purely cosmetic, like replacing a resource reference with a hard-coded ARN. -+ -_Default value_: `true` - -[#ref-cli-cmd-diff-options-context-lines] -`--context-lines <NUMBER>`:: -Number of context lines to include in arbitrary JSON diff rendering. -+ -_Default value_: `3` - -[#ref-cli-cmd-diff-options-exclusively] -`--exclusively, -e <BOOLEAN>`:: -Only diff requested stacks and don't include dependencies. - -[#ref-cli-cmd-diff-options-fail] -`--fail <BOOLEAN>`:: -Fail and exit with a code of `1` if differences are detected. - -[#ref-cli-cmd-diff-options-help] -`--help, -h <BOOLEAN>`:: -Show command reference information for the `cdk diff` command. - -[#ref-cli-cmd-diff-options-processed] -`--processed <BOOLEAN>`:: -Specify whether to compare against the template with CloudFormation transforms already processed. -+ -_Default value_: `false` - -[#ref-cli-cmd-diff-options-quiet] -`--quiet, -q <BOOLEAN>`:: -Do not print the CDK stack name and default `cdk diff` message to `stdout` when no changes are detected. -+ -_Default value_: `false` - -[#ref-cli-cmd-diff-options-security-only] -`--security-only <BOOLEAN>`:: -Only diff for broadened security changes. -+ -_Default value_: `false` - -[#ref-cli-cmd-diff-options-strict] -`--strict <BOOLEAN>`:: -Modify `cdk diff` behavior to be more precise or stringent. When true, the CDK CLI will not filter out `{aws}::CDK::Metadata` resources or unreadable non-ASCII characters. -+ -_Default value_: `false` - -[#ref-cli-cmd-diff-options-template] -`--template <STRING>`:: -The path to the CloudFormation template to compare a CDK stack with. - -[#ref-cli-cmd-diff-examples] -== Examples - -[#ref-cli-cmd-diff-examples-1] -=== Diff against the currently deployed stack named MyStackName - -The CDK CLI uses the following symbols in the diff output: - -* `[+]` – Identifies code or resources that will be added if you deploy your changes. -* `[-]` – Identifies code or resources that will be removed if you deploy your changes. -* `[~]` – Identifies a resource or property that will be modified if you deploy your changes. - -The following is an example that shows a diff of local changes to a Lambda function: - -[source,none,subs="verbatim,attributes"] ----- -$ cdk diff MyStackName -start: Building <asset-hash>:<account:Region> -success: Built <asset-hash>:<account:Region> -start: Publishing <asset-hash>:<account:Region> -success: Published <asset-hash>:<account:Region> -Hold on while we create a read-only change set to get a diff with accurate replacement information (use --no-change-set to use a less accurate but faster template-only diff) -Stack MyStackName -Resources -[~] {aws}::Lambda::Function HelloWorldFunction <resource-logical-ID> - └─ [~] Code - └─ [~] .ZipFile: - ├─ [-] - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello World!'), - }; - }; - - └─ [+] - exports.handler = async function(event) { - return { - statusCode: 200, - body: JSON.stringify('Hello from CDK!'), - }; - }; - - - -✨ Number of stacks with differences: 1 ----- - -A `[~]` indicator for resources that will be modified does not always mean a full resource replacement: - -* Some resource properties, like `Code`, will update the resource. -* Some resource properties, like `FunctionName`, may cause a full resource replacement. - -[#ref-cli-cmd-diff-examples-2] -=== Diff against a specific CloudFormation template - -[source,none,subs="verbatim,attributes"] ----- -$ cdk diff MyStackName --app='node bin/main.js' --template-path='./MyStackNameTemplate.yaml' ----- - -[#ref-cli-cmd-diff-examples-3] -=== Diff a local stack with its deployed stack. don't print to stdout if no changes are detected - -[source,none,subs="verbatim,attributes"] ----- -$ cdk diff MyStackName --app='node bin/main.js' --quiet ----- \ No newline at end of file diff --git a/v2/guide/ref-cli-cmd/ref-cli-cmd-docs.adoc b/v2/guide/ref-cli-cmd/ref-cli-cmd-docs.adoc deleted file mode 100644 index 2370a42d..00000000 --- a/v2/guide/ref-cli-cmd/ref-cli-cmd-docs.adoc +++ /dev/null @@ -1,51 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[#ref-cli-cmd-docs] -= `cdk docs` -:keywords: {aws} CDK, {aws} CDK CLI, CDK Toolkit, IaC, Infrastructure as code, {aws} Cloud, {aws} CloudFormation - -[abstract] --- -Open {aws} CDK documentation in your browser. --- - -// Content start - -Open {aws} CDK documentation in your browser. - -[#ref-cli-cmd-docs-usage] -== Usage - -[source,none,subs="verbatim,attributes"] ----- -$ cdk docs <options> ----- - -[#ref-cli-cmd-docs-options] -== Options - -For a list of global options that work with all CDK CLI commands, see xref:ref-cli-cmd-options[Global options]. - -[#ref-cli-cmd-docs-options-browser] -`--browser, -b <STRING>`:: -The command to use to open the browser, using `%u` as a placeholder for the path of the file to open. -+ -_Default value_: `open %u` - -[#ref-cli-cmd-docs-options-help] -`--help, -h <BOOLEAN>`:: -Show command reference information for the `cdk docs` command. - -[#ref-cli-cmd-docs-examples] -== Examples - -[#ref-cli-cmd-docs-examples-1] -=== Open {aws} CDK documentation in Google Chrome - -[source,none,subs="verbatim,attributes"] ----- -$ cdk docs --browser='chrome %u' ----- \ No newline at end of file diff --git a/v2/guide/ref-cli-cmd/ref-cli-cmd-doctor.adoc b/v2/guide/ref-cli-cmd/ref-cli-cmd-doctor.adoc deleted file mode 100644 index ed6c37e4..00000000 --- a/v2/guide/ref-cli-cmd/ref-cli-cmd-doctor.adoc +++ /dev/null @@ -1,51 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[#ref-cli-cmd-doctor] -= `cdk doctor` -:keywords: {aws} CDK, {aws} CDK CLI, CDK Toolkit, IaC, Infrastructure as code, {aws} Cloud, {aws} CloudFormation - -[abstract] --- -Inspect and display useful information about your local {aws} CDK project and development environment. --- - -// Content start - -Inspect and display useful information about your local {aws} CDK project and development environment. - -This information can help with troubleshooting CDK issues and should be provided when submitting bug reports. - -[#ref-cli-cmd-doctor-usage] -== Usage - -[source,none,subs="verbatim,attributes"] ----- -$ cdk doctor <options> ----- - -[#ref-cli-cmd-doctor-options] -== Options - -For a list of global options that work with all CDK CLI commands, see xref:ref-cli-cmd-options[Global options]. - -[#ref-cli-cmd-doctor-options-help] -`--help, -h <BOOLEAN>`:: -Show command reference information for the `cdk doctor` command. - -[#ref-cli-cmd-doctor-examples] -== Examples - -[#ref-cli-cmd-doctor-examples-1] -=== Simple example of the `cdk doctor` command - -[source,none,subs="verbatim,attributes"] ----- -$ cdk doctor -ℹ️ CDK Version: 1.0.0 (build e64993a) -ℹ️ {aws} environment variables: - - AWS_EC2_METADATA_DISABLED = 1 - - AWS_SDK_LOAD_CONFIG = 1 ----- \ No newline at end of file diff --git a/v2/guide/ref-cli-cmd/ref-cli-cmd-gc.adoc b/v2/guide/ref-cli-cmd/ref-cli-cmd-gc.adoc deleted file mode 100644 index 759c9002..00000000 --- a/v2/guide/ref-cli-cmd/ref-cli-cmd-gc.adoc +++ /dev/null @@ -1,158 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[#ref-cli-cmd-gc] -= `cdk gc` -:keywords: {aws} CDK, {aws} CDK CLI, CDK Toolkit, IaC, Infrastructure as code, {aws} Cloud, {aws} CloudFormation, cdk gc, garbage collection, assets, Amazon S3 - -[abstract] --- -Use the {aws} Cloud Development Kit ({aws} CDK) command line interface (CLI) `cdk gc` command to perform garbage collection on unused assets stored in the resources of your bootstrap stack. Use this command to view, manage, and delete assets that you no longer need. --- - -// Content start - -Use the {aws} Cloud Development Kit ({aws} CDK) command line interface (CLI) `cdk gc` command to perform garbage collection on unused assets stored in the resources of your bootstrap stack. Use this command to view, manage, and delete assets that you no longer need. - -For Amazon Simple Storage Service (Amazon S3) assets, the CDK CLI will check existing {aws} CloudFormation templates in the same environment to see if they are referenced. If not referenced, they will be considered unused and eligible for garbage collection actions. - -[WARNING] -==== - -The `cdk gc` command is in development for the {aws} CDK. The current features of this command are considered production-ready and safe to use. However, the scope of this command and its features are subject to change. Therefore, you must opt in by providing the `unstable=gc` option to use this command. - -==== - -[#ref-cli-cmd-gc-usage] -== Usage - -[source,none,subs="verbatim,attributes"] ----- -$ cdk gc <arguments> <options> ----- - -[#ref-cli-cmd-gc-args] -== Arguments - -[#ref-cli-cmd-gc-args-env] -*{aws} environment*:: -The target {aws} environment to perform garbage collection actions on. -+ -When providing an environment, use the following format: `aws://<account-id>/<region>`. For example, `aws://<123456789012>/<us-east-1>`. -+ -This argument can be provided multiple times in a single command to perform garbage collection actions on multiple environments. -+ -By default, the CDK CLI will perform garbage collection actions on all environments that you reference in your CDK app or provide as arguments. If you don't provide an environment, the CDK CLI will determine the environment from default sources. These sources include environments that you specify using the `--profile` option, environment variables, or default {aws} CLI sources. - -[#ref-cli-cmd-gc-options] -== Options -For a list of global options that work with all CDK CLI commands, see xref:ref-cli-cmd-options[Global options]. - -[#ref-cli-cmd-gc-options-action] -`--action <STRING>`:: -The action that `cdk gc` performs on your assets during a garbage collection. -+ --- -* `delete-tagged` – Deletes assets that have been tagged with a date within the range of buffer days that you provide, but does not tag newly identified unused assets. -* `full` – Perform all garbage collection actions. This includes deleting assets within the range of buffer days that you provide and tagging newly identified unused assets. -* `print` – Outputs the number of unused assets at the command prompt but doesn't make any actual changes within your {aws} environment. -* `tag` – Tags any newly identified unused assets, but doesn't delete any assets within the range of buffer days that you provide. --- -+ -_Accepted values_: `delete-tagged`, `full`, `print`, `tag` -+ -_Default value_: `full` - -[#ref-cli-cmd-gc-options-bootstrap-stack-name] -`--bootstrap-stack-name <STRING>`:: -The name of the CDK bootstrap stack in your {aws} environment. Provide this option if you customized your bootstrap stack name. If you are using the default `CDKToolkit` stack name, you don't have to provide this option. -+ -_Default value_: `CDKToolkit` - -[#ref-cli-cmd-gc-options-confirm] -`--confirm <BOOLEAN>`:: -Specify whether the CDK CLI will request manual confirmation from you before deleting any assets. -+ -Specify `false` to automatically delete assets without prompting you for manual confirmation. -+ -_Default value_: `true` - -[#ref-cli-cmd-gc-options-created-buffer-days] -`--created-buffer-days <NUMBER>`:: -The number of days an asset must exist before it is eligible for garbage collection actions. -+ -When you provide a number, assets that have not existed beyond your specified number of days are filtered out from garbage collection actions. -+ -_Default value_: `1` - -[#ref-cli-cmd-gc-options-help] -`--help, -h <BOOLEAN>`:: -Show command reference information for the `cdk gc` command. - -[#ref-cli-cmd-gc-options-rollback-buffer-days] -`--rollback-buffer-days <NUMBER>`:: -The number of days an asset must be tagged as isolated before it is eligible for garbage collection actions. -+ -When you provide a number, the CDK CLI will tag unused assets with the current date instead of deleting them. The CDK CLI will also check if any assets have been tagged during previous runs of the `cdk gc` command. Previously tagged assets that fall within the range of buffer days you provide will be deleted. -+ -_Default value_: `0` - -[#ref-cli-cmd-gc-options-type] -`--type <STRING>`:: -The bootstrap resource type within your bootstrap stack to perform garbage collection actions on. -+ --- -* `all` – Perform garbage collection actions on all bootstrapped resources. -* `ecr` – Perform garbage collection actions on assets in the Amazon Elastic Container Registry (Amazon ECR) repository of your bootstrap stack. -* `s3` – Perform garbage collection actions on assets in the Amazon S3 bucket of your bootstrap stack. --- -+ -_Accepted values_: `all`, `ecr`, `s3` -+ -_Default value_: `all` - -[#ref-cli-cmd-gc-options-unstable] -`--unstable <STRING>`:: -Allow the usage of CDK CLI commands that are still in development. -+ -This option is required to use any CDK CLI command that is still in development and subject to change. -+ -This option can be provided multiple times in a single command. -+ -To use `cdk gc`, provide `--unstable=gc`. - -[#ref-cli-cmd-gc-examples] -== Examples - -[#ref-cli-cmd-gc-examples-basic] -=== Basic examples - -The following example prompts you for manual confirmation to perform default garbage collection actions on assets in the Amazon S3 bucket of your bootstrap stack: - -[source,none,subs="verbatim,attributes"] ----- -$ cdk gc --unstable=gc --type=s3 - - ⏳ Garbage Collecting environment aws://<account-id>/<region>... -Found 99 assets to delete based off of the following criteria: -- assets have been isolated for > 0 days -- assets were created > 1 days ago - -Delete this batch (yes/no/delete-all)? ----- - -The following example performs garbage collection actions on a range of assets in the Amazon S3 bucket of your bootstrap stack. This range includes assets that have been previously tagged by `cdk gc` for over 30 days and have been created 10 days or older. This command will prompt for manual confirmation before deleting any assets: - -[source,none,subs="verbatim,attributes"] ----- -$ cdk gc --unstable=gc --type=s3 --rollback-buffer-days=30 --created-buffer-days=10 ----- - -The following example performs the action of deleting previously tagged assets in the Amazon S3 bucket of your bootstrap stack that have been unused for longer than 30 days: - -[source,none,subs="verbatim,attributes"] ----- -$ cdk gc --unstable=gc --type=s3 --action=delete-tagged --rollback-buffer-days=30 ----- \ No newline at end of file diff --git a/v2/guide/ref-cli-cmd/ref-cli-cmd-import.adoc b/v2/guide/ref-cli-cmd/ref-cli-cmd-import.adoc deleted file mode 100644 index 13380c92..00000000 --- a/v2/guide/ref-cli-cmd/ref-cli-cmd-import.adoc +++ /dev/null @@ -1,117 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[#ref-cli-cmd-import] -= `cdk import` -:keywords: {aws} CDK, {aws} CDK CLI, CDK Toolkit, IaC, Infrastructure as code, {aws} Cloud, {aws} CloudFormation, cdk import - -[abstract] --- -Use https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resource-import.html[{aws} CloudFormation resource imports] to import existing {aws} resources into a CDK stack. --- - -// Content start - -Use https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resource-import.html[{aws} CloudFormation resource imports] to import existing {aws} resources into a CDK stack. - -With this command, you can take existing resources that were created using other methods and start managing them using the {aws} CDK. - -When considering moving resources into CDK management, sometimes creating new resources is acceptable, such as with IAM roles, Lambda functions, and event rules. For other resources, such as stateful resources like Amazon S3 buckets and DynamoDB tables, creating new resources can cause impacts to your service. You can use `cdk import` to import existing resources with minimal disruption to your services. For a list of supported {aws} resources, see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resource-import-supported-resources.html[Resource type support] in the _{aws} CloudFormation User Guide_. - -*To import an existing resource to a CDK stack*:: -+ -. Run a `cdk diff` to make sure your CDK stack has no pending changes. When performing a ``cdk import``, the only changes allowed in an import operation are the addition of new resources being imported. -+ -. Add constructs for the resources you want to import to your stack. For example, add the following for an Amazon S3 bucket: -+ -[source,javascript,subs="verbatim,attributes"] ----- -new s3.Bucket(this, 'ImportedS3Bucket', {}); ----- -+ -Do not add any other changes. You must also make sure to exactly model the state that the resource currently has. For the bucket example, be sure to include {aws} KMS keys, lifecycle policies, and anything else that is relevant about the bucket. Otherwise, subsequent update operations may not do what you expect. -+ -. Run `cdk import`. If there are multiple stacks in the CDK app, pass a specific stack name as an argument. -+ -. The CDK CLI will prompt you to pass in the actual names of the resources you are importing. After you provide this information, import will begin. -+ -. When `cdk import` reports success, the resource will be managed by the CDK. Any subsequent changes in the construct configuration will be reflected on the resource. - -This feature currently has the following limitations: - -* Importing resources into nested stacks isn't possible. -* There is no check on whether the properties you specify are correct and complete for the imported resource. Try starting a drift detection operation after importing. -* Resources that depend on other resources must all be imported together, or individually, in the right order. Otherwise, the CloudFormation deployment will fail with unresolved references. -* This command uses the deploy role credentials, which is necessary to read the encrypted staging bucket. This requires version 12 of the bootstrap template, which includes the necessary IAM permissions for the deploy role. - -[#ref-cli-cmd-import-usage] -== Usage - -[source,none,subs="verbatim,attributes"] ----- -$ cdk import <arguments> <options> ----- - -[#ref-cli-cmd-import-args] -== Arguments - -[#ref-cli-cmd-import-args-stack-name] -*CDK stack ID*:: -The construct ID of the CDK stack from your app to import resources to. This argument can be provided multiple times in a single command. -+ -_Type_: String -+ -_Required_: No - -[#ref-cli-cmd-import-options] -== Options - -For a list of global options that work with all CDK CLI commands, see xref:ref-cli-cmd-options[Global options]. - -[#ref-cli-cmd-import-options-change-set-name] -`--change-set-name <STRING>`:: -The name of the CloudFormation change set to create. - -[#ref-cli-cmd-import-options-execute] -`--execute <BOOLEAN>`:: -Specify whether to execute change set. -+ -_Default value_: `true` - -[#ref-cli-cmd-import-options-force] -`--force, -f <BOOLEAN>`:: -By default, the CDK CLI exits the process if the template diff includes updates or deletions. Specify `true` to override this behavior and always continue with importing. - -[#ref-cli-cmd-import-options-help] -`--help, -h <BOOLEAN>`:: -Show command reference information for the `cdk import` command. - -[#ref-cli-cmd-import-options-record-resource-mapping] -`--record-resource-mapping, -r <STRING>`:: -Use this option to generate a mapping of existing physical resources to the CDK resources that will be imported. The mapping will be written to the file path that you provide. No actual import operations will be performed. - -[#ref-cli-cmd-import-options-resource-mapping] -`--resource-mapping, -m <STRING>`:: -Use this option to specify a file that defines your resource mapping. The CDK CLI will use this file to map physical resources to resources for import instead of interactively asking you. -+ -This option can be run from scripts. - -[#ref-cli-cmd-import-options-rollback] -`--rollback <BOOLEAN>`:: -Roll back the stack to stable state on failure. -+ -To specify `false`, you can use `--no-rollback` or `-R`. -+ -Specify `false` to iterate more rapidly. Deployments containing resource replacements will always fail. -+ -_Default value_: `true` - -[#ref-cli-cmd-import-options-toolkit-stack-name] -`--toolkit-stack-name <STRING>`:: -The name of the CDK Toolkit stack to create. -+ -By default, `cdk bootstrap` deploys a stack named `CDKToolkit` into the specified {aws} environment. Use this option to provide a different name for your bootstrap stack. -+ -The CDK CLI uses this value to verify your bootstrap stack version. \ No newline at end of file diff --git a/v2/guide/ref-cli-cmd/ref-cli-cmd-init.adoc b/v2/guide/ref-cli-cmd/ref-cli-cmd-init.adoc deleted file mode 100644 index 025f0b2a..00000000 --- a/v2/guide/ref-cli-cmd/ref-cli-cmd-init.adoc +++ /dev/null @@ -1,91 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[#ref-cli-cmd-init] -= `cdk init` -:keywords: {aws} CDK, {aws} CDK CLI, CDK Toolkit, IaC, Infrastructure as code, {aws} Cloud, {aws} CloudFormation, cdk init - -[abstract] --- -Create a new {aws} CDK project from a template. --- - -// Content start - -Create a new {aws} CDK project from a template. - -[#ref-cli-cmd-init-usage] -== Usage - -[source,none,subs="verbatim,attributes"] ----- -$ cdk init <arguments> <options> ----- - -[#ref-cli-cmd-init-args] -== Arguments - -[#ref-cli-cmd-init-args-template-type] -*Template type*:: -The CDK template type to initialize a new CDK project from. -+ --- -* `app` – Template for a CDK application. -* `lib` – Template for an {aws} Construct Library. -* `sample-app` – Example CDK application that includes some constructs. --- -+ -_Valid values_: `app`, `lib`, `sample-app` - -[#ref-cli-cmd-init-options] -== Options - -For a list of global options that work with all CDK CLI commands, see xref:ref-cli-cmd-options[Global options]. - -[#ref-cli-cmd-init-options-generate-only] -`--generate-only <BOOLEAN>`:: -Specify this option to generate project files without initiating additional operations such as setting up a git repository, installing dependencies, or compiling the project. -+ -_Default value_: `false` - -[#ref-cli-cmd-init-options-help] -`--help, -h <BOOLEAN>`:: -Show command reference information for the `cdk init` command. - -[#ref-cli-cmd-init-options-language] -`--language, -l <STRING>`:: -The language to be used for the new project. This option can be configured in the project's `cdk.json` configuration file or at `~/.cdk.json` on your local development machine. -+ -_Valid values_: `csharp`, `fsharp`, `go`, `java`, `javascript`, `python`, `typescript` - -[#ref-cli-cmd-init-options-list] -`--list <BOOLEAN>`:: -List the available template types and languages. - -[#ref-cli-cmd-init-examples] -== Examples - -[#ref-cli-cmd-init-examples-1] -=== List the available template types and languages - -[source,none,subs="verbatim,attributes"] ----- -$ cdk init --list -Available templates: -* app: Template for a CDK Application - └─ cdk init app --language=[csharp|fsharp|go|java|javascript|python|typescript] -* lib: Template for a CDK Construct Library - └─ cdk init lib --language=typescript -* sample-app: Example CDK Application with some constructs - └─ cdk init sample-app --language=[csharp|fsharp|go|java|javascript|python|typescript] ----- - -[#ref-cli-cmd-init-examples-2] -=== Create a new CDK app in TypeScript from the library template - -[source,none,subs="verbatim,attributes"] ----- -$ cdk init lib --language=typescript ----- \ No newline at end of file diff --git a/v2/guide/ref-cli-cmd/ref-cli-cmd-list.adoc b/v2/guide/ref-cli-cmd/ref-cli-cmd-list.adoc deleted file mode 100644 index 54fe9c87..00000000 --- a/v2/guide/ref-cli-cmd/ref-cli-cmd-list.adoc +++ /dev/null @@ -1,97 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[#ref-cli-cmd-list] -= `cdk list` -:keywords: {aws} CDK, {aws} CDK CLI, CDK Toolkit, IaC, Infrastructure as code, {aws} Cloud, {aws} CloudFormation, cdk list - -[abstract] --- -List all {aws} CDK stacks and their dependencies from a CDK app. --- - -// Content start - -List all {aws} CDK stacks and their dependencies from a CDK app. - -[#ref-cli-cmd-list-usage] -== Usage - -[source,none,subs="verbatim,attributes"] ----- -$ cdk list <arguments> <options> ----- - -[#ref-cli-cmd-list-args] -== Arguments - -[#ref-cli-cmd-list-args-stack-name] -*CDK stack ID*:: -The construct ID of the CDK stack from your app to perform this command against. -+ -_Type_: String -+ -_Required_: No - -[#ref-cli-cmd-list-options] -== Options - -For a list of global options that work with all CDK CLI commands, see xref:ref-cli-cmd-options[Global options]. - -[#ref-cli-cmd-list-options-help] -`--help, -h <BOOLEAN>`:: -Show command reference information for the `cdk list` command. - -[#ref-cli-cmd-list-options-long] -`--long, -l <BOOLEAN>`:: -Display {aws} environment information for each stack. -+ -_Default value_: `false` - -[#ref-cli-cmd-list-options-show-dependencies] -`--show-dependencies, -d <BOOLEAN>`:: -Display stack dependency information for each stack. -+ -_Default value_: `false` - -[#ref-cli-cmd-list-examples] -== Examples - -[#ref-cli-cmd-list-examples-1] -=== List all stacks in the CDK app '`node bin/main.js`' - -[source,none,subs="verbatim,attributes"] ----- -$ cdk list --app='node bin/main.js' -Foo -Bar -Baz ----- - -[#ref-cli-cmd-list-examples-] -=== List all stacks, including {aws} environment details for each stack - -[source,none,subs="verbatim,attributes"] ----- -$ cdk list --app='node bin/main.js' --long -- - name: Foo - environment: - name: 000000000000/bermuda-triangle-1 - account: '000000000000' - region: bermuda-triangle-1 -- - name: Bar - environment: - name: 111111111111/bermuda-triangle-2 - account: '111111111111' - region: bermuda-triangle-2 -- - name: Baz - environment: - name: 333333333333/bermuda-triangle-3 - account: '333333333333' - region: bermuda-triangle-3 ----- \ No newline at end of file diff --git a/v2/guide/ref-cli-cmd/ref-cli-cmd-metadata.adoc b/v2/guide/ref-cli-cmd/ref-cli-cmd-metadata.adoc deleted file mode 100644 index 626f6cfe..00000000 --- a/v2/guide/ref-cli-cmd/ref-cli-cmd-metadata.adoc +++ /dev/null @@ -1,45 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[#ref-cli-cmd-metadata] -= `cdk metadata` -:keywords: {aws} CDK, {aws} CDK CLI, CDK Toolkit, IaC, Infrastructure as code, {aws} Cloud, {aws} CloudFormation, cdk metadata - -[abstract] --- -Display metadata associated with a CDK stack. --- - -// Content start - -Display metadata associated with a CDK stack. - -[#ref-cli-cmd-metadata-usage] -== Usage - -[source,none,subs="verbatim,attributes"] ----- -$ cdk metadata <arguments> <options> ----- - -[#ref-cli-cmd-metadata-args] -== Arguments - -[#ref-cli-cmd-metadata-args-stack-name] -*CDK stack ID*:: -The construct ID of the CDK stack from your app to display metadata for. -+ -_Type_: String -+ -_Required_: No - -[#ref-cli-cmd-metadata-options] -== Options - -For a list of global options that work with all CDK CLI commands, see xref:ref-cli-cmd-options[Global options]. - -[#ref-cli-cmd-metadata-options-help] -`--help, -h <BOOLEAN>`:: -Show command reference information for the `cdk metadata` command. \ No newline at end of file diff --git a/v2/guide/ref-cli-cmd/ref-cli-cmd-migrate.adoc b/v2/guide/ref-cli-cmd/ref-cli-cmd-migrate.adoc deleted file mode 100644 index 6b806ed4..00000000 --- a/v2/guide/ref-cli-cmd/ref-cli-cmd-migrate.adoc +++ /dev/null @@ -1,174 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[#ref-cli-cdk-migrate] -= `cdk migrate` -:keywords: {aws} CDK, {aws} CDK CLI, cdk migrate - -[abstract] --- -Migrate deployed {aws} resources, {aws} CloudFormation stacks, and CloudFormation templates into a new {aws} CDK project. --- - -// Content start - -Migrate deployed {aws} resources, {aws} CloudFormation stacks, and CloudFormation templates into a new {aws} CDK project. - -This command creates a new CDK app that includes a single stack that is named with the value you provide using `--stack-name`. You can configure the migration source using `--from-scan`, `--from-stack`, or `--from-path`. - -For more information on using `cdk migrate`, see xref:migrate[Migrate existing resources and {aws} CloudFormation templates to the {aws} CDK]. - -[NOTE] -==== - -The `cdk migrate` command is experimental and may have breaking changes in the future. - -==== - -[#ref-cli-cdk-migrate-usage] -== Usage - -[source,none,subs="verbatim,attributes"] ----- -$ cdk migrate <options> ----- - -[#ref-cli-cdk-migrate-options] -== Options - -For a list of global options that work with all CDK CLI commands, see xref:ref-cli-cmd-options[Global options]. - -[#ref-cli-cdk-migrate-options-required] -=== Required options - -[#ref-cli-cdk-migrate-options-stack-name] -`--stack-name <STRING>`:: -The name of the {aws} CloudFormation stack that will be created within the CDK app after migrating. -+ -_Required_: Yes - -[#ref-cli-cdk-migrate-options-conditional] -=== Conditional options - -[#ref-cli-cdk-migrate-options-from-path] -`--from-path <PATH>`:: -The path to the {aws} CloudFormation template to migrate. Provide this option to specify a local template. -+ -_Required_: Conditional. Required if migrating from a local {aws} CloudFormation template. - -[#ref-cli-cdk-migrate-options-from-scan] -`--from-scan <STRING>`:: -When migrating deployed resources from an {aws} environment, use this option to specify whether a new scan should be started or if the {aws} CDK CLI should use the last successful scan. -+ -_Required_: Conditional. Required when migrating from deployed {aws} resources. -+ -_Accepted values_: `most-recent`, `new` - -[#ref-cli-cdk-migrate-options-from-stack] -`--from-stack <BOOLEAN>`:: -Provide this option to migrate from a deployed {aws} CloudFormation stack. Use `--stack-name` to specify the name of the deployed {aws} CloudFormation stack. -+ -_Required_: Conditional. Required if migrating from a deployed {aws} CloudFormation stack. - -[#ref-cli-cdk-migrate-options-optional] -=== Optional options - -[#ref-cli-cdk-migrate-options-account] -`--account <STRING>`:: -The account to retrieve the {aws} CloudFormation stack template from. -+ -_Required_: No -+ -_Default_: The {aws} CDK CLI obtains account information from default sources. - -[#ref-cli-cdk-migrate-options-compress] -`--compress <BOOLEAN>`:: -Provide this option to compress the generated CDK project into a `ZIP` file. -+ -_Required_: No - -[#ref-cli-cdk-migrate-options-filter] -`--filter <ARRAY>`:: -Use when migrating deployed resources from an {aws} account and {aws} Region. This option specifies a filter to determine which deployed resources to migrate. -+ -This option accepts an array of key-value pairs, where *key* represents the filter type and *value* represents the value to filter. -+ -The following are accepted keys: -+ --- -* `resource-identifier` – An identifier for the resource. Value can be the resource logical or physical ID. For example, `resource-identifier="ClusterName"`. -* `resource-type-prefix` – The {aws} CloudFormation resource type prefix. For example, specify `resource-type-prefix="{aws}::DynamoDB::"` to filter all Amazon DynamoDB resources. -* `tag-key` – The key of a resource tag. For example, `tag-key="myTagKey"`. -* `tag-value` – The value of a resource tag. For example, `tag-value="myTagValue"`. --- -+ -Provide multiple key-value pairs for `AND` conditional logic. The following example filters for any DynamoDB resource that is tagged with `myTagKey` as the tag key: `--filter resource-type-prefix="{aws}::DynamoDB::", tag-key="myTagKey"`. -+ -Provide the `--filter` option multiple times in a single command for `OR` conditional logic. The following example filters for any resource that is a DynamoDB resource or is tagged with `myTagKey` as the tag key: `--filter resource-type-prefix="{aws}::DynamoDB::" --filter tag-key="myTagKey"`. -+ -_Required_: No - -[#ref-cli-cdk-migrate-options-help] -`--help, -h <BOOLEAN>`:: -Show command reference information for the `cdk migrate` command. - -[#ref-cli-cdk-migrate-options-language] -`--language <STRING>`:: -The programming language to use for the CDK project created during migration. -+ -_Required_: No -+ -_Valid values_: `typescript`, `python`, `java`, `csharp`, `go`. -+ -_Default_: `typescript` - -[#ref-cli-cdk-migrate-options-output-path] -`--output-path <PATH>`:: -The output path for the migrated CDK project. -+ -_Required_: No -+ -_Default_: By default, the {aws} CDK CLI will use your current working directory. - -[#ref-cli-cdk-migrate-options-region] -`--region <STRING>`:: -The {aws} Region to retrieve the {aws} CloudFormation stack template from. -+ -_Required_: No -+ -_Default_: The {aws} CDK CLI obtains {aws} Region information from default sources. - -[#ref-cli-cdk-migrate-examples] -== Examples - -[#ref-cli-cdk-migrate-examples-1] -=== Simple example of migrating from a CloudFormation stack - -Migrate from a deployed CloudFormation stack in a specific {aws} environment using `--from-stack`. Provide `--stack-name` to name your new CDK stack. The following is an example that migrates `myCloudFormationStack` to a new CDK app that is using TypeScript: - -[source,none,subs="verbatim,attributes"] ----- -$ cdk migrate --language typescript --from-stack --stack-name 'myCloudFormationStack' ----- - -[#ref-cli-cdk-migrate-examples-2] -=== Simple example of migrating from a local CloudFormation template - -Migrate from a local JSON or YAML CloudFormation template using `--from-path`. Provide `--stack-name` to name your new CDK stack. The following is an example that creates a new CDK app in TypeScript that includes a `myCloudFormationStack` stack from a local `template.json` file: - -[source,none,subs="verbatim,attributes"] ----- -$ cdk migrate --stack-name "myCloudFormationStack" --language typescript --from-path "./template.json" ----- - -[#ref-cli-cdk-migrate-examples-3] -=== Simple example of migrating from deployed {aws} resources - -Migrate deployed {aws} resources from a specific {aws} environment that are not associated with a CloudFormation stack using `--from-scan`. The CDK CLI utilizes the [.noloc]`IaC generator` service to scan for resources and generate a template. Then, the CDK CLI references the template to create the new CDK app. The following is an example that creates a new CDK app in TypeScript with a new `myCloudFormationStack` stack containing migrated {aws} resources: - -[source,none,subs="verbatim,attributes"] ----- -$ cdk migrate --language typescript --from-scan --stack-name "myCloudFormationStack" ----- \ No newline at end of file diff --git a/v2/guide/ref-cli-cmd/ref-cli-cmd-notices.adoc b/v2/guide/ref-cli-cmd/ref-cli-cmd-notices.adoc deleted file mode 100644 index e299f91d..00000000 --- a/v2/guide/ref-cli-cmd/ref-cli-cmd-notices.adoc +++ /dev/null @@ -1,125 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[#ref-cli-cmd-notices] -= `cdk notices` -:keywords: {aws} CDK, {aws} CDK CLI, CDK Toolkit, IaC, Infrastructure as code, {aws} Cloud, {aws} CloudFormation, cdk notices - -[abstract] --- -Display notices for your CDK application. --- - -// Content start - -Display notices for your CDK application. - -Notices can include important messages regarding security vulnerabilities, regressions, and usage of unsupported versions. - -This command displays relevant notices, regardless of whether they have been acknowledged or not. Relevant notices may also appear after every command by default. - -You can suppress notices in the following ways: - -* Through command options. The following is an example: -+ -[source,none,subs="verbatim,attributes"] ----- -$ cdk deploy --no-notices ----- -+ -* Suppress all notices indefinitely through context in the project's `cdk.json` file: -+ -[source,json,subs="verbatim,attributes"] ----- -{ - "notices": false, - "context": { - // ... - } -} ----- -+ -* Acknowledge each notice with the `cdk acknowledge` command. - -[#ref-cli-cmd-notices-usage] -== Usage - -[source,none,subs="verbatim,attributes"] ----- -$ cdk notices <options> ----- - -[#ref-cli-cmd-notices-options] -== Options - -For a list of global options that work with all CDK CLI commands, see xref:ref-cli-cmd-options[Global options]. - -[#ref-cli-cmd-notices-options-help] -`--help, -h <BOOLEAN>`:: -Show command reference information for the `cdk notices` command. - -[#ref-cli-cmd-notices-examples] -== Examples - -[#ref-cli-cmd-notices-examples-1] -=== Example of a default notice that displays after running the cdk deploy command - -[source,none,subs="verbatim,attributes"] ----- -$ cdk deploy - -... # Normal output of the command - -NOTICES - -16603 Toggling off auto_delete_objects for Bucket empties the bucket - - Overview: If a stack is deployed with an S3 bucket with - auto_delete_objects=True, and then re-deployed with - auto_delete_objects=False, all the objects in the bucket - will be deleted. - - Affected versions: <1.126.0. - - More information at: https://github.com/aws/aws-cdk/issues/16603 - - -17061 Error when building EKS cluster with monocdk import - - Overview: When using monocdk/aws-eks to build a stack containing - an EKS cluster, error is thrown about missing - lambda-layer-node-proxy-agent/layer/package.json. - - Affected versions: >=1.126.0 <=1.130.0. - - More information at: https://github.com/aws/aws-cdk/issues/17061 - - -If you don’t want to see an notice anymore, use "cdk acknowledge ID". For example, "cdk acknowledge 16603" ----- - -[#ref-cli-cmd-notices-examples-2] -=== Simple example of running the cdk notices command - -[source,none,subs="verbatim,attributes"] ----- -$ cdk notices - -NOTICES - -16603 Toggling off auto_delete_objects for Bucket empties the bucket - - Overview: if a stack is deployed with an S3 bucket with - auto_delete_objects=True, and then re-deployed with - auto_delete_objects=False, all the objects in the bucket - will be deleted. - - Affected versions: framework: <=2.15.0 >=2.10.0 - - More information at: https://github.com/aws/aws-cdk/issues/16603 - - -If you don’t want to see a notice anymore, use "cdk acknowledge <id>". For example, "cdk acknowledge 16603" ----- \ No newline at end of file diff --git a/v2/guide/ref-cli-cmd/ref-cli-cmd-rollback.adoc b/v2/guide/ref-cli-cmd/ref-cli-cmd-rollback.adoc deleted file mode 100644 index b6b956ea..00000000 --- a/v2/guide/ref-cli-cmd/ref-cli-cmd-rollback.adoc +++ /dev/null @@ -1,93 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[#ref-cli-cmd-rollback] -= `cdk rollback` -:keywords: {aws} CDK, {aws} CDK CLI, CDK Toolkit, IaC, Infrastructure as code, {aws} Cloud, {aws} CloudFormation, cdk deploy, rollback - -[abstract] --- -Use the {aws} Cloud Development Kit ({aws} CDK) Command Line Interface (CLI) `cdk rollback` command to rollback a failed or paused stack from an {aws} CloudFormation deployment to its last stable state. --- - -// Content start - -Use the {aws} Cloud Development Kit ({aws} CDK) Command Line Interface (CLI) `cdk rollback` command to rollback a failed or paused stack from an {aws} CloudFormation deployment to its last stable state. - -[NOTE] -==== - -To use this command, you must have v23 of the bootstrap template deployed to your environment. For more information, see xref:bootstrap-template-history[Bootstrap template version history]. - -==== - -When you deploy using `cdk deploy`, the CDK CLI will rollback a failed deployment by default. If you specify `--no-rollback` with `cdk deploy`, you can then use the `cdk rollback` command to manually rollback a failed deployment. This will initiate a rollback to the last stable state of your stack. - -[#ref-cli-cmd-rollback-usage] -== Usage - -[source,none,subs="verbatim,attributes"] ----- -$ cdk rollback <arguments> <options> ----- - -[#ref-cli-cmd-rollback-args] -== Arguments - -[#ref-cli-cmd-rollback-args-stack-name] -*CDK stack ID*:: -The construct ID of the CDK stack from your app to rollback. -+ -_Type_: String -+ -_Required_: No - -[#ref-cli-cmd-rollback-options] -== Options - -For a list of global options that work with all CDK CLI commands, see xref:ref-cli-cmd-options[Global options]. - -[#ref-cli-cmd-rollback-options-all] -`--all <BOOLEAN>`:: -Rollback all stacks in your CDK app. -+ -_Default value_: `false` - -[#ref-cli-cmd-rollback-options-force] -`--force, -f <BOOLEAN>`:: -When you use `cdk rollback`, some resources may fail to rollback. Provide this option to force the rollback of all resources. This is the same behavior as providing the `--orphan` option for each resource in your stack. -+ -_Default value_: `false` - -[#ref-cli-cmd-rollback-options-help] -`--help, -h <BOOLEAN>`:: -Show command reference information for the `cdk rollback` command. - -[#ref-cli-cmd-rollback-options-orphan] -`--orphan <LogicalId>`:: -When you use `cdk rollback`, some resources may fail to rollback. When this happens, you can try to force the rollback of a resource by using this option and providing the logical ID of the resource that failed to rollback. -+ -This option can be provided multiple times in a single command The following is an example: -+ -[source,none,subs="verbatim,attributes"] ----- -$ cdk rollback MyStack --orphan MyLambdaFunction --orphan MyLambdaFunction2 ----- -+ -To force the rollback of all resources, use the `--force` option instead. - -[#ref-cli-cmd-rollback-options-toolkit-stack-name] -`--toolkit-stack-name <STRING>`:: -The name of the existing CDK Toolkit stack that the environment is bootstrapped with. -+ -By default, `cdk bootstrap` deploys a stack named `CDKToolkit` into the specified {aws} environment. Use this option to provide a different name for your bootstrap stack. -+ -The CDK CLI uses this value to verify your bootstrap stack version. - -[#ref-cli-cmd-rollback-options-validate-bootstrap-version] -`--validate-bootstrap-version <BOOLEAN>`:: -Specify whether to validate the bootstrap stack version. Provide `--validate-bootstrap-version=false` or `--no-validate-bootsrap-version` to turn off this behavior. -+ -_Default value_: `true` \ No newline at end of file diff --git a/v2/guide/ref-cli-cmd/ref-cli-cmd-synth.adoc b/v2/guide/ref-cli-cmd/ref-cli-cmd-synth.adoc deleted file mode 100644 index f8b73165..00000000 --- a/v2/guide/ref-cli-cmd/ref-cli-cmd-synth.adoc +++ /dev/null @@ -1,114 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[#ref-cli-cmd-synth] -= `cdk synthesize` -:info_titleabbrev: cdk synth -:keywords: {aws} CDK, {aws} CDK CLI, CDK Toolkit, IaC, Infrastructure as code, {aws} Cloud, {aws} CloudFormation, cdk synthesize, cdk synth - -[abstract] --- -Synthesize a CDK app to produce a cloud assembly, including an {aws} CloudFormation template for each stack. --- - -// Content start - -Synthesize a CDK app to produce a cloud assembly, including an {aws} CloudFormation template for each stack. - -Cloud assemblies are files that include everything needed to deploy your app to your {aws} environment. For example, it includes a CloudFormation template for each stack in your app, and a copy of the file assets or Docker images that you reference in your app. - -If your app contains a single stack or if a single stack is provided as an argument, the CloudFormation template will also be displayed in the standard output (`stdout`) in YAML format. - -If your app contains multiple stacks, `cdk synth` will synthesize the cloud assembly to `cdk.out`. - -[#ref-cli-cmd-synth-usage] -== Usage - -[source,none,subs="verbatim,attributes"] ----- -$ cdk synthesize <arguments> <options> ----- - -[#ref-cli-cmd-synth-args] -== Arguments - -[#ref-cli-cmd-synth-args-stack-name] -*CDK stack ID*:: -The construct ID of the CDK stack from your app to synthesize. -+ -_Type_: String -+ -_Required_: No - -[#ref-cli-cmd-synth-options] -== Options - -For a list of global options that work with all CDK CLI commands, see xref:ref-cli-cmd-options[Global options]. - -[#ref-cli-cmd-synth-options-exclusively] -`--exclusively, -e <BOOLEAN>`:: -Only synthesize requested stacks, don't include dependencies. - -[#ref-cli-cmd-synth-options-help] -`--help, -h <BOOLEAN>`:: -Show command reference information for the `cdk synthesize` command. - -[#ref-cli-cmd-synth-options-quiet] -`--quiet, -q <BOOLEAN>`:: -Do not output the CloudFormation template to `stdout`. -+ -This option can be configured in the CDK project's `cdk.json` file. The following is an example: -+ -[source,json,subs="verbatim,attributes"] ----- -{ - "quiet": true -} ----- -+ -_Default value_: `false` - -[#ref-cli-cmd-synth-options-validation] -`--validation <BOOLEAN>`:: -Validate the generated CloudFormation templates after synthesis by performing additional checks. -+ -You can also configure this option through the `validateOnSynth` attribute or `CDK_VALIDATION` environment variable. -+ -_Default value_: `true` - -[#ref-cli-cmd-synth-examples] -== Examples - -[#ref-cli-cmd-synth-examples-1] -=== Synthesize the cloud assembly for a CDK stack with logial ID MyStackName and output the CloudFormation template to stdout - -[source,none,subs="verbatim,attributes"] ----- -$ cdk synth MyStackName ----- - -[#ref-cli-cmd-synth-examples-2] -=== Synthesize the cloud assembly for all stacks in a CDK app and save them into cdk.out - -[source,none,subs="verbatim,attributes"] ----- -$ cdk synth ----- - -[#ref-cli-cmd-synth-examples-3] -=== Synthesize the cloud assembly for MyStackName, but don't include dependencies - -[source,none,subs="verbatim,attributes"] ----- -$ cdk synth MyStackName --exclusively ----- - -[#ref-cli-cmd-synth-examples-4] -=== Synthesize the cloud assembly for MyStackName, but don't output the CloudFormation template to stdout - -[source,none,subs="verbatim,attributes"] ----- -$ cdk synth MyStackName --quiet ----- \ No newline at end of file diff --git a/v2/guide/ref-cli-cmd/ref-cli-cmd-watch.adoc b/v2/guide/ref-cli-cmd/ref-cli-cmd-watch.adoc deleted file mode 100644 index 104773e3..00000000 --- a/v2/guide/ref-cli-cmd/ref-cli-cmd-watch.adoc +++ /dev/null @@ -1,204 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[#ref-cli-cmd-watch] -= `cdk watch` -:keywords: {aws} CDK, {aws} CDK CLI, CDK Toolkit, IaC, Infrastructure as code, {aws} Cloud, {aws} CloudFormation, cdk watch - -[abstract] --- -Continuously watch a local {aws} CDK project for changes to perform deployments and hotswaps. --- - -// Content start - -Continuously watch a local {aws} CDK project for changes to perform deployments and hotswaps. - -This command is similar to `cdk deploy`, except that it can perform continuous deployments and hotswaps through a single command. - -This command is a shortcut for `cdk deploy --watch`. - -To end a `cdk watch` session, interrupt the process by pressing `Ctrl+C`. - -The files that are observed is determined by the `"watch"` setting in your `cdk.json` file. It has two sub-keys, `"include"` and ``"exclude"``, that accepts a single string or an array of strings. Each entry is interpreted as a path relative to the location of the `cdk.json` file. Both `\*` and `**` are accepted. - -If you create a project using the `cdk init` command, the following default behavior is configured for `cdk watch` in your project's `cdk.json` file: - -* `"include"` is set to ``"\**/*"``, which includes all files and directories in the root of the project. -* `"exclude"` is optional, except for files and folders already ignored by default. This consists of files and directories starting with `.`, the CDK output directory, and the `node_modules` directory. - -The minimal setting to configure `watch` is `"watch": {}`. - -If either your CDK code or application code requires a build step before deployment, `cdk watch` works with the `"build"` key in the `cdk.json` file. - -[NOTE] -==== - -This command is considered experimental and may have breaking changes in the future. - -==== - -The same limitations of `cdk deploy --hotswap` applies to `cdk watch`. For more information, see `xref:ref-cli-cmd-deploy-options-hotswap[cdk deploy --hotswap]`. - -[#ref-cli-cmd-watch-usage] -== Usage - -[source,none,subs="verbatim,attributes"] ----- -$ cdk watch <arguments> <options> ----- - -[#ref-cli-cmd-watch-args] -== Arguments - -[#ref-cli-cmd-watch-args-stack-name] -*CDK stack ID*:: -The construct ID of the CDK stack from your app to watch. -+ -_Type_: String -+ -_Required_: No - -[#ref-cli-cmd-watch-options] -== Options -For a list of global options that work with all CDK CLI commands, see xref:ref-cli-cmd-options[Global options]. - - -[#ref-cli-cmd-watch-options-build-exclude] -`--build-exclude, -E <ARRAY>`:: -Do not rebuild asset with the given ID. -+ -This option can be specified multiple times in a single command. -+ -_Default value_: `[]` - -[#ref-cli-cmd-watch-options-change-set-name] -`--change-set-name <STRING>`:: -The name of the CloudFormation change set to create. - -[#ref-cli-cmd-watch-options-concurrency] -`--concurrency <NUMBER>`:: -Deploy and hotswap multiple stacks in parallel while accounting for inter-stack dependencies. Use this option to speed up deployments. You must still factor in CloudFormation and other {aws} account rate limiting. -+ -Provide a number to specify the maximum number of simultaneous deployments (dependency permitting) to perform. -+ -_Default value_: `1` - -[#ref-cli-cmd-watch-options-exclusively] -`--exclusively, -e <BOOLEAN>`:: -Only deploy requested stacks and don't include dependencies. - -[#ref-cli-cmd-watch-options-force] -`--force, -f <BOOLEAN>`:: -Always deploy stacks, even if templates are identical. -+ -_Default value_: `false` - -[#ref-cli-cmd-watch-options-help] -`--help, -h <BOOLEAN>`:: -Show command reference information for the `cdk watch` command. - -[#ref-cli-cmd-watch-options-hotswap] -`--hotswap <BOOLEAN>`:: -By default, `cdk watch` uses hotswap deployments when possible to update your resources. The CDK CLI will attempt to perform a hotswap deployment and will not fall back to a full CloudFormation deployment if unsuccessful. Any changes detected that cannot be updated through a hotswap are ignored. -+ -_Default value_: `true` - -[#ref-cli-cmd-watch-options-hotswap-fallback] -`--hotswap-fallback <BOOLEAN>`:: -By default, `cdk watch` attempts to perform hotswap deployments and ignores changes that require CloudFormation deployments. Provide `--hotswap-fallback` to fall back and perform a full CloudFormation deployment if the hotswap deployment is unsuccessful. - -[#ref-cli-cmd-watch-options-logs] -`--logs <BOOLEAN>`:: -By default, `cdk watch` monitors all CloudWatch log groups in your application and streams the log events locally to `stdout`. -+ -_Default value_: `true` - -[#ref-cli-cmd-watch-options-progress] -`--progress <STRING>`:: -Configure how the CDK CLI displays deployment progress. -+ --- -* `bar` – Display stack deployment events as a progress bar, with the events for the resource currently being deployed. -* `events` – Provide a complete history, including all CloudFormation events. --- -+ -You can also configure this option in the project's `cdk.json` file or at `~/.cdk.json` on your local development machine: -+ -[source,json,subs="verbatim,attributes"] ----- -{ - "progress": "events" -} ----- -+ -_Valid values_: `bar`, `events` -+ -_Default value_: `bar` - -[#ref-cli-cmd-watch-options-rollback] -`--rollback <BOOLEAN>`:: -During deployment, if a resource fails to be created or updated, the deployment will roll back to the latest stable state before the CDK CLI returns. All changes made up to that point will be undone. Resources that were created will be deleted and updates that were made will be rolled back. -+ -Use `--no-rollback` or `-R` to deactivate this behavior. If a resource fails to be created or updated, the CDK CLI will leave changes made up to that point in place and return. This may be helpful in development environments where you are iterating quickly. -+ -[NOTE] -==== -When `false`, deployments that cause resource replacements will always fail. You can only use this value for deployments that update or create new resources. -==== -+ -_Default value_: `true` - -[#ref-cli-cmd-watch-options-toolkit-stack-name] -`--toolkit-stack-name <STRING>`:: -The name of the existing CDK Toolkit stack. -+ -By default, `cdk bootstrap` deploys a stack named `CDKToolkit` into the specified {aws} environment. Use this option to provide a different name for your bootstrap stack. -+ -The CDK CLI uses this value to verify your bootstrap stack version. - -[#ref-cli-cmd-watch-examples] -== Examples - -[#ref-cli-cmd-watch-examples-1] -=== Watch a CDK stack with logical ID DevelopmentStack for changes - -[source,none,subs="verbatim,attributes"] ----- -$ cdk watch DevelopmentStack -Detected change to 'lambda-code/index.js' (type: change). Triggering 'cdk deploy' -DevelopmentStack: deploying... - - ✅ DevelopmentStack ----- - -[#ref-cli-cmd-watch-examples-2] -=== Configure a cdk.json file for what to include and exclude from being watched for changes - -[source,json,subs="verbatim,attributes"] ----- -{ - "app": "mvn -e -q compile exec:java", - "watch": { - "include": "src/main/**", - "exclude": "target/*" - } -} ----- - -[#ref-cli-cmd-watch-examples-3] -=== Build a CDK project using Java before deployment by configuring the cdk.json file - -[source,json,subs="verbatim,attributes"] ----- -{ - "app": "mvn -e -q exec:java", - "build": "mvn package", - "watch": { - "include": "src/main/**", - "exclude": "target/*" - } -} ----- \ No newline at end of file diff --git a/v2/guide/ref-cli-cmd/ref-cli-cmd.adoc b/v2/guide/ref-cli-cmd/ref-cli-cmd.adoc deleted file mode 100644 index 3435ce57..00000000 --- a/v2/guide/ref-cli-cmd/ref-cli-cmd.adoc +++ /dev/null @@ -1,385 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[#ref-cli-cmd] -= {aws} CDK CLI command reference -:keywords: {aws} CDK, {aws} CDK CLI, CDK Toolkit, IaC, Infrastructure as code, {aws} Cloud, {aws} CloudFormation - -[abstract] --- -This section contains command reference information for the {aws} Cloud Development Kit ({aws} CDK) Command Line Interface (CLI). The CDK CLI is also referred to as the CDK Toolkit. --- - -// Content start - -This section contains command reference information for the {aws} Cloud Development Kit ({aws} CDK) Command Line Interface (CLI). The CDK CLI is also referred to as the CDK Toolkit. - -[#ref-cli-cmd-usage] -== Usage - -[source,none,subs="verbatim,attributes"] ----- -$ cdk <command> <arguments> <options> ----- - -[#ref-cli-cmd-commands] -== Commands - -[#ref-cli-cmd-commands-acknowledge] -`xref:ref-cli-cmd-ack[acknowledge ack]`:: -Acknowledge a notice by issue number and hide it from displaying again. - -[#ref-cli-cmd-commands-bootstrap] -`xref:ref-cli-cmd-bootstrap[bootstrap]`:: -Prepare an {aws} environment for CDK deployments by deploying the CDK bootstrap stack, named `CDKToolkit`, into the {aws} environment. - -[#ref-cli-cmd-commands-context] -`xref:ref-cli-cmd-context[context]`:: -Manage cached context values for your CDK application. - -[#ref-cli-cmd-commands-deploy] -`xref:ref-cli-cmd-deploy[deploy]`:: -Deploy one or more CDK stacks into your {aws} environment. - -[#ref-cli-cmd-commands-destroy] -`xref:ref-cli-cmd-destroy[destroy]`:: -Delete one or more CDK stacks from your {aws} environment. - -[#ref-cli-cmd-commands-diff] -`xref:ref-cli-cmd-diff[diff]`:: -Perform a diff to see infrastructure changes between CDK stacks. - -[#ref-cli-cmd-commands-docs] -`xref:ref-cli-cmd-docs[docs doc]`:: -Open CDK documentation in your browser. - -[#ref-cli-cmd-commands-doctor] -`xref:ref-cli-cmd-doctor[doctor]`:: -Inspect and display useful information about your local CDK project and development environment. - -[#ref-cli-cmd-commands-import] -`xref:ref-cli-cmd-import[import]`:: -Use {aws} CloudFormation resource imports to import existing {aws} resources into a CDK stack. - -[#ref-cli-cmd-commands-init] -`xref:ref-cli-cmd-init[init]`:: -Create a new CDK project from a template. - -[#ref-cli-cmd-commands-list] -`xref:ref-cli-cmd-list[list, ls]`:: -List all CDK stacks and their dependencies from a CDK app. - -[#ref-cli-cmd-commands-metadata] -`xref:ref-cli-cmd-metadata[metadata]`:: -Display metadata associated with a CDK stack. - -[#ref-cli-cmd-commands-migrate] -`xref:ref-cli-cdk-migrate[migrate]`:: -Migrate {aws} resources, {aws} CloudFormation stacks, and {aws} CloudFormation templates into a new CDK project. - -[#ref-cli-cmd-commands-notices] -`xref:ref-cli-cmd-notices[notices]`:: -Display notices for your CDK application. - -[#ref-cli-cmd-commands-synthesize] -`xref:ref-cli-cmd-synth[synthesize, synth]`:: -Synthesize a CDK app to produce a cloud assembly, including an {aws} CloudFormation template for each stack. - -[#ref-cli-cmd-commands-watch] -`xref:ref-cli-cmd-watch[watch]`:: -Continuously watch a local CDK project for changes to perform deployments and hotswaps. - -[#ref-cli-cmd-options] -== Global options - -The following options are compatible with all CDK CLI commands. - -[#ref-cli-cmd-options-app] -`--app, -a <STRING>`:: -Provide the command for running your app or cloud assembly directory. -+ -_Required_: Yes - -[#ref-cli-cmd-options-asset-metadata] -`--asset-metadata <BOOLEAN>`:: -Include `aws:asset:*` {aws} CloudFormation metadata for resources that use assets. -+ -_Required_: No -+ -_Default value_: `true` - -[#ref-cli-cmd-options-build] -`--build <STRING>`:: -Command for running a pre-synthesis build. -+ -_Required_: No - -[#ref-cli-cmd-options-ca-bundle-path] -`--ca-bundle-path <STRING>`:: -Path to a CA certificate to use when validating HTTPS requests. -+ -If this option is not provided, the CDK CLI will read from the `AWS_CA_BUNDLE` environment variable. -+ -_Required_: Yes - -[#ref-cli-cmd-options-ci] -`--ci <BOOLEAN>`:: -Indicate that CDK CLI commands are being run in a continuous integration (CI) environment. -+ -This option modifies the behavior of the CDK CLI to better suit automated operations that are typical in CI pipelines. -+ -When you provide this option, logs are sent to `stdout` instead of `stderr`. -+ -_Required_: No -+ -_Default value_: `false` - -[#ref-cli-cmd-options-context] -`--context, -c <ARRAY>`:: -Add contextual string parameters as key-value pairs. - -[#ref-cli-cmd-options-debug] -`--debug <BOOLEAN>`:: -Enable detailed debugging information. This option produces a verbose output that includes a lot more detail about what the CDK CLI is doing behind the scenes. -+ -_Required_: No -+ -_Default value_: `false` - -[#ref-cli-cmd-options-ec2creds] -`--ec2creds, -i <BOOLEAN>`:: -Force the CDK CLI to try and fetch Amazon EC2 instance credentials. -+ -By default, the CDK CLI guesses the Amazon EC2 instance status. -+ -_Required_: No -+ -_Default value_: `false` - -[#ref-cli-cmd-options-help] -`--help, -h <BOOLEAN>`:: -Show command reference information for the CDK CLI. -+ -_Required_: No -+ -_Default value_: `false` - -[#ref-cli-cmd-options-ignore-errors] -`--ignore-errors <BOOLEAN>`:: -Ignore synthesis errors, which will likely produce an output that is not valid. -+ -_Required_: No -+ -_Default value_: `false` - -[#ref-cli-cmd-options-json] -`--json, -j <BOOLEAN>`:: -Use JSON instead of YAML for {aws} CloudFormation templates that are printed to standard output (``stdout``). -+ -_Required_: No -+ -_Default value_: `false` - -[#ref-cli-cmd-options-lookups] -`--lookups <BOOLEAN>`:: -Perform context lookups. -+ -Synthesis will fail if this value is `false` and context lookups need to be performed. -+ -_Required_: No -+ -_Default value_: `true` - -[#ref-cli-cmd-options-no-color] -`--no-color <BOOLEAN>`:: -Remove color and other styling from the console output. -+ -_Required_: No -+ -_Default value_: `false` - -[#ref-cli-cmd-options-notices] -`--notices <BOOLEAN>`:: -Show relevant notices. -+ -_Required_: No -+ -_Default value_: `false` - -[#ref-cli-cmd-options-output] -`--output, -o <STRING>`:: -Specify the directory to output the synthesized cloud assembly to. -+ -_Required_: Yes -+ -_Default value_: `cdk.out` - -[#ref-cli-cmd-options-path-metadata] -`--path-metadata <BOOLEAN>`:: -Include `aws::cdk::path` {aws} CloudFormation metadata for each resource. -+ -_Required_: No -+ -_Default value_: `true` - -[#ref-cli-cmd-options-plugin] -`--plugin, -p <ARRAY>`:: -Name or path of a node package that extends CDK features. This option can be provided multiple times in a single command. -+ -You can configure this option in the project's `cdk.json` file or at `~/.cdk.json` on your local development machine: -+ -[source,json,subs="verbatim,attributes"] ----- -{ - // ... - "plugin": [ - "module_1", - "module_2" - ], - // ... -} ----- -+ -_Required_: No - -[#ref-cli-cmd-options-profile] -`--profile <STRING>`:: -Specify the name of the {aws} profile, containing your {aws} environment information, to use with the CDK CLI. -+ -_Required_: Yes - -[#ref-cli-cmd-options-proxy] -`--proxy <STRING>`:: -Use the indicated proxy. -+ -If this option is not provided, the CDK CLI will read from the `HTTPS_PROXY` environment variable. -+ -_Required_: Yes -+ -_Default value_: Read from `HTTPS_PROXY` environment variable. - -[#ref-cli-cmd-options-role-arn] -`--role-arn, -r <STRING>`:: -The ARN of the IAM role that the CDK CLI will assume when interacting with {aws} CloudFormation. -+ -_Required_: No - -[#ref-cli-cmd-options-staging] -`--staging <BOOLEAN>`:: -Copy assets to the output directory. -+ -Specify `false` to prevent the copying of assets to the output directory. This allows the {aws} SAM CLI to reference the original source files when performing local debugging. -+ -_Required_: No -+ -_Default value_: `true` - -[#ref-cli-cmd-options-strict] -`--strict <BOOLEAN>`:: -Do not construct stacks that contain warnings. -+ -_Required_: No -+ -_Default value_: `false` - -[#ref-cli-cmd-options-trace] -`--trace <BOOLEAN>`:: -Print trace for stack warnings. -+ -_Required_: No -+ -_Default value_: `false` - -[#ref-cli-cmd-options-verbose] -`--verbose, -v <COUNT>`:: -Show debug logs. You can specify this option multiple times to increase verbosity. -+ -_Required_: No - -[#ref-cli-cmd-options-version] -`--version <BOOLEAN>`:: -Show the CDK CLI version number. -+ -_Required_: No -+ -_Default value_: `false` - -[#ref-cli-cmd-options-version-reporting] -`--version-reporting <BOOLEAN>`:: -Include the `{aws}::CDK::Metadata` resource in synthesized {aws} CloudFormation templates. -+ -_Required_: No -+ -_Default value_: `true` - -[#ref-cli-cmd-configure] -== Providing and configuring options - -You can pass options through command-line arguments. For most options, you can configure them in a `cdk.json` configuration file. When you use multiple configuration sources, the CDK CLI adheres to the following precedence: - -. *Command-line values* – Any option provided at the command-line overrides options configured in `cdk.json` files. -. *Project configuration file* – The `cdk.json` file in your CDK project's directory. -. *User configuration file* – The `cdk.json` file located at `~/.cdk.json` on your local machine. - -[#ref-cli-cmd-pass] -== Passing options at the command line - -[#ref-cli-cmd-pass-bool] -*Passing boolean values*:: -+ -For options that accept a boolean value, you can specify them in the following ways: -+ -* Use `true` and `false` values – Provide the boolean value with the command. The following is an example: -+ -[source,none,subs="verbatim,attributes"] ----- -$ cdk deploy --watch=true -$ cdk deploy --watch=false ----- -* Provide the option's counterpart – Modify the option name by adding `no` to specify a `false` value. The following is an example: -+ -[source,none,subs="verbatim,attributes"] ----- -$ cdk deploy --watch -$ cdk deploy --no-watch ----- -* For options that default to `true` or `false`, you don't have to provide the option unless you want to change from the default. - - -include::ref-cli-cmd-ack.adoc[leveloffset=+1] - -include::ref-cli-cmd-bootstrap.adoc[leveloffset=+1] - -include::ref-cli-cmd-context.adoc[leveloffset=+1] - -include::ref-cli-cmd-deploy.adoc[leveloffset=+1] - -include::ref-cli-cmd-destroy.adoc[leveloffset=+1] - -include::ref-cli-cmd-diff.adoc[leveloffset=+1] - -include::ref-cli-cmd-docs.adoc[leveloffset=+1] - -include::ref-cli-cmd-doctor.adoc[leveloffset=+1] - -include::ref-cli-cmd-gc.adoc[leveloffset=+1] - -include::ref-cli-cmd-import.adoc[leveloffset=+1] - -include::ref-cli-cmd-init.adoc[leveloffset=+1] - -include::ref-cli-cmd-list.adoc[leveloffset=+1] - -include::ref-cli-cmd-metadata.adoc[leveloffset=+1] - -include::ref-cli-cmd-migrate.adoc[leveloffset=+1] - -include::ref-cli-cmd-notices.adoc[leveloffset=+1] - -include::ref-cli-cmd-rollback.adoc[leveloffset=+1] - -include::ref-cli-cmd-synth.adoc[leveloffset=+1] - -include::ref-cli-cmd-watch.adoc[leveloffset=+1] \ No newline at end of file diff --git a/v2/guide/reference.adoc b/v2/guide/reference.adoc deleted file mode 100644 index e69de29b..00000000 diff --git a/v2/guide/reference/reference.adoc b/v2/guide/reference/reference.adoc deleted file mode 100644 index 2bde1628..00000000 --- a/v2/guide/reference/reference.adoc +++ /dev/null @@ -1,24 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[#reference] -= {aws} CDK reference - -// Content start - -This section contains reference information for the {aws} Cloud Development Kit ({aws} CDK). - -[#reference-api] -== API reference - -The https://docs.aws.amazon.com/cdk/api/v2[API Reference] contains information about the {aws} Construct Library and other APIs provided by the {aws} Cloud Development Kit ({aws} CDK). Most of the {aws} Construct Library is contained in a single package called by its TypeScript name: `aws-cdk-lib`. The actual package name varies by language. Separate versions of the API reference are provided for each supported programming language. - -The CDK API reference is organized into sub-modules. There are one or more sub-modules for each {aws} service. - -Each sub-module has an overview that includes information about how to use its APIs. For example, the link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3-readme.html[S3] overview demonstrates how to set default encryption on an Amazon Simple Storage Service (Amazon S3) bucket. - -include::versioning.adoc[leveloffset=+1] - - -include::videos.adoc[leveloffset=+1] diff --git a/v2/guide/reference/versioning.adoc b/v2/guide/reference/versioning.adoc deleted file mode 100644 index 2b99e18f..00000000 --- a/v2/guide/reference/versioning.adoc +++ /dev/null @@ -1,86 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[#versioning] -= {aws} CDK versioning -:info_titleabbrev: Versioning -:keywords: versioning, {aws} CDK reference - -[abstract] --- -This topic provides reference information on how the {aws} Cloud Development Kit ({aws} CDK) handles versioning. --- - -// Content start - -This topic provides reference information on how the {aws} Cloud Development Kit ({aws} CDK) handles versioning. - -Version numbers consist of three numeric version parts: _major_._minor_._patch_, and strictly adhere to the https://semver.org[semantic versioning] model. This means that breaking changes to stable APIs are limited to major releases. - -Minor and patch releases are backward compatible. The code written in a previous version with the same major version can be upgraded to a newer version within the same major version. It will also continue to build and run, producing the same output. - -[#cdk-toolkit-versioning] -== {aws} CDK CLI compatibility - -Each version of the main {aws} CDK library (`aws-cdk-lib`) is compatible with the {aws} CDK CLI (`aws-cdk-cli`) version that was current at the time of the CDK library's release. It is also compatible with any newer version of the CDK CLI. Each version of the CDK library maintains this compatibility until the library's _End of Life_ date. Therefore, as long as you're using a supported CDK library version, it is always safe to upgrade your CDK CLI version. - -Each version of the CDK library may also work with CDK CLI versions older than the version that was current at the time of the CDK library's release. However, this is not guaranteed. Compatibility depends on the CDK library's cloud assembly schema version. The {aws} CDK generates a cloud assembly during synthesis and the CDK CLI consumes it for deployment. The schema that defines the format of the cloud assembly is strictly specified and versioned. Therefore, an older version of the CDK CLI would need to support the cloud assembly schema version of the CDK library for them to be compatible. - -When the cloud assembly version required by the CDK library is not compatible with the version supported by the CDK CLI, you receive an error message like the following: - -[source,none,subs="verbatim,attributes"] ----- -Cloud assembly schema version mismatch: Maximum schema version supported is 3.0.0, but found 4.0.0. - Please upgrade your CLI in order to interact with this app. ----- - -To resolve this error, update the CDK CLI to a version compatible with the required cloud assembly version, or to the latest available version. The alternative (downgrading the construct library modules your app uses) is generally not recommended. - -[NOTE] -==== - -For more information on the exact combinations of versions that work together, see the https://github.com/aws/aws-cdk-cli/blob/main/COMPATIBILITY.md[compatibility table] in the _aws-cdk-cli GitHub repository_. - -==== - -[#aws-construct-lib-stability] -== {aws} Construct Library versioning - -The modules in the {aws} Construct Library move through various stages as they are developed from concept to mature API. Different stages offer varying degrees of API stability in subsequent versions of the {aws} CDK. - -APIs in the main {aws} CDK library, `aws-cdk-lib`, are stable, and the library is fully semantically versioned. This package includes {aws} CloudFormation (L1) constructs for all {aws} services and all stable higher-level (L2 and L3) modules. (It also includes the core CDK classes like `App` and `Stack`). APIs will not be removed from this package (though they may be deprecated) until the next major release of the CDK. No individual API will ever have breaking changes. When a breaking change is required, an entirely new API will be added. - -New APIs under development for a service already incorporated in `aws-cdk-lib` are identified using a `Beta<N>` suffix, where `N` starts at 1 and is incremented with each breaking change to the new API. `Beta<N>` APIs are never removed, only deprecated, so your existing app continues to work with newer versions of ``aws-cdk-lib``. When the API is deemed stable, a new API without the `Beta<N>` suffix is added. - -When higher-level (L2 or L3) APIs begin to be developed for an {aws} service that previously had only L1 APIs, those APIs are initially distributed in a separate package. The name of such a package has an "Alpha" suffix, and its version matches the first version of `aws-cdk-lib` it is compatible with, with an `alpha` sub-version. When the module supports the intended use cases, its APIs are added to `aws-cdk-lib`. - -[#aws-construct-lib-versioning-binding] -== Language binding stability - -Over time, we might add support to the {aws} CDK for additional programming languages. Although the API described in all the languages is the same, the way that API is expressed varies by language and might change as the language support evolves. For this reason, language bindings are deemed experimental for a time until they are considered ready for production use. - -[cols="1,1", options="header"] -|=== -| Language -| Stability - -|TypeScript -|Stable - -|JavaScript -|Stable - -|Python -|Stable - -|Java -|Stable - -|C#/.NET -|Stable - -|Go -|Stable -|=== \ No newline at end of file diff --git a/v2/guide/reference/videos.adoc b/v2/guide/reference/videos.adoc deleted file mode 100644 index 493655bd..00000000 --- a/v2/guide/reference/videos.adoc +++ /dev/null @@ -1,42 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[#videos] -= {aws} CDK video resources -:info_titleabbrev: Video resources - -Enjoy these videos presented by members of the {aws} CDK team. - -[NOTE] -==== - -Since the {aws} CDK is always evolving, some of the code presented in these videos may not work quite the same way it did when the video was recorded. This is especially true for modules that were under active development at the time. It's also possible that we've since added a better way to achieve the same result. Consult this Developer Guide and the https://docs.aws.amazon.com/cdk/api/v2/docs/aws-construct-library.html[{aws} CDK API Reference] for up-to-date information. - -==== - -[#videos-infrastructure-is-code] -== Infrastructure _is_ Code with the {aws} CDK - -video::ZWCvNFUN-sU[youtube,height = 450,fileref = https://www.youtube.com/embed/ZWCvNFUN-sU,width = 800] - -[#videos-deep-dive] -== Deep dive into {aws} Cloud Development Kit ({aws} CDK) - -video::9As_ZIjUGmY[youtube,height = 450,fileref = https://www.youtube.com/embed/9As_ZIjUGmY,width = 800] - -[#videos-contributing] -== Contributing to the {aws} Construct Library - -video::LsYlf7ggyrY[youtube,height = 450,fileref = https://www.youtube.com/embed/LsYlf7ggyrY,width = 800] - -[#videos-pipelines] -== Faster deployments with CDK Pipelines - -video::1ps0Wh19MHQ[youtube,height = 450,fileref = https://www.youtube.com/embed/1ps0Wh19MHQ,width = 800] - -[#videos-gitpod] -== How to contribute to the {aws} CDK using GitPod - -video::u6XcIgs-Nok[youtube,height = 450,fileref = https://www.youtube.com/embed/u6XcIgs-Nok,width = 800] \ No newline at end of file diff --git a/v2/guide/security/_security-entities.ent b/v2/guide/security/_security-entities.ent deleted file mode 100644 index 89a6b742..00000000 --- a/v2/guide/security/_security-entities.ent +++ /dev/null @@ -1,3 +0,0 @@ -<!ENTITY SERVICENAME 'the &CDK;'> -<!ENTITY SERVICENAMESENTENCECASE 'The &CDK;'> -<!ENTITY SERVICENAMETITLE 'the &CDKlong;'> \ No newline at end of file diff --git a/v2/guide/security/compliance-validation.adoc b/v2/guide/security/compliance-validation.adoc deleted file mode 100644 index 57024829..00000000 --- a/v2/guide/security/compliance-validation.adoc +++ /dev/null @@ -1,30 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[#compliance-validation] -= Compliance validation for the {aws} Cloud Development Kit ({aws} CDK) -:info_titleabbrev: Compliance validation - -[abstract] --- -Provides information about compliance validation for the {aws} CDK. --- - -// Content start - -The {aws} CDK follows the link:https://aws.amazon.com/compliance/shared-responsibility-model/[shared responsibility model] through the specific Amazon Web Services ({aws}) services it supports. For {aws} service security information, see the link:https://docs.aws.amazon.com/security/?id=docs_gateway#aws-security[{aws} service security documentation page] and link:https://aws.amazon.com/compliance/services-in-scope/[{aws} services that are in scope of {aws} compliance efforts by compliance program]. - -The security and compliance of {aws} services is assessed by third-party auditors as part of multiple {aws} compliance programs. These include SOC, PCI, FedRAMP, HIPAA, and others. {aws} provides a frequently updated list of {aws} services in scope of specific compliance programs at link:https://aws.amazon.com/compliance/services-in-scope/[{aws} Services in Scope by Compliance Program]. - -Third-party audit reports are available for you to download using {aws} Artifact. For more information, see link:https://docs.aws.amazon.com/artifact/latest/ug/downloading-documents.html[Downloading Reports in {aws} Artifact]. - -For more information about {aws} compliance programs, see https://aws.amazon.com/compliance/programs/[{aws} Compliance Programs]. - -Your compliance responsibility when using the {aws} CDK to access an {aws} service is determined by the sensitivity of your data, your organization's compliance objectives, and applicable laws and regulations. If your use of an {aws} service is subject to compliance with standards such as HIPAA, PCI, or FedRAMP, {aws} provides resources to help: - -* link:https://aws.amazon.com/quickstart/?quickstart-all.sort-by=item.additionalFields.updateDate&quickstart-all.sort-order=desc&awsf.quickstart-homepage-filter=categories%23security-identity-compliance[Security and Compliance Quick Start Guides] – Deployment guides that discuss architectural considerations and provide steps for deploying security-focused and compliance-focused baseline environments on {aws}. -* link:https://aws.amazon.com/compliance/resources/[{aws} Compliance Resources] – A collection of workbooks and guides that might apply to your industry and location. -* link:https://aws.amazon.com/config/[{aws} Config] – A service that assesses how well your resource configurations comply with internal practices, industry guidelines, and regulations. -* link:https://aws.amazon.com/security-hub/[{aws} Security Hub] – A comprehensive view of your security state within {aws} that helps you check your compliance with security industry standards and best practices. \ No newline at end of file diff --git a/v2/guide/security/disaster-recovery-resiliency.adoc b/v2/guide/security/disaster-recovery-resiliency.adoc deleted file mode 100644 index 51932e1d..00000000 --- a/v2/guide/security/disaster-recovery-resiliency.adoc +++ /dev/null @@ -1,25 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[#disaster-recovery-resiliency] -= Resilience for the {aws} Cloud Development Kit ({aws} CDK) -:info_titleabbrev: Resilience - -[abstract] --- -Provides information about resilience for the {aws} CDK. --- - -// Content start - -The Amazon Web Services ({aws}) global infrastructure is built around {aws} Regions and Availability Zones. - -{aws} Regions provide multiple physically separated and isolated Availability Zones, which are connected with low-latency, high-throughput, and highly redundant networking. - -With Availability Zones, you can design and operate applications and databases that automatically fail over between Availability Zones without interruption. Availability Zones are more highly available, fault tolerant, and scalable than traditional single or multiple data center infrastructures. - -For more information about {aws} Regions and Availability Zones, see link:https://aws.amazon.com/about-aws/global-infrastructure/[{aws} Global Infrastructure]. - -The {aws} CDK follows the link:https://aws.amazon.com/compliance/shared-responsibility-model/[shared responsibility model] through the specific Amazon Web Services ({aws}) services it supports. For {aws} service security information, see the link:https://docs.aws.amazon.com/security/?id=docs_gateway#aws-security[{aws} service security documentation page] and https://aws.amazon.com/compliance/services-in-scope/[{aws} services that are in scope of {aws} compliance efforts by compliance program]. \ No newline at end of file diff --git a/v2/guide/security/infrastructure-security.adoc b/v2/guide/security/infrastructure-security.adoc deleted file mode 100644 index ee860fd2..00000000 --- a/v2/guide/security/infrastructure-security.adoc +++ /dev/null @@ -1,15 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[#infrastructure-security] -= Infrastructure security for the {aws} Cloud Development Kit ({aws} CDK) -:info_titleabbrev: Infrastructure security - -[abstract] --- -Provides information about infrastructure security for the {aws} CDK. --- - -The {aws} CDK follows the link:https://aws.amazon.com/compliance/shared-responsibility-model/[shared responsibility model] through the specific Amazon Web Services ({aws}) services it supports. For {aws} service security information, see the link:https://docs.aws.amazon.com/security/?id=docs_gateway#aws-security[{aws} service security documentation page] and https://aws.amazon.com/compliance/services-in-scope/[{aws} services that are in scope of {aws} compliance efforts by compliance program]. \ No newline at end of file diff --git a/v2/guide/security/security-iam.adoc b/v2/guide/security/security-iam.adoc deleted file mode 100644 index beb87878..00000000 --- a/v2/guide/security/security-iam.adoc +++ /dev/null @@ -1,84 +0,0 @@ -include::../attributes.txt[] - -// Attributes -[.topic] -[#security-iam] -= Identity and access management for the {aws} Cloud Development Kit ({aws} CDK) -:info_titleabbrev: Identity and access management - -[abstract] --- -Provides information about identity and access management for the {aws} CDK. --- - -// Content start - -{aws} Identity and Access Management (IAM) is an {aws} service that helps an administrator securely control access to {aws} resources. IAM administrators control who can be _authenticated_ (signed in) and _authorized_ (have permissions) to use {aws} resources. IAM is an {aws} service that you can use with no additional charge. - -[#security-iam-audience] -== Audience - -How you use {aws} Identity and Access Management (IAM) differs, depending on the work that you do in {aws}. - -*Service user* – If you use {aws} services to do your job, then your administrator provides you with the credentials and permissions that you need. As you use more {aws} features to do your work, you might need additional permissions. Understanding how access is managed can help you request the right permissions from your administrator. - -*Service administrator* – If you're in charge of {aws} resources at your company, you probably have full access to {aws} resources. It's your job to determine which {aws} services and resources your service users should access. You must then submit requests to your IAM administrator to change the permissions of your service users. Review the information on this page to understand the basic concepts of IAM. - -*IAM administrator* – If you're an IAM administrator, you might want to learn details about how you can write policies to manage access to {aws} services. - -[#security-iam-authentication] -== Authenticating with identities - -Authentication is how you sign in to {aws} using your identity credentials. You must be _authenticated_ (signed in to {aws}) as the {aws} account root user, as an IAM user, or by assuming an IAM role. - -You can sign in to {aws} as a federated identity by using credentials provided through an identity source. {aws} IAM Identity Center (IAM Identity Center) users, your company's single sign-on authentication, and your Google or Facebook credentials are examples of federated identities. When you sign in as a federated identity, your administrator previously set up identity federation using IAM roles. When you access {aws} by using federation, you are indirectly assuming a role. - -Depending on the type of user you are, you can sign in to the {aws} Management Console or the {aws} access portal. For more information about signing in to {aws}, see link:https://docs.aws.amazon.com/signin/latest/userguide/how-to-sign-in.html[How to sign in to your {aws} account] in the _{aws} Sign-In User Guide_. - -To access {aws} programmatically, {aws} provides the {aws} CDK, software development kits (SDKs), and a command line interface (CLI) to cryptographically sign your requests using your credentials. If you don't use {aws} tools, you must sign requests yourself. For more information about using the recommended method to sign requests yourself, see link:https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html[Signature Version 4 signing process] in the _{aws} General Reference_. - -Regardless of the authentication method that you use, you might be required to provide additional security information. For example, {aws} recommends that you use multi-factor authentication (MFA) to increase the security of your account. To learn more, see https://docs.aws.amazon.com/singlesignon/latest/userguide/enable-mfa.html[Multi-factor authentication] in the _{aws} IAM Identity Center User Guide_ and link:https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_mfa.html[Using multi-factor authentication (MFA) in {aws}] in the _IAM User Guide_. - -[#security-iam-authentication-rootuser] -=== {aws} account root user - -When you create an {aws} account, you begin with one sign-in identity that has complete access to all {aws} services and resources in the account. This identity is called the {aws} account _root user_ and is accessed by signing in with the email address and password that you used to create the account. We strongly recommend that you don't use the root user for your everyday tasks. Safeguard your root user credentials and use them to perform the tasks that only the root user can perform. For the complete list of tasks that require you to sign in as the root user, see link:https://docs.aws.amazon.com/IAM/latest/UserGuide/id_root-user.html#root-user-tasks[Tasks that require root user credentials] in the _IAM User Guide_. - -[#security-iam-authentication-federated] -=== Federated identity - -As a best practice, require human users, including users that require administrator access, to use federation with an identity provider to access {aws} services by using temporary credentials. - -A _federated identity_ is a user from your enterprise user directory, a web identity provider, the {aws} Directory Service, the Identity Center directory, or any user that accesses {aws} services by using credentials provided through an identity source. When federated identities access {aws} accounts, they assume roles, and the roles provide temporary credentials. - -For centralized access management, we recommend that you use {aws} IAM Identity Center. You can create users and groups in IAM Identity Center, or you can connect and synchronize to a set of users and groups in your own identity source for use across all your {aws} accounts and applications. For information about IAM Identity Center, see link:https://docs.aws.amazon.com/singlesignon/latest/userguide/what-is.html[What is IAM Identity Center?] in the _{aws} IAM Identity Center User Guide_. - -[#security-iam-authentication-iamuser] -=== IAM users and groups - -An _link:https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users.html[IAM user]_ is an identity within your {aws} account that has specific permissions for a single person or application. Where possible, we recommend relying on temporary credentials instead of creating IAM users who have long-term credentials such as passwords and access keys. However, if you have specific use cases that require long-term credentials with IAM users, we recommend that you rotate access keys. For more information, see link:https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#rotate-credentials[Rotate access keys regularly for use cases that require long-term credentials] in the _IAM User Guide_. - -An link:https://docs.aws.amazon.com/IAM/latest/UserGuide/id_groups.html[IAM group] is an identity that specifies a collection of IAM users. You can't sign in as a group. You can use groups to specify permissions for multiple users at a time. Groups make permissions easier to manage for large sets of users. For example, you could have a group named _IAMAdmins_ and give that group permissions to administer IAM resources. - -Users are different from roles. A user is uniquely associated with one person or application, but a role is intended to be assumable by anyone who needs it. Users have permanent long-term credentials, but roles provide temporary credentials. To learn more, see link:https://docs.aws.amazon.com/IAM/latest/UserGuide/gs-identities-iam-users.html[Use cases for IAM users] in the _IAM User Guide_. - -[#security-iam-authentication-iamrole] -=== IAM roles - -An _link:https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html[IAM role]_ is an identity within your {aws} account that has specific permissions. It's similar to an IAM user, but isn't associated with a specific person. You can temporarily assume an IAM role in the {aws} Management Console by link:https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-console.html[switching roles]. You can assume a role by calling an {aws} CLI or {aws} API operation or by using a custom URL. For more information about methods for using roles, see link:https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use.html[Using IAM roles] in the _IAM User Guide_. - -IAM roles with temporary credentials are useful in the following situations: - -* *Federated user access* – To assign permissions to a federated identity, you create a role and define permissions for the role. When a federated identity authenticates, the identity is associated with the role and is granted the permissions that are defined by the role. For information about roles for federation, see link:https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-idp.html[Create a role for a third-party identity provider (federation)] in the _IAM User Guide_. If you use IAM Identity Center, you configure a permission set. To control what your identities can access after they authenticate, IAM Identity Center correlates the permission set to a role in IAM. For information about permissions sets, see https://docs.aws.amazon.com/singlesignon/latest/userguide/permissionsetsconcept.html[Permission sets] in the _{aws} IAM Identity Center User Guide_. -* *Temporary IAM user permissions* – An IAM user or role can assume an IAM role to temporarily take on different permissions for a specific task. -* *Cross-account access* – You can use an IAM role to allow someone (a trusted principal) in a different account to access resources in your account. Roles are the primary way to grant cross-account access. However, with some {aws} services, you can attach a policy directly to a resource (instead of using a role as a proxy). To learn the difference between roles and resource-based policies for cross-account access, see link:https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_compare-resource-policies.html[How IAM roles differ from resource-based policies] in the __IAM User Guide__. -* *Cross-service access* – Some {aws} services use features in other {aws} services. For example, when you make a call in a service, it's common for that service to run applications in Amazon EC2 or store objects in Amazon S3. A service might do this using the calling principal's permissions, using a service role, or using a service-linked role. -+ --- -** *Service role* – A service role is an link:https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html[IAM role] that a service assumes to perform actions on your behalf. An IAM administrator can create, modify, and delete a service role from within IAM. For more information, see link:https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-service.html[Create a role to delegate permissions to an {aws} service] in the _IAM User Guide_. -** *Service-linked role* – A service-linked role is a type of service role that is linked to an {aws} service. The service can assume the role to perform an action on your behalf. Service-linked roles appear in your {aws} account and are owned by the service. An IAM administrator can view, but not edit the permissions for service-linked roles. --- -+ -* *Applications running on Amazon EC2* – You can use an IAM role to manage temporary credentials for applications that are running on an EC2 instance and making {aws} CLI or {aws} API requests. This is preferable to storing access keys within the EC2 instance. To assign an {aws} role to an EC2 instance and make it available to all of its applications, you create an instance profile that is attached to the instance. An instance profile contains the role and enables programs that are running on the EC2 instance to get temporary credentials. For more information, see link:https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2.html[Use an IAM role to grant permissions to applications running on Amazon EC2 instances] in the _IAM User Guide_. - -To learn whether to use IAM roles or IAM users, see link:https://docs.aws.amazon.com/IAM/latest/UserGuide/id.html#id_which-to-choose_role[When to create an IAM role (instead of a user)] in the _IAM User Guide_. \ No newline at end of file diff --git a/v2/guide/security/security.adoc b/v2/guide/security/security.adoc deleted file mode 100644 index d7437fa4..00000000 --- a/v2/guide/security/security.adoc +++ /dev/null @@ -1,33 +0,0 @@ -include::../attributes.txt[] - -// Attributes -[.topic] -[#security] -= Security for the {aws} Cloud Development Kit ({aws} CDK) -:info_titleabbrev: Security - -[abstract] --- -Provides security-related information for the {aws} CDK. --- - -// Content start - -Cloud security at Amazon Web Services ({aws}) is the highest priority. As an {aws} customer, you benefit from a data center and network architecture that is built to meet the requirements of the most security-sensitive organizations. Security is a shared responsibility between {aws} and you. The link:https://aws.amazon.com/compliance/shared-responsibility-model/[Shared Responsibility Model] describes this as Security of the Cloud and Security in the Cloud. - -*Security of the Cloud* – {aws} is responsible for protecting the infrastructure that runs all of the services offered in the {aws} Cloud and providing you with services that you can use securely. Our security responsibility is the highest priority at {aws}, and the effectiveness of our security is regularly tested and verified by third-party auditors as part of the https://aws.amazon.com/compliance/programs/[{aws} Compliance Programs]. - -*Security in the Cloud* – Your responsibility is determined by the {aws} service you are using, and other factors including the sensitivity of your data, your organization's requirements, and applicable laws and regulations. - -The {aws} CDK follows the link:https://aws.amazon.com/compliance/shared-responsibility-model/[shared responsibility model] through the specific Amazon Web Services ({aws}) services it supports. For {aws} service security information, see the link:https://docs.aws.amazon.com/security/?id=docs_gateway#aws-security[{aws} service security documentation page] and https://aws.amazon.com/compliance/services-in-scope/[{aws} services that are in scope of {aws} compliance efforts by compliance program]. - -include::security-iam.adoc[leveloffset=+1] - - -include::compliance-validation.adoc[leveloffset=+1] - - -include::disaster-recovery-resiliency.adoc[leveloffset=+1] - - -include::infrastructure-security.adoc[leveloffset=+1] \ No newline at end of file diff --git a/v2/guide/snippets/cdk.typescript.widget_service.txt b/v2/guide/snippets/cdk.typescript.widget_service.txt deleted file mode 100644 index da8ed81c..00000000 --- a/v2/guide/snippets/cdk.typescript.widget_service.txt +++ /dev/null @@ -1,56 +0,0 @@ -import cdk = require("@aws-cdk/core"); -import apigateway = require("@aws-cdk/aws-apigateway"); -import lambda = require("@aws-cdk/aws-lambda"); -import s3 = require("@aws-cdk/aws-s3"); - -export class WidgetService extends cdk.Construct { - constructor(scope: cdk.Construct, id: string) { - super(scope, id); - - const bucket = new s3.Bucket(this, "WidgetStore", { - // The default removal policy is RETAIN, which means that cdk destroy will not attempt to delete - // the new bucket, and it will remain in your account until manually deleted. By setting the policy to - // DESTROY, cdk destroy will attempt to delete the bucket, but will error if the bucket is not empty. - removalPolicy: cdk.RemovalPolicy.DESTROY, // NOT recommended for production code - }); - - const handler = new lambda.Function(this, "WidgetHandler", { - runtime: lambda.Runtime.NODEJS_10_X, // So we can use async in widget.js - code: lambda.AssetCode.asset("resources"), - handler: "widgets.main", - environment: { - BUCKET: bucket.bucketName - } - }); - - bucket.grantReadWrite(handler); // was: handler.role); - - const api = new apigateway.RestApi(this, "widgets-api", { - restApiName: "Widget Service", - description: "This service serves widgets." - }); - - const getWidgetsIntegration = new apigateway.LambdaIntegration(handler, { - requestTemplates: { "application/json": '{ "statusCode": "200" }' } - }); - - api.root.addMethod("GET", getWidgetsIntegration); // GET / - - // snippet-start:[cdk.typescript.widget_service.wire_up_functions] - const widget = api.root.addResource("{id}"); - - // Add new widget to bucket with: POST /{id} - const postWidgetIntegration = new apigateway.LambdaIntegration(handler); - - // Get a specific widget from bucket with: GET /{id} - const getWidgetIntegration = new apigateway.LambdaIntegration(handler); - - // Remove a specific widget from the bucket with: DELETE /{id} - const deleteWidgetIntegration = new apigateway.LambdaIntegration(handler); - - widget.addMethod("POST", postWidgetIntegration); // POST /{id} - widget.addMethod("GET", getWidgetIntegration); // GET /{id} - widget.addMethod("DELETE", deleteWidgetIntegration); // DELETE /{id} - // snippet-end:[cdk.typescript.widget_service.wire_up_functions] - } -} diff --git a/v2/guide/snippets/cdk.typescript.widgets.exports_main.txt b/v2/guide/snippets/cdk.typescript.widgets.exports_main.txt deleted file mode 100644 index d8249432..00000000 --- a/v2/guide/snippets/cdk.typescript.widgets.exports_main.txt +++ /dev/null @@ -1,101 +0,0 @@ -exports.main = async function(event, context) { - try { - var method = event.httpMethod; - // Get name, if present - var widgetName = event.path.startsWith('/') ? event.path.substring(1) : event.path; - - if (method === "GET") { - // GET / to get the names of all widgets - if (event.path === "/") { - const data = await S3.listObjectsV2({ Bucket: bucketName }).promise(); - var body = { - widgets: data.Contents.map(function(e) { return e.Key }) - }; - return { - statusCode: 200, - headers: {}, - body: JSON.stringify(body) - }; - } - - if (widgetName) { - // GET /name to get info on widget name - const data = await S3.getObject({ Bucket: bucketName, Key: widgetName}).promise(); - var body = data.Body.toString('utf-8'); - - return { - statusCode: 200, - headers: {}, - body: JSON.stringify(body) - }; - } - } - - if (method === "POST") { - // POST /name - // Return error if we do not have a name - if (!widgetName) { - return { - statusCode: 400, - headers: {}, - body: "Widget name missing" - }; - } - - // Create some dummy data to populate object - const now = new Date(); - var data = widgetName + " created: " + now; - - var base64data = new Buffer(data, 'binary'); - - await S3.putObject({ - Bucket: bucketName, - Key: widgetName, - Body: base64data, - ContentType: 'application/json' - }).promise(); - - return { - statusCode: 200, - headers: {}, - body: JSON.stringify(event.widgets) - }; - } - - if (method === "DELETE") { - // DELETE /name - // Return an error if we do not have a name - if (!widgetName) { - return { - statusCode: 400, - headers: {}, - body: "Widget name missing" - }; - } - - await S3.deleteObject({ - Bucket: bucketName, Key: widgetName - }).promise(); - - return { - statusCode: 200, - headers: {}, - body: "Successfully deleted widget " + widgetName - }; - } - - // We got something besides a GET, POST, or DELETE - return { - statusCode: 400, - headers: {}, - body: "We only accept GET, POST, and DELETE, not " + method - }; - } catch(error) { - var body = error.stack || JSON.stringify(error, null, 2); - return { - statusCode: 400, - headers: {}, - body: body - } - } -} diff --git a/v2/guide/snippets/cdk.typescript.widgets.imports.txt b/v2/guide/snippets/cdk.typescript.widgets.imports.txt deleted file mode 100644 index 5310c677..00000000 --- a/v2/guide/snippets/cdk.typescript.widgets.imports.txt +++ /dev/null @@ -1,2 +0,0 @@ -const AWS = require('aws-sdk'); -const S3 = new AWS.S3(); diff --git a/v2/guide/snippets/cdk.typescript.widgets.txt b/v2/guide/snippets/cdk.typescript.widgets.txt deleted file mode 100644 index 2bf47f75..00000000 --- a/v2/guide/snippets/cdk.typescript.widgets.txt +++ /dev/null @@ -1,106 +0,0 @@ -const AWS = require('aws-sdk'); -const S3 = new AWS.S3(); - -const bucketName = process.env.BUCKET; - -exports.main = async function(event, context) { - try { - var method = event.httpMethod; - // Get name, if present - var widgetName = event.path.startsWith('/') ? event.path.substring(1) : event.path; - - if (method === "GET") { - // GET / to get the names of all widgets - if (event.path === "/") { - const data = await S3.listObjectsV2({ Bucket: bucketName }).promise(); - var body = { - widgets: data.Contents.map(function(e) { return e.Key }) - }; - return { - statusCode: 200, - headers: {}, - body: JSON.stringify(body) - }; - } - - if (widgetName) { - // GET /name to get info on widget name - const data = await S3.getObject({ Bucket: bucketName, Key: widgetName}).promise(); - var body = data.Body.toString('utf-8'); - - return { - statusCode: 200, - headers: {}, - body: JSON.stringify(body) - }; - } - } - - if (method === "POST") { - // POST /name - // Return error if we do not have a name - if (!widgetName) { - return { - statusCode: 400, - headers: {}, - body: "Widget name missing" - }; - } - - // Create some dummy data to populate object - const now = new Date(); - var data = widgetName + " created: " + now; - - var base64data = new Buffer(data, 'binary'); - - await S3.putObject({ - Bucket: bucketName, - Key: widgetName, - Body: base64data, - ContentType: 'application/json' - }).promise(); - - return { - statusCode: 200, - headers: {}, - body: JSON.stringify(event.widgets) - }; - } - - if (method === "DELETE") { - // DELETE /name - // Return an error if we do not have a name - if (!widgetName) { - return { - statusCode: 400, - headers: {}, - body: "Widget name missing" - }; - } - - await S3.deleteObject({ - Bucket: bucketName, Key: widgetName - }).promise(); - - return { - statusCode: 200, - headers: {}, - body: "Successfully deleted widget " + widgetName - }; - } - - // We got something besides a GET, POST, or DELETE - return { - statusCode: 400, - headers: {}, - body: "We only accept GET, POST, and DELETE, not " + method - }; - } catch(error) { - var body = error.stack || JSON.stringify(error, null, 2); - return { - statusCode: 400, - headers: {}, - body: body - } - } -} diff --git a/v2/guide/testing/testing-locally-build-with-sam-cli.adoc b/v2/guide/testing/testing-locally-build-with-sam-cli.adoc deleted file mode 100644 index 76d3a244..00000000 --- a/v2/guide/testing/testing-locally-build-with-sam-cli.adoc +++ /dev/null @@ -1,31 +0,0 @@ -include::../attributes.txt[] - -// Attributes -[.topic] -[#testing-locally-build-with-sam-cli] -= Building {aws} CDK applications with {aws} SAM -:info_titleabbrev: Building -:keywords: {aws} SAM, build, {aws} CDK, Lambda - -[abstract] --- -Use the `sam build` command to build {aws} CDK applications. --- - -// Content start - -The {aws} SAM CLI provides support for building Lambda functions and layers defined in your {aws} CDK application with `link:https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-build.html[sam build]`. - -For Lambda functions that use zip artifacts, run `cdk synth` before you run `sam local` commands. `sam build` isn't required. - -If your {aws} CDK application uses functions with the image type, run `cdk synth` and then run `sam build` before you run `sam local` commands. When you run `sam build`, {aws} SAM doesn't build Lambda functions or layers that use runtime-specific constructs, for example, `link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda_nodejs.NodejsFunction.html[NodejsFunction]`. `sam build` doesn't support https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.BundlingOptions.html[bundled assets]. - -[#testing-locally-build-with-sam-cli-examples] -== Example - -Running the following command from the {aws} CDK project root directory builds the application. - -[source,bash,subs="verbatim,attributes"] ----- -$ sam build -t <./cdk.out/CdkSamExampleStack.template.json> ----- \ No newline at end of file diff --git a/v2/guide/testing/testing-locally-getting-started.adoc b/v2/guide/testing/testing-locally-getting-started.adoc deleted file mode 100644 index 14c65411..00000000 --- a/v2/guide/testing/testing-locally-getting-started.adoc +++ /dev/null @@ -1,151 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[#testing-locally-getting-started] -= Getting started with locally testing -:info_titleabbrev: Getting started -:keywords: CLI, {aws} CDK, {aws} SAM - -[abstract] --- -Getting Started documentation that provides the prerequisites for using {aws} CDK with {aws} SAM, and tutorial for building, locally testing, and deploying a simple {aws} CDK application. --- - -// Content start - -This topic describes what you need to use the {aws} SAM CLI with {aws} CDK applications, and it provides instructions for building and locally testing a simple {aws} CDK application. - -[#testing-locally-getting-started-prerequisites] -== Prerequisites - -To test locally, you must install the {aws} SAM CLI. see link:https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/getting_started.html[Install the {aws} SAM CLI] for installation instructions. - -[#testing-locally-getting-started-tutorial] -== Creating and locally testing an {aws} CDK application - -[abstract] --- -Learn how to use {aws} SAM to download, build, and locally test a {aws} CDK application. --- - -To locally test an {aws} CDK application using the {aws} SAM CLI, you must have an {aws} CDK application that contains a Lambda function. Use the following steps to create a basic {aws} CDK application with a Lambda function. For more information, see link:https://docs.aws.amazon.com/cdk/latest/guide/serverless_example.html[Creating a serverless application using the {aws} CDK] in the _{aws} Cloud Development Kit ({aws} CDK) Developer Guide_. - -[#testing-locally-getting-started-tutorial-init] -*Step 1: Create an {aws} CDK application*:: -+ -For this tutorial, initialize an {aws} CDK application that uses TypeScript. -+ -Command to run: -+ -[source,none,subs="verbatim,attributes"] ----- -$ mkdir cdk-sam-example -$ cd cdk-sam-example -$ cdk init app --language typescript ----- - -[#testing-locally-getting-started-tutorial-lambda] -*Step 2: Add a Lambda function to your application*:: -+ -Replace the code in `lib/cdk-sam-example-stack.ts` with the following: -+ -[source,typescript,subs="verbatim,attributes"] ----- -import { Stack, StackProps } from 'aws-cdk-lib'; -import { Construct } from 'constructs'; -import * as lambda from 'aws-cdk-lib/aws-lambda'; - -export class CdkSamExampleStack extends Stack { - constructor(scope: Construct, id: string, props?: StackProps) { - super(scope, id, props); - - new lambda.Function(this, 'MyFunction', { - runtime: lambda.Runtime.PYTHON_3_12, - handler: 'app.lambda_handler', - code: lambda.Code.fromAsset('./my_function'), - }); - } -} ----- - -[#testing-locally-getting-started-tutorial-code] -*Step 3: Add your Lambda function code*:: -+ -Create a directory named `my_function`. In that directory, create a file named `app.py`. -+ -Command to run: -+ -==== -[role="tablist"] -macOS / Linux:: -+ -[source,none,subs="verbatim,attributes"] ----- -$ mkdir my_function -$ cd my_function -$ touch app.py ----- - -Windows:: -+ -[source,none,subs="verbatim,attributes"] ----- -$ mkdir my_function -$ cd my_function -$ type nul > app.py ----- - -PowerShell:: -+ -[source,none,subs="verbatim,attributes"] ----- -$ mkdir my_function -$ cd my_function -$ New-Item -Path "app.py” ----- -+ -Add the following code to `app.py`: - -[source,none,subs="verbatim,attributes"] ----- -def lambda_handler(event, context): - return "Hello from SAM and the CDK!" ----- -==== - -[#testing-locally-getting-started-tutorial-function] -*Step 4: Test your Lambda function*:: -+ -You can use the {aws} SAM CLI to locally invoke a Lambda function that you define in an {aws} CDK application. To do this, you need the function construct identifier and the path to your synthesized {aws} CloudFormation template. -+ -Run the following command to go back to the `lib` directory: -+ -[source,none,subs="verbatim,attributes"] ----- -$ cd .. ----- -+ -*Command to run:* -+ -[source,none,subs="verbatim,attributes"] ----- -$ cdk synth --no-staging ----- -+ -[source,none,subs="verbatim,attributes"] ----- -$ sam local invoke MyFunction --no-event -t ./cdk.out/CdkSamExampleStack.template.json ----- -+ -*Example output:* -+ ----- -Invoking app.lambda_handler (python3.9) - -START RequestId: 5434c093-7182-4012-9b06-635011cac4f2 Version: $LATEST -"Hello from SAM and the CDK!" -END RequestId: 5434c093-7182-4012-9b06-635011cac4f2 -REPORT RequestId: 5434c093-7182-4012-9b06-635011cac4f2 Init Duration: 0.32 ms Duration: 177.47 ms Billed Duration: 178 ms Memory Size: 128 MB Max Memory Used: 128 MB ----- \ No newline at end of file diff --git a/v2/guide/testing/testing-locally-with-sam-cli.adoc b/v2/guide/testing/testing-locally-with-sam-cli.adoc deleted file mode 100644 index 7bebe68c..00000000 --- a/v2/guide/testing/testing-locally-with-sam-cli.adoc +++ /dev/null @@ -1,96 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[#testing-locally-with-sam-cli] -= Local testing {aws} CDK applications with {aws} SAM -:info_titleabbrev: Local testing -:keywords: sam local, test, {aws} CDK, {aws} SAM - -[abstract] --- -Use the `sam local` command to locally test {aws} CDK applications. --- - -// Content start - -You can use the {aws} SAM CLI to locally test your {aws} CDK applications by running the following commands from the project root directory of your {aws} CDK application: - -* `link:https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-local-invoke.html[sam local invoke]` -* `link:https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-local-start-api.html[sam local start-api]` -* `link:https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-local-start-lambda.html[sam local start-lambda]` - -Before you run any of the `sam local` commands with a {aws} CDK application, you must run `cdk synth`. - -When running `sam local invoke` you need the function construct identifier that you want to invoke, and the path to your synthesized {aws} CloudFormation template. If your application uses nested stacks, to resolve naming conflicts, you also need the stack name where the function is defined. - -*Usage*:: -+ -[source,none,subs="verbatim,attributes"] ----- -# Invoke the function FUNCTION_IDENTIFIER declared in the stack STACK_NAME -$ sam local invoke <OPTIONS> <STACK_NAME/FUNCTION_IDENTIFIER> - -# Start all APIs declared in the {aws} CDK application -$ sam local start-api -t <./cdk.out/CdkSamExampleStack.template.json> <OPTIONS> - -# Start a local endpoint that emulates {aws} Lambda -$ sam local start-lambda -t <./cdk.out/CdkSamExampleStack.template.json> <OPTIONS> ----- - -[#testing-cdk-applications-examples] -== Example - -Consider stacks and functions that are declared with the following sample: - -[source,javascript,subs="verbatim,attributes"] ----- -app = new HelloCdkStack(app, "HelloCdkStack", - ... -) -class HelloCdkStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - ... - new lambda.Function(this, 'MyFunction', { - ... - }); - - new HelloCdkNestedStack(this, 'HelloNestedStack' ,{ - ... - }); - } -} - -class HelloCdkNestedStack extends cdk.NestedStack { - constructor(scope: Construct, id: string, props?: cdk.NestedStackProps) { - ... - new lambda.Function(this, 'MyFunction', { - ... - }); - new lambda.Function(this, 'MyNestedFunction', { - ... - }); - } -} ----- - -The following commands locally invokes the Lambda functions defined in example presented above: - -[source,none,subs="verbatim,attributes"] ----- -# Invoke MyFunction from the HelloCdkStack -$ sam local invoke -t <./cdk.out/HelloCdkStack.template.json> <MyFunction> ----- - -[source,none,subs="verbatim,attributes"] ----- -# Invoke MyNestedFunction from the HelloCdkNestedStack -$ sam local invoke -t <./cdk.out/HelloCdkStack.template.json> <MyNestedFunction> ----- - -[source,none,subs="verbatim,attributes"] ----- -# Invoke MyFunction from the HelloCdkNestedStack -$ sam local invoke -t <./cdk.out/HelloCdkStack.template.json> <HelloNestedStack/MyFunction> ----- \ No newline at end of file diff --git a/v2/guide/testing/testing-locally.adoc b/v2/guide/testing/testing-locally.adoc deleted file mode 100644 index 010d3389..00000000 --- a/v2/guide/testing/testing-locally.adoc +++ /dev/null @@ -1,29 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[#testing-locally] -= Locally test and build {aws} CDK applications with the {aws} SAM CLI -:info_titleabbrev: Local testing -:keywords: build, test, {aws} CDK, {aws} SAM - -[abstract] --- -You can use {aws} SAM to build and locally test your {aws} CDK applications. --- - -// Content start - -You can use the {aws} SAM CLI to locally test and build serverless applications defined using the {aws} Cloud Development Kit ({aws} CDK). Because the {aws} SAM CLI works within the {aws} CDK project structure, you can still use the xref:cli[{aws} CDK CLI reference] for creating, modifying, and deploying your {aws} CDK applications. - -For details on using {aws} SAM, see https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-getting-started.html[Getting started with {aws} SAM] in the _{aws} Serverless Application Model Developer Guide_. - -[.topiclist] -[[Topic List]] - -include::testing-locally-getting-started.adoc[leveloffset=+1] - -include::testing-locally-with-sam-cli.adoc[leveloffset=+1] - -include::testing-locally-build-with-sam-cli.adoc[leveloffset=+1] \ No newline at end of file diff --git a/v2/guide/toolkit-library.adoc b/v2/guide/toolkit-library.adoc deleted file mode 100644 index bb0260cf..00000000 --- a/v2/guide/toolkit-library.adoc +++ /dev/null @@ -1,50 +0,0 @@ -include::attributes.txt[] - -// Attributes -[.topic] -[#toolkit-library] -= Perform programmatic actions using the CDK Toolkit Library -:info_titleabbrev: Use the CDK Toolkit Library -:keywords: CDK Toolkit Library, Programmatic access, {aws} CDK, {aws} Cloud Development Kit ({aws} CDK), deploy, {aws} CloudFormation, Infrastructure as Code, synthesize - -[abstract] --- -The {aws} Cloud Development Kit ({aws} CDK) Toolkit Library enables you to perform {aws} CDK actions requiring programmatic access on {aws}. --- - -// Content start - -[NOTE] -==== - -CDK Toolkit Library is in developer preview and is subject to change. - -==== - -[#toolkit-library-intro] -== What is the CDK Toolkit Library Library? - -The {aws} Cloud Development Kit ({aws} CDK) Toolkit Library enables you to perform {aws} CDK actions requiring programmatic access on {aws}. You can use the CDK Toolkit Library to implement actions such as bootstrapping, synthesizing, and deploying through code rather than CDK CLI commands. With this library, you can create custom tools, build specialized CLI applications, and integrate CDK programmatic access capabilities into your development workflows. - -The following is an example, that installs the CDK Toolkit Library and uses it to deploy a cloud assembly of your CDK app: - -[source,javascript,subs="verbatim,attributes"] ----- -import { Toolkit } from '@aws-cdk/toolkit-lib'; // Install the CDK Toolkit Library - -const cdk = new Toolkit(); // Create a CDK Toolkit instance - -// ... - -// Implement a deployment -await cdk.deploy(cloudAssembly, { - deploymentMethod: { method: "direct" }, // Configure deployment options - ... -}) ----- - -[#toolkit-library-gs] -== Get started with the CDK Toolkit Library -To get started, see the `link:https://www.npmjs.com/package/@aws-cdk/toolkit-lib[ReadMe]` in the _@aws-cdk/toolkit-lib_ `npm` package. - -For API reference information, see the link:https://docs.aws.amazon.com/cdk/api/toolkit-lib/[CDK Toolkit Library API reference]. \ No newline at end of file diff --git a/v2/guide/tools.adoc b/v2/guide/tools.adoc deleted file mode 100644 index 61a354e3..00000000 --- a/v2/guide/tools.adoc +++ /dev/null @@ -1,28 +0,0 @@ -include::attributes.txt[] - -// Attributes - -[.topic] -[#tools] -= Use other tools with the {aws} CDK -:doctype: book -:info_titleabbrev: Use tools with the CDK - -[abstract] --- -Tools for the {aws} CDK --- - -// Content start - -You can use other tools with the {aws} CDK to improve your development workflows. - -[#vscode] -== {aws} Toolkit for Visual Studio Code - -The https://aws.amazon.com/visualstudiocode/[{aws} Toolkit for Visual Studio Code] is an open source plugin for Visual Studio Code that makes it easier to create, debug, and deploy applications on {aws}. The toolkit provides an integrated experience for developing {aws} CDK applications. It includes the {aws} CDK Explorer feature to list your {aws} CDK projects and browse the various components of the CDK application. https://docs.aws.amazon.com/toolkit-for-vscode/latest/userguide/setup-toolkit.html[Install the {aws} Toolkit] and learn more about https://docs.aws.amazon.com/toolkit-for-vscode/latest/userguide/cdk-explorer.html[using the {aws} CDK Explorer]. - -[#sam] -== {aws} SAM integration - -Use the {aws} CDK and the {aws} Serverless Application Model ({aws} SAM) together to locally build and test serverless applications defined in the CDK. For complete information, see https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-cdk.html[{aws} Cloud Development Kit ({aws} CDK)] in the _{aws} Serverless Application Model Developer Guide_. To install the {aws} SAM CLI, see https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html[Install the {aws} SAM CLI]. \ No newline at end of file diff --git a/v2/guide/troubleshooting.adoc b/v2/guide/troubleshooting.adoc deleted file mode 100644 index 85cd953e..00000000 --- a/v2/guide/troubleshooting.adoc +++ /dev/null @@ -1,294 +0,0 @@ -include::attributes.txt[] - -// Attributes - -[.topic] -[#troubleshooting] -= Troubleshooting common {aws} CDK issues -:info_titleabbrev: {aws} CDK troubleshooting - -// Content start - -This topic describes how to troubleshoot the following issues with the {aws} CDK. - -* xref:troubleshooting-toolkit[After updating the {aws} CDK the {aws} CDK Toolkit (CLI) reports a mismatch with the {aws} Construct Library] -* xref:troubleshooting-nobucket[When deploying my {aws} CDK stack I receive a NoSuchBucket error] -* xref:troubleshooting-forbidden-null[When deploying my {aws} CDK stack I receive a forbidden: null message] -* xref:troubleshooting-app-required[When synthesizing an {aws} CDK stack I get the message --app is required either in command-line in cdk.json or in ~/.cdk.json] -* xref:troubleshooting-resource-count[When synthesizing an {aws} CDK stack I receive an error because the {aws} CloudFormation template contains too many resources] -* xref:troubleshooting-availability-zones[I specified three (or more) Availability Zones for my Auto Scaling group or VPC but it was only deployed in two] -* xref:troubleshooting-resource-not-deleted[My S3 bucket DynamoDB table or other resource is not deleted when I issue cdk destroy] - -[#troubleshooting-toolkit] -== After updating the {aws} CDK, the {aws} CDK Toolkit (CLI) reports a mismatch with the {aws} Construct Library - -The version of the {aws} CDK Toolkit (which provides the `cdk` command) must be at least equal to the version of the main {aws} Construct Library module, `aws-cdk-lib`. The Toolkit is intended to be backward compatible. The latest 2.x version of the toolkit can be used with any 1.x or 2.x release of the library. For this reason, we recommend you install this component globally and keep it up to date. - -[source,none,subs="verbatim,attributes"] ----- -npm update -g aws-cdk ----- - -If you need to work with multiple versions of the {aws} CDK Toolkit, install a specific version of the toolkit locally in your project folder. - -If you are using TypeScript or JavaScript, your project directory already contains a versioned local copy of the CDK Toolkit. - -If you are using another language, use `npm` to install the {aws} CDK Toolkit, omitting the `-g` flag and specifying the desired version. For example: - -[source,none,subs="verbatim,attributes"] ----- -npm install aws-cdk@2.0 ----- - -To run a locally installed {aws} CDK Toolkit, use the command `npx aws-cdk` instead of only ``cdk``. For example: - -[source,none,subs="verbatim,attributes"] ----- -npx aws-cdk deploy MyStack ----- - -`npx aws-cdk` runs the local version of the {aws} CDK Toolkit if one exists. It falls back to the global version when a project doesn't have a local installation. You may find it convenient to set up a shell alias to make sure `cdk` is always invoked this way. - -==== -[role="tablist"] -macOS/Linux:: -+ -[source,none,subs="verbatim,attributes"] ----- -alias cdk="npx aws-cdk" ----- - -Windows:: -+ -[source,none,subs="verbatim,attributes"] ----- -doskey cdk=npx aws-cdk $* ----- -==== - -[#troubleshooting-nobucket] -== When deploying my {aws} CDK stack, I receive a `NoSuchBucket` error - -Your {aws} environment has not been bootstrapped, and so does not have an Amazon S3 bucket to hold resources during deployment. You can create the staging bucket and other required resources with the following command: - -[source,none,subs="verbatim,attributes"] ----- -cdk bootstrap aws://ACCOUNT-NUMBER/REGION ----- - -To avoid generating unexpected {aws} charges, the {aws} CDK does not automatically bootstrap any environment. You must explicitly bootstrap each environment into which you will deploy. - -By default, the bootstrap resources are created in the Region or Regions that are used by stacks in the current {aws} CDK application. Alternatively, they are created in the Region specified in your local {aws} profile (set by ``aws configure``), using that profile's account. You can specify a different account and Region on the command line as follows. (You must specify the account and Region if you are not in an app's directory.) - -[source,none,subs="verbatim,attributes"] ----- -cdk bootstrap aws://ACCOUNT-NUMBER/REGION ----- - -For more information, see xref:bootstrapping[{aws} CDK bootstrapping]. - -[#troubleshooting-forbidden-null] -== When deploying my {aws} CDK stack, I receive a `forbidden: null` message - -You are deploying a stack that requires bootstrap resources, but are using an IAM role or account that lacks permission to write to it. (The staging bucket is used when deploying stacks that contain assets or that synthesize an {aws} CloudFormation template larger than 50K.) Use an account or role that has permission to perform the action `s3:*` against the bucket mentioned in the error message. - -[#troubleshooting-app-required] -== When synthesizing an {aws} CDK stack, I get the message `--app is required either in command-line, in cdk.json or in ~/.cdk.json` - -This message usually means that you aren't in the main directory of your {aws} CDK project when you issue `cdk synth`. The file `cdk.json` in this directory, created by the `cdk init` command, contains the command line needed to run (and thereby synthesize) your {aws} CDK app. For a TypeScript app, for example, the default `cdk.json` looks something like this: - -[source,json,subs="verbatim,attributes"] ----- -{ - "app": "npx ts-node bin/my-cdk-app.ts" -} ----- - -We recommend issuing `cdk` commands only in your project's main directory, so the {aws} CDK toolkit can find `cdk.json` there and successfully run your app. - -If this isn't practical for some reason, the {aws} CDK Toolkit looks for the app's command line in two other locations: - -* In `cdk.json` in your home directory -* On the `cdk synth` command itself using the `-a` option - -For example, you might synthesize a stack from a TypeScript app as follows. - -[source,none,subs="verbatim,attributes"] ----- -cdk synth --app "npx ts-node my-cdk-app.ts" MyStack ----- - -[#troubleshooting-resource-count] -== When synthesizing an {aws} CDK stack, I receive an error because the {aws} CloudFormation template contains too many resources - -The {aws} CDK generates and deploys {aws} CloudFormation templates. {aws} CloudFormation has a hard limit on the number of resources a stack can contain. With the {aws} CDK, you can run up against this limit more quickly than you might expect. - -[NOTE] -==== - -The {aws} CloudFormation resource limit is 500 at this writing. See https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cloudformation-limits.html[{aws} CloudFormation quotas] for the current resource limit. - -==== - -The {aws} Construct Library's higher-level, intent-based constructs automatically provision any auxiliary resources that are needed for logging, key management, authorization, and other purposes. For example, granting one resource access to another generates any IAM objects needed for the relevant services to communicate. - -In our experience, real-world use of intent-based constructs results in 1–5 {aws} CloudFormation resources per construct, though this can vary. For serverless applications, 5–8 {aws} resources per API endpoint is typical. - -Patterns, which represent a higher level of abstraction, let you define even more {aws} resources with even less code. The {aws} CDK code in xref:ecs-example[Example: Create an {aws} Fargate service using the {aws} CDK], for example, generates more than 50 {aws} CloudFormation resources while defining only three constructs! - -Exceeding the {aws} CloudFormation resource limit is an error during {aws} CloudFormation synthesis. The {aws} CDK issues a warning if your stack exceeds 80% of the limit. You can use a different limit by setting the `maxResources` property on your stack, or disable validation by setting `maxResources` to 0. - -[TIP] -==== - -You can get an exact count of the resources in your synthesized output using the following utility script. (Since every {aws} CDK developer needs Node.js, the script is written in JavaScript.) - -[source,javascript,subs="verbatim,attributes"] ----- -// rescount.js - count the resources defined in a stack -// invoke with: node rescount.js <path-to-stack-json> -// e.g. node rescount.js cdk.out/MyStack.template.json - -import * as fs from 'fs'; -const path = process.argv[2]; - -if (path) fs.readFile(path, 'utf8', function(err, contents) { - console.log(err ? `${err}` : - `${Object.keys(JSON.parse(contents).Resources).length} resources defined in ${path}`); -}); else console.log("Please specify the path to the stack's output .json file"); ----- -==== - -As your stack's resource count approaches the limit, consider re-architecting to reduce the number of resources your stack contains: for example, by combining some Lambda functions, or by breaking your stack into multiple stacks. The CDK supports xref:resource-stack[references between stacks], so you can separate your app's functionality into different stacks in whatever way makes the most sense to you. - -[NOTE] -==== - -{aws} CloudFormation experts often suggest the use of nested stacks as a solution to the resource limit. The {aws} CDK supports this approach via the xref:stack-nesting[NestedStack] construct. - -==== - -[#troubleshooting-availability-zones] -== I specified three (or more) Availability Zones for my Auto Scaling group or VPC, but it was only deployed in two - -To get the number of Availability Zones that you request, specify the account and Region in the stack's `env` property. If you do not specify both, the {aws} CDK, by default, synthesizes the stack as environment-agnostic. You can then deploy the stack to a specific Region using {aws} CloudFormation. Because some Regions have only two Availability Zones, an environment-agnostic template doesn't use more than two. - -[NOTE] -==== - -In the past, Regions have occasionally launched with only one Availability Zone. Environment-agnostic {aws} CDK stacks cannot be deployed to such Regions. At this writing, however, all {aws} Regions have at least two AZs. - -==== - -You can change this behavior by overriding your stack's link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html#availabilityzones[availabilityZones] (Python: `availability_zones`) property to explicitly specify the zones that you want to use. - -For more information about specifying a stack's account and region at synthesis time, while retaining the flexibility to deploy to any region, see xref:environments[Environments for the {aws} CDK]. - -[#troubleshooting-resource-not-deleted] -== My S3 bucket, DynamoDB table, or other resource is not deleted when I issue `cdk destroy` - -By default, resources that can contain user data have a `removalPolicy` (Python: `removal_policy`) property of `RETAIN`, and the resource is not deleted when the stack is destroyed. Instead, the resource is orphaned from the stack. You must then delete the resource manually after the stack is destroyed. Until you do, redeploying the stack fails. This is because the name of the new resource being created during deployment conflicts with the name of the orphaned resource. - -If you set a resource's removal policy to `DESTROY`, that resource will be deleted when the stack is destroyed. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -import * as cdk from 'aws-cdk-lib'; -import { Construct } from 'constructs'; -import * as s3 from 'aws-cdk-lib/aws-s3'; - -export class CdkTestStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - const bucket = new s3.Bucket(this, 'Bucket', { - removalPolicy: cdk.RemovalPolicy.DESTROY, - }); - } -} ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const cdk = require('aws-cdk-lib'); -const s3 = require('aws-cdk-lib/aws-s3'); - -class CdkTestStack extends cdk.Stack { - constructor(scope, id, props) { - super(scope, id, props); - - const bucket = new s3.Bucket(this, 'Bucket', { - removalPolicy: cdk.RemovalPolicy.DESTROY - }); - } -} - -module.exports = { CdkTestStack } ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -import aws_cdk as cdk -from constructs import Construct -import aws_cdk.aws_s3 as s3 - -class CdkTestStack(cdk.stack): - def __init__(self, scope: Construct, id: str, **kwargs): - super().__init__(scope, id, **kwargs) - - bucket = s3.Bucket(self, "Bucket", - removal_policy=cdk.RemovalPolicy.DESTROY) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -software.amazon.awscdk.*; -import software.amazon.awscdk.services.s3.*; -import software.constructs; - -public class CdkTestStack extends Stack { - public CdkTestStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public CdkTestStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - Bucket.Builder.create(this, "Bucket") - .removalPolicy(RemovalPolicy.DESTROY).build(); - } -} ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -using Amazon.CDK; -using Amazon.CDK.{aws}.S3; - -public CdkTestStack(Construct scope, string id, IStackProps props) : base(scope, id, props) -{ - new Bucket(this, "Bucket", new BucketProps { - RemovalPolicy = RemovalPolicy.DESTROY - }); -} ----- -==== - -[NOTE] -==== - -{aws} CloudFormation cannot delete a non-empty Amazon S3 bucket. If you set an Amazon S3 bucket's removal policy to `DESTROY`, and it contains data, attempting to destroy the stack will fail because the bucket cannot be deleted. You can have the {aws} CDK delete the objects in the bucket before attempting to destroy it by setting the bucket's `autoDeleteObjects` prop to `true`. - -==== \ No newline at end of file diff --git a/v2/guide/what-is/home.adoc b/v2/guide/what-is/home.adoc deleted file mode 100644 index 203a9a0c..00000000 --- a/v2/guide/what-is/home.adoc +++ /dev/null @@ -1,338 +0,0 @@ -include::../attributes.txt[] - -// Page attributes -[.topic] -[#home] -= What is the {aws} CDK? -:info_titleabbrev: What is the {aws} CDK? -:keywords: {aws} CDK, Developer tool, {aws}, Infrastructure as code, IaC, constructs, {aws} CloudFormation, serverless, modern applications - -[abstract] --- -The {aws} Cloud Development Kit ({aws} CDK) is an open-source software development framework for defining cloud infrastructure in code and provisioning it through {aws} CloudFormation. --- - -// Content start - -The {aws} Cloud Development Kit ({aws} CDK) is an open-source software development framework for defining cloud infrastructure in code and provisioning it through {aws} CloudFormation. - -The {aws} CDK consists of two primary parts: - -* *xref:constructs[{aws} CDK Construct Library]* – A collection of pre-written modular and reusable pieces of code, called constructs, that you can use, modify, and integrate to develop your infrastructure quickly. The goal of the {aws} CDK Construct Library is to reduce the complexity required to define and integrate {aws} services together when building applications on {aws}. - -* *xref:cli[{aws} CDK Command Line Interface ({aws} CDK CLI)]* – A command line tool for interacting with CDK apps. Use the CDK CLI to create, manage, and deploy your {aws} CDK projects. The CDK CLI is also referred to as the CDK Toolkit. - -The {aws} CDK supports TypeScript, JavaScript, Python, Java, C#/.Net, and [.noloc]`Go`. You can use any of these supported programming languages to define reusable cloud components known as xref:constructs[constructs]. You compose these together into xref:stacks[stacks] and xref:apps[apps]. Then, you deploy your CDK applications to {aws} CloudFormation to provision or update your resources. - -image::./images/AppStacks.png[CDK app and process overview] - -[#home-benefits] -== Benefits of the {aws} CDK - -Use the {aws} CDK to develop reliable, scalable, cost-effective applications in the cloud with the considerable expressive power of a programming language. This approach yields many benefits, including: - -[#home-benefits-iac] -*Develop and manage your infrastructure as code (IaC)*:: -Practice _infrastructure as code_ to create, deploy, and maintain infrastructure in a programmatic, descriptive, and declarative way. With IaC, you treat infrastructure the same way developers treat code. This results in a scalable and structured approach to managing infrastructure. To learn more about IaC, see https://docs.aws.amazon.com/whitepapers/latest/introduction-devops-aws/infrastructure-as-code.html[Infrastructure as code] in the _Introduction to DevOps on {aws} Whitepaper_. -+ -With the {aws} CDK, you can put your infrastructure, application code, and configuration all in one place, ensuring that you have a complete, cloud-deployable system at every milestone. Employ software engineering best practices such as code reviews, unit tests, and source control to make your infrastructure more robust. - -[#home-benefits-languages] -*Define your cloud infrastructure using general-purpose programming languages*:: -With the {aws} CDK, you can use any of the following programming languages to define your cloud infrastructure: TypeScript, JavaScript, Python, Java, C#/.Net, and [.noloc]`Go`. Choose your preferred language and use programming elements like parameters, conditionals, loops, composition, and inheritance to define the desired outcome of your infrastructure. -+ -Use the same programming language to define your infrastructure and your application logic. -+ -Receive the benefits of developing infrastructure in your preferred IDE (Integrated Development Environment), such as syntax highlighting and intelligent code completion. -+ -image::./images/CodeCompletion.png[Code snippet showing CDK setup for ECS cluster with VPC and Fargate service configuration.,scaledwidth=100%] - -[#home-benefits-cfn] -*Deploy infrastructure through {aws} CloudFormation*:: -{aws} CDK integrates with {aws} CloudFormation to deploy and provision your infrastructure on {aws}. {aws} CloudFormation is a managed {aws} service that offers extensive support of resource and property configurations for provisioning services on {aws}. With {aws} CloudFormation, you can perform infrastructure deployments predictably and repeatedly, with rollback on error. If you are already familiar with {aws} CloudFormation, you don't have to learn a new IaC management service when getting started with the {aws} CDK. - -[#home-benefits-constructs] -*Get started developing your application quickly with constructs*:: -Develop faster by using and sharing reusable components called constructs. Use low-level constructs to define individual {aws} CloudFormation resources and their properties. Use high-level constructs to quickly define larger components of your application, with sensible, secure defaults for your {aws} resources, defining more infrastructure with less code. -+ -Create your own constructs that are customized for your unique use cases and share them across your organization or even with the public. - -[#home-example] -== Example of the {aws} CDK - -The following is an example of using the {aws} CDK Constructs Library to create an Amazon Elastic Container Service (Amazon ECS) service with {aws} Fargate launch type. For more details of this example, see xref:ecs-example[Example: Create an {aws} Fargate service using the {aws} CDK]. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -export class MyEcsConstructStack extends Stack { - constructor(scope: App, id: string, props?: StackProps) { - super(scope, id, props); - - const vpc = new ec2.Vpc(this, "MyVpc", { - maxAzs: 3 // Default is all AZs in region - }); - - const cluster = new ecs.Cluster(this, "MyCluster", { - vpc: vpc - }); - - // Create a load-balanced Fargate service and make it public - new ecs_patterns.ApplicationLoadBalancedFargateService(this, "MyFargateService", { - cluster: cluster, // Required - cpu: 512, // Default is 256 - desiredCount: 6, // Default is 1 - taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample") }, - memoryLimitMiB: 2048, // Default is 512 - publicLoadBalancer: true // Default is false - }); - } -} ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -class MyEcsConstructStack extends Stack { - constructor(scope, id, props) { - super(scope, id, props); - - const vpc = new ec2.Vpc(this, "MyVpc", { - maxAzs: 3 // Default is all AZs in region - }); - - const cluster = new ecs.Cluster(this, "MyCluster", { - vpc: vpc - }); - - // Create a load-balanced Fargate service and make it public - new ecs_patterns.ApplicationLoadBalancedFargateService(this, "MyFargateService", { - cluster: cluster, // Required - cpu: 512, // Default is 256 - desiredCount: 6, // Default is 1 - taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample") }, - memoryLimitMiB: 2048, // Default is 512 - publicLoadBalancer: true // Default is false - }); - } -} - -module.exports = { MyEcsConstructStack } ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- -class MyEcsConstructStack(Stack): - - def __init__(self, scope: Construct, id: str, **kwargs) -> None: - super().__init__(scope, id, **kwargs) - - vpc = ec2.Vpc(self, "MyVpc", max_azs=3) # default is all AZs in region - - cluster = ecs.Cluster(self, "MyCluster", vpc=vpc) - - ecs_patterns.ApplicationLoadBalancedFargateService(self, "MyFargateService", - cluster=cluster, # Required - cpu=512, # Default is 256 - desired_count=6, # Default is 1 - task_image_options=ecs_patterns.ApplicationLoadBalancedTaskImageOptions( - image=ecs.ContainerImage.from_registry("amazon/amazon-ecs-sample")), - memory_limit_mib=2048, # Default is 512 - public_load_balancer=True) # Default is False ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -public class MyEcsConstructStack extends Stack { - - public MyEcsConstructStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public MyEcsConstructStack(final Construct scope, final String id, - StackProps props) { - super(scope, id, props); - - Vpc vpc = Vpc.Builder.create(this, "MyVpc").maxAzs(3).build(); - - Cluster cluster = Cluster.Builder.create(this, "MyCluster") - .vpc(vpc).build(); - - ApplicationLoadBalancedFargateService.Builder.create(this, "MyFargateService") - .cluster(cluster) - .cpu(512) - .desiredCount(6) - .taskImageOptions( - ApplicationLoadBalancedTaskImageOptions.builder() - .image(ContainerImage - .fromRegistry("amazon/amazon-ecs-sample")) - .build()).memoryLimitMiB(2048) - .publicLoadBalancer(true).build(); - } -} ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -public class MyEcsConstructStack : Stack -{ - public MyEcsConstructStack(Construct scope, string id, IStackProps props=null) : base(scope, id, props) - { - var vpc = new Vpc(this, "MyVpc", new VpcProps - { - MaxAzs = 3 - }); - - var cluster = new Cluster(this, "MyCluster", new ClusterProps - { - Vpc = vpc - }); - - new ApplicationLoadBalancedFargateService(this, "MyFargateService", - new ApplicationLoadBalancedFargateServiceProps - { - Cluster = cluster, - Cpu = 512, - DesiredCount = 6, - TaskImageOptions = new ApplicationLoadBalancedTaskImageOptions - { - Image = ContainerImage.FromRegistry("amazon/amazon-ecs-sample") - }, - MemoryLimitMiB = 2048, - PublicLoadBalancer = true, - }); - } -} ----- - -Go:: -+ -[source,go,subs="verbatim,attributes"] ----- -func NewMyEcsConstructStack(scope constructs.Construct, id string, props *MyEcsConstructStackProps) awscdk.Stack { - - var sprops awscdk.StackProps - - if props != nil { - sprops = props.StackProps - } - - stack := awscdk.NewStack(scope, &id, &sprops) - - vpc := awsec2.NewVpc(stack, jsii.String("MyVpc"), &awsec2.VpcProps{ - MaxAzs: jsii.Number(3), // Default is all AZs in region - }) - - cluster := awsecs.NewCluster(stack, jsii.String("MyCluster"), &awsecs.ClusterProps{ - Vpc: vpc, - }) - - awsecspatterns.NewApplicationLoadBalancedFargateService(stack, jsii.String("MyFargateService"), - &awsecspatterns.ApplicationLoadBalancedFargateServiceProps{ - Cluster: cluster, // required - Cpu: jsii.Number(512), // default is 256 - DesiredCount: jsii.Number(5), // default is 1 - MemoryLimitMiB: jsii.Number(2048), // Default is 512 - TaskImageOptions: &awsecspatterns.ApplicationLoadBalancedTaskImageOptions{ - Image: awsecs.ContainerImage_FromRegistry(jsii.String("amazon/amazon-ecs-sample"), nil), - }, - PublicLoadBalancer: jsii.Bool(true), // Default is false - }) - - return stack - -} ----- -==== - -This class produces an {aws} CloudFormation link:https://github.com/awsdocs/aws-cdk-guide/blob/main/doc_source/my_ecs_construct-stack.yaml[template of more than 500 lines]. Deploying the {aws} CDK app produces more than 50 resources of the following types: - -* link:https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-eip.html[`{aws}::EC2::EIP`] -* link:https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-internetgateway.html[`{aws}::EC2::InternetGateway`] -* link:https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-natgateway.html[`{aws}::EC2::NatGateway`] -* link:https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-route.html[`{aws}::EC2::Route`] -* link:https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-routetable.html[`{aws}::EC2::RouteTable`] -* link:https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-security-group.html[`{aws}::EC2::SecurityGroup`] -* link:https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-subnet.html[`{aws}::EC2::Subnet`] -* link:https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-subnet-route-table-assoc.html[`{aws}::EC2::SubnetRouteTableAssociation`] -* link:https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpc-gateway-attachment.html[`{aws}::EC2::VPCGatewayAttachment`] -* link:https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpc.html[`{aws}::EC2::VPC`] -* link:https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ecs-cluster.html[`{aws}::ECS::Cluster`] -* link:https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ecs-service.html[`{aws}::ECS::Service`] -* link:https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ecs-taskdefinition.html[`{aws}::ECS::TaskDefinition`] -* link:https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticloadbalancingv2-listener.html[`{aws}::ElasticLoadBalancingV2::Listener`] -* link:https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticloadbalancingv2-loadbalancer.html[`{aws}::ElasticLoadBalancingV2::LoadBalancer`] -* link:https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticloadbalancingv2-targetgroup.html[`{aws}::ElasticLoadBalancingV2::TargetGroup`] -* link:https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-policy.html[`{aws}::IAM::Policy`] -* link:https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html[`{aws}::IAM::Role`] -* link:https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-logs-loggroup.html[`{aws}::Logs::LogGroup`] - -[#home-features] -== {aws} CDK features - -[#home-features-repo] -=== The {aws} CDK [.noloc]`GitHub` repository - -For the official {aws} CDK [.noloc]`GitHub` repository, see link:https://github.com/aws/aws-cdk[aws-cdk]. Here, you can submit link:https://github.com/aws/aws-cdk/issues[issues], view our link:https://github.com/aws/aws-cdk/blob/main/LICENSE[license], track link:https://github.com/aws/aws-cdk/releases[releases], and more. - -Because the {aws} CDK is open-source, the team encourages you to contribute to make it an even better tool. For details, see link:https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md[Contributing to the {aws} Cloud Development Kit ({aws} CDK)]. - -[#home-features-api] -=== The {aws} CDK API reference - -The {aws} CDK Construct Library provides APIs to define your CDK application and add CDK constructs to the application. For more information, see the link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-construct-library.html[{aws} CDK API Reference]. - -[#home-features-cpm] -=== The Construct Programming Model - -The Construct Programming Model (CPM) extends the concepts behind the {aws} CDK into additional domains. Other tools using the CPM include: - -* link:https://www.terraform.io/docs/cdktf/index.html[CDK for Terraform] (CDKtf) -* link:https://cdk8s.io/[CDK for Kubernetes] (CDK8s) -* link:https://github.com/projen/projen[Projen], for building project configurations - -[#home-features-hub] -=== The Construct Hub - -The link:https://constructs.dev/[Construct Hub] is an online registry where you can find, publish, and share open-source {aws} CDK libraries. - -[#home-next] -== Next steps - -To get started with using the {aws} CDK, see xref:getting-started[Getting started with the {aws} CDK]. - -[#home-learn] -== Learn more - -To continue learning about the {aws} CDK, see the following: - -* *xref:core-concepts[Learn {aws} CDK core concepts]* – Important concepts and terms for the {aws} CDK. -* *link:https://cdkworkshop.com/[{aws} CDK Workshop]* – Hands-on workshop to learn and use the {aws} CDK. -* *link:https://cdkpatterns.com/[{aws} CDK Patterns]* – Open-source collection of {aws} serverless architecture patterns, built for the {aws} CDK by {aws} experts. -* *link:https://github.com/aws-samples/aws-cdk-examples[{aws} CDK code examples]* – [.noloc]`GitHub` repository of example {aws} CDK projects. -* *link:https://cdk.dev/[cdk.dev]* – Community-driven hub for the {aws} CDK, including a community [.noloc]`Slack` workspace. -* *link:https://github.com/kalaiser/awesome-cdk[Awesome CDK]* – [.noloc]`GitHub` repository containing a curated list of {aws} CDK open-source projects, guides, blogs, and other resources. -* *link:https://aws.amazon.com/solutions/constructs/[{aws} Solutions Constructs]* – Vetted, configuration infrastructure as code (IaC) patterns that can easily be assembled into production-ready applications. -* *link:https://aws.amazon.com/blogs/developer/category/developer-tools/aws-cloud-development-kit/[{aws} Developer Tools Blog]* – Blog posts filtered for the {aws} CDK. -* *link:https://stackoverflow.com/questions/tagged/aws-cdk[{aws} CDK on Stack Overflow]* – Questions tagged with *aws-cdk* on [.noloc]`Stack Overflow`. -* *link:https://docs.aws.amazon.com/cloud9/latest/user-guide/sample-cdk.html[{aws} CDK tutorial for {aws} Cloud9]* – Tutorial on using the {aws} CDK with the {aws} Cloud9 development environment. - -To learn more about related topics to the {aws} CDK, see the following: - -* *link:https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-whatis-concepts.html[{aws} CloudFormation concepts]* – Since the {aws} CDK is built to work with {aws} CloudFormation, we recommend that you learn and understand key {aws} CloudFormation concepts. -* *link:https://docs.aws.amazon.com/general/latest/gr/glos-chap.html[{aws} Glossary]* – Definitions of key terms used across {aws}. - -To learn more about tools related to the {aws} CDK that can be used to simplify serverless application development and deployment, see the following: - -* *link:https://aws.amazon.com/serverless/sam/[{aws} Serverless Application Model]* – An open-source developer tool that simplifies and improves the experience of building and running serverless applications on {aws}. -* *link:https://github.com/aws/chalice[{aws} Chalice]* – A framework for writing serverless apps in Python. \ No newline at end of file diff --git a/v2/guide/work-with/work-with-cdk-csharp.adoc b/v2/guide/work-with/work-with-cdk-csharp.adoc deleted file mode 100644 index c73d1b5d..00000000 --- a/v2/guide/work-with/work-with-cdk-csharp.adoc +++ /dev/null @@ -1,221 +0,0 @@ -include::../attributes.txt[] - -// Attributes -[.topic] -[#work-with-cdk-csharp] -= Working with the {aws} CDK in C# -:info_titleabbrev: In C# - -// Content start - -+++.NET+++ is a fully-supported client language for the {aws} CDK and is considered stable. C# is the main .NET language for which we provide examples and support. You can choose to write {aws} CDK applications in other .NET languages, such as Visual Basic or F#, but {aws} offers limited support for using these languages with the CDK. - -You can develop {aws} CDK applications in C# using familiar tools including Visual Studio, Visual Studio Code, the `dotnet` command, and the NuGet package manager. The modules comprising the {aws} Construct Library are distributed via https://www.nuget.org/packages?q=amazon.cdk.aws[nuget.org]. - -We suggest using https://visualstudio.microsoft.com/downloads/[Visual Studio 2019] (any edition) on Windows to develop {aws} CDK apps in C#. - -[#csharp-prerequisites] -== Get started with C# - -To work with the {aws} CDK, you must have an {aws} account and credentials and have installed Node.js and the {aws} CDK Toolkit. See xref:getting-started[Getting started with the {aws} CDK]. - -C# {aws} CDK applications require .NET Core v3.1 or later, available https://dotnet.microsoft.com/download/dotnet-core/3.1[here]. - -The .NET toolchain includes `dotnet`, a command-line tool for building and running .NET applications and managing NuGet packages. Even if you work mainly in Visual Studio, this command can be useful for batch operations and for installing {aws} Construct Library packages. - -[#csharp-newproject] -== Creating a project - -You create a new {aws} CDK project by invoking `cdk init` in an empty directory. Use the `--language` option and specify `csharp`: - -[source,none,subs="verbatim,attributes"] ----- -mkdir my-project -cd my-project -cdk init app --language csharp ----- - -`cdk init` uses the name of the project folder to name various elements of the project, including classes, subfolders, and files. Hyphens in the folder name are converted to underscores. However, the name should otherwise follow the form of a C# identifier; for example, it should not start with a number or contain spaces. - -The resulting project includes a reference to the `Amazon.CDK.Lib` NuGet package. It and its dependencies are installed automatically by NuGet. - -[#csharp-managemodules] -== Managing {aws} Construct Library modules - -The .NET ecosystem uses the NuGet package manager. The main CDK package, which contains the core classes and all stable service constructs, is `Amazon.CDK.Lib`. Experimental modules, where new functionality is under active development, are named like `Amazon.CDK.{aws}.<SERVICE-NAME>.Alpha`, where the service name is a short name without an {aws} or Amazon prefix. For example, the NuGet package name for the {aws} IoT module is `Amazon.CDK.{aws}.IoT.Alpha`. If you can't find a package you want, https://www.nuget.org/packages?q=amazon.cdk.aws[search Nuget.org]. - -[NOTE] -==== - -The https://docs.aws.amazon.com/cdk/api/latest/dotnet/api/index.html[.NET edition of the CDK API Reference] also shows the package names. - -==== - -Some services' {aws} Construct Library support is in more than one module. For example, {aws} IoT has a second module named `Amazon.CDK.{aws}.IoT.Actions.Alpha`. - -The {aws} CDK's main module, which you'll need in most {aws} CDK apps, is imported in C# code as `Amazon.CDK`. Modules for the various services in the {aws} Construct Library live under `Amazon.CDK.{aws}`. For example, the Amazon S3 module's namespace is `Amazon.CDK.{aws}.S3`. - -We recommend writing C# `using` directives for the CDK core constructs and for each {aws} service you use in each of your C# source files. You may find it convenient to use an alias for a namespace or type to help resolve name conflicts. You can always use a type's fully-qualfiied name (including its namespace) without a `using` statement. - -[#work-with-cdk-csharp-dependencies] -== Managing dependencies in C# - -In C# {aws} CDK apps, you manage dependencies using NuGet. NuGet has four standard, mostly equivalent interfaces. Use the one that suits your needs and working style. You can also use compatible tools, such as https://fsprojects.github.io/Paket/[Paket] or https://www.myget.org/[MyGet] or even edit the `.csproj` file directly. - -NuGet does not let you specify version ranges for dependencies. Every dependency is pinned to a specific version. - -After updating your dependencies, Visual Studio will use NuGet to retrieve the specified versions of each package the next time you build. If you are not using Visual Studio, use the `dotnet restore` command to update your dependencies. - -[#manage-dependencies-csharp-direct-edit] -=== Editing the project file directly - -Your project's `.csproj` file contains an `<ItemGroup>` container that lists your dependencies as `<PackageReference` elements. - -[source,none,subs="verbatim,attributes"] ----- -<ItemGroup> - <PackageReference Include="Amazon.CDK.Lib" Version="2.14.0" /> - <PackageReference Include="Constructs" Version="%constructs-version%" /> -</ItemGroup> ----- - -[#manage-dependencies-csharp-vs-nuget-gui] -=== The Visual Studio NuGet GUI - -Visual Studio's NuGet tools are accessible from *Tools* > *NuGet Package Manager* > *Manage NuGet Packages for Solution*. Use the *Browse* tab to find the {aws} Construct Library packages you want to install. You can choose the desired version, including prerelease versions of your modules, and add them to any of the open projects. - -[NOTE] -==== - -All {aws} Construct Library modules deemed "experimental" (see xref:versioning[{aws} CDK versioning]) are flagged as prerelease in NuGet and have an `alpha` name suffix. - -==== - -image::images/visual-studio-nuget.png[NuGet package manager showing Amazon CDK{aws} alpha packages for various services.,scaledwidth=100%] - -Look on the *Updates* page to install new versions of your packages. - -[#manage-dependencies-csharp-vs-nuget-console] -=== The NuGet console - -The NuGet console is a PowerShell-based interface to NuGet that works in the context of a Visual Studio project. You can open it in Visual Studio by choosing *Tools* > *NuGet Package Manager* > *Package Manager Console*. For more information about using this tool, see https://docs.microsoft.com/en-us/nuget/consume-packages/install-use-packages-powershell[Install and Manage Packages with the Package Manager Console in Visual Studio]. - -[#manage-dependencies-csharp-vs-dotnet-command] -=== The `dotnet` command - -The `dotnet` command is the primary command line tool for working with Visual Studio C# projects. You can invoke it from any Windows command prompt. Among its many capabilities, `dotnet` can add NuGet dependencies to a Visual Studio project. - -Assuming you're in the same directory as the Visual Studio project (`.csproj`) file, issue a command like the following to install a package. Because the main CDK library is included when you create a project, you only need to explicitly install experimental modules. Experimental modules require you to specify an explicit version number. - -[source,none,subs="verbatim,attributes"] ----- -dotnet add package Amazon.CDK.{aws}.IoT.Alpha -v <VERSION-NUMBER> ----- - -You can issue the command from another directory. To do so, include the path to the project file, or to the directory that contains it, after the `add` keyword. The following example assumes that you are in your {aws} CDK project's main directory. - -[source,none,subs="verbatim,attributes"] ----- -dotnet add src/<PROJECT-DIR> package Amazon.CDK.{aws}.IoT.Alpha -v <VERSION-NUMBER> ----- - -To install a specific version of a package, include the `-v` flag and the desired version. - -To update a package, issue the same `dotnet add` command you used to install it. For experimental modules, again, you must specify an explicit version number. - -For more information about managing packages using the `dotnet` command, see https://docs.microsoft.com/en-us/nuget/consume-packages/install-use-packages-dotnet-cli[Install and Manage Packages Using the dotnet CLI]. - -[#manage-dependencies-csharp-vs-nuget-command] -=== The `nuget` command - -The `nuget` command line tool can install and update NuGet packages. However, it requires your Visual Studio project to be set up differently from the way `cdk init` sets up projects. (Technical details: `nuget` works with `Packages.config` projects, while `cdk init` creates a newer-style `PackageReference` project.) - -We do not recommend the use of the `nuget` tool with {aws} CDK projects created by `cdk init`. If you are using another type of project, and want to use `nuget`, see the https://docs.microsoft.com/en-us/nuget/reference/nuget-exe-cli-reference[NuGet CLI Reference]. - -[#csharp-cdk-idioms] -== {aws} CDK idioms in C# - -[#csharp-props] -=== Props - -All {aws} Construct Library classes are instantiated using three arguments: the _scope_ in which the construct is being defined (its parent in the construct tree), an _id_, and _props_, a bundle of key/value pairs that the construct uses to configure the resources it creates. Other classes and methods also use the "bundle of attributes" pattern for arguments. - -In C#, props are expressed using a props type. In idiomatic C# fashion, we can use an object initializer to set the various properties. Here we're creating an Amazon S3 bucket using the `Bucket` construct; its corresponding props type is `BucketProps`. - -[source,csharp,subs="verbatim,attributes"] ----- -var bucket = new Bucket(this, "amzn-s3-demo-bucket", new BucketProps { - Versioned = true -}); ----- - -[TIP] -==== - -Add the package `Amazon.JSII.Analyzers` to your project to get required-values checking in your props definitions inside Visual Studio. - -==== - -When extending a class or overriding a method, you may want to accept additional props for your own purposes that are not understood by the parent class. To do this, subclass the appropriate props type and add the new attributes. - -[source,csharp,subs="verbatim,attributes"] ----- -// extend BucketProps for use with MimeBucket -class MimeBucketProps : BucketProps { - public string MimeType { get; set; } -} - -// hypothetical bucket that enforces MIME type of objects inside it -class MimeBucket : Bucket { - public MimeBucket( readonly Construct scope, readonly string id, readonly MimeBucketProps props=null) : base(scope, id, props) { - // ... - } -} - -// instantiate our MimeBucket class -var bucket = new MimeBucket(this, "amzn-s3-demo-bucket", new MimeBucketProps { - Versioned = true, - MimeType = "image/jpeg" -}); ----- - -When calling the parent class's initializer or overridden method, you can generally pass the props you received. The new type is compatible with its parent, and extra props you added are ignored. - -A future release of the {aws} CDK could coincidentally add a new property with a name you used for your own property. This won't cause any technical issues using your construct or method (since your property isn't passed "up the chain," the parent class or overridden method will simply use a default value) but it may cause confusion for your construct's users. You can avoid this potential problem by naming your properties so they clearly belong to your construct. If there are many new properties, bundle them into an appropriately-named class and pass them as a single property. - -[#csharp-generic-structures] -=== Generic structures - -In some APIs, the {aws} CDK uses JavaScript arrays or untyped objects as input to a method. (See, for example, {aws} CodeBuild's link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_codebuild.BuildSpec.html[`BuildSpec.fromObject()`] method.) In C#, these objects are represented as `System.Collections.Generic.Dictionary<String, Object>`. In cases where the values are all strings, you can use `Dictionary<String, String>`. JavaScript arrays are represented as `object[]` or `string[]` array types in C#. - -[TIP] -==== - -You might define short aliases to make it easier to work with these specific dictionary types. - -[source,csharp,subs="verbatim,attributes"] ----- -using StringDict = System.Collections.Generic.Dictionary<string, string>; -using ObjectDict = System.Collections.Generic.Dictionary<string, object>; ----- - -==== - -[#csharp-missing-values] -=== Missing values - -In C#, missing values in {aws} CDK objects such as props are represented by `null`. The null-conditional member access operator `?.` and the null coalescing operator `??` are convenient for working with these values. - -[source,csharp,subs="verbatim,attributes"] ----- -// mimeType is null if props is null or if props.MimeType is null -string mimeType = props?.MimeType; - -// mimeType defaults to text/plain. either props or props.MimeType can be null -string MimeType = props?.MimeType ?? "text/plain"; ----- - -[#csharp-running] -== Build and run CDK appliations - -The {aws} CDK automatically compiles your app before running it. However, it can be useful to build your app manually to check for errors and run tests. You can do this by pressing F6 in Visual Studio or by issuing `dotnet build src` from the command line, where `src` is the directory in your project directory that contains the Visual Studio Solution (`.sln`) file. \ No newline at end of file diff --git a/v2/guide/work-with/work-with-cdk-go.adoc b/v2/guide/work-with/work-with-cdk-go.adoc deleted file mode 100644 index 71c3a7a0..00000000 --- a/v2/guide/work-with/work-with-cdk-go.adoc +++ /dev/null @@ -1,159 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[#work-with-cdk-go] -= Working with the {aws} CDK in [.noloc]`Go` -:info_titleabbrev: In Go - -// Content start - -[.noloc]`Go` is a fully-supported client language for the {aws} Cloud Development Kit ({aws} CDK) and is considered stable. Working with the {aws} CDK in Go uses familiar tools. The Go version of the {aws} CDK even uses Go-style identifiers. - -Unlike the other languages the CDK supports, [.noloc]`Go` is not a traditional object-oriented programming language. [.noloc]`Go` uses composition where other languages often leverage inheritance. We have tried to employ idiomatic [.noloc]`Go` approaches as much as possible, but there are places where the CDK may differ. - -This topic provides guidance when working with the {aws} CDK in [.noloc]`Go`. See the https://aws.amazon.com/blogs/developer/getting-started-with-the-aws-cloud-development-kit-and-go/[announcement blog post] for a walkthrough of a simple Go project for the {aws} CDK. - -[#go-prerequisites] -== Get started with [.noloc]`Go` - -To work with the {aws} CDK, you must have an {aws} account and credentials and have installed Node.js and the {aws} CDK Toolkit. See xref:getting-started[Getting started with the {aws} CDK]. - -The [.noloc]`Go` bindings for the {aws} CDK use the standard https://golang.org/dl/[Go toolchain], v1.18 or later. You can use the editor of your choice. - -[NOTE] -==== - -Third-party language deprecation: language version is only supported until its EOL (End Of Life) shared by the vendor or community and is subject to change with prior notice. - -==== - -[#go-newproject] -== Creating a project - -You create a new {aws} CDK project by invoking `cdk init` in an empty directory. Use the `--language` option and specify `go`: - -[source,none,subs="verbatim,attributes"] ----- -mkdir my-project -cd my-project -cdk init app --language go ----- - -`cdk init` uses the name of the project folder to name various elements of the project, including classes, subfolders, and files. Hyphens in the folder name are converted to underscores. However, the name should otherwise follow the form of a [.noloc]`Go` identifier; for example, it should not start with a number or contain spaces. - -The resulting project includes a reference to the core {aws} CDK [.noloc]`Go` module, `github.com/aws/aws-cdk-go/awscdk/v2`, in `go.mod`. Issue `go get` to install this and other required modules. - -[#go-managemodules] -== Managing {aws} Construct Library modules - -In most {aws} CDK documentation and examples, the word "module" is often used to refer to {aws} Construct Library modules, one or more per {aws} service, which differs from idiomatic [.noloc]`Go` usage of the term. The CDK Construct Library is provided in one [.noloc]`Go` module with the individual Construct Library modules, which support the various {aws} services, provided as [.noloc]`Go` packages within that module. - -Some services' {aws} Construct Library support is in more than one Construct Library module ([.noloc]`Go` package). For example, Amazon Route 53 has three Construct Library modules in addition to the main `awsroute53` package, named `awsroute53patterns`, `awsroute53resolver`, and `awsroute53targets`. - -The {aws} CDK's core package, which you'll need in most {aws} CDK apps, is imported in [.noloc]`Go` code as `github.com/aws/aws-cdk-go/awscdk/v2`. Packages for the various services in the {aws} Construct Library live under `github.com/aws/aws-cdk-go/awscdk/v2`. For example, the Amazon S3 module's namespace is `github.com/aws/aws-cdk-go/awscdk/v2/awss3`. - -[source,go,subs="verbatim,attributes"] ----- - -import ( - "github.com/aws/aws-cdk-go/awscdk/v2/awss3" - // ... -) ----- - -Once you have imported the Construct Library modules ([.noloc]`Go` packages) for the services you want to use in your app, you access constructs in that module using, for example, `awss3.Bucket`. - -[#work-with-cdk-go-dependencies] -== Managing dependencies in [.noloc]`Go` - -In [.noloc]`Go`, dependencies versions are defined in `go.mod`. The default `go.mod` is similar to the one shown here. - -[source,go,subs="verbatim,attributes"] ----- -module my-package - -go 1.16 - -require ( - github.com/aws/aws-cdk-go/awscdk/v2 v2.16.0 - github.com/aws/constructs-go/constructs/v10 v10.0.5 - github.com/aws/jsii-runtime-go v1.29.0 -) ----- - -Package names (modules, in Go parlance) are specified by URL with the required version number appended. [.noloc]``Go``'s module system does not support version ranges. - -Issue the `go get` command to install all required modules and update `go.mod`. To see a list of available updates for your dependencies, issue `go list -m -u all`. - -[#go-cdk-idioms] -== {aws} CDK idioms in [.noloc]`Go` - -[#go-naming] -=== Field and method names - -Field and method names use camel casing (`likeThis`) in TypeScript, the CDK's language of origin. In [.noloc]`Go`, these follow [.noloc]`Go` conventions, so are Pascal-cased (`LikeThis`). - -[#go-cdk-jsii-close] -=== Cleaning up - -In your `main` method, use `defer jsii.Close()` to make sure your CDK app cleans up after itself. - -[#go-missing-values] -=== Missing values and pointer conversion - -In [.noloc]`Go`, missing values in {aws} CDK objects such as property bundles are represented by `nil`. [.noloc]`Go` doesn't have nullable types; the only type that can contain `nil` is a pointer. To allow values to be optional, then, all CDK properties, arguments, and return values are pointers, even for primitive types. This applies to required values as well as optional ones, so if a required value later becomes optional, no breaking change in type is needed. - -When passing literal values or expressions, use the following helper functions to create pointers to the values. - -* `jsii.String` -* `jsii.Number` -* `jsii.Bool` -* `jsii.Time` - -For consistency, we recommend that you use pointers similarly when defining your own constructs, even though it may seem more convenient to, for example, receive your construct's `id` as a string rather than a pointer to a string. - -When dealing with optional {aws} CDK values, including primitive values as well as complex types, you should explicitly test pointers to make sure they are not `nil` before doing anything with them. Go does not have "syntactic sugar" to help handle empty or missing values as some other languages do. However, required values in property bundles and similar structures are guaranteed to exist (construction fails otherwise), so these values need not be ``nil``-checked. - -[#go-props] -=== Constructs and Props - -Constructs, which represent one or more {aws} resources and their associated attributes, are represented in [.noloc]`Go` as interfaces. For example, `awss3.Bucket` is an interface. Every construct has a factory function, such as `awss3.NewBucket`, to return a struct that implements the corresponding interface. - -All factory functions take three arguments: the `scope` in which the construct is being defined (its parent in the construct tree), an `id`, and `props`, a bundle of key/value pairs that the construct uses to configure the resources it creates. The "bundle of attributes" pattern is also used elsewhere in the {aws} CDK. - -In [.noloc]`Go`, props are represented by a specific struct type for each construct. For example, an `awss3.Bucket` takes a props argument of type `awss3.BucketProps`. Use a struct literal to write props arguments. - -[source,go,subs="verbatim,attributes"] ----- -var bucket = awss3.NewBucket(stack, jsii.String("amzn-s3-demo-bucket"), &awss3.BucketProps{ - Versioned: jsii.Bool(true), -}) ----- - -[#go-generic-structures] -=== Generic structures - -In some places, the {aws} CDK uses JavaScript arrays or untyped objects as input to a method. (See, for example, {aws} CodeBuild's link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_codebuild.BuildSpec.html#static-fromwbrobjectvalue[`BuildSpec.fromObject()`] method.) In Go, these objects are represented as slices and an empty interface, respectively. - -The CDK provides variadic helper functions such as `jsii.Strings` for building slices containing primitive types. - -[source,go,subs="verbatim,attributes"] ----- -jsii.Strings("One", "Two", "Three") ----- - -[#go-writing-constructs] -=== Developing custom constructs - -In [.noloc]`Go`, it is usually more straightforward to write a new construct than to extend an existing one. First, define a new struct type, anonymously embedding one or more existing types if extension-like semantics are desired. Write methods for any new functionality you're adding and the fields necessary to hold the data they need. Define a props interface if your construct needs one. Finally, write a factory function `NewMyConstruct()` to return an instance of your construct. - -If you are simply changing some default values on an existing construct or adding a simple behavior at instantiation, you don't need all that plumbing. Instead, write a factory function that calls the factory function of the construct you're "extending." In other CDK languages, for example, you might create a `TypedBucket` construct that enforces the type of objects in an Amazon S3 bucket by overriding the `s3.Bucket` type and, in your new type's initializer, adding a bucket policy that allows only specified filename extensions to be added to the bucket. In [.noloc]`Go`, it is easier to simply write a `NewTypedBucket` that returns an `s3.Bucket` (instantiated using `s3.NewBucket`) to which you have added an appropriate bucket policy. No new construct type is necessary because the functionality is already available in the standard bucket construct; the new "construct" just provides a simpler way to configure it. - -[#go-running] -== Building, synthesizing, and deploying - -The {aws} CDK automatically compiles your app before running it. However, it can be useful to build your app manually to check for errors and to run tests. You can do this by issuing `go build` at a command prompt while in your project's root directory. - -Run any tests you've written by running `go test` at a command prompt. \ No newline at end of file diff --git a/v2/guide/work-with/work-with-cdk-java.adoc b/v2/guide/work-with/work-with-cdk-java.adoc deleted file mode 100644 index c4c230d8..00000000 --- a/v2/guide/work-with/work-with-cdk-java.adoc +++ /dev/null @@ -1,198 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[#work-with-cdk-java] -= Working with the {aws} CDK in Java -:info_titleabbrev: In Java - -// Content start - -Java is a fully-supported client language for the {aws} CDK and is considered stable. You can develop {aws} CDK applications in Java using familiar tools, including the JDK (Oracle's, or an OpenJDK distribution such as Amazon Corretto) and Apache Maven. - -The {aws} CDK supports Java 8 and later. We recommend using the latest version you can, however, because later versions of the language include improvements that are particularly convenient for developing {aws} CDK applications. For example, Java 9 introduces the `Map.of()` method (a convenient way to declare hashmaps that would be written as object literals in TypeScript). Java 10 introduces local type inference using the `var` keyword. - -[NOTE] -==== - -Most code examples in this Developer Guide work with Java 8. A few examples use ``Map.of()``; these examples include comments noting that they require Java 9. - -==== - -You can use any text editor, or a Java IDE that can read Maven projects, to work on your {aws} CDK apps. We provide https://www.eclipse.org/downloads/[Eclipse] hints in this Guide, but IntelliJ IDEA, NetBeans, and other IDEs can import Maven projects and can be used for developing {aws} CDK applications in Java. - -It is possible to write {aws} CDK applications in JVM-hosted languages other than Java (for example, Kotlin, Groovy, Clojure, or Scala), but the experience may not be particularly idiomatic, and we are unable to provide any support for these languages. - -[#java-prerequisites] -== Get started with Java - -To work with the {aws} CDK, you must have an {aws} account and credentials and have installed Node.js and the {aws} CDK Toolkit. See xref:getting-started[Getting started with the {aws} CDK]. - -Java {aws} CDK applications require Java 8 (v1.8) or later. We recommend https://aws.amazon.com/corretto/[Amazon Corretto], but you can use any OpenJDK distribution or https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html[Oracle's JDK]. You will also need https://maven.apache.org/download.cgi[Apache Maven] 3.5 or later. You can also use tools such as Gradle, but the application skeletons generated by the {aws} CDK Toolkit are Maven projects. - -[NOTE] -==== - -Third-party language deprecation: language version is only supported until its EOL (End Of Life) shared by the vendor or community and is subject to change with prior notice. - -==== - -[#java-newproject] -== Creating a project - -You create a new {aws} CDK project by invoking `cdk init` in an empty directory. Use the `--language` option and specify `java`: - -[source,bash,subs="verbatim,attributes"] ----- -$ mkdir my-project -$ cd my-project -$ cdk init app --language java ----- - -`cdk init` uses the name of the project folder to name various elements of the project, including classes, subfolders, and files. Hyphens in the folder name are converted to underscores. However, the name should otherwise follow the form of a Java identifier; for example, it should not start with a number or contain spaces. - -The resulting project includes a reference to the `software.amazon.awscdk` Maven package. It and its dependencies are automatically installed by Maven. - -If you are using an IDE, you can now open or import the project. In Eclipse, for example, choose *File* > *Import* > *Maven* > **Existing Maven Projects**. Make sure that the project settings are set to use Java 8 (1.8). - -[#java-managemodules] -== Managing {aws} Construct Library modules - -Use Maven to install {aws} Construct Library packages, which are in the group `software.amazon.awscdk`. Most constructs are in the artifact `aws-cdk-lib`, which is added to new Java projects by default. Modules for services whose higher-level CDK support is still being developed are in separate "experimental" packages, named with a short version (no {aws} or Amazon prefix) of their service's name. https://search.maven.org/search?q=software.amazon.awscdk[Search the Maven Central Repository] to find the names of all {aws} CDK and {aws} Construct Module libraries. - -[NOTE] -==== - -The https://docs.aws.amazon.com/cdk/api/v2/java/index.html[Java edition of the CDK API Reference] also shows the package names. - -==== - -Some services' {aws} Construct Library support is in more than one namespace. For example, Amazon Route 53 has its functionality divided into `software.amazon.awscdk.route53`, `route53-patterns`, `route53resolver`, and `route53-targets`. - -The main {aws} CDK package is imported in Java code as `software.amazon.awscdk`. Modules for the various services in the {aws} Construct Library live under `software.amazon.awscdk.services` and are named similarly to their Maven package name. For example, the Amazon S3 module's namespace is `software.amazon.awscdk.services.s3`. - -We recommend writing a separate Java `import` statement for each {aws} Construct Library class you use in each of your Java source files, and avoiding wildcard imports. You can always use a type's fully-qualified name (including its namespace) without an `import` statement. - -If your application depends on an experimental package, edit your project's `pom.xml` and add a new `<dependency>` element in the `<dependencies>` container. For example, the following `<dependency>` element specifies the CodeStar experimental construct library module: - -[source,xml,subs="verbatim,attributes"] ----- -<dependency> - <groupId>software.amazon.awscdk</groupId> - <artifactId>codestar-alpha</artifactId> - <version>2.0.0-alpha.10</version> -</dependency> ----- - -[TIP] -==== - -If you use a Java IDE, it probably has features for managing Maven dependencies. We recommend editing `pom.xml` directly, however, unless you are absolutely sure the IDE's functionality matches what you'd do by hand. - -==== - -[#work-with-cdk-java-dependencies] -== Managing dependencies in Java - -In Java, dependencies are specified in `pom.xml` and installed using Maven. The `<dependencies>` container includes a `<dependency>` element for each package. Following is a section of `pom.xml` for a typical CDK Java app. - -[source,xml,subs="verbatim,attributes"] ----- -<dependencies> - <dependency> - <groupId>software.amazon.awscdk</groupId> - <artifactId>aws-cdk-lib</artifactId> - <version>2.14.0</version> - </dependency> - <dependency> - <groupId>software.amazon.awscdk</groupId> - <artifactId>appsync-alpha</artifactId> - <version>2.10.0-alpha.0</version> - </dependency> -</dependencies> ----- - -[TIP] -==== - -Many Java IDEs have integrated Maven support and visual `pom.xml` editors, which you may find convenient for managing dependencies. - -==== - -Maven does not support dependency locking. Although it's possible to specify version ranges in `pom.xml`, we recommend you always use exact versions to keep your builds repeatable. - -Maven automatically installs transitive dependencies, but there can only be one installed copy of each package. The version that is specified highest in the POM tree is selected; applications always have the last word in what version of packages get installed. - -Maven automatically installs or updates your dependencies whenever you build (`mvn compile`) or package (`mvn package`) your project. The CDK Toolkit does this automatically every time you run it, so generally there is no need to manually invoke Maven. - -[#java-cdk-idioms] -== {aws} CDK idioms in Java - -[#java-props] -=== Props - -All {aws} Construct Library classes are instantiated using three arguments: the _scope_ in which the construct is being defined (its parent in the construct tree), an _id_, and _props_, a bundle of key/value pairs that the construct uses to configure the resources it creates. Other classes and methods also use the "bundle of attributes" pattern for arguments. - -In Java, props are expressed using the link:https://en.wikipedia.org/wiki/Builder_pattern[Builder pattern]. Each construct type has a corresponding props type; for example, the `Bucket` construct (which represents an Amazon S3 bucket) takes as its props an instance of `BucketProps`. - -The `BucketProps` class (like every {aws} Construct Library props class) has an inner class called `Builder`. The `BucketProps.Builder` type offers methods to set the various properties of a `BucketProps` instance. Each method returns the `Builder` instance, so the method calls can be chained to set multiple properties. At the end of the chain, you call `build()` to actually produce the `BucketProps` object. - -[source,java,subs="verbatim,attributes"] ----- -Bucket bucket = new Bucket(this, "amzn-s3-demo-bucket", new BucketProps.Builder() - .versioned(true) - .encryption(BucketEncryption.KMS_MANAGED) - .build()); ----- - -Constructs, and other classes that take a props-like object as their final argument, offer a shortcut. The class has a `Builder` of its own that instantiates it and its props object in one step. This way, you don't need to explicitly instantiate (for example) both `BucketProps` and a `Bucket`--and you don't need an import for the props type. - -[source,java,subs="verbatim,attributes"] ----- -Bucket bucket = Bucket.Builder.create(this, "amzn-s3-demo-bucket") - .versioned(true) - .encryption(BucketEncryption.KMS_MANAGED) - .build(); ----- - -When deriving your own construct from an existing construct, you may want to accept additional properties. We recommend that you follow these builder patterns. However, this isn't as simple as subclassing a construct class. You must provide the moving parts of the two new `Builder` classes yourself. You may prefer to simply have your construct accept one or more additional arguments. You should provide additional constructors when an argument is optional. - -[#java-generic-structures] -=== Generic structures - -In some APIs, the {aws} CDK uses JavaScript arrays or untyped objects as input to a method. (See, for example, {aws} CodeBuild's link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_codebuild.BuildSpec.html#static-fromwbrobjectvalue[`BuildSpec.fromObject()`] method.) In Java, these objects are represented as `java.util.Map<String, Object>`. In cases where the values are all strings, you can use `Map<String, String>`. - -Java does not provide a way to write literals for such containers like some other languages do. In Java 9 and later, you can use link:https://docs.oracle.com/javase/9/docs/api/java/util/Map.html#ofEntries-java.util.Map.Entry...-[`java.util.Map.of()`] to conveniently define maps of up to ten entries inline with one of these calls. - -[source,java,subs="verbatim,attributes"] ----- -java.util.Map.of( - "base-directory", "dist", - "files", "LambdaStack.template.json" - ) ----- - -To create maps with more than ten entries, use link:https://docs.oracle.com/javase/9/docs/api/java/util/Map.html#ofEntries-java.util.Map.Entry...-[`java.util.Map.ofEntries()`]. - -If you are using Java 8, you could provide your own methods similar to to these. - -JavaScript arrays are represented as `List<Object>` or `List<String>` in Java. The method `java.util.Arrays.asList` is convenient for defining short pass:[<code>List</code>s]. - -[source,java,subs="verbatim,attributes"] ----- -List<String> cmds = Arrays.asList("cd lambda", "npm install", "npm install typescript") ----- - - -[#java-missing-values] -=== Missing values - -In Java, missing values in {aws} CDK objects such as props are represented by `null`. You must explicitly test any value that could be `null` to make sure it contains a value before doing anything with it. Java does not have "syntactic sugar" to help handle null values as some other languages do. You may find Apache ObjectUtil's link:https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/ObjectUtils.html#defaultIfNull-T-T-[`defaultIfNull`] and link:https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/ObjectUtils.html#firstNonNull-T...-[`firstNonNull`] useful in some situations. Alternatively, write your own static helper methods to make it easier to handle potentially null values and make your code more readable. - -[#java-running] -== Build and run CDK applications - -The {aws} CDK automatically compiles your app before running it. However, it can be useful to build your app manually to check for errors and to run tests. You can do this in your IDE (for example, press Control-B in Eclipse) or by issuing `mvn compile` at a command prompt while in your project's root directory. - -Run any tests you've written by running `mvn test` at a command prompt. \ No newline at end of file diff --git a/v2/guide/work-with/work-with-cdk-javascript.adoc b/v2/guide/work-with/work-with-cdk-javascript.adoc deleted file mode 100644 index a9346d49..00000000 --- a/v2/guide/work-with/work-with-cdk-javascript.adoc +++ /dev/null @@ -1,461 +0,0 @@ -include::../attributes.txt[] - -// Attributes - -[.topic] -[#work-with-cdk-javascript] -= Working with the {aws} CDK in JavaScript -:info_titleabbrev: In JavaScript - -// Content start - -JavaScript is a fully-supported client language for the {aws} CDK and is considered stable. Working with the {aws} Cloud Development Kit ({aws} CDK) in JavaScript uses familiar tools, including https://nodejs.org/[Node.js] and the Node Package Manager (`npm`). You may also use https://yarnpkg.com/[Yarn] if you prefer, though the examples in this Guide use NPM. The modules comprising the {aws} Construct Library are distributed via the NPM repository, https://www.npmjs.com/[npmjs.org]. - -You can use any editor or IDE. Many {aws} CDK developers use https://code.visualstudio.com/[Visual Studio Code] (or its open-source equivalent https://vscodium.com/[VSCodium]), which has good support for JavaScript. - -[#javascript-prerequisites] -== Get started with JavaScript - -To work with the {aws} CDK, you must have an {aws} account and credentials and have installed Node.js and the {aws} CDK Toolkit. See xref:getting-started[Getting started with the {aws} CDK]. - -JavaScript {aws} CDK applications require no additional prerequisites beyond these. - -[NOTE] -==== - -Third-party language deprecation: language version is only supported until its EOL (End Of Life) shared by the vendor or community and is subject to change with prior notice. - -==== - -[#javascript-newproject] -== Creating a project - -You create a new {aws} CDK project by invoking `cdk init` in an empty directory. Use the `--language` option and specify `javascript`: - -[source,bash,subs="verbatim,attributes"] ----- -$ mkdir my-project -$ cd my-project -$ cdk init app --language javascript ----- - -Creating a project also installs the https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib-readme.html[aws-cdk-lib] module and its dependencies. - -`cdk init` uses the name of the project folder to name various elements of the project, including classes, subfolders, and files. Hyphens in the folder name are converted to underscores. However, the name should otherwise follow the form of a JavaScript identifier; for example, it should not start with a number or contain spaces. - -[#javascript-local] -== Using local `cdk` - -For the most part, this guide assumes you install the CDK Toolkit globally (`npm install -g aws-cdk`), and the provided command examples (such as `cdk synth`) follow this assumption. This approach makes it easy to keep the CDK Toolkit up to date, and since the CDK takes a strict approach to backward compatibility, there is generally little risk in always using the latest version. - -Some teams prefer to specify all dependencies within each project, including tools like the CDK Toolkit. This practice lets you pin such components to specific versions and ensure that all developers on your team (and your CI/CD environment) use exactly those versions. This eliminates a possible source of change, helping to make builds and deployments more consistent and repeatable. - -The CDK includes a dependency for the CDK Toolkit in the JavaScript project template's `package.json`, so if you want to use this approach, you don't need to make any changes to your project. All you need to do is use slightly different commands for building your app and for issuing `cdk` commands. - -[cols="1h,1,1"] -|=== -|Operation | Use global tools | Use local tools - -|Initialize project -|`cdk init --language javascript` -|`npx aws-cdk init --language javascript` - -|Run CDK Toolkit command -|`cdk ...` -|`npm run cdk ...` or `npx aws-cdk ...` -|=== - -`npx aws-cdk` runs the version of the CDK Toolkit installed locally in the current project, if one exists, falling back to the global installation, if any. If no global installation exists, `npx` downloads a temporary copy of the CDK Toolkit and runs that. You may specify an arbitrary version of the CDK Toolkit using the `@` syntax: `npx aws-cdk@1.120 --version` prints `1.120.0`. - -[TIP] -==== -Set up an alias so you can use the `cdk` command with a local CDK Toolkit installation. - -[role="tablist"] -macOS/Linux:: -+ -[source,bash,subs="verbatim,attributes"] ----- -$ alias cdk="npx aws-cdk" ----- - -Windows:: -+ -[source,none,subs="verbatim,attributes"] ----- -doskey cdk=npx aws-cdk $* ----- -==== - -[[javascript-managemodules,javascript-managemodules.title]] -== Managing {aws} Construct Library modules - -Use the Node Package Manager (``npm``) to install and update {aws} Construct Library modules for use by your apps, as well as other packages you need. (You may use `yarn` instead of `npm` if you prefer.) `npm` also installs the dependencies for those modules automatically. - -Most {aws} CDK constructs are in the main CDK package, named `aws-cdk-lib`, which is a default dependency in new projects created by `cdk init`. "Experimental" {aws} Construct Library modules, where higher-level constructs are still under development, are named like `aws-cdk-lib/<SERVICE-NAME>-alpha`. The service name has an _aws-_ prefix. If you're unsure of a module's name, https://www.npmjs.com/search?q=%40aws-cdk[search for it on NPM]. - -[NOTE] -==== - -The https://docs.aws.amazon.com/cdk/api/v2/docs/aws-construct-library.html[CDK API Reference] also shows the package names. - -==== - -For example, the command below installs the experimental module for {aws} CodeStar. - -[source,none,subs="verbatim,attributes"] ----- -npm install @aws-cdk/aws-codestar-alpha ----- - -Some services' Construct Library support is in more than one namespace. For example, besides `aws-route53`, there are three additional Amazon Route 53 namespaces, `aws-route53-targets`, `aws-route53-patterns`, and `aws-route53resolver`. - -Your project's dependencies are maintained in `package.json`. You can edit this file to lock some or all of your dependencies to a specific version or to allow them to be updated to newer versions under certain criteria. To update your project's NPM dependencies to the latest permitted version according to the rules you specified in `package.json`: - -[source,none,subs="verbatim,attributes"] ----- -npm update ----- - -In JavaScript, you import modules into your code under the same name you use to install them using NPM. We recommend the following practices when importing {aws} CDK classes and {aws} Construct Library modules in your applications. Following these guidelines will help make your code consistent with other {aws} CDK applications as well as easier to understand. - -* Use `require()`, not ES6-style `import` directives. Older versions of Node.js do not support ES6 imports, so using the older syntax is more widely compatible. (If you really want to use ES6 imports, use https://www.npmjs.com/package/esm[esm] to ensure your project is compatible with all supported versions of Node.js.) -* Generally, import individual classes from `aws-cdk-lib`. -+ -[source,javascript,subs="verbatim,attributes"] ----- -const { App, Stack } = require('aws-cdk-lib'); ----- -* If you need many classes from ``aws-cdk-lib``, you may use a namespace alias of `cdk` instead of importing the individual classes. Avoid doing both. -+ -[source,javascript,subs="verbatim,attributes"] ----- -const cdk = require('aws-cdk-lib'); ----- -* Generally, import {aws} Construct Libraries using short namespace aliases. -+ -[source,javascript,subs="verbatim,attributes"] ----- -const { s3 } = require('aws-cdk-lib/aws-s3'); ----- - -[#work-with-cdk-javascript-dependencies] -== Managing dependencies in JavaScript - -In JavaScript CDK projects, dependencies are specified in the `package.json` file in the project's main directory. The core {aws} CDK modules are in a single `NPM` package called `aws-cdk-lib`. - -When you install a package using `npm install`, NPM records the package in `package.json` for you. - -If you prefer, you may use Yarn in place of NPM. However, the CDK does not support Yarn's plug-and-play mode, which is default mode in Yarn 2. Add the following to your project's `.yarnrc.yml` file to turn off this feature. - -[source,yaml,subs="verbatim,attributes"] ----- -nodeLinker: node-modules ----- - -[#work-with-cdk-javascript-dependencies-apps] -=== CDK applications - -The following is an example `package.json` file generated by the `cdk init --language typescript` command. The file generated for JavaScript is similar, only without the TypeScript-related entries. - -[source,json,subs="verbatim,attributes"] ----- -{ - "name": "my-package", - "version": "0.1.0", - "bin": { - "my-package": "bin/my-package.js" - }, - "scripts": { - "build": "tsc", - "watch": "tsc -w", - "test": "jest", - "cdk": "cdk" - }, - "devDependencies": { - "@types/jest": "^26.0.10", - "@types/node": "10.17.27", - "jest": "^26.4.2", - "ts-jest": "^26.2.0", - "aws-cdk": "2.16.0", - "ts-node": "^9.0.0", - "typescript": "~3.9.7" - }, - "dependencies": { - "aws-cdk-lib": "2.16.0", - "constructs": "^10.0.0", - "source-map-support": "^0.5.16" - } -} ----- - -For deployable CDK apps, `aws-cdk-lib` must be specified in the `dependencies` section of `package.json`. You can use a caret (^) version number specifier to indicate that you will accept later versions than the one specified as long as they are within the same major version. - -For experimental constructs, specify exact versions for the alpha construct library modules, which have APIs that may change. Do not use ^ or ~ since later versions of these modules may bring API changes that can break your app. - -Specify versions of libraries and tools needed to test your app (for example, the `jest` testing framework) in the `devDependencies` section of `package.json`. Optionally, use ^ to specify that later compatible versions are acceptable. - -[#work-with-cdk-javascript-dependencies-libraries] -=== Third-party construct libraries - -If you're developing a construct library, specify its dependencies using a combination of the `peerDependencies` and `devDependencies` sections, as shown in the following example `package.json` file. - -[source,json,subs="verbatim,attributes"] ----- -{ - "name": "my-package", - "version": "0.0.1", - "peerDependencies": { - "aws-cdk-lib": "^2.14.0", - "@aws-cdk/aws-appsync-alpha": "2.10.0-alpha", - "constructs": "^10.0.0" - }, - "devDependencies": { - "aws-cdk-lib": "2.14.0", - "@aws-cdk/aws-appsync-alpha": "2.10.0-alpha", - "constructs": "10.0.0", - "jsii": "^1.50.0", - "aws-cdk": "^2.14.0" - } -} ----- - -In `peerDependencies`, use a caret (^) to specify the lowest version of `aws-cdk-lib` that your library works with. This maximizes the compatibility of your library with a range of CDK versions. Specify exact versions for alpha construct library modules, which have APIs that may change. Using `peerDependencies` makes sure that there is only one copy of all CDK libraries in the `node_modules` tree. - -In `devDependencies`, specify the tools and libraries you need for testing, optionally with ^ to indicate that later compatible versions are acceptable. Specify exactly (without ^ or ~) the lowest versions of `aws-cdk-lib` and other CDK packages that you advertise your library be compatible with. This practice makes sure that your tests run against those versions. This way, if you inadvertently use a feature found only in newer versions, your tests can catch it. - -[WARNING] -==== - -`peerDependencies` are installed automatically only by NPM 7 and later. If you are using NPM 6 or earlier, or if you are using Yarn, you must include the dependencies of your dependencies in `devDependencies`. Otherwise, they won't be installed, and you will receive a warning about unresolved peer dependencies. - -==== - -[#work-with-cdk-javascript-dependencies-install] -=== Installing and updating dependencies - -Run the following command to install your project's dependencies. - -==== -[role="tablist"] -NPM:: -+ -[source,none,subs="verbatim,attributes"] ----- -# Install the latest version of everything that matches the ranges in 'package.json' -npm install - -# Install the same exact dependency versions as recorded in 'package-lock.json' -npm ci ----- - -Yarn:: -+ -[source,none,subs="verbatim,attributes"] ----- -# Install the latest version of everything that matches the ranges in 'package.json' -yarn upgrade - -# Install the same exact dependency versions as recorded in 'yarn.lock' -yarn install --frozen-lockfile ----- -==== - -To update the installed modules, the preceding `npm install` and `yarn upgrade` commands can be used. Either command updates the packages in `node_modules` to the latest versions that satisfy the rules in `package.json`. However, they do not update `package.json` itself, which you might want to do to set a new minimum version. If you host your package on GitHub, you can configure https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuring-dependabot-version-updates[Dependabot version updates] to automatically update `package.json`. Alternatively, use https://www.npmjs.com/package/npm-check-updates[npm-check-updates]. - -[IMPORTANT] -==== - -By design, when you install or update dependencies, NPM and Yarn choose the latest version of every package that satisfies the requirements specified in `package.json`. There is always a risk that these versions may be broken (either accidentally or intentionally). Test thoroughly after updating your project's dependencies. - -==== - -[#javascript-cdk-idioms] -== {aws} CDK idioms in JavaScript - -[#javascript-props] -=== Props - -All {aws} Construct Library classes are instantiated using three arguments: the _scope_ in which the construct is being defined (its parent in the construct tree), an _id_, and _props_, a bundle of key/value pairs that the construct uses to configure the {aws} resources it creates. Other classes and methods also use the "bundle of attributes" pattern for arguments. - -Using an IDE or editor that has good JavaScript autocomplete will help avoid misspelling property names. If a construct is expecting an `encryptionKeys` property, and you spell it `encryptionkeys`, when instantiating the construct, you haven't passed the value you intended. This can cause an error at synthesis time if the property is required, or cause the property to be silently ignored if it is optional. In the latter case, you may get a default behavior you intended to override. Take special care here. - -When subclassing an {aws} Construct Library class (or overriding a method that takes a props-like argument), you may want to accept additional properties for your own use. These values will be ignored by the parent class or overridden method, because they are never accessed in that code, so you can generally pass on all the props you received. - -A future release of the {aws} CDK could coincidentally add a new property with a name you used for your own property. Passing the value you receive up the inheritance chain can then cause unexpected behavior. It's safer to pass a shallow copy of the props you received with your property removed or set to `undefined`. For example: - -[source,javascript,subs="verbatim,attributes"] ----- -super(scope, name, {...props, encryptionKeys: undefined}); ----- - -Alternatively, name your properties so that it is clear that they belong to your construct. This way, it is unlikely they will collide with properties in future {aws} CDK releases. If there are many of them, use a single appropriately-named object to hold them. - -[#javascript-missing-values] -=== Missing values - -Missing values in an object (such as `props`) have the value `undefined` in JavaScript. The usual techniques apply for dealing with these. For example, a common idiom for accessing a property of a value that may be undefined is as follows: - -[source,javascript,subs="verbatim,attributes"] ----- -// a may be undefined, but if it is not, it may have an attribute b -// c is undefined if a is undefined, OR if a doesn't have an attribute b -let c = a && a.b; ----- - -However, if `a` could have some other "falsy" value besides `undefined`, it is better to make the test more explicit. Here, we'll take advantage of the fact that `null` and `undefined` are equal to test for them both at once: - -[source,javascript,subs="verbatim,attributes"] ----- -let c = a == null ? a : a.b; ----- - -[TIP] -==== - -Node.js 14.0 and later support new operators that can simplify the handling of undefined values. For more information, see the https://github.com/tc39/proposal-optional-chaining/blob/master/README.md[optional chaining] and https://github.com/tc39/proposal-nullish-coalescing/blob/master/README.md[nullish coalescing] proposals. - -==== - -[#javascript-using-typescript-examples] -== Using TypeScript examples with JavaScript - -https://www.typescriptlang.org/[TypeScript] is the language we use to develop the {aws} CDK, and it was the first language supported for developing applications, so many available {aws} CDK code examples are written in TypeScript. These code examples can be a good resource for JavaScript developers; you just need to remove the TypeScript-specific parts of the code. - -TypeScript snippets often use the newer ECMAScript `import` and `export` keywords to import objects from other modules and to declare the objects to be made available outside the current module. Node.js has just begun supporting these keywords in its latest releases. Depending on the version of Node.js you're using (or wish to support), you might rewrite imports and exports to use the older syntax. - -Imports can be replaced with calls to the `require()` function. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -import * as cdk from 'aws-cdk-lib'; -import { Bucket, BucketPolicy } from 'aws-cdk-lib/aws-s3'; ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -const cdk = require('aws-cdk-lib'); -const { Bucket, BucketPolicy } = require('aws-cdk-lib/aws-s3'); ----- -==== - -Exports can be assigned to the `module.exports` object. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -export class Stack1 extends cdk.Stack { - // ... -} - -export class Stack2 extends cdk.Stack { - // ... -} ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -class Stack1 extends cdk.Stack { - // ... -} - -class Stack2 extends cdk.Stack { - // ... -} - -module.exports = { Stack1, Stack2 } ----- -==== - -[NOTE] -==== - -An alternative to using the old-style imports and exports is to use the https://www.npmjs.com/package/esm[esm] module. - -==== - -Once you've got the imports and exports sorted, you can dig into the actual code. You may run into these commonly-used TypeScript features: - -* Type annotations -* Interface definitions -* Type conversions/casts -* Access modifiers - -Type annotations may be provided for variables, class members, function parameters, and function return types. For variables, parameters, and members, types are specified by following the identifier with a colon and the type. Function return values follow the function signature and consist of a colon and the type. - -To convert type-annotated code to JavaScript, remove the colon and the type. Class members must have some value in JavaScript; set them to `undefined` if they only have a type annotation in TypeScript. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -var encrypted: boolean = true; - -class myStack extends cdk.Stack { - bucket: s3.Bucket; - // ... -} - -function makeEnv(account: string, region: string) : object { - // ... -} ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -var encrypted = true; - -class myStack extends cdk.Stack { - bucket = undefined; - // ... -} - -function makeEnv(account, region) { - // ... -} ----- - -In TypeScript, interfaces are used to give bundles of required and optional properties, and their types, a name. You can then use the interface name as a type annotation. TypeScript will make sure that the object you use as, for example, an argument to a function has the required properties of the right types. - -[source,javascript,subs="verbatim,attributes"] ----- -interface myFuncProps { - code: lambda.Code, - handler?: string -} ----- -==== - -JavaScript does not have an interface feature, so once you've removed the type annotations, delete the interface declarations entirely. - -When a function or method returns a general-purpose type (such as `object`), but you want to treat that value as a more specific child type to access properties or methods that are not part of the more general type's interface, TypeScript lets you _cast_ the value using `as` followed by a type or interface name. JavaScript doesn't support (or need) this, so simply remove `as` and the following identifier. A less-common cast syntax is to use a type name in brackets, `<LikeThis>`; these casts, too, must be removed. - -Finally, TypeScript supports the access modifiers `public`, `protected`, and `private` for members of classes. All class members in JavaScript are public. Simply remove these modifiers wherever you see them. - -Knowing how to identify and remove these TypeScript features goes a long way toward adapting short TypeScript snippets to JavaScript. But it may be impractical to convert longer TypeScript examples in this fashion, since they are more likely to use other TypeScript features. For these situations, we recommend https://github.com/alangpierce/sucrase[Sucrase]. Sucrase won't complain if code uses an undefined variable, for example, as `tsc` would. If it is syntactically valid, then with few exceptions, Sucrase can translate it to JavaScript. This makes it particularly valuable for converting snippets that may not be runnable on their own. - -[#javascript-to-typescript] -== Migrating to TypeScript - -Many JavaScript developers move to https://www.typescriptlang.org/[TypeScript] as their projects get larger and more complex. TypeScript is a superset of JavaScript--all JavaScript code is valid TypeScript code, so no changes to your code are required--and it is also a supported {aws} CDK language. Type annotations and other TypeScript features are optional and can be added to your {aws} CDK app as you find value in them. TypeScript also gives you early access to new JavaScript features, such as optional chaining and nullish coalescing, before they're finalized--and without requiring that you upgrade Node.js. - -TypeScript's "shape-based" interfaces, which define bundles of required and optional properties (and their types) within an object, allow common mistakes to be caught while you're writing the code, and make it easier for your IDE to provide robust autocomplete and other real-time coding advice. - -Coding in TypeScript does involve an additional step: compiling your app with the TypeScript compiler, `tsc`. For typical {aws} CDK apps, compilation requires a few seconds at most. - -The easiest way to migrate an existing JavaScript {aws} CDK app to TypeScript is to create a new TypeScript project using `cdk init app --language typescript`, then copy your source files (and any other necessary files, such as assets like {aws} Lambda function source code) to the new project. Rename your JavaScript files to end in `.ts` and begin developing in TypeScript. \ No newline at end of file diff --git a/v2/guide/work-with/work-with-cdk-python.adoc b/v2/guide/work-with/work-with-cdk-python.adoc deleted file mode 100644 index 9b44b4e1..00000000 --- a/v2/guide/work-with/work-with-cdk-python.adoc +++ /dev/null @@ -1,325 +0,0 @@ -include::../attributes.txt[] - -// Attributes -[.topic] -[#work-with-cdk-python] -= Working with the {aws} CDK in Python -:info_titleabbrev: In Python - -// Content start - -Python is a fully-supported client language for the {aws} Cloud Development Kit ({aws} CDK) and is considered stable. Working with the {aws} CDK in Python uses familiar tools, including the standard Python implementation (CPython), virtual environments with `virtualenv`, and the Python package installer `pip`. The modules comprising the {aws} Construct Library are distributed via https://pypi.org/search/?q=aws-cdk[pypi.org]. The Python version of the {aws} CDK even uses Python-style identifiers (for example, `snake_case` method names). - -You can use any editor or IDE. Many {aws} CDK developers use https://code.visualstudio.com/[Visual Studio Code] (or its open-source equivalent https://vscodium.com/[VSCodium]), which has good support for Python via an https://marketplace.visualstudio.com/items?itemName=ms-python.python[official extension]. The IDLE editor included with Python will suffice to get started. The Python modules for the {aws} CDK do have type hints, which are useful for a linting tool or an IDE that supports type validation. - -[#python-prerequisites] -== Get started with Python - -To work with the {aws} CDK, you must have an {aws} account and credentials and have installed Node.js and the {aws} CDK Toolkit. See xref:getting-started[Getting started with the {aws} CDK]. - -Python {aws} CDK applications require Python 3.6 or later. If you don't already have it installed, https://www.python.org/downloads/[download a compatible version] for your operating system at https://www.python.org/[python.org]. If you run Linux, your system may have come with a compatible version, or you may install it using your distro's package manager (`yum`, `apt`, etc.). Mac users may be interested in https://brew.sh/[Homebrew], a Linux-style package manager for macOS. - -[NOTE] -==== - -Third-party language deprecation: language version is only supported until its EOL (End Of Life) shared by the vendor or community and is subject to change with prior notice. - -==== - -The Python package installer, `pip`, and virtual environment manager, `virtualenv`, are also required. Windows installations of compatible Python versions include these tools. On Linux, `pip` and `virtualenv` may be provided as separate packages in your package manager. Alternatively, you may install them with the following commands: - -[source,none,subs="verbatim,attributes"] ----- -python -m ensurepip --upgrade -python -m pip install --upgrade pip -python -m pip install --upgrade virtualenv ----- - -If you encounter a permission error, run the above commands with the `--user` flag so that the modules are installed in your user directory, or use `sudo` to obtain the permissions to install the modules system-wide. - -[NOTE] -==== - -It is common for Linux distros to use the executable name `python3` for Python 3.x, and have `python` refer to a Python 2.x installation. Some distros have an optional package you can install that makes the `python` command refer to Python 3. Failing that, you can adjust the command used to run your application by editing `cdk.json` in the project's main directory. - -==== - -[NOTE] -==== - -On Windows, you may want to invoke Python (and `pip`) using the `py` executable, the link:https://docs.python.org/3/using/windows.html#launcher[Python launcher for Windows]. Among other things, the launcher allows you to easily specify which installed version of Python you want to use. - -If typing `python` at the command line results in a message about installing Python from the Windows Store, even after installing a Windows version of Python, open Windows' Manage App Execution Aliases settings panel and turn off the two App Installer entries for Python. - -==== - -[#python-newproject] -== Creating a project - -You create a new {aws} CDK project by invoking `cdk init` in an empty directory. Use the `--language` option and specify `python`: - -[source,bash,subs="verbatim,attributes"] ----- -$ mkdir my-project -$ cd my-project -$ cdk init app --language python ----- - -`cdk init` uses the name of the project folder to name various elements of the project, including classes, subfolders, and files. Hyphens in the folder name are converted to underscores. However, the name should otherwise follow the form of a Python identifier; for example, it should not start with a number or contain spaces. - -To work with the new project, activate its virtual environment. This allows the project's dependencies to be installed locally in the project folder, instead of globally. - -[source,bash,subs="verbatim,attributes"] ----- -$ source .venv/bin/activate ----- - -[NOTE] -==== - -You may recognize this as the Mac/Linux command to activate a virtual environment. The Python templates include a batch file, `source.bat`, that allows the same command to be used on Windows. The traditional Windows command, `.\venv\Scripts\activate`, works, too. - -If you initialized your {aws} CDK project using CDK Toolkit v1.70.0 or earlier, your virtual environment is in the `.env` directory instead of `.venv`. - -==== - -[IMPORTANT] -==== - -Activate the project's virtual environment whenever you start working on it. Otherwise, you won't have access to the modules installed there, and modules you install will go in the Python global module directory (or will result in a permission error). - -==== - -After activating your virtual environment for the first time, install the app's standard dependencies: - -[source,bash,subs="verbatim,attributes"] ----- -$ python -m pip install -r requirements.txt ----- - - -[#python-managemodules] -== Managing {aws} Construct Library modules - -Use the Python package installer, `pip`, to install and update {aws} Construct Library modules for use by your apps, as well as other packages you need. `pip` also installs the dependencies for those modules automatically. If your system does not recognize `pip` as a standalone command, invoke `pip` as a Python module, like this: - -[source,bash,subs="verbatim,attributes"] ----- -$ python -m pip <PIP-COMMAND> ----- - -Most {aws} CDK constructs are in `aws-cdk-lib`. Experimental modules are in separate modules named like `aws-cdk.<SERVICE-NAME>.alpha`. The service name includes an _aws_ prefix. If you're unsure of a module's name, https://pypi.org/search/?q=aws-cdk[search for it at PyPI]. For example, the command below installs the {aws} CodeStar library. - -[source,bash,subs="verbatim,attributes"] ----- -$ python -m pip install aws-cdk.aws-codestar-alpha ----- - -Some services' constructs are in more than one namespace. For example, besides `aws-cdk.aws-route53`, there are three additional Amazon Route 53 namespaces, named `aws-route53-targets`, `aws-route53-patterns`, and `aws-route53resolver`. - -[NOTE] -==== - -The https://docs.aws.amazon.com/cdk/api/v2/python/index.html[Python edition of the CDK API Reference] also shows the package names. - -==== - -The names used for importing {aws} Construct Library modules into your Python code look like the following. - -[source,python,subs="verbatim,attributes"] ----- -import aws_cdk.aws_s3 as s3 -import aws_cdk.aws_lambda as lambda_ ----- - -We recommend the following practices when importing {aws} CDK classes and {aws} Construct Library modules in your applications. Following these guidelines will help make your code consistent with other {aws} CDK applications as well as easier to understand. - -* Generally, import individual classes from top-level `aws_cdk`. -+ -[source,python,subs="verbatim,attributes"] ----- -from aws_cdk import App, Construct ----- -* If you need many classes from the ``aws_cdk``, you may use a namespace alias of `cdk` instead of importing individual classes. Avoid doing both. -+ -[source,python,subs="verbatim,attributes"] ----- -import aws_cdk as cdk ----- -* Generally, import {aws} Construct Libraries using short namespace aliases. -+ -[source,python,subs="verbatim,attributes"] ----- -import aws_cdk.aws_s3 as s3 ----- - -After installing a module, update your project's `requirements.txt` file, which lists your project's dependencies. It is best to do this manually rather than using `pip freeze`. `pip freeze` captures the current versions of all modules installed in your Python virtual environment, which can be useful when bundling up a project to be run elsewhere. - -Usually, though, your `requirements.txt` should list only top-level dependencies (modules that your app depends on directly) and not the dependencies of those libraries. This strategy makes updating your dependencies simpler. - -You can edit `requirements.txt` to allow upgrades; simply replace the `==` preceding a version number with `~=` to allow upgrades to a higher compatible version, or remove the version requirement entirely to specify the latest available version of the module. - -With `requirements.txt` edited appropriately to allow upgrades, issue this command to upgrade your project's installed modules at any time: - -[source,bash,subs="verbatim,attributes"] ----- -$ pip install --upgrade -r requirements.txt ----- - -[#work-with-cdk-python-dependencies] -== Managing dependencies in Python - -In Python, you specify dependencies by putting them in `requirements.txt` for applications or `setup.py` for construct libraries. Dependencies are then managed with the PIP tool. PIP is invoked in one of the following ways: - -[source,none,subs="verbatim,attributes"] ----- -pip <command options> -python -m pip <command options> ----- - -The `python -m pip` invocation works on most systems; `pip` requires that PIP's executable be on the system path. If `pip` doesn't work, try replacing it with `python -m pip`. - -The `cdk init --language python` command creates a virtual environment for your new project. This lets each project have its own versions of dependencies, and also a basic `requirements.txt` file. You must activate this virtual environment by running `source .venv/bin/activate` each time you begin working with the project. On Windows, run `.\venv\Scripts\activate` instead - -[#work-with-cdk-python-dependencies-apps] -=== CDK applications - -The following is an example `requirements.txt` file. Because PIP does not have a dependency-locking feature, we recommend that you use the == operator to specify exact versions for all dependencies, as shown here. - -[source,none,subs="verbatim,attributes"] ----- -aws-cdk-lib==2.14.0 -aws-cdk.aws-appsync-alpha==2.10.0a0 ----- - -Installing a module with `pip install` does not automatically add it to `requirements.txt`. You must do that yourself. If you want to upgrade to a later version of a dependency, edit its version number in `requirements.txt`. - -To install or update your project's dependencies after creating or editing `requirements.txt`, run the following: - -[source,none,subs="verbatim,attributes"] ----- -python -m pip install -r requirements.txt ----- - -[TIP] -==== - -The `pip freeze` command outputs the versions of all installed dependencies in a format that can be written to a text file. This can be used as a requirements file with `pip install -r`. This file is convenient for pinning all dependencies (including transitive ones) to the exact versions that you tested with. To avoid problems when upgrading packages later, use a separate file for this, such as `freeze.txt` (not `requirements.txt`). Then, regenerate it when you upgrade your project's dependencies. - -==== - -[#work-with-cdk-python-dependencies-libraries] -=== Third-party construct libraries - -In libraries, dependencies are specified in `setup.py`, so that transitive dependencies are automatically downloaded when the package is consumed by an application. Otherwise, every application that wants to use your package needs to copy your dependencies into their `requirements.txt`. An example `setup.py` is shown here. - -[source,python,subs="verbatim,attributes"] ----- -from setuptools import setup - -setup( - name='my-package', - version='0.0.1', - install_requires=[ - 'aws-cdk-lib==2.14.0', - ], - ... -) ----- - -To work on the package for development, create or activate a virtual environment, then run the following command. - -[source,none,subs="verbatim,attributes"] ----- -python -m pip install -e . ----- - -Although PIP automatically installs transitive dependencies, there can only be one installed copy of any one package. The version that is specified highest in the dependency tree is selected; applications always have the last word in what version of packages get installed. - -[#python-cdk-idioms] -== {aws} CDK idioms in Python - -[#python-keywords] -=== Language conflicts - -In Python, `lambda` is a language keyword, so you cannot use it as a name for the {aws} Lambda construct library module or Lambda functions. The Python convention for such conflicts is to use a trailing underscore, as in `lambda_`, in the variable name. - -By convention, the second argument to {aws} CDK constructs is named `id`. When writing your own stacks and constructs, calling a parameter `id` "shadows" the Python built-in function `id()`, which returns an object's unique identifier. This function isn't used very often, but if you should happen to need it in your construct, rename the argument, for example `construct_id`. - -[#python-props] -=== Arguments and properties - -All {aws} Construct Library classes are instantiated using three arguments: the _scope_ in which the construct is being defined (its parent in the construct tree), an __id__, and __props__, a bundle of key/value pairs that the construct uses to configure the resources it creates. Other classes and methods also use the "bundle of attributes" pattern for arguments. - -_scope_ and _id_ should always be passed as positional arguments, not keyword arguments, because their names change if the construct accepts a property named _scope_ or _id_. - -In Python, props are expressed as keyword arguments. If an argument contains nested data structures, these are expressed using a class which takes its own keyword arguments at instantiation. The same pattern is applied to other method calls that take a structured argument. - -For example, in a Amazon S3 bucket's `add_lifecycle_rule` method, the `transitions` property is a list of `Transition` instances. - -[source,python,subs="verbatim,attributes"] ----- -bucket.add_lifecycle_rule( - transitions=[ - Transition( - storage_class=StorageClass.GLACIER, - transition_after=Duration.days(10) - ) - ] -) ----- - -When extending a class or overriding a method, you may want to accept additional arguments for your own purposes that are not understood by the parent class. In this case you should accept the arguments you don't care about using the +++**kwargs+++ idiom, and use keyword-only arguments to accept the arguments you're interested in. When calling the parent's constructor or the overridden method, pass only the arguments it is expecting (often just +++**kwargs+++). Passing arguments that the parent class or method doesn't expect results in an error. - -[source,python,subs="verbatim,attributes"] ----- -class MyConstruct(Construct): - def __init__(self, id, *, MyProperty=42, **kwargs): - super().__init__(self, id, **kwargs) - # ... ----- - -A future release of the {aws} CDK could coincidentally add a new property with a name you used for your own property. This won't cause any technical issues for users of your construct or method (since your property isn't passed "up the chain," the parent class or overridden method will simply use a default value) but it may cause confusion. You can avoid this potential problem by naming your properties so they clearly belong to your construct. If there are many new properties, bundle them into an appropriately-named class and pass it as a single keyword argument. - -[#python-missing-values,] -=== Missing values - -The {aws} CDK uses `None` to represent missing or undefined values. When working with +++**kwargs+++, use the dictionary's `get()` method to provide a default value if a property is not provided. Avoid using `kwargs[...]`, as this raises `KeyError` for missing values. - -[source,bash,subs="verbatim,attributes"] ----- -encrypted = kwargs.get("encrypted") # None if no property "encrypted" exists -encrypted = kwargs.get("encrypted", False) # specify default of False if property is missing ----- - -Some {aws} CDK methods (such as `tryGetContext()` to get a runtime context value) may return `None`, which you will need to check explicitly. - -[#python-interfaces] -=== Using interfaces - -Python doesn't have an interface feature as some other languages do, though it does have https://docs.python.org/3/library/abc.html[abstract base classes], which are similar. (If you're not familiar with interfaces, Wikipedia has link:https://en.wikipedia.org/wiki/Interface_(computing)#In_object-oriented_languages[a good introduction].) TypeScript, the language in which the {aws} CDK is implemented, does provide interfaces, and constructs and other {aws} CDK objects often require an object that adheres to a particular interface, rather than inheriting from a particular class. So the {aws} CDK provides its own interface feature as part of the https://github.com/aws/jsii[JSII] layer. - -To indicate that a class implements a particular interface, you can use the `@jsii.implements` decorator: - -[source,python,subs="verbatim,attributes"] ----- -from aws_cdk import IAspect, IConstruct -import jsii - -@jsii.implements(IAspect) -class MyAspect(): - def visit(self, node: IConstruct) -> None: - print("Visited", node.node.path) ----- - -[#python-type-pitfalls] -=== Type pitfalls - -Python uses dynamic typing, where all variables may refer to a value of any type. Parameters and return values may be annotated with types, but these are "hints" and are not enforced. This means that in Python, it is easy to pass the incorrect type of value to a {aws} CDK construct. Instead of getting a type error during build, as you would from a statically-typed language, you may instead get a runtime error when the JSII layer (which translates between Python and the {aws} CDK's TypeScript core) is unable to deal with the unexpected type. - -In our experience, the type errors Python programmers make tend to fall into these categories. - -* Passing a single value where a construct expects a container (Python list or dictionary) or vice versa. -* Passing a value of a type associated with a layer 1 (`CfnXxxxxx`) construct to a L2 or L3 construct, or vice versa. - -The {aws} CDK Python modules do include type annotations, so you can use tools that support them to help with types. If you are not using an IDE that supports these, such as https://www.jetbrains.com/pycharm/[PyCharm], you might want to call the http://mypy-lang.org/[MyPy] type validator as a step in your build process. There are also runtime type checkers that can improve error messages for type-related errors. \ No newline at end of file diff --git a/v2/guide/work-with/work-with-cdk-typescript.adoc b/v2/guide/work-with/work-with-cdk-typescript.adoc deleted file mode 100644 index 68da2857..00000000 --- a/v2/guide/work-with/work-with-cdk-typescript.adoc +++ /dev/null @@ -1,331 +0,0 @@ -include::../attributes.txt[] - -// Attributes -[.topic] -[#work-with-cdk-typescript] -= Working with the {aws} CDK in TypeScript -:info_titleabbrev: In TypeScript - -[abstract] --- -TypeScript is a fully-supported client language for the {aws} CDK and is considered stable. --- - -// Content start - -TypeScript is a fully-supported client language for the {aws} Cloud Development Kit ({aws} CDK) and is considered stable. Working with the {aws} CDK in TypeScript uses familiar tools, including Microsoft's TypeScript compiler (`tsc`), https://nodejs.org/[Node.js] and the Node Package Manager (`npm`). You may also use link:https://yarnpkg.com/[Yarn] if you prefer, though the examples in this Guide use NPM. The modules comprising the {aws} Construct Library are distributed via the NPM repository, https://www.npmjs.com/[npmjs.org]. - -You can use any editor or IDE. Many {aws} CDK developers use https://code.visualstudio.com/[Visual Studio Code] (or its open-source equivalent https://vscodium.com/[VSCodium]), which has excellent support for TypeScript. - -[#typescript-prerequisites] -== Get started with TypeScript - -To work with the {aws} CDK, you must have an {aws} account and credentials and have installed Node.js and the {aws} CDK Toolkit. See xref:getting-started[Getting started with the {aws} CDK]. - -You also need TypeScript itself (version 3.8 or later). If you don't already have it, you can install it using `npm`. - -[source,bash,subs="verbatim,attributes"] ----- -$ npm install -g typescript ----- - -[NOTE] -==== - -If you get a permission error, and have administrator access on your system, try `sudo npm install -g typescript`. - -==== - -Keep TypeScript up to date with a regular `npm update -g typescript`. - -[NOTE] -==== - -Third-party language deprecation: language version is only supported until its EOL (End Of Life) shared by the vendor or community and is subject to change with prior notice. - -==== - -[#typescript-newproject] -== Creating a project - -You create a new {aws} CDK project by invoking `cdk init` in an empty directory. Use the `--language` option and specify `typescript`: - -[source,bash,subs="verbatim,attributes"] ----- -$ mkdir my-project -$ cd my-project -$ cdk init app --language typescript ----- - -Creating a project also installs the https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib-readme.html[`aws-cdk-lib`] module and its dependencies. - -`cdk init` uses the name of the project folder to name various elements of the project, including classes, subfolders, and files. Hyphens in the folder name are converted to underscores. However, the name should otherwise follow the form of a TypeScript identifier; for example, it should not start with a number or contain spaces. - -[#typescript-local] -== Using local `tsc` and `cdk` - -For the most part, this guide assumes you install TypeScript and the CDK Toolkit globally (`npm install -g typescript aws-cdk`), and the provided command examples (such as `cdk synth`) follow this assumption. This approach makes it easy to keep both components up to date, and since both take a strict approach to backward compatibility, there is generally little risk in always using the latest versions. - -Some teams prefer to specify all dependencies within each project, including tools like the TypeScript compiler and the CDK Toolkit. This practice lets you pin these components to specific versions and ensure that all developers on your team (and your CI/CD environment) use exactly those versions. This eliminates a possible source of change, helping to make builds and deployments more consistent and repeatable. - -The CDK includes dependencies for both TypeScript and the CDK Toolkit in the TypeScript project template's `package.json`, so if you want to use this approach, you don't need to make any changes to your project. All you need to do is use slightly different commands for building your app and for issuing `cdk` commands. - -[cols="1h,1,1"] -|=== -|Operation | Use global tools | Use local tools - -|Initialize project -|`cdk init --language typescript` -|`npx aws-cdk init --language typescript` - -|Build -|`tsc` -|`npm run build` - -|Run CDK Toolkit command -|`cdk ...` -|`npm run cdk ...` or `npx aws-cdk ...` -|=== - -`npx aws-cdk` runs the version of the CDK Toolkit installed locally in the current project, if one exists, falling back to the global installation, if any. If no global installation exists, `npx` downloads a temporary copy of the CDK Toolkit and runs that. You may specify an arbitrary version of the CDK Toolkit using the `@` syntax: `npx aws-cdk@2.0 --version` prints `2.0.0`. - -[TIP] -==== -Set up an alias so you can use the `cdk` command with a local CDK Toolkit installation. - -[role="tablist"] -macOS/Linux:: -+ -[source,bash,subs="verbatim,attributes"] ----- -$ alias cdk="npx aws-cdk" ----- - -Windows:: -+ -[source,none,subs="verbatim,attributes"] ----- -doskey cdk=npx aws-cdk $* ----- -==== - -[#typescript-managemodules] -== Managing {aws} Construct Library modules - -Use the Node Package Manager (`npm`) to install and update {aws} Construct Library modules for use by your apps, as well as other packages you need. (You may use `yarn` instead of `npm` if you prefer.) `npm` also installs the dependencies for those modules automatically. - -Most {aws} CDK constructs are in the main CDK package, named `aws-cdk-lib`, which is a default dependency in new projects created by `cdk init`. "Experimental" {aws} Construct Library modules, where higher-level constructs are still under development, are named like `@aws-cdk/<SERVICE-NAME>-alpha`. The service name has an _aws-_ prefix. If you're unsure of a module's name, https://www.npmjs.com/search?q=%40aws-cdk[search for it on NPM]. - -[NOTE] -==== - -The https://docs.aws.amazon.com/cdk/api/v2/docs/aws-construct-library.html[CDK API Reference] also shows the package names. - -==== - -For example, the command below installs the experimental module for {aws} CodeStar. - -[source,bash,subs="verbatim,attributes"] ----- -$ npm install @aws-cdk/aws-codestar-alpha ----- - -Some services' Construct Library support is in more than one namespace. For example, besides `aws-route53`, there are three additional Amazon Route 53 namespaces, `aws-route53-targets`, `aws-route53-patterns`, and `aws-route53resolver`. - -Your project's dependencies are maintained in `package.json`. You can edit this file to lock some or all of your dependencies to a specific version or to allow them to be updated to newer versions under certain criteria. To update your project's NPM dependencies to the latest permitted version according to the rules you specified in `package.json`: - -[source,bash,subs="verbatim,attributes"] ----- -$ npm update ----- - -In TypeScript, you import modules into your code under the same name you use to install them using NPM. We recommend the following practices when importing {aws} CDK classes and {aws} Construct Library modules in your applications. Following these guidelines will help make your code consistent with other {aws} CDK applications as well as easier to understand. - -* Use ES6-style `import` directives, not `require()`. -* Generally, import individual classes from `aws-cdk-lib`. -+ -[source,javascript,subs="verbatim,attributes"] ----- -import { App, Stack } from 'aws-cdk-lib'; ----- -* If you need many classes from `aws-cdk-lib`, you may use a namespace alias of `cdk` instead of importing the individual classes. Avoid doing both. -+ -[source,javascript,subs="verbatim,attributes"] ----- -import * as cdk from 'aws-cdk-lib'; ----- - -* Generally, import {aws} service constructs using short namespace aliases. -+ -[source,javascript,subs="verbatim,attributes"] ----- -import { aws_s3 as s3 } from 'aws-cdk-lib'; ----- - -[#work-with-cdk-typescript-dependencies] -== Managing dependencies in TypeScript - -In TypeScript CDK projects, dependencies are specified in the `package.json` file in the project's main directory. The core {aws} CDK modules are in a single `NPM` package called `aws-cdk-lib`. - -When you install a package using `npm install`, NPM records the package in `package.json` for you. - -If you prefer, you may use Yarn in place of NPM. However, the CDK does not support Yarn's plug-and-play mode, which is default mode in Yarn 2. Add the following to your project's `.yarnrc.yml` file to turn off this feature. - -[source,yaml,subs="verbatim,attributes"] ----- -nodeLinker: node-modules ----- - -[#work-with-cdk-typescript-dependencies-apps] -=== CDK applications - -The following is an example `package.json` file generated by the `cdk init --language typescript` command: - -[source,json,subs="verbatim,attributes"] ----- -{ - "name": "my-package", - "version": "0.1.0", - "bin": { - "my-package": "bin/my-package.js" - }, - "scripts": { - "build": "tsc", - "watch": "tsc -w", - "test": "jest", - "cdk": "cdk" - }, - "devDependencies": { - "@types/jest": "^26.0.10", - "@types/node": "10.17.27", - "jest": "^26.4.2", - "ts-jest": "^26.2.0", - "aws-cdk": "2.16.0", - "ts-node": "^9.0.0", - "typescript": "~3.9.7" - }, - "dependencies": { - "aws-cdk-lib": "2.16.0", - "constructs": "^10.0.0", - "source-map-support": "^0.5.16" - } -} ----- - -For deployable CDK apps, `aws-cdk-lib` must be specified in the `dependencies` section of `package.json`. You can use a caret (^) version number specifier to indicate that you will accept later versions than the one specified as long as they are within the same major version. - -For experimental constructs, specify exact versions for the alpha construct library modules, which have APIs that may change. Do not use ^ or ~ since later versions of these modules may bring API changes that can break your app. - -Specify versions of libraries and tools needed to test your app (for example, the `jest` testing framework) in the `devDependencies` section of `package.json`. Optionally, use ^ to specify that later compatible versions are acceptable. - -[#work-with-cdk-typescript-dependencies-libraries] -=== Third-party construct libraries - -If you're developing a construct library, specify its dependencies using a combination of the `peerDependencies` and `devDependencies` sections, as shown in the following example `package.json` file. - -[source,json,subs="verbatim,attributes"] ----- -{ - "name": "my-package", - "version": "0.0.1", - "peerDependencies": { - "aws-cdk-lib": "^2.14.0", - "@aws-cdk/aws-appsync-alpha": "2.10.0-alpha", - "constructs": "^10.0.0" - }, - "devDependencies": { - "aws-cdk-lib": "2.14.0", - "@aws-cdk/aws-appsync-alpha": "2.10.0-alpha", - "constructs": "10.0.0", - "jsii": "^1.50.0", - "aws-cdk": "^2.14.0" - } -} ----- - -In `peerDependencies`, use a caret (^) to specify the lowest version of `aws-cdk-lib` that your library works with. This maximizes the compatibility of your library with a range of CDK versions. Specify exact versions for alpha construct library modules, which have APIs that may change. Using `peerDependencies` makes sure that there is only one copy of all CDK libraries in the `node_modules` tree. - -In `devDependencies`, specify the tools and libraries you need for testing, optionally with ^ to indicate that later compatible versions are acceptable. Specify exactly (without ^ or ~) the lowest versions of `aws-cdk-lib` and other CDK packages that you advertise your library be compatible with. This practice makes sure that your tests run against those versions. This way, if you inadvertently use a feature found only in newer versions, your tests can catch it. - -[WARNING] -==== - -`peerDependencies` are installed automatically only by NPM 7 and later. If you are using NPM 6 or earlier, or if you are using Yarn, you must include the dependencies of your dependencies in `devDependencies`. Otherwise, they won't be installed, and you will receive a warning about unresolved peer dependencies. - -==== - -[#work-with-cdk-typescript-dependencies-install] -=== Installing and updating dependencies - -Run the following command to install your project's dependencies. - -==== -[role="tablist"] -NPM:: -+ -[source,none,subs="verbatim,attributes"] ----- -# Install the latest version of everything that matches the ranges in 'package.json' -npm install - -# Install the same exact dependency versions as recorded in 'package-lock.json' -npm ci ----- - -Yarn:: -+ -[source,bash,subs="verbatim,attributes"] ----- -# Install the latest version of everything that matches the ranges in 'package.json' -$ yarn upgrade - -# Install the same exact dependency versions as recorded in 'yarn.lock' -$ yarn install --frozen-lockfile ----- -==== - -To update the installed modules, the preceding `npm install` and `yarn upgrade` commands can be used. Either command updates the packages in `node_modules` to the latest versions that satisfy the rules in `package.json`. However, they do not update `package.json` itself, which you might want to do to set a new minimum version. If you host your package on GitHub, you can configure https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuring-dependabot-version-updates[Dependabot version updates] to automatically update `package.json`. Alternatively, use https://www.npmjs.com/package/npm-check-updates[npm-check-updates]. - -[IMPORTANT] -==== - -By design, when you install or update dependencies, NPM and Yarn choose the latest version of every package that satisfies the requirements specified in `package.json`. There is always a risk that these versions may be broken (either accidentally or intentionally). Test thoroughly after updating your project's dependencies. - -==== - -[#typescript-cdk-idioms] -== {aws} CDK idioms in TypeScript - -[#typescript-props] -=== Props - -All {aws} Construct Library classes are instantiated using three arguments: the _scope_ in which the construct is being defined (its parent in the construct tree), an _id_, and _props_. Argument _props_ is a bundle of key/value pairs that the construct uses to configure the {aws} resources it creates. Other classes and methods also use the "bundle of attributes" pattern for arguments. - -In TypeScript, the shape of `props` is defined using an interface that tells you the required and optional arguments and their types. Such an interface is defined for each kind of `props` argument, usually specific to a single construct or method. For example, the https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html[`Bucket`] construct (in the `aws-cdk-lib/aws-s3` module) specifies a `props` argument conforming to the https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.BucketProps.html[`BucketProps`] interface. - -If a property is itself an object, for example the https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.BucketProps.html#websiteredirect[`websiteRedirect`] property of `BucketProps`, that object will have its own interface to which its shape must conform, in this case https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.RedirectTarget.html[`RedirectTarget`]. - -If you are subclassing an {aws} Construct Library class (or overriding a method that takes a props-like argument), you can inherit from the existing interface to create a new one that specifies any new props your code requires. When calling the parent class or base method, generally you can pass the entire props argument you received, since any attributes provided in the object but not specified in the interface will be ignored. - -A future release of the {aws} CDK could coincidentally add a new property with a name you used for your own property. Passing the value you receive up the inheritance chain can then cause unexpected behavior. It's safer to pass a shallow copy of the props you received with your property removed or set to `undefined`. For example: - -[source,javascript,subs="verbatim,attributes"] ----- -super(scope, name, {...props, encryptionKeys: undefined}); ----- - -Alternatively, name your properties so that it is clear that they belong to your construct. This way, it is unlikely they will collide with properties in future {aws} CDK releases. If there are many of them, use a single appropriately-named object to hold them. - -[#typescript-missing-values] -=== Missing values - -Missing values in an object (such as props) have the value `undefined` in TypeScript. Version 3.7 of the language introduced operators that simplify working with these values, making it easier to specify defaults and "short-circuit" chaining when an undefined value is reached. For more information about these features, see the https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html[TypeScript 3.7 Release Notes], specifically the first two features, Optional Chaining and Nullish Coalescing. - -[#typescript-running] -== Build and run CDK apps - -Generally, you should be in the project's root directory when building and running your application. - -Node.js cannot run TypeScript directly; instead, your application is converted to JavaScript using the TypeScript compiler, `tsc`. The resulting JavaScript code is then executed. - -The {aws} CDK automatically does this whenever it needs to run your app. However, it can be useful to compile manually to check for errors and to run tests. To compile your TypeScript app manually, issue `npm run build`. You may also issue `npm run watch` to enter watch mode, in which the TypeScript compiler automatically rebuilds your app whenever you save changes to a source file. \ No newline at end of file diff --git a/v2/guide/work-with/work-with-cdk.adoc b/v2/guide/work-with/work-with-cdk.adoc deleted file mode 100644 index 9c5d77fd..00000000 --- a/v2/guide/work-with/work-with-cdk.adoc +++ /dev/null @@ -1,599 +0,0 @@ -include::../attributes.txt[] - -// Attributes -[.topic] -[#work-with] -= Work with the {aws} CDK library -:info_titleabbrev: Work with the CDK library -:keywords: {aws} CDK, IaC, Infrastructure as code, {aws} CloudFormation, {aws}, {aws} Cloud - -[abstract] --- -Import and use the {aws} Cloud Development Kit ({aws} CDK) library to define your {aws} Cloud infrastructure with a xref:languages[supported programming language]. --- - -// Content start - -Import and use the {aws} Cloud Development Kit ({aws} CDK) library to define your {aws} Cloud infrastructure with a xref:languages[supported programming language]. - -[#work-with-library] -== Import the {aws} CDK Library - -The xref:libraries[{aws} CDK Library] is often referred to by its TypeScript package name of `aws-cdk-lib`. The actual package name varies by language. The following is an example of how to install and import the CDK Library: - -==== -[role="tablist"] -TypeScript:: -+ -[cols="1,1"] -|=== -|*Install* -|`npm install aws-cdk-lib` - -|*Import* -|`import * as cdk from 'aws-cdk-lib';` -|=== - -JavaScript:: -+ -[cols="1,1"] -|=== -|*Install* -|`npm install aws-cdk-lib` - -|*Import* -|`const cdk = require('aws-cdk-lib');` -|=== - -Python:: -+ -[cols="1,1"] -|=== -|*Install* -|`python -m pip install aws-cdk-lib` - -|*Import* -|`import aws_cdk as cdk` -|=== - -Java:: -+ -[cols="1,1"] -|=== -|*In `pom.xml`, add* -|`Group software.amazon.awscdk; artifact aws-cdk-lib` - -|*Import* -|`import software.amazon.awscdk.App;` -|=== - -C#:: -+ -[cols="1,1"] -|=== -|*Install* -|`dotnet add package Amazon.CDK.Lib` - -|*Import* -|`using Amazon.CDK;` -|=== - -Go:: -+ -[cols="1,1"] -|=== -|*Install* -|`go get github.com/aws/aws-cdk-go/awscdk/v2` - -|*Import* -a|[source,go,subs="verbatim,attributes"] ----- -import ( - "github.com/aws/aws-cdk-go/awscdk/v2" -) ----- -|=== -==== - -The `construct` base class and supporting code is in the `constructs` library. Experimental constructs, where the API is still undergoing refinement, are distributed as separate modules. - -[#work-with-library-reference] -== Using the {aws} CDK API Reference - -Use the xref:libraries-reference[{aws} CDK API reference] as you develop with the {aws} CDK. - -Each module's reference material is broken into the following sections. - -* _Overview_: Introductory material you'll need to know to work with the service in the {aws} CDK, including concepts and examples. -* _Constructs_: Library classes that represent one or more concrete {aws} resources. These are the "curated" (L2) resources or patterns (L3 resources) that provide a high-level interface with sane defaults. -* _Classes_: Non-construct classes that provide functionality used by constructs in the module. -* _Structs_: Data structures (attribute bundles) that define the structure of composite values such as properties (the `props` argument of constructs) and options. -* _Interfaces_: Interfaces, whose names all begin with "I", define the absolute minimum functionality for the corresponding construct or other class. The CDK uses construct interfaces to represent {aws} resources that are defined outside your {aws} CDK app and referenced by methods such as `Bucket.fromBucketArn()`. -* _Enums_: Collections of named values for use in specifying certain construct parameters. Using an enumerated value allows the CDK to check these values for validity during synthesis. -* _CloudFormation Resources_: These L1 constructs, whose names begin with "Cfn", represent exactly the resources defined in the CloudFormation specification. They are automatically generated from that specification with each CDK release. Each L2 or L3 construct encapsulates one or more CloudFormation resources. -* _CloudFormation Property Types_: The collection of named values that define the properties for each CloudFormation Resource. - -[#work-with-library-interfaces] -== Interfaces compared with construct classes - -The {aws} CDK uses interfaces in a specific way that may not be obvious even if you are familiar with interfaces as a programming concept. - -The {aws} CDK supports using resources defined outside CDK applications using methods such as `Bucket.fromBucketArn()`. External resources cannot be modified and may not have all the functionality available with resources defined in your CDK app using e.g. the `Bucket` class. Interfaces, then, represent the bare minimum functionality available in the CDK for a given {aws} resource type, _including external resources_. - -When instantiating resources in your CDK app, then, you should always use concrete classes such as `Bucket`. When specifying the type of an argument you are accepting in one of your own constructs, use the interface type such as `IBucket` if you are prepared to deal with external resources (that is, you won't need to change them). If you require a CDK-defined construct, specify the most general type you can use. - -Some interfaces are minimum versions of properties or options bundles associated with specific classes, rather than constructs. Such interfaces can be useful when subclassing to accept arguments that you'll pass on to your parent class. If you require one or more additional properties, you'll want to implement or derive from this interface, or from a more specific type. - -[NOTE] -==== - -Some programming languages supported by the {aws} CDK don't have an interface feature. In these languages, interfaces are just ordinary classes. You can identify them by their names, which follow the pattern of an initial "I" followed by the name of some other construct (e.g. `IBucket`). The same rules apply. - -==== - -[#work-with-cdk-dependencies] -== Managing dependencies - -Dependencies for your {aws} CDK app or library are managed using package management tools. These tools are commonly used with the programming languages. - -Typically, the {aws} CDK supports the language's standard or official package management tool if there is one. Otherwise, the {aws} CDK will support the language's most popular or widely supported one. You may also be able to use other tools, especially if they work with the supported tools. However, official support for other tools is limited. - -The {aws} CDK supports the following package managers: - -[cols="1,1", options="header"] -|=== -| Language -| Supported package management tool - -|TypeScript/JavaScript -|NPM (Node Package Manager) or Yarn - -|Python -|PIP (Package Installer for Python) - -|Java -|Maven - -|C# -|NuGet - -|Go -|Go modules -|=== - -When you create a new project using the {aws} CDK CLI `cdk init` command, dependencies for the CDK core libraries and stable constructs are automatically specified. - -For more information on managing dependencies for supported programming languages, see the following: - -* xref:work-with-cdk-typescript-dependencies[Managing dependencies in TypeScript]. -* xref:work-with-cdk-javascript-dependencies[Managing dependencies in JavaScript]. -* xref:work-with-cdk-python-dependencies[Managing dependencies in Python]. -* xref:work-with-cdk-java-dependencies[Managing dependencies in Java]. -* xref:work-with-cdk-csharp-dependencies[Managing dependencies in C#]. -* xref:work-with-cdk-go-dependencies[Managing dependencies in Go]. - -[#work-with-cdk-compare] -== Comparing {aws} CDK in TypeScript with other languages - -TypeScript was the first language supported for developing {aws} CDK applications. Therefore, a substantial amount of example CDK code is written in TypeScript. If you are developing in another language, it might be useful to compare how {aws} CDK code is implemented in TypeScript compared to your language of choice. This can help you use the examples throughout documentation. - -[#work-with-cdk-compare-import] -== Importing a module - -==== -[role="tablist"] -TypeScript/JavaScript:: -TypeScript supports importing either an entire namespace, or individual objects from a namespace. Each namespace includes constructs and other classes for use with a given {aws} service. -+ -[source,javascript,subs="verbatim,attributes"] ----- -// Import main CDK library as cdk -import * as cdk from 'aws-cdk-lib'; // ES6 import preferred in TS -const cdk = require('aws-cdk-lib'); // Node.js require() preferred in JS - -// Import specific core CDK classes -import { Stack, App } from 'aws-cdk-lib'; -const { Stack, App } = require('aws-cdk-lib'); - -// Import {aws} S3 namespace as s3 into current namespace -import { aws_s3 as s3 } from 'aws-cdk-lib'; // TypeScript -const s3 = require('aws-cdk-lib/aws-s3'); // JavaScript - -// Having imported cdk already as above, this is also valid -const s3 = cdk.aws_s3; - -// Now use s3 to access the S3 types -const bucket = s3.Bucket(...); - -// Selective import of s3.Bucket -import { Bucket } from 'aws-cdk-lib/aws-s3'; // TypeScript -const { Bucket } = require('aws-cdk-lib/aws-s3'); // JavaScript - -// Now use Bucket to instantiate an S3 bucket -const bucket = Bucket(...); ----- - -Python:: -Like TypeScript, Python supports namespaced module imports and selective imports. Namespaces in Python look like **aws_cdk.**__xxx__, where _xxx_ represents an {aws} service name, such as *s3* for Amazon S3. (Amazon S3 is used in these examples). -+ -[source,python,subs="verbatim,attributes"] ----- -# Import main CDK library as cdk -import aws_cdk as cdk - -# Selective import of specific core classes -from aws_cdk import Stack, App - -# Import entire module as s3 into current namespace -import aws_cdk.aws_s3 as s3 - -# s3 can now be used to access classes it contains -bucket = s3.Bucket(...) - -# Selective import of s3.Bucket into current namespace -from aws_cdk.s3 import Bucket - -# Bucket can now be used to instantiate a bucket -bucket = Bucket(...) ----- - -Java:: -Java's imports work differently from TypeScript's. Each import statement imports either a single class name from a given package, or all classes defined in that package (using `\*`). Classes may be accessed using either the class name by itself if it has been imported, or the _qualified_ class name including its package. -+ -Libraries are named like `software.amazon.awscdk.services.xxx` for the {aws} Construct Library (the main library is `software.amazon.awscdk`). The Maven group ID for {aws} CDK packages is `software.amazon.awscdk`. -+ -[source,java,subs="verbatim,attributes"] ----- -// Make certain core classes available -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.App; - -// Make all Amazon S3 construct library classes available -import software.amazon.awscdk.services.s3.*; - -// Make only Bucket and EventType classes available -import software.amazon.awscdk.services.s3.Bucket; -import software.amazon.awscdk.services.s3.EventType; - -// An imported class may now be accessed using the simple class name (assuming that name -// does not conflict with another class) -Bucket bucket = Bucket.Builder.create(...).build(); - -// We can always use the qualified name of a class (including its package) even without an -// import directive -software.amazon.awscdk.services.s3.Bucket bucket = - software.amazon.awscdk.services.s3.Bucket.Builder.create(...) - .build(); - -// Java 10 or later can use var keyword to avoid typing the type twice -var bucket = - software.amazon.awscdk.services.s3.Bucket.Builder.create(...) - .build(); ----- - -C#:: -In C#, you import types with the `using` directive. There are two styles. One gives you access to all the types in the specified namespace by using their plain names. With the other, you can refer to the namespace itself by using an alias. -+ -Packages are named like `Amazon.CDK.{aws}.xxx` for {aws} Construct Library packages. (The core module is `Amazon.CDK`.) -+ -[source,csharp,subs="verbatim,attributes"] ----- -// Make CDK base classes available under cdk -using cdk = Amazon.CDK; - -// Make all Amazon S3 construct library classes available -using Amazon.CDK.{aws}.S3; - -// Now we can access any S3 type using its name -var bucket = new Bucket(...); - -// Import the S3 namespace under an alias -using s3 = Amazon.CDK.{aws}.S3; - -// Now we can access an S3 type through the namespace alias -var bucket = new s3.Bucket(...); - -// We can always use the qualified name of a type (including its namespace) even without a -// using directive -var bucket = new Amazon.CDK.{aws}.S3.Bucket(...); ----- - -Go:: -Each {aws} Construct Library module is provided as a Go package. -+ -[source,go,subs="verbatim,attributes"] ----- -import ( - "github.com/aws/aws-cdk-go/awscdk/v2" // CDK core package - "github.com/aws/aws-cdk-go/awscdk/v2/awss3" // {aws} S3 construct library module -) - -// now instantiate a bucket -bucket := awss3.NewBucket(...) - -// use aliases for brevity/clarity -import ( - cdk "github.com/aws/aws-cdk-go/awscdk/v2" // CDK core package - s3 "github.com/aws/aws-cdk-go/awscdk/v2/awss3" // {aws} S3 construct library module -) - -bucket := s3.NewBucket(...) ----- -==== - -[#work-with-cdk-compare-class] -== Instantiating a construct - -{aws} CDK construct classes have the same name in all supported languages. Most languages use the `new` keyword to instantiate a class (Python and Go do not). Also, in most languages, the keyword `this` refers to the current instance. (Python uses `self` by convention.) You should pass a reference to the current instance as the `scope` parameter to every construct you create. - -The third argument to an {aws} CDK construct is `props`, an object containing attributes needed to build the construct. This argument may be optional, but when it is required, the supported languages handle it in idiomatic ways. The names of the attributes are also adapted to the language's standard naming patterns. - -==== -[role="tablist"] -TypeScript/JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -// Instantiate default Bucket -const bucket = new s3.Bucket(this, 'amzn-s3-demo-bucket'); - -// Instantiate Bucket with bucketName and versioned properties -const bucket = new s3.Bucket(this, 'amzn-s3-demo-bucket', { - bucketName: 'amzn-s3-demo-bucket', - versioned: true, -}); - -// Instantiate Bucket with websiteRedirect, which has its own sub-properties -const bucket = new s3.Bucket(this, 'amzn-s3-demo-bucket', { - websiteRedirect: {host: 'aws.amazon.com'}}); ----- - -Python:: -Python doesn't use a `new` keyword when instantiating a class. The properties argument is represented using keyword arguments, and the arguments are named using `snake_case`. -+ -If a props value is itself a bundle of attributes, it is represented by a class named after the property, which accepts keyword arguments for the subproperties. -+ -In Python, the current instance is passed to methods as the first argument, which is named `self` by convention. -+ -[source,python,subs="verbatim,attributes"] ----- -# Instantiate default Bucket -bucket = s3.Bucket(self, "amzn-s3-demo-bucket") - -# Instantiate Bucket with bucket_name and versioned properties -bucket = s3.Bucket(self, "amzn-s3-demo-bucket", bucket_name="amzn-s3-demo-bucket", versioned=true) - -# Instantiate Bucket with website_redirect, which has its own sub-properties -bucket = s3.Bucket(self, "amzn-s3-demo-bucket", website_redirect=s3.WebsiteRedirect( - host_name="aws.amazon.com")) ----- - -Java:: -In Java, the props argument is represented by a class named `XxxxProps` (for example, `BucketProps` for the `Bucket` construct's props). You build the props argument using a builder pattern. -+ -Each `XxxxProps` class has a builder. There is also a convenient builder for each construct that builds the props and the construct in one step, as shown in the following example. -+ -Props are named the same as in TypeScript, using `camelCase`. -+ -[source,java,subs="verbatim,attributes"] ----- -// Instantiate default Bucket -Bucket bucket = Bucket(self, "amzn-s3-demo-bucket"); - -// Instantiate Bucket with bucketName and versioned properties -Bucket bucket = Bucket.Builder.create(self, "amzn-s3-demo-bucket") - .bucketName("amzn-s3-demo-bucket").versioned(true) - .build(); - -# Instantiate Bucket with websiteRedirect, which has its own sub-properties -Bucket bucket = Bucket.Builder.create(self, "amzn-s3-demo-bucket") - .websiteRedirect(new websiteRedirect.Builder() - .hostName("aws.amazon.com").build()) - .build(); ----- - -C#:: -In C#, props are specified using an object initializer to a class named `XxxxProps` (for example, `BucketProps` for the `Bucket` construct's props). -+ -Props are named similarly to TypeScript, except using `PascalCase`. -+ -It is convenient to use the `var` keyword when instantiating a construct, so you don't need to type the class name twice. However, your local code style guide may vary. -+ -[source,csharp,subs="verbatim,attributes"] ----- -// Instantiate default Bucket -var bucket = Bucket(self, "amzn-s3-demo-bucket"); - -// Instantiate Bucket with BucketName and Versioned properties -var bucket = Bucket(self, "amzn-s3-demo-bucket", new BucketProps { - BucketName = "amzn-s3-demo-bucket", - Versioned = true}); - -// Instantiate Bucket with WebsiteRedirect, which has its own sub-properties -var bucket = Bucket(self, "amzn-s3-demo-bucket", new BucketProps { - WebsiteRedirect = new WebsiteRedirect { - HostName = "aws.amazon.com" - }}); ----- - -Go:: -To create a construct in Go, call the function `NewXxxxxx` where `Xxxxxxx` is the name of the construct. The constructs' properties are defined as a struct. -+ -In Go, all construct parameters are pointers, including values like numbers, Booleans, and strings. Use the convenience functions like `jsii.String` to create these pointers. -+ -[source,go,subs="verbatim,attributes"] ----- - // Instantiate default Bucket - bucket := awss3.NewBucket(stack, jsii.String("amzn-s3-demo-bucket"), nil) - - // Instantiate Bucket with BucketName and Versioned properties - bucket1 := awss3.NewBucket(stack, jsii.String("amzn-s3-demo-bucket"), &awss3.BucketProps{ - BucketName: jsii.String("amzn-s3-demo-bucket"), - Versioned: jsii.Bool(true), - }) - - // Instantiate Bucket with WebsiteRedirect, which has its own sub-properties - bucket2 := awss3.NewBucket(stack, jsii.String("amzn-s3-demo-bucket"), &awss3.BucketProps{ - WebsiteRedirect: &awss3.RedirectTarget{ - HostName: jsii.String("aws.amazon.com"), - }}) ----- -==== - -[#work-with-cdk-compare-members] -== Accessing members - -It is common to refer to attributes or properties of constructs and other {aws} CDK classes and use these values as, for example, inputs to build other constructs. The naming differences described previously for methods apply here also. Furthermore, in Java, it is not possible to access members directly. Instead, a getter method is provided. - -==== -[role="tablist"] -TypeScript/JavaScript:: -Names are `camelCase`. -+ -[source,javascript,subs="verbatim,attributes"] ----- -bucket.bucketArn ----- - -Python:: -Names are `snake_case`. -+ -[source,python,subs="verbatim,attributes"] ----- -bucket.bucket_arn ----- - -Java:: -A getter method is provided for each property; these names are ``camelCase``. -+ -[source,java,subs="verbatim,attributes"] ----- -bucket.getBucketArn() ----- - -C#:: -Names are `PascalCase`. -+ -[source,javascript,subs="verbatim,attributes"] ----- -bucket.BucketArn ----- - -Go:: -Names are `PascalCase`. -+ -[source,javascript,subs="verbatim,attributes"] ----- -bucket.BucketArn ----- -==== - -[#work-with-cdk-compare-enums] -== Enum constants - -Enum constants are scoped to a class, and have uppercase names with underscores in all languages (sometimes referred to as `SCREAMING_SNAKE_CASE`). Since class names also use the same casing in all supported languages except Go, qualified enum names are also the same in these languages. - -[source,javascript,subs="verbatim,attributes"] ----- -s3.BucketEncryption.KMS_MANAGED ----- - -In Go, enum constants are attributes of the module namespace and are written as follows. - -[source,javascript,subs="verbatim,attributes"] ----- -awss3.BucketEncryption_KMS_MANAGED ----- - -[#work-with-cdk-compare-object] -== Object interfaces - -The {aws} CDK uses TypeScript object interfaces to indicate that a class implements an expected set of methods and properties. You can recognize an object interface because its name starts with `I`. A concrete class indicates the interfaces that it implements by using the `implements` keyword. - -==== -[role="tablist"] -TypeScript/JavaScript:: -+ -NOTE: JavaScript doesn't have an interface feature. You can ignore the `implements` keyword and the class names following it. -+ - -[source,javascript,subs="verbatim,attributes"] ----- -import { IAspect, IConstruct } from 'aws-cdk-lib'; - -class MyAspect implements IAspect { - public visit(node: IConstruct) { - console.log('Visited', node.node.path); - } -} ----- - -Python:: -Python doesn't have an interface feature. However, for the {aws} CDK you can indicate interface implementation by decorating your class with `@jsii.implements(interface)`. -+ -[source,python,subs="verbatim,attributes"] ----- -from aws_cdk import IAspect, IConstruct -import jsii - -@jsii.implements(IAspect) -class MyAspect(): - def visit(self, node: IConstruct) -> None: - print("Visited", node.node.path) ----- - -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- -import software.amazon.awscdk.IAspect; -import software.amazon.awscdk.IConstruct; - -public class MyAspect implements IAspect { - public void visit(IConstruct node) { - System.out.format("Visited %s", node.getNode().getPath()); - } -} ----- - -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- -using Amazon.CDK; - -public class MyAspect : IAspect -{ - public void Visit(IConstruct node) - { - System.Console.WriteLine($"Visited ${node.Node.Path}"); - } -} ----- - -Go:: -Go structs do not need to explicitly declare which interfaces they implement. The Go compiler determines implementation based on the methods and properties available on the structure. For example, in the following code, `MyAspect` implements the `IAspect` interface because it provides a `Visit` method that takes a construct. -+ -[source,go,subs="verbatim,attributes"] ----- -type MyAspect struct { -} - -func (a MyAspect) Visit(node constructs.IConstruct) { - fmt.Println("Visited", *node.Node().Path()) -} ----- -==== - - -include::work-with-cdk-typescript.adoc[leveloffset=+1] - -include::work-with-cdk-javascript.adoc[leveloffset=+1] - -include::work-with-cdk-python.adoc[leveloffset=+1] - -include::work-with-cdk-java.adoc[leveloffset=+1] - -include::work-with-cdk-csharp.adoc[leveloffset=+1] - -include::work-with-cdk-go.adoc[leveloffset=+1] \ No newline at end of file diff --git a/v2/hello_world.md b/v2/hello_world.md new file mode 100644 index 00000000..3ac8ecaa --- /dev/null +++ b/v2/hello_world.md @@ -0,0 +1,618 @@ +# Your first AWS CDK app<a name="hello_world"></a> + +You've read [Getting started with the AWS CDK](getting_started.md) and set up your development environment for writing AWS CDK apps? Great\! Now let's see how it feels to work with the AWS CDK by building the simplest possible AWS CDK app\. + +In this tutorial, you'll learn about the following: ++ The structure of an AWS CDK project ++ How to use the AWS Construct Library to define AWS resources using code ++ How to synthesize, diff, and deploy collections of resources using the AWS CDK Toolkit command line tool + +The standard AWS CDK development workflow is similar to what you're already familiar with as a developer, with only a few extra steps\. + +1. Create the app from a template provided by the AWS CDK\. + +1. Add code to the app to create resources within stacks\. + +1. \(Optional\) Build the app\. \(The AWS CDK Toolkit does this for you if you forget\.\) + +1. Synthesize one or more stacks in the app to create an AWS CloudFormation template\. + +1. Deploy one or more stacks to your AWS account\. + +The build step catches syntax and type errors\. The synthesis step catches logical errors in defining your AWS resources\. The deployment may find permission issues\. As always, you go back to the code, find the problem, fix it, then build, synthesize, and deploy again\. + +**Tip** +Don't forget to keep your AWS CDK code under version control\! + +This tutorial walks you through creating and deploying a simple AWS CDK app, from initializing the project to deploying the resulting AWS CloudFormation template\. The app contains one stack, which contains one resource, an Amazon S3 bucket\. + +We'll also show what happens when you make a change and re\-deploy, and how to clean up when you're done\. + +## Create the app<a name="hello_world_tutorial_create_app"></a> + +Each AWS CDK app should be in its own directory, with its own local module dependencies\. Create a new directory for your app\. Starting in your home directory, or another directory if you prefer, issue the following commands\. + +**Important** +Be sure to name your project directory `hello-cdk`, *exactly as shown here\.* The AWS CDK project template uses the directory name to name things in the generated code\. If you use a different name, the code in this tutorial won't work\. + +``` +mkdir hello-cdk +cd hello-cdk +``` + +Now initialize the app by using the cdk init command\. Specify the desired template \("app"\) and programming language as shown in the following examples: + +------ +#### [ TypeScript ] + +``` +cdk init app --language typescript +``` + +------ +#### [ JavaScript ] + +``` +cdk init app --language javascript +``` + +------ +#### [ Python ] + +``` +cdk init app --language python +``` + +After the app has been created, also enter the following two commands\. These activate the app's Python virtual environment and install the AWS CDK core dependencies\. + +``` +source .venv/bin/activate +python -m pip install -r requirements.txt +``` + +------ +#### [ Java ] + +``` +cdk init app --language java +``` + +If you are using an IDE, you can now open or import the project\. In Eclipse, for example, choose **File** > **Import** > **Maven** > **Existing Maven Projects**\. Make sure that the project settings are set to use Java 8 \(1\.8\)\. + +------ +#### [ C\# ] + +``` +cdk init app --language csharp +``` + +If you are using Visual Studio, open the solution file in the `src` directory\. + +------ +#### [ Go ] + +``` +cdk init app --language go +``` + +After the app has been created, also enter the following command to install the AWS Construct Library modules that the app requires\. + +``` +go get +``` + +------ + +**Tip** +If you don't specify a template, the default is "app," which is the one we wanted anyway\. Technically, you can omit it and save four keystrokes\. + +The cdk init command creates a number of files and folders inside the `hello-cdk` directory to help you organize the source code for your AWS CDK app\. Take a moment to explore\. The structure of a basic app is all there; you'll fill in the details in this tutorial\. + +If you have Git installed, each project you create using cdk init is also initialized as a Git repository\. We'll ignore that for now, but it's there when you need it\. + +## Build the app<a name="hello_world_tutorial_build"></a> + +In most programming environments, after changing your code, you build \(compile\) it\. This isn't strictly necessary with the AWS CDK—the Toolkit does it for you so that you can't forget\. But you can still build manually whenever you want to catch syntax and type errors\. For reference, here's how\. + +------ +#### [ TypeScript ] + +``` +npm run build +``` + +------ +#### [ JavaScript ] + +No build step is necessary\. + +------ +#### [ Python ] + +No build step is necessary\. + +------ +#### [ Java ] + +``` +mvn compile -q +``` + +Or press Control\-B in Eclipse \(other Java IDEs may vary\) + +------ +#### [ C\# ] + +``` +dotnet build src +``` + +Or press F6 in Visual Studio + +------ +#### [ Go ] + +``` +go build +``` + +------ + +## List the stacks in the app<a name="hello_world_tutorial_list_stacks"></a> + +To verify that everything is working correctly, list the stacks in your app\. + +``` +cdk ls +``` + +If you don't see `HelloCdkStack`, make sure you named your app's directory `hello-cdk`\. If you didn't, go back to [Create the app](#hello_world_tutorial_create_app) and try again\. + +## Add an Amazon S3 bucket<a name="hello_world_tutorial_add_bucket"></a> + +At this point, your app doesn't do anything because the stack it contains doesn't define any resources\. Let's add an Amazon S3 bucket\. + +The CDK's Amazon S3 support is part of its main library, `aws-cdk-lib`, so we don't need to install another library\. We can define an Amazon S3 bucket in the stack using the [Bucket](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html) construct\. + +------ +#### [ TypeScript ] + +In `lib/hello-cdk-stack.ts`: + +``` +import * as cdk from 'aws-cdk-lib'; +import { aws_s3 as s3 } from 'aws-cdk-lib'; + +export class HelloCdkStack extends cdk.Stack { + constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { + super(scope, id, props); + + new s3.Bucket(this, 'MyFirstBucket', { + versioned: true + }); + } +} +``` + +------ +#### [ JavaScript ] + +In `lib/hello-cdk-stack.js`: + +``` +const cdk = require('aws-cdk-lib'); +const s3 = require('aws-cdk-lib/aws-s3'); + +class HelloCdkStack extends cdk.Stack { + constructor(scope, id, props) { + super(scope, id, props); + + new s3.Bucket(this, 'MyFirstBucket', { + versioned: true + }); + } +} + +module.exports = { HelloCdkStack } +``` + +------ +#### [ Python ] + +In `hello_cdk/hello_cdk_stack.py`: + +``` +import aws_cdk as cdk +import aws_cdk.aws_s3 as s3 + +class HelloCdkStack(cdk.Stack): + + def __init__(self, scope: cdk.App, construct_id: str, **kwargs) -> None: + super().__init__(scope, construct_id, **kwargs) + + bucket = s3.Bucket(self, "MyFirstBucket", versioned=True) +``` + +------ +#### [ Java ] + +In `src/main/java/com/myorg/HelloCdkStack.java`: + +``` +package com.myorg; + +import software.amazon.awscdk.*; +import software.amazon.awscdk.services.s3.Bucket; + +public class HelloCdkStack extends Stack { + public HelloCdkStack(final App scope, final String id) { + this(scope, id, null); + } + + public HelloCdkStack(final App scope, final String id, final StackProps props) { + super(scope, id, props); + + Bucket.Builder.create(this, "MyFirstBucket") + .versioned(true).build(); + } +} +``` + +------ +#### [ C\# ] + +In `src/HelloCdk/HelloCdkStack.cs`: + +``` +using Amazon.CDK; +using Amazon.CDK.AWS.S3; + +namespace HelloCdk +{ + public class HelloCdkStack : Stack + { + public HelloCdkStack(App scope, string id, IStackProps props=null) : base(scope, id, props) + { + new Bucket(this, "MyFirstBucket", new BucketProps + { + Versioned = true + }); + } + } +} +``` + +------ +#### [ Go ] + +In `hello-cdk.go`: + +``` +package main + +import ( + "github.com/aws/aws-cdk-go/awscdk/v2" + "github.com/aws/aws-cdk-go/awscdk/v2/awss3" + "github.com/aws/constructs-go/constructs/v10" + "github.com/aws/jsii-runtime-go" +) + +type HelloCdkStackProps struct { + awscdk.StackProps +} + +func NewHelloCdkStack(scope constructs.Construct, id string, props *HelloCdkStackProps) awscdk.Stack { + var sprops awscdk.StackProps + if props != nil { + sprops = props.StackProps + } + stack := awscdk.NewStack(scope, &id, &sprops) + + awss3.NewBucket(stack, jsii.String("MyFirstBucket"), &awss3.BucketProps{ + Versioned: jsii.Bool(true), + }) + + return stack +} + +func main() { + defer jsii.Close() + + app := awscdk.NewApp(nil) + + NewHelloCdkStack(app, "HelloCdkStack", &HelloCdkStackProps{ + awscdk.StackProps{ + Env: env(), + }, + }) + + app.Synth(nil) +} + +func env() *awscdk.Environment { + return nil +} +``` + +------ + +`Bucket` is the first construct that we've seen, so let's take a closer look\. Like all constructs, the `Bucket` class takes three parameters\. ++ **scope:** Tells the bucket that the stack is its parent: it is defined within the scope of the stack\. You can define constructs inside of constructs, creating a hierarchy \(tree\)\. Here, and in most cases, the scope is `this` \(`self` in Python\), meaning the construct that contains the bucket: the stack\. ++ **Id:** The logical ID of the Bucket within your AWS CDK app\. This \(plus a hash based on the bucket's location within the stack\) uniquely identifies the bucket across deployments\. This way, the AWS CDK can update it if you change how it's defined in your app\. Here, it's "MyFirstBucket\." Buckets can also have a name, which is separate from this ID \(it's the `bucketName` property\)\. ++ **props:** A bundle of values that define properties of the bucket\. Here we've defined only one property: `versioned`, which enables versioning for the files in the bucket\. + +All constructs take these same three arguments, so it's easy to stay oriented as you learn about new ones\. And as you might expect, you can subclass any construct to extend it to suit your needs, or if you want to change its defaults\. + +**Tip** +If a construct's props are all optional, you can omit the `props` parameter entirely\. + +Props are represented differently in the languages supported by the AWS CDK\. ++ In TypeScript and JavaScript, `props` is a single argument and you pass in an object containing the desired properties\. ++ In Python, props are passed as keyword arguments\. ++ In Java, a Builder is provided to pass the props\. There are two: one for `BucketProps`, and a second for `Bucket` to let you build the construct and its props object in one step\. This code uses the latter\. ++ In C\#, you instantiate a `BucketProps` object using an object initializer and pass it as the third parameter\. + +## Synthesize an AWS CloudFormation template<a name="hello_world_tutorial_synth"></a> + +Synthesize an AWS CloudFormation template for the app, as follows\. + +``` +cdk synth +``` + +If your app contained more than one stack, you'd need to specify which stack or stacks to synthesize\. But since it only contains one, the CDK Toolkit knows you must mean that one\. + +**Tip** +If you received an error like `--app is required...`, it's probably because you are running the command from a subdirectory\. Navigate to the main app directory and try again\. + +The `cdk synth` command executes your app, which causes the resources defined in it to be translated into an AWS CloudFormation template\. The displayed output of `cdk synth` is a YAML\-format template\. Following, you can see the beginning of our app's output\. The template is also saved in the `cdk.out` directory in JSON format\. + +``` +Resources: + MyFirstBucketB8884501: + Type: AWS::S3::Bucket + Properties: + VersioningConfiguration: + Status: Enabled + UpdateReplacePolicy: Retain + DeletionPolicy: Retain + Metadata:... +``` + +Even if you aren't familiar with AWS CloudFormation, you can find the bucket definition and see how the `versioned` property was translated\. + +**Note** +Every generated template contains a `AWS::CDK::Metadata` resource by default\. \(We haven't shown it here\.\) The AWS CDK team uses this metadata to gain insight into how the AWS CDK is used, so that we can continue to improve it\. For details, including how to opt out of version reporting, see [Version reporting](cli.md#version_reporting)\. + +The `cdk synth` generates a perfectly valid AWS CloudFormation template\. You could take it and deploy it using the AWS CloudFormation console or another tool\. But the AWS CDK Toolkit can also do that\. + +## Deploying the stack<a name="hello_world_tutorial_deploy"></a> + +To deploy the stack using AWS CloudFormation, issue: + +``` +cdk deploy +``` + +As with `cdk synth`, you don't need to specify the name of the stack since there's only one in the app\. + +It is optional \(though good practice\) to synthesize before deploying\. The AWS CDK synthesizes your stack before each deployment\. + +If your code has security implications, you'll see a summary of these and need to confirm them before deployment proceeds\. This isn't the case in our stack\. + +`cdk deploy` displays progress information as your stack is deployed\. When it's done, the command prompt reappears\. You can go to the [AWS CloudFormation console](https://console.aws.amazon.com/cloudformation/home) and see that it now lists `HelloCdkStack`\. You'll also find `MyFirstBucket` in the Amazon S3 console\. + +You've deployed your first stack using the AWS CDK—congratulations\! But that's not all there is to the AWS CDK\. + +## Modifying the app<a name="hello_world_tutorial_modify"></a> + +The AWS CDK can update your deployed resources after you modify your app\. Let's change the bucket so it can be automatically deleted when deleting the stack\. This involves changing the bucket's `RemovalPolicy`\. Also, use the `autoDeleteObjects` property to ask the AWS CDK to delete the objects from the bucket before destroying it\. \(AWS CloudFormation doesn't delete S3 buckets that contain any objects\.\) + +------ +#### [ TypeScript ] + +Update `lib/hello-cdk-stack.ts`\. + +``` +new s3.Bucket(this, 'MyFirstBucket', { + versioned: true, + removalPolicy: cdk.RemovalPolicy.DESTROY, + autoDeleteObjects: true +}); +``` + +------ +#### [ JavaScript ] + +Update `lib/hello-cdk-stack.js`\. + +``` +new s3.Bucket(this, 'MyFirstBucket', { + versioned: true, + removalPolicy: cdk.RemovalPolicy.DESTROY, + autoDeleteObjects: true +}); +``` + +------ +#### [ Python ] + +Update `hello_cdk/hello_cdk_stack.py`\. + +``` +bucket = s3.Bucket(self, "MyFirstBucket", + versioned=True, + removal_policy=cdk.RemovalPolicy.DESTROY, + auto_delete_objects=True) +``` + +------ +#### [ Java ] + +Update `src/main/java/com/myorg/HelloCdkStack.java`\. + +``` +Bucket.Builder.create(this, "MyFirstBucket") + .versioned(true) + .removalPolicy(RemovalPolicy.DESTROY) + .autoDeleteObjects(true) + .build(); +``` + +------ +#### [ C\# ] + +Update `src/HelloCdk/HelloCdkStack.cs`\. + +``` +new Bucket(this, "MyFirstBucket", new BucketProps +{ + Versioned = true, + RemovalPolicy = RemovalPolicy.DESTROY, + AutoDeleteObjects = true +}); +``` + +------ +#### [ Go ] + +Update `hello-cdk.go`\. + +``` + awss3.NewBucket(stack, jsii.String("MyFirstBucket"), &awss3.BucketProps{ + Versioned: jsii.Bool(true), + RemovalPolicy: awscdk.RemovalPolicy_DESTROY, + AutoDeleteObjects: jsii.Bool(true), + }) +``` + +------ + +Here, we haven't written any code that, in itself, changes our Amazon S3 bucket\. Instead, our code defines the desired state of the bucket\. The AWS CDK synthesizes that state to a new AWS CloudFormation template\. Then, it deploys a changeset that makes only the changes necessary to reach that state\. + +To see these changes, we'll use the `cdk diff` command\. + +``` +cdk diff +``` + +The AWS CDK Toolkit queries your AWS account for the last\-deployed AWS CloudFormation template for the `HelloCdkStack`\. Then, it compares the last\-deployed template with the template it just synthesized from your app\. The output should look like the following\. + +``` +Stack HelloCdkStack +IAM Statement Changes +┌───┬──────────────────────────────┬────────┬──────────────────────────────┬──────────────────────────────┬───────────┐ +│ │ Resource │ Effect │ Action │ Principal │ Condition │ +├───┼──────────────────────────────┼────────┼──────────────────────────────┼──────────────────────────────┼───────────┤ +│ + │ ${Custom::S3AutoDeleteObject │ Allow │ sts:AssumeRole │ Service:lambda.amazonaws.com │ │ +│ │ sCustomResourceProvider/Role │ │ │ │ │ +│ │ .Arn} │ │ │ │ │ +├───┼──────────────────────────────┼────────┼──────────────────────────────┼──────────────────────────────┼───────────┤ +│ + │ ${MyFirstBucket.Arn} │ Allow │ s3:DeleteObject* │ AWS:${Custom::S3AutoDeleteOb │ │ +│ │ ${MyFirstBucket.Arn}/* │ │ s3:GetBucket* │ jectsCustomResourceProvider/ │ │ +│ │ │ │ s3:GetObject* │ Role.Arn} │ │ +│ │ │ │ s3:List* │ │ │ +└───┴──────────────────────────────┴────────┴──────────────────────────────┴──────────────────────────────┴───────────┘ +IAM Policy Changes +┌───┬────────────────────────────────────────────────────────┬────────────────────────────────────────────────────────┐ +│ │ Resource │ Managed Policy ARN │ +├───┼────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────┤ +│ + │ ${Custom::S3AutoDeleteObjectsCustomResourceProvider/Ro │ {"Fn::Sub":"arn:${AWS::Partition}:iam::aws:policy/serv │ +│ │ le} │ ice-role/AWSLambdaBasicExecutionRole"} │ +└───┴────────────────────────────────────────────────────────┴────────────────────────────────────────────────────────┘ +(NOTE: There may be security-related changes not in this list. See https://github.com/aws/aws-cdk/issues/1299) + +Parameters +[+] Parameter AssetParameters/4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392/S3Bucket AssetParameters4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392S3BucketBF7A7F3F: {"Type":"String","Description":"S3 bucket for asset \"4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392\""} +[+] Parameter AssetParameters/4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392/S3VersionKey AssetParameters4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392S3VersionKeyFAF93626: {"Type":"String","Description":"S3 key for asset version \"4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392\""} +[+] Parameter AssetParameters/4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392/ArtifactHash AssetParameters4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392ArtifactHashE56CD69A: {"Type":"String","Description":"Artifact hash for asset \"4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392\""} + +Resources +[+] AWS::S3::BucketPolicy MyFirstBucket/Policy MyFirstBucketPolicy3243DEFD +[+] Custom::S3AutoDeleteObjects MyFirstBucket/AutoDeleteObjectsCustomResource MyFirstBucketAutoDeleteObjectsCustomResourceC52FCF6E +[+] AWS::IAM::Role Custom::S3AutoDeleteObjectsCustomResourceProvider/Role CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092 +[+] AWS::Lambda::Function Custom::S3AutoDeleteObjectsCustomResourceProvider/Handler CustomS3AutoDeleteObjectsCustomResourceProviderHandler9D90184F +[~] AWS::S3::Bucket MyFirstBucket MyFirstBucketB8884501 + ├─ [~] DeletionPolicy + │ ├─ [-] Retain + │ └─ [+] Delete + └─ [~] UpdateReplacePolicy + ├─ [-] Retain + └─ [+] Delete +``` + +This diff has four sections\. ++ **IAM Statement Changes** and **IAM Policy Changes** \- These permission changes are there because we set the `AutoDeleteObjects` property on our Amazon S3 bucket\. The auto\-delete feature uses a custom resource to delete the objects in the bucket before the bucket itself is deleted\. The IAM objects grant the custom resource's code access to the bucket\. ++ **Parameters** \- The AWS CDK uses these entries to locate the Lambda function asset for the custom resource\. ++ **Resources** \- The new and changed resources in this stack\. We can see the previously mentioned IAM objects, the custom resource, and its associated Lambda function being added\. We can also see that the bucket's `DeletionPolicy` and `UpdateReplacePolicy` attributes are being updated\. These allow the bucket to be deleted along with the stack, and to be replaced with a new one\. + +You may be curious about why we specified `RemovalPolicy` in our AWS CDK app but got a `DeletionPolicy` property in the resulting AWS CloudFormation template\. The AWS CDK uses a different name for the property\. This is because the AWS CDK default is to retain the bucket when the stack is deleted, while AWS CloudFormation's default is to delete it\. For more information, see [Removal policies](resources.md#resources_removal)\. + +It's informative to compare the output of cdk synth here with the previous output\. You can see the many additional lines of AWS CloudFormation template that the AWS CDK generated for us based on these relatively small changes\. + +**Important** +All AWS CDK v2 deployments use dedicated AWS resources to hold data during deployment\. Therefore, your AWS account and Region must be [bootstrapped](bootstrapping.md) to create these resources before you can deploy\. If you haven't already bootstrapped, issue the following command: + +``` +cdk bootstrap aws://ACCOUNT-NUMBER/REGION +``` + +Now let's deploy\. + +``` +cdk deploy +``` + +The AWS CDK warns you about the security policy changes we've already seen in the diff\. Enter y to approve the changes and deploy the updated stack\. The CDK Toolkit updates the bucket configuration as you requested\. + +``` +HelloCdkStack: deploying... +[0%] start: Publishing 4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392:current +[100%] success: Published 4cd61014b71160e8c66fe167e43710d5ba068b80b134e9bd84508cf9238b2392:current +HelloCdkStack: creating CloudFormation changeset... + 0/5 | 4:32:31 PM | UPDATE_IN_PROGRESS | AWS::CloudFormation::Stack | HelloCdkStack User Initiated + 0/5 | 4:32:36 PM | CREATE_IN_PROGRESS | AWS::IAM::Role | Custom::S3AutoDeleteObjectsCustomResourceProvider/Role (CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092) + 1/5 | 4:32:36 PM | UPDATE_COMPLETE | AWS::S3::Bucket | MyFirstBucket (MyFirstBucketB8884501) + 1/5 | 4:32:36 PM | CREATE_IN_PROGRESS | AWS::IAM::Role | Custom::S3AutoDeleteObjectsCustomResourceProvider/Role (CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092) Resource creation Initiated + 3/5 | 4:32:54 PM | CREATE_COMPLETE | AWS::IAM::Role | Custom::S3AutoDeleteObjectsCustomResourceProvider/Role (CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092) + 3/5 | 4:32:56 PM | CREATE_IN_PROGRESS | AWS::Lambda::Function | Custom::S3AutoDeleteObjectsCustomResourceProvider/Handler (CustomS3AutoDeleteObjectsCustomResourceProviderHandler9D90184F) + 3/5 | 4:32:56 PM | CREATE_IN_PROGRESS | AWS::S3::BucketPolicy | MyFirstBucket/Policy (MyFirstBucketPolicy3243DEFD) + 3/5 | 4:32:56 PM | CREATE_IN_PROGRESS | AWS::Lambda::Function | Custom::S3AutoDeleteObjectsCustomResourceProvider/Handler (CustomS3AutoDeleteObjectsCustomResourceProviderHandler9D90184F) Resource creation Initiated + 3/5 | 4:32:57 PM | CREATE_COMPLETE | AWS::Lambda::Function | Custom::S3AutoDeleteObjectsCustomResourceProvider/Handler (CustomS3AutoDeleteObjectsCustomResourceProviderHandler9D90184F) + 3/5 | 4:32:57 PM | CREATE_IN_PROGRESS | AWS::S3::BucketPolicy | MyFirstBucket/Policy (MyFirstBucketPolicy3243DEFD) Resource creation Initiated + 4/5 | 4:32:57 PM | CREATE_COMPLETE | AWS::S3::BucketPolicy | MyFirstBucket/Policy (MyFirstBucketPolicy3243DEFD) + 4/5 | 4:32:59 PM | CREATE_IN_PROGRESS | Custom::S3AutoDeleteObjects | MyFirstBucket/AutoDeleteObjectsCustomResource/Default (MyFirstBucketAutoDeleteObjectsCustomResourceC52FCF6E) + 5/5 | 4:33:06 PM | CREATE_IN_PROGRESS | Custom::S3AutoDeleteObjects | MyFirstBucket/AutoDeleteObjectsCustomResource/Default (MyFirstBucketAutoDeleteObjectsCustomResourceC52FCF6E) Resource creation Initiated + 5/5 | 4:33:06 PM | CREATE_COMPLETE | Custom::S3AutoDeleteObjects | MyFirstBucket/AutoDeleteObjectsCustomResource/Default (MyFirstBucketAutoDeleteObjectsCustomResourceC52FCF6E) + 5/5 | 4:33:08 PM | UPDATE_COMPLETE_CLEA | AWS::CloudFormation::Stack | HelloCdkStack + 6/5 | 4:33:09 PM | UPDATE_COMPLETE | AWS::CloudFormation::Stack | HelloCdkStack + + ✅ HelloCdkStack + +Stack ARN: +arn:aws:cloudformation:REGION:ACCOUNT:stack/HelloCdkStack/UNIQUE-ID +``` + +## Destroying the app's resources<a name="hello_world_tutorial_destroy"></a> + +Now that you're done with the quick tour, destroy your app's resources to avoid incurring any costs from the bucket you created, as follows\. + +``` +cdk destroy +``` + +Enter y to approve the changes and delete any stack resources\. + +**Note** +If we didn't change the bucket's `RemovalPolicy`, the stack deletion would complete successfully, but the bucket would become orphaned \(no longer associated with the stack\)\. + +## Next steps<a name="hello_world_next_steps"></a> + +Where do you go now that you've dipped your toes in the AWS CDK? ++ Try the [CDK Workshop](https://cdkworkshop.com/) for a more in\-depth tour involving a more complex project\. ++ Dig deeper into concepts like [Environments](environments.md), [Assets](assets.md), [Permissions](permissions.md), [Runtime context](context.md), [Parameters](parameters.md), and [Abstractions and escape hatches](cfn_layer.md)\. ++ See the [API reference](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-construct-library.html) to begin exploring the CDK constructs available for your favorite AWS services\. ++ Visit [Construct Hub](https://constructs.dev/search?q=&cdk=aws-cdk&cdkver=2&sort=downloadsDesc&offset=0) to discover constructs created by AWS and others\. ++ Explore [Examples](https://github.com/aws-samples/aws-cdk-examples) of using the AWS CDK\. + +The AWS CDK is an open\-source project\. Want to [contribute](https://github.com/aws/aws-cdk)? \ No newline at end of file diff --git a/v2/home.md b/v2/home.md new file mode 100644 index 00000000..92301a9e --- /dev/null +++ b/v2/home.md @@ -0,0 +1,303 @@ +# What is the AWS CDK?<a name="home"></a> + +Welcome to the *AWS Cloud Development Kit \(AWS CDK\) Developer Guide*\. This document provides information about the AWS CDK, a framework for defining cloud infrastructure in code and provisioning it through AWS CloudFormation\. + +**Note** +The CDK has been released in two major versions, v1 and v2\. This is the Developer Guide for AWS CDK v2\. The earlier CDK v1 entered maintenance on June 1, 2022\. Support for CDK v1 will end on June 1, 2023\. + +The AWS CDK lets you build reliable, scalable, cost\-effective applications in the cloud with the considerable expressive power of a programming language\. This approach yields many benefits, including: ++ Build with high\-level constructs that automatically provide sensible, secure defaults for your AWS resources, defining more infrastructure with less code\. ++ Use programming idioms like parameters, conditionals, loops, composition, and inheritance to model your system design from building blocks provided by AWS and others\. ++ Put your infrastructure, application code, and configuration all in one place, ensuring that at every milestone you have a complete, cloud\-deployable system\. ++ Employ software engineering practices such as code reviews, unit tests, and source control to make your infrastructure more robust\. ++ Connect your AWS resources together \(even across stacks\) and grant permissions using simple, intent\-oriented APIs\. ++ Import existing AWS CloudFormation templates to give your resources a CDK API\. ++ Use the power of AWS CloudFormation to perform infrastructure deployments predictably and repeatedly, with rollback on error\. ++ Easily share infrastructure design patterns among teams within your organization or even with the public\. + +The AWS CDK supports TypeScript, JavaScript, Python, Java, C\#/\.Net, and Go\. Developers can use one of these supported programming languages to define reusable cloud components known as [Constructs](constructs.md)\. You compose these together into [Stacks](stacks.md) and [Apps](apps.md)\. + +![\[Image NOT FOUND\]](http://docs.aws.amazon.com/cdk/v2/guide/images/AppStacks.png) + +## Why use the AWS CDK?<a name="why_use_cdk"></a> + +It's easier to show than to explain\! Here's some CDK code that creates an Amazon ECS service with AWS Fargate launch type \(this is the code we use in the [Creating an AWS Fargate service using the AWS CDK](ecs_example.md)\)\. + +------ +#### [ TypeScript ] + +``` +export class MyEcsConstructStack extends Stack { + constructor(scope: App, id: string, props?: StackProps) { + super(scope, id, props); + + const vpc = new ec2.Vpc(this, "MyVpc", { + maxAzs: 3 // Default is all AZs in region + }); + + const cluster = new ecs.Cluster(this, "MyCluster", { + vpc: vpc + }); + + // Create a load-balanced Fargate service and make it public + new ecs_patterns.ApplicationLoadBalancedFargateService(this, "MyFargateService", { + cluster: cluster, // Required + cpu: 512, // Default is 256 + desiredCount: 6, // Default is 1 + taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample") }, + memoryLimitMiB: 2048, // Default is 512 + publicLoadBalancer: true // Default is false + }); + } +} +``` + +------ +#### [ JavaScript ] + +``` +class MyEcsConstructStack extends Stack { + constructor(scope, id, props) { + super(scope, id, props); + + const vpc = new ec2.Vpc(this, "MyVpc", { + maxAzs: 3 // Default is all AZs in region + }); + + const cluster = new ecs.Cluster(this, "MyCluster", { + vpc: vpc + }); + + // Create a load-balanced Fargate service and make it public + new ecs_patterns.ApplicationLoadBalancedFargateService(this, "MyFargateService", { + cluster: cluster, // Required + cpu: 512, // Default is 256 + desiredCount: 6, // Default is 1 + taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample") }, + memoryLimitMiB: 2048, // Default is 512 + publicLoadBalancer: true // Default is false + }); + } +} + +module.exports = { MyEcsConstructStack } +``` + +------ +#### [ Python ] + +``` +class MyEcsConstructStack(Stack): + + def __init__(self, scope: Construct, id: str, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + vpc = ec2.Vpc(self, "MyVpc", max_azs=3) # default is all AZs in region + + cluster = ecs.Cluster(self, "MyCluster", vpc=vpc) + + ecs_patterns.ApplicationLoadBalancedFargateService(self, "MyFargateService", + cluster=cluster, # Required + cpu=512, # Default is 256 + desired_count=6, # Default is 1 + task_image_options=ecs_patterns.ApplicationLoadBalancedTaskImageOptions( + image=ecs.ContainerImage.from_registry("amazon/amazon-ecs-sample")), + memory_limit_mib=2048, # Default is 512 + public_load_balancer=True) # Default is False +``` + +------ +#### [ Java ] + +``` +public class MyEcsConstructStack extends Stack { + + public MyEcsConstructStack(final Construct scope, final String id) { + this(scope, id, null); + } + + public MyEcsConstructStack(final Construct scope, final String id, + StackProps props) { + super(scope, id, props); + + Vpc vpc = Vpc.Builder.create(this, "MyVpc").maxAzs(3).build(); + + Cluster cluster = Cluster.Builder.create(this, "MyCluster") + .vpc(vpc).build(); + + ApplicationLoadBalancedFargateService.Builder.create(this, "MyFargateService") + .cluster(cluster) + .cpu(512) + .desiredCount(6) + .taskImageOptions( + ApplicationLoadBalancedTaskImageOptions.builder() + .image(ContainerImage + .fromRegistry("amazon/amazon-ecs-sample")) + .build()).memoryLimitMiB(2048) + .publicLoadBalancer(true).build(); + } +} +``` + +------ +#### [ C\# ] + +``` +public class MyEcsConstructStack : Stack +{ + public MyEcsConstructStack(Construct scope, string id, IStackProps props=null) : base(scope, id, props) + { + var vpc = new Vpc(this, "MyVpc", new VpcProps + { + MaxAzs = 3 + }); + + var cluster = new Cluster(this, "MyCluster", new ClusterProps + { + Vpc = vpc + }); + + new ApplicationLoadBalancedFargateService(this, "MyFargateService", + new ApplicationLoadBalancedFargateServiceProps + { + Cluster = cluster, + Cpu = 512, + DesiredCount = 6, + TaskImageOptions = new ApplicationLoadBalancedTaskImageOptions + { + Image = ContainerImage.FromRegistry("amazon/amazon-ecs-sample") + }, + MemoryLimitMiB = 2048, + PublicLoadBalancer = true, + }); + } +} +``` + +------ +#### [ Go ] + +``` +func NewMyEcsConstructStack(scope constructs.Construct, id string, props *MyEcsConstructStackProps) awscdk.Stack { + + var sprops awscdk.StackProps + + if props != nil { + sprops = props.StackProps + } + + stack := awscdk.NewStack(scope, &id, &sprops) + + vpc := awsec2.NewVpc(stack, jsii.String("MyVpc"), &awsec2.VpcProps{ + MaxAzs: jsii.Number(3), // Default is all AZs in region + }) + + cluster := awsecs.NewCluster(stack, jsii.String("MyCluster"), &awsecs.ClusterProps{ + Vpc: vpc, + }) + + awsecspatterns.NewApplicationLoadBalancedFargateService(stack, jsii.String("MyFargateService"), + &awsecspatterns.ApplicationLoadBalancedFargateServiceProps{ + Cluster: cluster, // required + Cpu: jsii.Number(512), // default is 256 + DesiredCount: jsii.Number(5), // default is 1 + MemoryLimitMiB: jsii.Number(2048), // Default is 512 + TaskImageOptions: &awsecspatterns.ApplicationLoadBalancedTaskImageOptions{ + Image: awsecs.ContainerImage_FromRegistry(jsii.String("amazon/amazon-ecs-sample"), nil), + }, + PublicLoadBalancer: jsii.Bool(true), // Default is false + }) + + return stack + +} +``` + +------ + +This class produces an AWS CloudFormation [template of more than 500 lines](https://github.com/awsdocs/aws-cdk-guide/blob/main/doc_source/my_ecs_construct-stack.yaml); deploying the AWS CDK app produces more than 50 resources of the following types\. ++ [AWS::EC2::EIP](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-eip.html) ++ [AWS::EC2::InternetGateway](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-internetgateway.html) ++ [AWS::EC2::NatGateway](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-natgateway.html) ++ [AWS::EC2::Route](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-route.html) ++ [AWS::EC2::RouteTable](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-routetable.html) ++ [AWS::EC2::SecurityGroup](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-security-group.html) ++ [AWS::EC2::Subnet](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-subnet.html) ++ [AWS::EC2::SubnetRouteTableAssociation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-subnet-route-table-assoc.html) ++ [AWS::EC2::VPCGatewayAttachment](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpc-gateway-attachment.html) ++ [AWS::EC2::VPC](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpc.html) ++ [AWS::ECS::Cluster](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ecs-cluster.html) ++ [AWS::ECS::Service](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ecs-service.html) ++ [AWS::ECS::TaskDefinition](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ecs-taskdefinition.html) ++ [AWS::ElasticLoadBalancingV2::Listener](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticloadbalancingv2-listener.html) ++ [AWS::ElasticLoadBalancingV2::LoadBalancer](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticloadbalancingv2-loadbalancer.html) ++ [AWS::ElasticLoadBalancingV2::TargetGroup](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticloadbalancingv2-targetgroup.html) ++ [AWS::IAM::Policy](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-policy.html) ++ [AWS::IAM::Role](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html) ++ [AWS::Logs::LogGroup](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-logs-loggroup.html) + +And let's not forget\.\.\. code completion within your IDE or editor\! + +![\[Image NOT FOUND\]](http://docs.aws.amazon.com/cdk/v2/guide/images/CodeCompletion.png) + +## Developing with the AWS CDK<a name="developing"></a> + +It's easy to [get set up](getting_started.md) and [write your first CDK app](hello_world.md)\. Short code examples are available throughout this Guide in the AWS CDK's supported programming languages: TypeScript, JavaScript, Python, Java, and C\#\. Longer examples are available [in our GitHub repository](https://github.com/aws-samples/aws-cdk-examples)\. + +The [AWS CDK Toolkit](cli.md) is a command line tool for interacting with CDK apps\. Developers can use the AWS CDK Toolkit to synthesize artifacts such as AWS CloudFormation templates and to deploy stacks to development AWS accounts\. You can also diff against a deployed stack to understand the impact of a code change\. + +The [AWS Construct Library](constructs.md) offers constructs for each AWS service, many with "rich" APIs that provide high\-level abstractions\. The aim of the AWS Construct Library is to reduce the complexity and glue logic required when integrating various AWS services to achieve your goals on AWS\. + +**Note** +There is no charge for using the AWS CDK, but you might incur AWS charges for creating or using AWS [chargeable resources](https://docs.aws.amazon.com/general/latest/gr/glos-chap.html#chargeable-resources)\. These might include running Amazon EC2 instances or using Amazon S3 storage\. Use the [AWS Pricing Calculator](https://calculator.aws/#/) to estimate charges for the use of various AWS resources\. + +## The Construct Programming Model<a name="cpm"></a> + +The Construct Programming Model \(CPM\) extends the concepts behind the AWS CDK into additional domains\. Other tools using the CPM include: ++ [CDK for Terraform](https://www.terraform.io/docs/cdktf/index.html) \(CDKtf\) ++ [CDK for Kubernetes](https://cdk8s.io/) \(CDK8s\) ++ [Projen](https://github.com/projen/projen), for building project configurations + +[Construct Hub](https://constructs.dev/) is an online registry where you can find and publish construct libraries for CDKs like the AWS CDK\. + +## Additional documentation and resources<a name="additional_docs"></a> + +In addition to this guide, the following other resources are available to AWS CDK users: ++ [API Reference](https://docs.aws.amazon.com/cdk/api/v2) ++ [AWS CDK Workshop](https://cdkworkshop.com/) ++ [cdk\.dev](https://cdk.dev/) community hub, including a Slack channel ++ [AWS CDK Examples](https://github.com/aws-samples/aws-cdk-examples) ++ [CDK Patterns](https://cdkpatterns.com/) ++ [Awesome CDK](https://github.com/kolomied/awesome-cdk) ++ [AWS Solutions Constructs](http://aws.amazon.com/solutions/constructs/) ++ [AWS Developer Blog](https://aws.amazon.com/blogs/developer/category/developer-tools/aws-cloud-development-kit) CDK category ++ [Stack Overflow](https://stackoverflow.com/questions/tagged/aws-cdk) ++ [GitHub Repository](https://github.com/awslabs/aws-cdk) + + [Issues](https://github.com/awslabs/aws-cdk/issues) + + [Examples](https://github.com/aws-samples/aws-cdk-examples) + + [Documentation Source](https://github.com/awsdocs/aws-cdk-guide) + + [License](https://github.com/awslabs/aws-cdk/blob/main/LICENSE) + + [Releases](https://github.com/awslabs/aws-cdk/releases) + + [AWS CDK OpenPGP key](pgp-keys.md#cdk_pgp_key) + + [jsii OpenPGP key](pgp-keys.md#jsii_pgp_key) ++ [AWS CDK Sample for Cloud9](https://docs.aws.amazon.com/cloud9/latest/user-guide/sample-cdk.html) ++ [AWS CloudFormation Concepts](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-whatis-concepts.html) ++ [AWS Glossary](https://docs.aws.amazon.com/general/latest/gr/glos-chap.html) + +### Resources for serverless apps with CDK<a name="additional_serverless"></a> + +These tools can work with the AWS CDK to simplify serverless application development and deployment\. ++ [AWS Serverless Application Model](http://aws.amazon.com/serverless/sam/) ++ [AWS Chalice](https://github.com/aws/chalice), a Python serverless microframework + +## Contributing to the AWS CDK<a name="contributing"></a> + +Because the AWS CDK is open source, the team encourages you to contribute to make it an even better tool\. For details, see [Contributing](https://github.com/awslabs/aws-cdk/blob/main/CONTRIBUTING.md)\. + +## About Amazon Web Services<a name="about_aws"></a> + +Amazon Web Services \(AWS\) is a collection of digital infrastructure services that developers can use when developing their applications\. The services include computing, storage, database, and application synchronization \(messaging and queueing\)\. + +AWS uses a pay\-as\-you\-go service model\. You are charged only for the services that you — or your applications — use\. Also, to make AWS useful as a platform for prototyping and experimentation, AWS offers a free usage tier\. In the tier, services are free below a certain level of usage\. For more information about AWS costs and the free usage tier, see [Test\-Driving AWS in the Free Usage Tier](https://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/billing-free-tier.html)\. + +To obtain an AWS account, go to [aws\.amazon\.com](https://aws.amazon.com), and then choose **Create an AWS Account**\. \ No newline at end of file diff --git a/v2/how_to_set_cw_alarm.md b/v2/how_to_set_cw_alarm.md new file mode 100644 index 00000000..d6cb9254 --- /dev/null +++ b/v2/how_to_set_cw_alarm.md @@ -0,0 +1,239 @@ +# Set a CloudWatch alarm<a name="how_to_set_cw_alarm"></a> + +The [aws\-cloudwatch](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_cloudwatch-readme.html) package supports setting CloudWatch alarms on CloudWatch metrics\. So the first thing you need is a metric\. You can use a predefined metric or you can create your own\. + +## Using an existing metric<a name="how_to_set_cw_alarm_use_metric"></a> + +Many AWS Construct Library modules let you set an alarm on an existing metric by passing the metric's name to a convenience method on an instance of an object that has metrics\. For example, given an Amazon SQS queue, you can get the metric **ApproximateNumberOfMessagesVisible** from the queue's [metric\(\)](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_sqs.Queue.html#metricmetricname-props) method\. + +------ +#### [ TypeScript ] + +``` +const metric = queue.metric("ApproximateNumberOfMessagesVisible"); +``` + +------ +#### [ JavaScript ] + +``` +const metric = queue.metric("ApproximateNumberOfMessagesVisible"); +``` + +------ +#### [ Python ] + +``` +metric = queue.metric("ApproximateNumberOfMessagesVisible") +``` + +------ +#### [ Java ] + +``` +Metric metric = queue.metric("ApproximateNumberOfMessagesVisible"); +``` + +------ +#### [ C\# ] + +``` +var metric = queue.Metric("ApproximateNumberOfMessagesVisible"); +``` + +------ + +## Creating your own metric<a name="how_to_set_cw_alarm_new_metric"></a> + +Create your own [metric](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_cloudwatch.Metric.html) as follows, where the *namespace* value should be something like **AWS/SQS** for an Amazon SQS queue\. You also need to specify your metric's name and dimension\. + +------ +#### [ TypeScript ] + +``` +const metric = new cloudwatch.Metric({ + namespace: 'MyNamespace', + metricName: 'MyMetric', + dimensionsMap: { MyDimension: 'MyDimensionValue' } +}); +``` + +------ +#### [ JavaScript ] + +``` +const metric = new cloudwatch.Metric({ + namespace: 'MyNamespace', + metricName: 'MyMetric', + dimensionsMap: { MyDimension: 'MyDimensionValue' } +}); +``` + +------ +#### [ Python ] + +``` +metric = cloudwatch.Metric( + namespace="MyNamespace", + metric_name="MyMetric", + dimensionsMap=dict(MyDimension="MyDimensionValue") +) +``` + +------ +#### [ Java ] + +``` +Metric metric = Metric.Builder.create() + .namespace("MyNamespace") + .metricName("MyMetric") + .dimensionsMap(java.util.Map.of( // Java 9 or later + "MyDimension", "MyDimensionValue")) + .build(); +``` + +------ +#### [ C\# ] + +``` +var metric = new Metric(this, "Metric", new MetricProps +{ + Namespace = "MyNamespace", + MetricName = "MyMetric", + dimensionsMap = new Dictionary<string, object> + { + { "MyDimension", "MyDimensionValue" } + } +}); +``` + +------ + +## Creating the alarm<a name="how_to_set_cw_alarm_create"></a> + +Once you have a metric, either an existing one or one you defined, you can create an alarm\. In this example, the alarm is raised when there are more than 100 of your metric in two of the last three evaluation periods\. You can use comparisons such as less\-than in your alarms via the `comparisonOperator` property\. Greater\-than\-or\-equal\-to is the AWS CDK default, so we don't need to specify it\. + +------ +#### [ TypeScript ] + +``` +const alarm = new cloudwatch.Alarm(this, 'Alarm', { + metric: metric, + threshold: 100, + evaluationPeriods: 3, + datapointsToAlarm: 2, +}); +``` + +------ +#### [ JavaScript ] + +``` +const alarm = new cloudwatch.Alarm(this, 'Alarm', { + metric: metric, + threshold: 100, + evaluationPeriods: 3, + datapointsToAlarm: 2 +}); +``` + +------ +#### [ Python ] + +``` +alarm = cloudwatch.Alarm(self, "Alarm", + metric=metric, + threshold=100, + evaluation_periods=3, + datapoints_to_alarm=2 +) +``` + +------ +#### [ Java ] + +``` +import software.amazon.awscdk.services.cloudwatch.Alarm; +import software.amazon.awscdk.services.cloudwatch.Metric; + +Alarm alarm = Alarm.Builder.create(this, "Alarm") + .metric(metric) + .threshold(100) + .evaluationPeriods(3) + .datapointsToAlarm(2).build(); +``` + +------ +#### [ C\# ] + +``` +var alarm = new Alarm(this, "Alarm", new AlarmProps +{ + Metric = metric, + Threshold = 100, + EvaluationPeriods = 3, + DatapointsToAlarm = 2 +}); +``` + +------ + +An alternative way to create an alarm is using the metric's [createAlarm\(\)](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_cloudwatch.Metric.html#createwbralarmscope-id-props) method, which takes essentially the same properties as the `Alarm` constructor\. You don't need to pass in the metric, because it's already known\. + +------ +#### [ TypeScript ] + +``` +metric.createAlarm(this, 'Alarm', { + threshold: 100, + evaluationPeriods: 3, + datapointsToAlarm: 2, +}); +``` + +------ +#### [ JavaScript ] + +``` +metric.createAlarm(this, 'Alarm', { + threshold: 100, + evaluationPeriods: 3, + datapointsToAlarm: 2, +}); +``` + +------ +#### [ Python ] + +``` +metric.create_alarm(self, "Alarm", + threshold=100, + evaluation_periods=3, + datapoints_to_alarm=2 +) +``` + +------ +#### [ Java ] + +``` +metric.createAlarm(this, "Alarm", new CreateAlarmOptions.Builder() + .threshold(100) + .evaluationPeriods(3) + .datapointsToAlarm(2) + .build()); +``` + +------ +#### [ C\# ] + +``` +metric.CreateAlarm(this, "Alarm", new CreateAlarmOptions +{ + Threshold = 100, + EvaluationPeriods = 3, + DatapointsToAlarm = 2 +}); +``` + +------ diff --git a/v2/how_tos.md b/v2/how_tos.md new file mode 100644 index 00000000..229bd4c7 --- /dev/null +++ b/v2/how_tos.md @@ -0,0 +1,3 @@ +# AWS CDK how\-tos<a name="how_tos"></a> + +This section contains short code examples that show you how to accomplish a task using the AWS CDK\. \ No newline at end of file diff --git a/v2/identifiers.md b/v2/identifiers.md new file mode 100644 index 00000000..5cc1f58e --- /dev/null +++ b/v2/identifiers.md @@ -0,0 +1,281 @@ +# Identifiers<a name="identifiers"></a> + +The AWS CDK deals with many types of identifiers and names\. To use the AWS CDK effectively and avoid errors, you need to understand the types of identifiers\. + +Identifiers must be unique within the scope in which they are created; they do not need to be globally unique in your AWS CDK application\. + +If you attempt to create an identifier with the same value within the same scope, the AWS CDK throws an exception\. + +## Construct IDs<a name="identifiers_construct_ids"></a> + +The most common identifier, `id`, is the identifier passed as the second argument when instantiating a construct object\. This identifier, like all identifiers, only needs to be unique within the scope in which it is created, which is the first argument when instantiating a construct object\. + +**Note** +The `id` of a stack is also the identifier that you use to refer to it in the [AWS CDK Toolkit \(`cdk` command\)](cli.md)\. + +Let's look at an example where we have two constructs with the identifier `MyBucket` in our app\. The first is defined in the scope of the stack with the identifier `Stack1`\. The second is defined in the scope of a stack with the identifier `Stack2`\. Because they're defined in different scopes, this doesn't cause any conflict, and they can coexist in the same app without issues\. + +------ +#### [ TypeScript ] + +``` +import { App, Stack, StackProps } from 'aws-cdk-lib'; +import { Construct } from 'constructs'; +import * as s3 from 'aws-cdk-lib/aws-s3'; + +class MyStack extends Stack { + constructor(scope: Construct, id: string, props: StackProps = {}) { + super(scope, id, props); + + new s3.Bucket(this, 'MyBucket'); + } +} + +const app = new App(); +new MyStack(app, 'Stack1'); +new MyStack(app, 'Stack2'); +``` + +------ +#### [ JavaScript ] + +``` +const { App , Stack } = require('aws-cdk-lib'); +const s3 = require('aws-cdk-lib/aws-s3'); + +class MyStack extends Stack { + constructor(scope, id, props = {}) { + super(scope, id, props); + + new s3.Bucket(this, 'MyBucket'); + } +} + +const app = new App(); +new MyStack(app, 'Stack1'); +new MyStack(app, 'Stack2'); +``` + +------ +#### [ Python ] + +``` +from aws_cdk import App, Construct, Stack, StackProps +from constructs import Construct +from aws_cdk import aws_s3 as s3 + +class MyStack(Stack): + + def __init__(self, scope: Construct, id: str, **kwargs): + + super().__init__(scope, id, **kwargs) + s3.Bucket(self, "MyBucket") + +app = App() +MyStack(app, 'Stack1') +MyStack(app, 'Stack2') +``` + +------ +#### [ Java ] + +``` +// MyStack.java +package com.myorg; + +import software.amazon.awscdk.App; +import software.amazon.awscdk.Stack; +import software.amazon.awscdk.StackProps; +import software.constructs.Construct; +import software.amazon.awscdk.services.s3.Bucket; + +public class MyStack extends Stack { + public MyStack(final Construct scope, final String id) { + this(scope, id, null); + } + + public MyStack(final Construct scope, final String id, final StackProps props) { + super(scope, id, props); + new Bucket(this, "MyBucket"); + } +} + +// Main.java +package com.myorg; + +import software.amazon.awscdk.App; + +public class Main { + public static void main(String[] args) { + App app = new App(); + new MyStack(app, "Stack1"); + new MyStack(app, "Stack2"); + } +} +``` + +------ +#### [ C\# ] + +``` +using Amazon.CDK; +using constructs; +using Amazon.CDK.AWS.S3; + +public class MyStack : Stack +{ + public MyStack(Construct scope, string id, IStackProps props) : base(scope, id, props) + { + new Bucket(this, "MyBucket"); + } +} + +class Program +{ + static void Main(string[] args) + { + var app = new App(); + new MyStack(app, "Stack1"); + new MyStack(app, "Stack2"); + } +} +``` + +------ + +## Paths<a name="identifiers_paths"></a> + +The constructs in an AWS CDK application form a hierarchy rooted in the `App` class\. We refer to the collection of IDs from a given construct, its parent construct, its grandparent, and so on to the root of the construct tree, as a *path*\. + +The AWS CDK typically displays paths in your templates as a string\. The IDs from the levels are separated by slashes, starting at the node immediately under the root `App` instance, which is usually a stack\. For example, the paths of the two Amazon S3 bucket resources in the previous code example are `Stack1/MyBucket` and `Stack2/MyBucket`\. + +You can access the path of any construct programmatically, as shown in the following example\. This gets the path of `myConstruct` \(or `my_construct`, as Python developers would write it\)\. Since IDs must be unique within the scope they are created, their paths are always unique within an AWS CDK application\. + +------ +#### [ TypeScript ] + +``` +const path: string = myConstruct.node.path; +``` + +------ +#### [ JavaScript ] + +``` +const path = myConstruct.node.path; +``` + +------ +#### [ Python ] + +``` +path = my_construct.node.path +``` + +------ +#### [ Java ] + +``` +String path = myConstruct.getNode().getPath(); +``` + +------ +#### [ C\# ] + +``` +string path = myConstruct.Node.Path; +``` + +------ + +## Unique IDs<a name="identifiers_unique_ids"></a> + +AWS CloudFormation requires that all logical IDs in a template be unique\. Because of this, the AWS CDK must be able to generate a unique identifier for each construct in an application\. Resources have paths that are globally unique \(the names of all scopes from the stack to a specific resource\)\. Therefore, the AWS CDK generates the necessary unique identifiers by concatenating the elements of the path and adding an 8\-digit hash\. \(The hash is necessary to distinguish distinct paths, such as `A/B/C` and `A/BC`, that would result in the same AWS CloudFormation identifier\. AWS CloudFormation identifiers are alphanumeric and cannot contain slashes or other separator characters\.\) The AWS CDK calls this string the *unique ID* of the construct\. + +In general, your AWS CDK app should not need to know about unique IDs\. You can, however, access the unique ID of any construct programmatically, as shown in the following example\. + +------ +#### [ TypeScript ] + +``` +const uid: string = Names.uniqueId(myConstruct); +``` + +------ +#### [ JavaScript ] + +``` +const uid = Names.uniqueId(myConstruct); +``` + +------ +#### [ Python ] + +``` +uid = Names.unique_id(my_construct) +``` + +------ +#### [ Java ] + +``` +String uid = Names.uniqueId(myConstruct); +``` + +------ +#### [ C\# ] + +``` +string uid = Names.Uniqueid(myConstruct); +``` + +------ + +The *address* is another kind of unique identifier that uniquely distinguishes CDK resources\. Derived from the SHA\-1 hash of the path, it is not human\-readable\. However, its constant, relatively short length \(always 42 hexadecimal characters\) makes it useful in situations where the "traditional" unique ID might be too long\. Some constructs may use the address in the synthesized AWS CloudFormation template instead of the unique ID\. Again, your app generally should not need to know about its constructs' addresses, but you can retrieve a construct's address as follows\. + +------ +#### [ TypeScript ] + +``` +const addr: string = myConstruct.node.addr; +``` + +------ +#### [ JavaScript ] + +``` +const addr = myConstruct.node.addr; +``` + +------ +#### [ Python ] + +``` +addr = my_construct.node.addr +``` + +------ +#### [ Java ] + +``` +String addr = myConstruct.getNode().getAddr(); +``` + +------ +#### [ C\# ] + +``` +string addr = myConstruct.Node.Addr; +``` + +------ + +## Logical IDs<a name="identifiers_logical_ids"></a> + +Unique IDs serve as the *logical identifiers* \(or *logical names*\) of resources in the generated AWS CloudFormation templates for constructs that represent AWS resources\. + +For example, the Amazon S3 bucket in the previous example that is created within `Stack2` results in an `AWS::S3::Bucket` resource\. The resource's logical ID is `Stack2MyBucket4DD88B4F` in the resulting AWS CloudFormation template\. \(For details on how this identifier is generated, see [Unique IDs](#identifiers_unique_ids)\.\) + +### Logical ID stability<a name="identifiers_logical_id_stability"></a> + +Avoid changing the logical ID of a resource after it has been created\. AWS CloudFormation identifies resources by their logical ID\. Therefore, if you change the logical ID of a resource, AWS CloudFormation creates a new resource with the new logical ID, then deletes the existing one\. Depending on the type of resource, this might cause service interruption, data loss, or both\. \ No newline at end of file diff --git a/v2/index.md b/v2/index.md new file mode 100644 index 00000000..fc00a714 --- /dev/null +++ b/v2/index.md @@ -0,0 +1,77 @@ +# AWS Cloud Development Kit (AWS CDK) v2 Developer Guide + +----- +*****Copyright © Amazon Web Services, Inc. and/or its affiliates. All rights reserved.***** + +----- +Amazon's trademarks and trade dress may not be used in +connection with any product or service that is not Amazon's, +in any manner that is likely to cause confusion among customers, +or in any manner that disparages or discredits Amazon. All other +trademarks not owned by Amazon are the property of their respective +owners, who may or may not be affiliated with, connected to, or +sponsored by Amazon. + +----- +## Contents ++ [What is the AWS CDK?](home.md) ++ [Getting started with the AWS CDK](getting_started.md) + + [Your first AWS CDK app](hello_world.md) ++ [Working with the AWS CDK](work-with.md) + + [Working with the AWS CDK in TypeScript](work-with-cdk-typescript.md) + + [Working with the AWS CDK in JavaScript](work-with-cdk-javascript.md) + + [Working with the AWS CDK in Python](work-with-cdk-python.md) + + [Working with the AWS CDK in Java](work-with-cdk-java.md) + + [Working with the AWS CDK in C#](work-with-cdk-csharp.md) + + [Working with the AWS CDK in Go](work-with-cdk-go.md) ++ [Managing dependencies](manage-dependencies.md) ++ [Migrating to AWS CDK v2](migrating-v2.md) ++ [Translating TypeScript AWS CDK code to other languages](multiple_languages.md) ++ [Concepts](core_concepts.md) + + [Constructs](constructs.md) + + [Apps](apps.md) + + [Stacks](stacks.md) + + [Environments](environments.md) + + [Resources](resources.md) + + [Identifiers](identifiers.md) + + [Tokens](tokens.md) + + [Parameters](parameters.md) + + [Tagging](tagging.md) + + [Assets](assets.md) + + [Permissions](permissions.md) + + [Runtime context](context.md) + + [Feature flags](featureflags.md) + + [Aspects](aspects.md) + + [Bootstrapping](bootstrapping.md) ++ [Abstractions and escape hatches](cfn_layer.md) ++ [Best practices for developing and deploying cloud infrastructure with the AWS CDK](best-practices.md) ++ [API reference](reference.md) ++ [Examples](examples.md) + + [Creating a serverless application using the AWS CDK](serverless_example.md) + + [Creating an AWS Fargate service using the AWS CDK](ecs_example.md) + + [AWS CDK examples](about_examples.md) ++ [AWS CDK how-tos](how_tos.md) + + [Get a value from an environment variable](get_env_var.md) + + [Use an AWS CloudFormation value](get_cfn_param.md) + + [Import or migrate an existing AWS CloudFormation template](use_cfn_template.md) + + [Using resources from the AWS CloudFormation Public Registry](use_cfn_public_registry.md) + + [Get a value from the Systems Manager Parameter Store](get_ssm_value.md) + + [Get a value from AWS Secrets Manager](get_secrets_manager_value.md) + + [Create an app with multiple stacks](stack_how_to_create_multiple_stacks.md) + + [Set a CloudWatch alarm](how_to_set_cw_alarm.md) + + [Get a value from a context variable](get_context_var.md) + + [Continuous integration and delivery (CI/CD) using CDK Pipelines](cdk_pipeline.md) ++ [AWS CDK tools](tools.md) + + [AWS CDK Toolkit (cdk command)](cli.md) + + [AWS Toolkit for Visual Studio Code](vscode.md) + + [AWS SAM integration](sam.md) ++ [Testing constructs](testing.md) ++ [Security for the AWS Cloud Development Kit (AWS CDK)](security.md) + + [Identity and access management for the AWS Cloud Development Kit (AWS CDK)](security-iam.md) + + [Compliance validation for the AWS Cloud Development Kit (AWS CDK)](compliance-validation.md) + + [Resilience for the AWS Cloud Development Kit (AWS CDK)](disaster-recovery-resiliency.md) + + [Infrastructure security for the AWS Cloud Development Kit (AWS CDK)](infrastructure-security.md) ++ [Troubleshooting common AWS CDK issues](troubleshooting.md) ++ [Videos](videos.md) ++ [OpenPGP keys for the AWS CDK and jsii](pgp-keys.md) ++ [AWS CDK Developer Guide history](doc-history.md) \ No newline at end of file diff --git a/v2/infrastructure-security.md b/v2/infrastructure-security.md new file mode 100644 index 00000000..e2052b67 --- /dev/null +++ b/v2/infrastructure-security.md @@ -0,0 +1,3 @@ +# Infrastructure security for the AWS Cloud Development Kit \(AWS CDK\)<a name="infrastructure-security"></a> + +The AWS CDK follows the [shared responsibility model](https://aws.amazon.com/compliance/shared-responsibility-model/) through the specific Amazon Web Services \(AWS\) services it supports\. For AWS service security information, see the [AWS service security documentation page](https://docs.aws.amazon.com/security/?id=docs_gateway#aws-security) and [AWS services that are in scope of AWS compliance efforts by compliance program](https://aws.amazon.com/compliance/services-in-scope/)\. \ No newline at end of file diff --git a/v2/manage-dependencies.md b/v2/manage-dependencies.md new file mode 100644 index 00000000..b90077aa --- /dev/null +++ b/v2/manage-dependencies.md @@ -0,0 +1,305 @@ +# Managing dependencies<a name="manage-dependencies"></a> + +Dependencies for your AWS CDK app or library are managed using package management tools\. These tools are commonly used with the programming language in which you develop your app\. + +Typically, the CDK supports the language's standard or official package management tool, if there is one, or its most popular or widely supported one if not\. You might also be able to use other tools, especially if they interoperate with the supported tools, although our ability to support alternatives is limited\. + +The CDK supports the following package managers\. + + +| Language | Supported package management tool | +| --- | --- | +| TypeScript/JavaScript | NPM \(Node Package Manager\) or Yarn | +| Python | PIP \(Package Installer for Python\) | +| Java | Maven | +| C\# | NuGet | +| Go | Go modules | + +**Note** +The projects generated by cdk init specify dependencies for the CDK core libraries and stable constructs\. + +The remainder of this topic provides details on using AWS CDK dependencies in each language\. + +## TypeScript and JavaScript<a name="manage-dependencies-ts-js"></a> + +In TypeScript and JavaScript CDK projects, dependencies are specified in `package.json` in the project's main directory\. The core AWS CDK modules \(including all stable constructs\) are in a single NPM package, `aws-cdk-lib`\. Unstable modules, where the API is still undergoing refinement, are distributed in their own modules\. Additionally, the `construct` base class and supporting code is in the `constructs` module\. + +**Tip** +When you install a package using npm install, NPM records it in `package.json` for you\. + +If you prefer, you may use Yarn in place of NPM\. However, the CDK does not support Yarn's plug\-and\-play mode, which is default mode in Yarn 2\. Add the following to your project's `.yarnrc.yml` file to turn off this feature\. + +``` +nodeLinker: node-modules +``` + +### Applications<a name="w55aac17c15c11"></a> + +The following is an example `package.json` generated by cdk init \-\-language typescript\. The file generated for JavaScript is similar, only without the TypeScript\-related entries\. + +``` +{ + "name": "my-package", + "version": "0.1.0", + "bin": { + "my-package": "bin/my-package.js" + }, + "scripts": { + "build": "tsc", + "watch": "tsc -w", + "test": "jest", + "cdk": "cdk" + }, + "devDependencies": { + "@types/jest": "^26.0.10", + "@types/node": "10.17.27", + "jest": "^26.4.2", + "ts-jest": "^26.2.0", + "aws-cdk": "2.16.0", + "ts-node": "^9.0.0", + "typescript": "~3.9.7" + }, + "dependencies": { + "aws-cdk-lib": "2.16.0", + "constructs": "^10.0.0", + "source-map-support": "^0.5.16" + } +} +``` + +For deployable CDK apps, `aws-cdk-lib` must be specified in the `dependencies` section of `package.json`\. You can use a caret \(^\) version number specifier to indicate that you will accept later versions than the one specified as long as they are within the same major version\. + +Specify exact versions for alpha construct library modules, which have APIs that may change\. Do not use ^ or \~ since later versions of these modules may bring API changes that can break your app\. + +Specify versions of libraries and tools needed to test your app \(for example, the `jest` testing framework\) in the `devDependencies` section of `package.json`\. Optionally, use ^ to specify that later compatible versions are acceptable\. + +### Construct libraries<a name="w55aac17c15c13"></a> + +If you're developing a construct library, specify its dependencies via a combination of the `peerDependencies` and `devDependencies` sections, as shown in the following example `package.json` file\. + +``` +{ + "name": "my-package", + "version": "0.0.1", + "peerDependencies": { + "aws-cdk-lib": "^2.14.0", + "@aws-cdk/aws-appsync-alpha": "2.10.0-alpha", + "constructs": "^10.0.0" + }, + "devDependencies": { + "aws-cdk-lib": "2.14.0", + "@aws-cdk/aws-appsync-alpha": "2.10.0-alpha", + "constructs": "10.0.0", + "jsii": "^1.50.0", + "aws-cdk": "^2.14.0" + } +} +``` + +In `peerDependencies`, use a caret \(^\) to specify the lowest version of `aws-cdk-lib` that your library works with\. This maximizes the compatibility of your library with a range of CDK versions\. Specify exact versions for alpha construct library modules, which have APIs that may change\. Using `peerDependencies` makes sure that there is only one copy of all CDK libraries in the `node_modules` tree\. + +In `devDependencies`, specify the tools and libraries you need for testing, optionally with ^ to indicate that later compatible versions are acceptable\. Specify exactly \(without ^ or \~\) the lowest versions of `aws-cdk-lib` and other CDK packages that you advertise your library be compatible with\. This practice makes sure that your tests run against those versions\. This way, if you inadvertently use a feature found only in newer versions, your tests can catch it\. + +**Warning** +`peerDependencies` are installed automatically only by NPM 7 and later\. If you are using NPM 6 or earlier, or if you are using Yarn, you must include the dependencies of your dependencies in `devDependencies`\. Otherwise, they won't be installed, and you will receive a warning about unresolved peer dependencies\. + +### Installing and updating dependencies<a name="w55aac17c15c17"></a> + +Run the following command to install your project's dependencies\. + +------ +#### [ NPM ] + +``` +# Install the latest version of everything that matches the ranges in 'package.json' +npm install + +# Install the same exact dependency versions as recorded in 'package-lock.json' +npm ci +``` + +------ +#### [ Yarn ] + +``` +# Install the latest version of everything that matches the ranges in 'package.json' +yarn upgrade + +# Install the same exact dependency versions as recorded in 'yarn.lock' +yarn install --frozen-lockfile +``` + +------ + +To update the installed modules, the preceding npm install and yarn upgrade commands can be used\. Either command updates the packages in `node_modules` to the latest versions that satisfy the rules in `package.json`\. However, they do not update `package.json` itself, which you might want to do to set a new minimum version\. If you host your package on GitHub, you can configure [Dependabot version updates](https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuring-dependabot-version-updates) to automatically update `package.json`\. Alternatively, use [npm\-check\-updates](https://www.npmjs.com/package/npm-check-updates)\. + +**Important** +By design, when you install or update dependencies, NPM and Yarn choose the latest version of every package that satisfies the requirements specified in `package.json`\. There is always a risk that these versions may be broken \(either accidentally or intentionally\)\. Test thoroughly after updating your project's dependencies\. + +## Python<a name="manage-dependencies-python"></a> + +In Python, you specify dependencies by putting them in `requirements.txt` \(for applications\) or `setup.py` \(for construct libraries\)\. Dependencies are then managed with the PIP tool\. PIP is invoked in one of the following ways: + +``` +pip command options +python -m pip command options +``` + +The python \-m pip invocation works on most systems; pip requires that PIP's executable be on the system path\. If pip doesn't work, try replacing it with python \-m pip\. + +cdk init \-\-language python creates a virtual environment for your new project\. This lets each project have its own versions of dependencies, and also a basic `requirements.txt` file\. You must activate this virtual environment \(source \.venv/bin/activate\) each time you begin working with the project\. + +### Applications<a name="w55aac17c17c11"></a> + +An example `requirements.txt` follows\. Because PIP does not have a dependency\-locking feature, we recommend that you use the == operator to specify exact versions for all dependencies, as shown here\. + +``` +aws-cdk-lib==2.14.0 +aws-cdk.aws-appsync-alpha==2.10.0a0 +``` + +Installing a module with pip install does not add it to `requirements.txt`; you should do that yourself\. If you want to upgrade to a later version of a dependency, edit its version number in `requirements.txt`\. + +To install or update your project's dependencies after creating or editing `requirements.txt`, issue: + +``` +python -m pip install -r requirements.txt +``` + +**Tip** +The pip freeze command outputs the versions of all installed dependencies in a format that can be written to a text file\. This can be used as a requirements file with `pip install -r`\. This file is convenient for pinning all dependencies \(including transitive ones\) to the exact versions that you tested with\. To avoid problems when upgrading packages later, use a separate file for this, such as `freeze.txt` \(not `requirements.txt`\)\. Then, regenerate it when you upgrade your project's dependencies\. + +### Construct libraries<a name="w55aac17c17c13"></a> + +In libraries, dependencies are specified in `setup.py`, so that transitive dependencies are automatically downloaded when the package is consumed by an application\. Otherwise, every application that wants to use your package needs to copy your dependencies into their `requirements.txt`\. An example `setup.py` is shown here\. + +``` +from setuptools import setup + +setup( + name='my-package', + version='0.0.1', + install_requires=[ + 'aws-cdk-lib==2.14.0', + ], + ... +) +``` + +To work on the package for development, create or activate a virtual environment, then run the following command\. + +``` +python -m pip install -e . +``` + +Although PIP automatically installs transitive dependencies, there can only be one installed copy of any one package\. The version that is specified highest in the dependency tree is selected; applications always have the last word in what version of packages get installed\. + +## Java<a name="manage-dependencies-java"></a> + +In Java, dependencies are specified in `pom.xml` and installed using Maven\. The `<dependencies>` container includes a `<dependency>` element for each package\. Following is a section of `pom.xml` for a typical CDK Java app\. + +**Tip** +Many Java IDEs have integrated Maven support and visual `pom.xml` editors, which you may find convenient for managing dependencies\. + +``` +<dependencies> + <dependency> + <groupId>software.amazon.awscdk</groupId> + <artifactId>aws-cdk-lib</artifactId> + <version>2.14.0</version> + </dependency> + <dependency> + <groupId>software.amazon.awscdk</groupId> + <artifactId>appsync-alpha</artifactId> + <version>2.10.0-alpha.0</version> + </dependency> + </dependencies> +``` + +Maven does not support dependency locking\. Although it's possible to specify version ranges in `pom.xml`, we recommend you always use exact versions to keep your builds repeatable\. + +Maven automatically installs transitive dependencies, but there can only be one installed copy of each package\. The version that is specified highest in the POM tree is selected; applications always have the last word in what version of packages get installed\. + +Maven automatically installs or updates your dependencies whenever you build \(mvn compile\) or package \(mvn package\) your project\. The CDK Toolkit does this automatically every time you run it, so generally there is no need to manually invoke Maven\. + +## C\#<a name="manage-dependencies-csharp"></a> + +In C\# AWS CDK apps, you manage dependencies using NuGet\. NuGet has four standard, mostly equivalent interfaces; you can use the one that suits your needs and working style\. You can also use compatible tools, such as [Paket](https://fsprojects.github.io/Paket/) or [MyGet](https://www.myget.org/) or even edit the `.csproj` file directly\. + +NuGet does not let you specify version ranges for dependencies\. Every dependency is pinned to a specific version\. + +After updating your dependencies, Visual Studio will use NuGet to retrieve the specified versions of each package the next time you build\. If you are not using Visual Studio, use the dotnet restore command to update your dependencies\. + +### Editing the project file directly<a name="manage-dependencies-csharp-direct-edit"></a> + +Your project's `.csproj` file contains an `<ItemGroup>` container that lists your dependencies as `<PackageReference` elements\. + +``` +<ItemGroup> + <PackageReference Include="Amazon.CDK.Lib" Version="2.14.0" /> + <PackageReference Include="Constructs" Version="%constructs-version%" /> +</ItemGroup> +``` + +### The Visual Studio NuGet GUI<a name="manage-dependencies-csharp-vs-nuget-gui"></a> + +Visual Studio's NuGet tools are accessible from **Tools** > **NuGet Package Manager** > **Manage NuGet Packages for Solution**\. Use the **Browse** tab to find the AWS Construct Library packages you want to install\. You can choose the desired version, including prerelease versions of your modules, and add them to any of the open projects\. + +**Note** +All AWS Construct Library modules deemed "experimental" \(see [Versioning](reference.md#versioning)\) are flagged as prerelease in NuGet and have an `alpha` name suffix\. + +![\[Image NOT FOUND\]](http://docs.aws.amazon.com/cdk/v2/guide/images/visual-studio-nuget.png) + +Look on the **Updates** page to install new versions of your packages\. + +### The NuGet console<a name="manage-dependencies-csharp-vs-nuget-console"></a> + +The NuGet console is a PowerShell\-based interface to NuGet that works in the context of a Visual Studio project\. You can open it in Visual Studio by choosing **Tools** > **NuGet Package Manager** > **Package Manager Console**\. For more information about using this tool, see [Install and Manage Packages with the Package Manager Console in Visual Studio](https://docs.microsoft.com/en-us/nuget/consume-packages/install-use-packages-powershell)\. + +### The `dotnet` command<a name="manage-dependencies-csharp-vs-dotnet-command"></a> + +The `dotnet` command is the primary command line tool for working with Visual Studio C\# projects\. You can invoke it from any Windows command prompt\. Among its many capabilities, `dotnet` can add NuGet dependencies to a Visual Studio project\. + +Assuming you're in the same directory as the Visual Studio project \(`.csproj`\) file, issue a command like the following to install a package\. Because the main CDK library is included when you create a project, you only need to explicitly install experimental modules\. Experimental modules require you to specify an explicit version number\. + +``` +dotnet add package Amazon.CDK.AWS.IoT.Alpha -v VERSION-NUMBER +``` + +You can issue the command from another directory\. To do so, include the path to the project file, or to the directory that contains it, after the `add` keyword\. The following example assumes that you are in your AWS CDK project's main directory\. + +``` +dotnet add src/PROJECT-DIR package Amazon.CDK.AWS.IoT.Alpha -v VERSION-NUMBER +``` + +To install a specific version of a package, include the `-v` flag and the desired version\. + +To update a package, issue the same `dotnet add` command you used to install it\. For experimental modules, again, you must specify an explicit version number\. + +For more information about managing packages using the `dotnet` command, see [Install and Manage Packages Using the dotnet CLI](https://docs.microsoft.com/en-us/nuget/consume-packages/install-use-packages-dotnet-cli)\. + +### The `nuget` command<a name="manage-dependencies-csharp-vs-nuget-command"></a> + +The `nuget` command line tool can install and update NuGet packages\. However, it requires your Visual Studio project to be set up differently from the way `cdk init` sets up projects\. \(Technical details: `nuget` works with `Packages.config` projects, while `cdk init` creates a newer\-style `PackageReference` project\.\) + +We do not recommend the use of the `nuget` tool with AWS CDK projects created by `cdk init`\. If you are using another type of project, and want to use `nuget`, see the [NuGet CLI Reference](https://docs.microsoft.com/en-us/nuget/reference/nuget-exe-cli-reference)\. + +## Go<a name="manage-dependencies-go"></a> + +In Go, dependencies versions are defined in `go.mod`\. The default `go.mod` is similar to the one shown here\. + +``` +module my-package + +go 1.16 + +require ( + github.com/aws/aws-cdk-go/awscdk/v2 v2.16.0 + github.com/aws/constructs-go/constructs/v10 v10.0.5 + github.com/aws/jsii-runtime-go v1.29.0 +) +``` + +Package names \(modules, in Go parlance\) are specified by URL with the required version number appended\. Go's module system does not support version ranges\. + +Issue the go get command to install all required modules and update `go.mod`\. To see a list of available updates for your dependencies, issue go list \-m \-u all\. \ No newline at end of file diff --git a/v2/migrating-v2.md b/v2/migrating-v2.md new file mode 100644 index 00000000..fc9b4a11 --- /dev/null +++ b/v2/migrating-v2.md @@ -0,0 +1,379 @@ +# Migrating to AWS CDK v2<a name="migrating-v2"></a> + +Version 2 of the AWS Cloud Development Kit \(AWS CDK\) is designed to make writing infrastructure as code in your preferred programming language easier\. This topic describes the changes between v1 and v2 of the AWS CDK\. + +**Tip** +To identify stacks deployed with AWS CDK v1, use the [awscdk\-v1\-stack\-finder](https://www.npmjs.com/package/awscdk-v1-stack-finder) utility\. + +The main changes from AWS CDK v1 to CDK v2 are as follows\. ++ AWS CDK v2 consolidates the stable parts of the AWS Construct Library, including the core library, into a single package, `aws-cdk-lib`\. Developers no longer need to install additional packages for the individual AWS services they use\. This single\-package approach also means that you don't have to synchronize the versions of the various CDK library packages\. + + L1 \(CfnXXXX\) constructs, which represent the exact resources available in AWS CloudFormation, are always considered stable and so are included in `aws-cdk-lib`\. ++ Experimental modules, where we're still working with the community to develop new [L2 or L3 constructs](constructs.md#constructs_lib), are not included in `aws-cdk-lib`\. Instead, they're distributed as individual packages\. Experimental packages are named with an `alpha` suffix and a semantic version number\. The semantic version number matches the first version of the AWS Construct Library that they're compatible with, also with an `alpha` suffix\. Constructs move into `aws-cdk-lib` after being designated stable, permitting the main Construct Library to adhere to strict semantic versioning\. + + Stability is specified at the service level\. For example, if we begin creating one or more [L2 constructs](constructs.md#constructs_lib) for Amazon AppFlow, which at this writing has only L1 constructs, they first appear in a module named `@aws-cdk/aws-appflow-alpha`\. Then, they move to `aws-cdk-lib` when we feel that the new constructs meet the fundamental needs of customers\. + + Once a module has been designated stable and incorporated into `aws-cdk-lib`, new APIs are added using the "BetaN" convention described in the next bullet\. + + A new version of each experimental module is released with every release of the AWS CDK\. For the most part, however, they needn't be kept in sync\. You can upgrade `aws-cdk-lib` or the experimental module whenever you want\. The exception is that when two or more related experimental modules depend on each other, they must be the same version\. ++ For stable modules to which new functionality is being added, new APIs \(whether entirely new constructs or new methods or properties on an existing construct\) receive a `Beta1` suffix while work is in progress\. \(Followed by `Beta2`, `Beta3`, and so on when breaking changes are needed\.\) A version of the API without the suffix is added when the API is designated stable\. All methods except the latest \(whether beta or final\) are then deprecated\. + + For example, if we add a new method `grantPower()` to a construct, it initially appears as `grantPowerBeta1()`\. If breaking changes are needed \(for example, a new required parameter or property\), the next version of the method would be named `grantPowerBeta2()`, and so on\. When work is complete and the API is finalized, the method `grantPower()` \(with no suffix\) is added, and the BetaN methods are deprecated\. + + All the beta APIs remain in the Construct Library until the next major version \(3\.0\) release, and their signatures will not change\. You'll see deprecation warnings if you use them, so you should move to the final version of the API at your earliest convenience\. However, no future AWS CDK 2\.x releases will break your application\. ++ The `Construct` class has been extracted from the AWS CDK into a separate library, along with related types\. This is done to support efforts to apply the Construct Programming Model to other domains\. If you are writing your own constructs or using related APIs, you must declare the `constructs` module as a dependency and make minor changes to your imports\. If you are using advanced features, such as hooking into the CDK app lifecycle, more changes may be needed\. For full details, [see the RFC](https://github.com/aws/aws-cdk-rfcs/blob/master/text/0192-remove-constructs-compat.md#release-notes)\. ++ Deprecated properties, methods, and types in AWS CDK v1\.x and its Construct Library have been removed completely from the CDK v2 API\. In most supported languages, these APIs produce warnings under v1\.x, so you may have already migrated to the replacement APIs\. A complete [list of deprecated APIs](https://github.com/aws/aws-cdk/blob/master/DEPRECATED_APIs.md) in CDK v1\.x is available on GitHub\. ++ Behavior that was gated by feature flags in AWS CDK v1\.x is enabled by default in CDK v2\. The earlier feature flags are no longer needed, and in most cases they're not supported\. A few are still available to let you revert to CDK v1 behavior in very specific circumstances\. For more information, see [Updating feature flags](#migrating-v2-v1-upgrade-cdk-json)\. ++ With CDK v2, the environments you deploy into must be bootstrapped using the modern bootstrap stack\. The legacy bootstrap stack \(the default under v1\) is no longer supported\. CDK v2 furthermore requires a new version of the modern stack\. To upgrade your existing environments, re\-bootstrap them\. It is no longer necessary to set any feature flags or environment variables to use the modern bootstrap stack\. + +**Important** +The modern bootstrap template effectively grants the permissions implied by the `--cloudformation-execution-policies` to any AWS account in the `--trust` list\. By default, this extends permissions to read and write to any resource in the bootstrapped account\. Make sure to [configure the bootstrapping stack](bootstrapping.md#bootstrapping-customizing) with policies and trusted accounts that you are comfortable with\. + +## New prerequisites<a name="migrating-v2-prerequisites"></a> + +Most requirements for AWS CDK v2 are the same as for AWS CDK v1\.x\. Additional requirements are listed here\. ++ For TypeScript developers, TypeScript 3\.8 or later is required\. ++ A new version of the CDK Toolkit is required for use with CDK v2\. Now that CDK v2 is generally available, v2 is the default version when installing the CDK Toolkit\. It is backward\-compatible with CDK v1 projects, so you don't need to keep the earlier version installed unless you want to create CDK v1 projects\. To upgrade, issue `npm install -g aws-cdk`\. + +## Upgrading from AWS CDK v2 Developer Preview<a name="migrating-v2-dp-upgrade"></a> + +If you're using the CDK v2 Developer Preview, you have dependencies in your project on a Release Candidate version of the AWS CDK, such as `2.0.0-rc1`\. Update these to `2.0.0`, then update the modules installed in your project\. + +------ +#### [ TypeScript ] + +`npm install` or `yarn install` + +------ +#### [ JavaScript ] + +`npm install` or `yarn install` + +------ +#### [ Python ] + +``` +python -m pip install -r requirements.txt +``` + +------ +#### [ Java ] + +``` +mvn package +``` + +------ +#### [ C\# ] + +``` +dotnet restore +``` + +------ +#### [ Go ] + +``` +go get +``` + +------ + +After updating your dependencies, issue `npm update -g aws-cdk` to update the CDK Toolkit to the release version\. + +## Migrating from AWS CDK v1 to CDK v2<a name="migrating-v2-v1-uppgrade"></a> + +To migrate your app to AWS CDK v2, first update the feature flags in `cdk.json`\. Then update your app's dependencies and imports as necessary for the programming language that it's written in\. + +### Updating feature flags<a name="migrating-v2-v1-upgrade-cdk-json"></a> + +Remove the following v1 feature flags from `cdk.json` if they exist, as these are all active by default in AWS CDK v2\. If their old effect is important for your infrastructure, you will need to make source code changes\. See [the list of flags on GitHub](https://github.com/aws/aws-cdk/blob/main/packages/%40aws-cdk/cx-api/FEATURE_FLAGS.md) for more information\. ++ `@aws-cdk/core:enableStackNameDuplicates` ++ `aws-cdk:enableDiffNoFail` ++ `@aws-cdk/aws-ecr-assets:dockerIgnoreSupport` ++ `@aws-cdk/aws-secretsmanager:parseOwnedSecretName` ++ `@aws-cdk/aws-kms:defaultKeyPolicies` ++ `@aws-cdk/aws-s3:grantWriteWithoutAcl` ++ `@aws-cdk/aws-efs:defaultEncryptionAtRest` + +A handful of v1 feature flags can be set to `false` in order to revert to specific AWS CDK v1 behaviors; see [Reverting to v1 behavior](featureflags.md#featureflags_disabling) or the list on GitHub for a complete reference\. + +For both types of flags, use the `cdk diff` command to inspect the changes to your synthesized template to see if the changes to any of these flags affect your infrastructure\. + +### CDK Toolkit compatibility<a name="work-with-cdk-v2-cli"></a> + +CDK v2 requires v2 or later of the CDK Toolkit\. This version is backward\-compatible with CDK v1 apps\. Therefore, you can use a single globally installed version of CDK Toolkit with all your AWS CDK projects, whether they use v1 or v2\. An exception is that CDK Toolkit v2 only creates CDK v2 projects\. + +If you need to create both v1 and v2 CDK projects, **do not install CDK Toolkit v2 globally\.** \(Remove it if you already have it installed: `npm remove -g aws-cdk`\.\) To invoke the CDK Toolkit, use npx to run v1 or v2 of the CDK Toolkit as desired\. + +``` +npx aws-cdk@1.x init app --language typescript +npx aws-cdk@2.x init app --language typescript +``` + +**Tip** +Set up command line aliases so you can use the cdk and cdk1 commands to invoke the desired version of the CDK Toolkit\. + +``` +alias cdk1="npx aws-cdk@1.x" +alias cdk="npx aws-cdk@2.x" +``` + +``` +doskey cdk1=npx aws-cdk@1.x $* +doskey cdk=npx aws-cdk@2.x $* +``` + +### Updating dependencies and imports<a name="migrating-v2-v1-upgrade-dependencies"></a> + +Update your app's dependencies, then install the new packages\. Finally, update the imports in your code\. + +------ +#### [ TypeScript ] + +**Applications** +For CDK apps, update `package.json` as follows\. Remove dependencies on v1\-style individual stable modules and establish the lowest version of `aws-cdk-lib` you require for your application \(2\.0\.0 here\)\. + +Experimental constructs are provided in separate, independently versioned packages with names that end in `alpha` and an alpha version number\. The alpha version number corresponds to the first release of `aws-cdk-lib` with which they're compatible\. Here, we have pinned `aws-codestar` to v2\.0\.0\-alpha\.1\. + +``` +{ + "dependencies": { + "aws-cdk-lib": "^2.0.0", + "@aws-cdk/aws-codestar-alpha": "2.0.0-alpha.1", + "constructs": "^10.0.0" + } +} +``` + +**Construct libraries** +For construct libraries, establish the lowest version of `aws-cdk-lib` you require for your application \(2\.0\.0 here\) and update `package.json` as follows\. + +Note that `aws-cdk-lib` appears both as a peer dependency and a dev dependency\. + +``` +{ + "peerDependencies": { + "aws-cdk-lib": "^2.0.0", + "constructs": "^10.0.0" + }, + "devDependencies": { + "aws-cdk-lib": "^2.0.0", + "constructs": "^10.0.0", + "typescript": "~3.9.0" + } +} +``` + +**Note** +You should perform a major version bump on your library's version number when releasing a v2\-compatible library, because this is a breaking change for library consumers\. It is not possible to support both CDK v1 and v2 with a single library\. To continue to support customers who are still using v1, you could maintain the earlier release in parallel, or create a new package for v2\. +It's up to you how long you want to continue supporting AWS CDK v1 customers\. You might take your cue from the lifecycle of CDK v1 itself, which entered maintenance on June 1, 2022 and will reach end\-of\-life on June 1, 2023\. For full details, see [AWS CDK Maintenance Policy](https://github.com/aws/aws-cdk-rfcs/blob/master/text/0079-cdk-2.0.md#aws-cdk-maintenance-policy)\. + +**Both libraries and apps** +Install the new dependencies by running `npm install` or `yarn install`\. + +Change your imports to import `Construct` from the new `constructs` module, core types such as `App` and `Stack` from the top level of `aws-cdk-lib`, and stable Construct Library modules for the services you use from namespaces under `aws-cdk-lib`\. + +``` +import { Construct } from 'constructs'; +import { App, Stack } from 'aws-cdk-lib'; // core constructs +import { aws_s3 as s3 } from 'aws-cdk-lib'; // stable module +import * as codestar from '@aws-cdk/aws-codestar-alpha'; // experimental module +``` + +------ +#### [ JavaScript ] + +Update `package.json` as follows\. Remove dependencies on v1\-style individual stable modules and establish the lowest version of `aws-cdk-lib` you require for your application \(2\.0\.0 here\)\. + +Experimental constructs are provided in separate, independently versioned packages with names that end in `alpha` and an alpha version number\. The alpha version number corresponds to the first release of `aws-cdk-lib` with which they're compatible\. Here, we have pinned `aws-codestar` to v2\.0\.0\-alpha\.1\. + +``` +{ + "dependencies": { + "aws-cdk-lib": "^2.0.0", + "@aws-cdk/aws-codestar-alpha": "2.0.0-alpha.1", + "constructs": "^10.0.0" + } +} +``` + +Install the new dependencies by running `npm install` or `yarn install`\. + +Change your app's imports to do the following: ++ Import `Construct` from the new `constructs` module ++ Import core types, such as `App` and `Stack`, from the top level of `aws-cdk-lib` ++ Import AWS Construct Library modules from namespaces under `aws-cdk-lib` + +``` +const { Construct } = require('constructs'); +const { App, Stack } = require('aws-cdk-lib'); // core constructs +const s3 = require('aws-cdk-lib').aws_s3; // stable module +const codestar = require('@aws-cdk/aws-codestar-alpha'); // experimental module +``` + +------ +#### [ Python ] + +Update `requirements.txt` or the `install_requires` definition in `setup.py` as follows\. Remove dependencies on v1\-style individual stable modules\. + +Experimental constructs are provided in separate, independently versioned packages with names that end in `alpha` and an alpha version number\. The alpha version number corresponds to the first release of `aws-cdk-lib` with which they're compatible\. Here, we have pinned `aws-codestar` to v2\.0\.0alpha1\. + +``` +install_requires=[ + "aws-cdk-lib>=2.0.0", + "constructs>=10.0.0", + "aws-cdk.aws-codestar-alpha>=2.0.0alpha1", + # ... +], +``` + +**Tip** +Uninstall any other versions of AWS CDK modules already installed in your app's virtual environment using `pip uninstall`\. Then Install the new dependencies with `python -m pip install -r requirements.txt`\. + +Change your app's imports to do the following: ++ Import `Construct` from the new `constructs` module ++ Import core types, such as `App` and `Stack`, from the top level of `aws_cdk` ++ Import AWS Construct Library modules from namespaces under `aws_cdk` + +``` +from constructs import Construct +from aws_cdk import App, Stack # core constructs +from aws_cdk import aws_s3 as s3 # stable module +import aws_cdk.aws_codestar_alpha as codestar # experimental module + +# ... + +class MyConstruct(Construct): + # ... + +class MyStack(Stack): + # ... + +s3.Bucket(...) +``` + +------ +#### [ Java ] + +In `pom.xml`, remove all `software.amazon.awscdk` dependencies for stable modules and replace them with dependencies on `software.constructs` \(for `Construct`\) and `software.amazon.awscdk`\. + +Experimental constructs are provided in separate, independently versioned packages with names that end in `alpha` and an alpha version number\. The alpha version number corresponds to the first release of `aws-cdk-lib` with which they're compatible\. Here, we have pinned `aws-codestar` to v2\.0\.0\-alpha\.1\. + +``` +<dependency> + <groupId>software.amazon.awscdk</groupId> + <artifactId>aws-cdk-lib</artifactId> + <version>2.0.0</version> +</dependency><dependency> + <groupId>software.amazon.awscdk</groupId> + <artifactId>code-star-alpha</artifactId> + <version>2.0.0-alpha.1</version> +</dependency> +<dependency> + <groupId>software.constructs</groupId> + <artifactId>constructs</artifactId> + <version>10.0.0</version> +</dependency> +``` + +Install the new dependencies by running `mvn package`\. + +Change your code to do the following: ++ Import `Construct` from the new `software.constructs` library ++ Import core classes, like `Stack` and `App`, from `software.amazon.awscdk` ++ Import service constructs from `software.amazon.awscdk.services` + +``` +import software.constructs.Construct; +import software.amazon.awscdk.Stack; +import software.amazon.awscdk.StackProps; +import software.amazon.awscdk.App; +import software.amazon.awscdk.services.s3.Bucket; +import software.amazon.awscdk.services.codestar.alpha.GitHubRepository; +``` + +------ +#### [ C\# ] + +The most straightforward way to upgrade the dependencies of a C\# CDK application is to edit the `.csproj` file manually\. Remove all stable `Amazon.CDK.*` package references and replace them with references to the `Amazon.CDK.Lib` and `Constructs` packages\. + +Experimental constructs are provided in separate, independently versioned packages with names that end in `alpha` and an alpha version number\. The alpha version number corresponds to the first release of `aws-cdk-lib` with which they're compatible\. Here, we have pinned `aws-codestar` to v2\.0\.0\-alpha\.1\. + +``` +<PackageReference Include="Amazon.CDK.Lib" Version="2.0.0" /> +<PackageReference Include="Amazon.CDK.AWS.Codestar.Alpha" Version="2.0.0-alpha.1" /> +<PackageReference Include="Constructs" Version="10.0.0" /> +``` + +Install the new dependencies by running `dotnet restore`\. + +Change the imports in your source files as follows\. + +``` +using Constructs; // for Construct class +using Amazon.CDK; // for core classes like App and Stack +using Amazon.CDK.AWS.S3; // for stable constructs like Bucket +using Amazon.CDK.Codestar.Alpha; // for experimental constructs +``` + +------ +#### [ Go ] + +Issue go get to update your dependencies to the latest version and update your project's `.mod` file\. + +------ + +## Testing your migrated app before deploying<a name="migrating-v2-diff.title"></a> + +Before deploying your stacks, use `cdk diff` to check for unexpected changes to the resources\. Changes to logical IDs \(causing replacement of resources\) are **not** expected\. + +Expected changes include but are not limited to: ++ Changes to the `CDKMetadata` resource\. ++ Updated asset hashes\. ++ Changes related to the new\-style stack synthesis\. Applies if your app used the legacy stack synthesizer in v1\. \(CDK v2 does not support the legacy stack synthesizer\.\) ++ The addition of a `CheckBootstrapVersion` rule\. + +Unexpected changes are typically not caused by upgrading to AWS CDK v2 in itself\. Usually, they're the result of deprecated behavior that was previously changed by feature flags\. This is a symptom of upgrading from a version of CDK earlier than about 1\.85\.x\. You would see the same changes upgrading to the latest v1\.x release\. You can usually resolve this by doing the following: + +1. Upgrade your app to the latest v1\.x release + +1. Remove feature flags + +1. Revise your code as necessary + +1. Deploy + +1. Upgrade to v2 + +**Note** +If your upgraded app is undeployable after the two\-stage upgrade, [report the issue](https://github.com/aws/aws-cdk/issues/new/choose)\. + +When you are ready to deploy the stacks in your app, consider deploying a copy first so you can test it\. The easiest way to do this is to deploy it into a different Region\. However, you can also change the IDs of your stacks\. After testing, be sure to destroy the testing copy with cdk destroy\. + +## Troubleshooting<a name="migrating-v2-trouble.title"></a> + +**TypeScript `'from' expected` or `';' expected` error in imports** +Upgrade to TypeScript 3\.8 or later\. + +**Run 'cdk bootstrap'** +If you see an error like the following: + +``` +❌ MyStack failed: Error: MyStack: SSM parameter /cdk-bootstrap/hnb659fds/version not found. Has the environment been bootstrapped? Please run 'cdk bootstrap' (see https://docs.aws.amazon.com/cdk/latest/guide/bootstrapping.html) + at CloudFormationDeployments.validateBootstrapStackVersion (.../aws-cdk/lib/api/cloudformation-deployments.ts:323:13) + at processTicksAndRejections (internal/process/task_queues.js:97:5) +MyStack: SSM parameter /cdk-bootstrap/hnb659fds/version not found. Has the environment been bootstrapped? Please run 'cdk bootstrap' (see https://docs.aws.amazon.com/cdk/latest/guide/bootstrapping.html) +``` + +AWS CDK v2 requires an updated bootstrap stack, and furthermore, all v2 deployments require bootstrap resources\. \(With v1, you could deploy simple stacks without bootstrapping\.\) For complete details, see [Bootstrapping](bootstrapping.md)\. + +## Finding v1 stacks<a name="finding-v1-stacks.title"></a> + +When migrating your CDK application from v1 to v2, you might want to identify the deployed AWS CloudFormation stacks that were created using v1\. To do this, run the following command: + +``` +npx awscdk-v1-stack-finder +``` + +For usage details, see the awscdk\-v1\-stack\-finder [README](https://github.com/cdklabs/awscdk-v1-stack-finder/blob/main/README.md)\. \ No newline at end of file diff --git a/v2/multiple_languages.md b/v2/multiple_languages.md new file mode 100644 index 00000000..9633fc8b --- /dev/null +++ b/v2/multiple_languages.md @@ -0,0 +1,432 @@ +# Translating TypeScript AWS CDK code to other languages<a name="multiple_languages"></a> + +TypeScript was the first language supported for developing AWS CDK applications\. Therefore, a substantial amount of example CDK code is written in TypeScript\. If you are developing in another language, it might be useful to compare how AWS CDK code is implemented in TypeScript and your language of choice\. This can help you use these examples\. + +For more details on working with the AWS CDK in its supported programming languages, see: ++ [Working with the AWS CDK in TypeScript](work-with-cdk-typescript.md) ++ [Working with the AWS CDK in JavaScript](work-with-cdk-javascript.md) ++ [Working with the AWS CDK in Python](work-with-cdk-python.md) ++ [Working with the AWS CDK in Java](work-with-cdk-java.md) ++ [Working with the AWS CDK in C\#](work-with-cdk-csharp.md) ++ [Working with the AWS CDK in Go](work-with-cdk-go.md) + +## Importing a module<a name="multiple_languages_import"></a> + +------ +#### [ TypeScript/JavaScript ] + +TypeScript supports importing either an entire namespace, or individual objects from a namespace\. Each namespace includes constructs and other classes for use with a given AWS service\. + +``` +// Import main CDK library as cdk +import * as cdk from 'aws-cdk-lib'; // ES6 import preferred in TS +const cdk = require('aws-cdk-lib'); // Node.js require() preferred in JS + +// Import specific core CDK classes +import { Stack, App } from 'aws-cdk-lib'; +const { Stack, App } = require('aws-cdk-lib'); + +// Import AWS S3 namespace as s3 into current namespace +import { aws_s3 as s3 } from 'aws-cdk-lib'; // TypeScript +const s3 = require('aws-cdk-lib/aws-s3'); // JavaScript + +// Having imported cdk already as above, this is also valid +const s3 = cdk.aws_s3; + +// Now use s3 to access the S3 types +const bucket = s3.Bucket(...); + +// Selective import of s3.Bucket +import { Bucket } from 'aws-cdk-lib/aws-s3'; // TypeScript +const { Bucket } = require('aws-cdk-lib/aws-s3'); // JavaScript + +// Now use Bucket to instantiate an S3 bucket +const bucket = Bucket(...); +``` + +------ + +------ +#### [ Python ] + +Like TypeScript, Python supports namespaced module imports and selective imports\. Namespaces in Python look like **aws\_cdk\.***xxx*, where *xxx* represents an AWS service name, such as **s3** for Amazon S3\. \(Amazon S3 is used in these examples\)\. + +``` +# Import main CDK library as cdk +import aws_cdk as cdk + +# Selective import of specific core classes +from aws_cdk import Stack, App + +# Import entire module as s3 into current namespace +import aws_cdk.aws_s3 as s3 + +# s3 can now be used to access classes it contains +bucket = s3.Bucket(...) + +# Selective import of s3.Bucket into current namespace +from aws_cdk.s3 import Bucket + +# Bucket can now be used to instantiate a bucket +bucket = Bucket(...) +``` + +------ +#### [ Java ] + +Java's imports work differently from TypeScript's\. Each import statement imports either a single class name from a given package, or all classes defined in that package \(using `*`\)\. Classes may be accessed using either the class name by itself if it has been imported, or the *qualified* class name including its package\. + +Libraries are named like `software.amazon.awscdk.services.xxx` for the AWS Construct Library \(the main library is `software.amazon.awscdk`\)\. The Maven group ID for AWS CDK packages is `software.amazon.awscdk`\. + +``` +// Make certain core classes available +import software.amazon.awscdk.Stack; +import software.amazon.awscdk.App; + +// Make all Amazon S3 construct library classes available +import software.amazon.awscdk.services.s3.*; + +// Make only Bucket and EventType classes available +import software.amazon.awscdk.services.s3.Bucket; +import software.amazon.awscdk.services.s3.EventType; + +// An imported class may now be accessed using the simple class name (assuming that name +// does not conflict with another class) +Bucket bucket = Bucket.Builder.create(...).build(); + +// We can always use the qualified name of a class (including its package) even without an +// import directive +software.amazon.awscdk.services.s3.Bucket bucket = + software.amazon.awscdk.services.s3.Bucket.Builder.create(...) + .build(); + +// Java 10 or later can use var keyword to avoid typing the type twice +var bucket = + software.amazon.awscdk.services.s3.Bucket.Builder.create(...) + .build(); +``` + +------ +#### [ C\# ] + +In C\#, you import types with the `using` directive\. There are two styles\. One gives you access to all the types in the specified namespace by using their plain names\. With the other, you can refer to the namespace itself by using an alias\. + +Packages are named like `Amazon.CDK.AWS.xxx` for AWS Construct Library packages\. \(The core module is `Amazon.CDK`\.\) + +``` +// Make CDK base classes available under cdk +using cdk = Amazon.CDK; + +// Make all Amazon S3 construct library classes available +using Amazon.CDK.AWS.S3; + +// Now we can access any S3 type using its name +var bucket = new Bucket(...); + +// Import the S3 namespace under an alias +using s3 = Amazon.CDK.AWS.S3; + +// Now we can access an S3 type through the namespace alias +var bucket = new s3.Bucket(...); + +// We can always use the qualified name of a type (including its namespace) even without a +// using directive +var bucket = new Amazon.CDK.AWS.S3.Bucket(...) +``` + +------ +#### [ Go ] + +Each AWS Construct Library module is provided as a Go package\. + +``` +import ( + "github.com/aws/aws-cdk-go/awscdk/v2" // CDK core package + "github.com/aws/aws-cdk-go/awscdk/v2/awss3" // AWS S3 construct library module +) + +// now instantiate a bucket +bucket := awss3.NewBucket(...) + +// use aliases for brevity/clarity +import ( + cdk "github.com/aws/aws-cdk-go/awscdk/v2" // CDK core package + s3 "github.com/aws/aws-cdk-go/awscdk/v2/awss3" // AWS S3 construct library module +) + +bucket := s3.NewBucket(...) +``` + +------ + +## Instantiating a construct<a name="multiple_languages_class"></a> + +AWS CDK construct classes have the same name in all supported languages\. Most languages use the `new` keyword to instantiate a class \(Python and Go do not\)\. Also, in most languages, the keyword `this` refers to the current instance\. \(Python uses `self` by convention\.\) You should pass a reference to the current instance as the `scope` parameter to every construct you create\. + +The third argument to an AWS CDK construct is `props`, an object containing attributes needed to build the construct\. This argument may be optional, but when it is required, the supported languages handle it in idiomatic ways\. The names of the attributes are also adapted to the language's standard naming patterns\. + +------ +#### [ TypeScript/JavaScript ] + +``` +// Instantiate default Bucket +const bucket = new s3.Bucket(this, 'MyBucket'); + +// Instantiate Bucket with bucketName and versioned properties +const bucket = new s3.Bucket(this, 'MyBucket', { + bucketName: 'my-bucket', + versioned: true, +}); + +// Instantiate Bucket with websiteRedirect, which has its own sub-properties +const bucket = new s3.Bucket(this, 'MyBucket', { + websiteRedirect: {host: 'aws.amazon.com'}}); +``` + +------ + +------ +#### [ Python ] + +Python doesn't use a `new` keyword when instantiating a class\. The properties argument is represented using keyword arguments, and the arguments are named using `snake_case`\. + +If a props value is itself a bundle of attributes, it is represented by a class named after the property, which accepts keyword arguments for the subproperties\. + +In Python, the current instance is passed to methods as the first argument, which is named `self` by convention\. + +``` +# Instantiate default Bucket +bucket = s3.Bucket(self, "MyBucket") + +# Instantiate Bucket with bucket_name and versioned properties +bucket = s3.Bucket(self, "MyBucket", bucket_name="my-bucket", versioned=true) + +# Instantiate Bucket with website_redirect, which has its own sub-properties +bucket = s3.Bucket(self, "MyBucket", website_redirect=s3.WebsiteRedirect( + host_name="aws.amazon.com")) +``` + +------ +#### [ Java ] + +In Java, the props argument is represented by a class named `XxxxProps` \(for example, `BucketProps` for the `Bucket` construct's props\)\. You build the props argument using a builder pattern\. + +Each `XxxxProps` class has a builder\. There is also a convenient builder for each construct that builds the props and the construct in one step, as shown in the following example\. + +Props are named the same as in TypeScript, using `camelCase`\. + +``` +// Instantiate default Bucket +Bucket bucket = Bucket(self, "MyBucket"); + +// Instantiate Bucket with bucketName and versioned properties +Bucket bucket = Bucket.Builder.create(self, "MyBucket") + .bucketName("my-bucket").versioned(true) + .build(); + +# Instantiate Bucket with websiteRedirect, which has its own sub-properties +Bucket bucket = Bucket.Builder.create(self, "MyBucket") + .websiteRedirect(new websiteRedirect.Builder() + .hostName("aws.amazon.com").build()) + .build(); +``` + +------ +#### [ C\# ] + +In C\#, props are specified using an object initializer to a class named `XxxxProps` \(for example, `BucketProps` for the `Bucket` construct's props\)\. + +Props are named similarly to TypeScript, except using `PascalCase`\. + +It is convenient to use the `var` keyword when instantiating a construct, so you don't need to type the class name twice\. However, your local code style guide may vary\. + +``` +// Instantiate default Bucket +var bucket = Bucket(self, "MyBucket"); + +// Instantiate Bucket with BucketName and Versioned properties +var bucket = Bucket(self, "MyBucket", new BucketProps { + BucketName = "my-bucket", + Versioned = true}); + +// Instantiate Bucket with WebsiteRedirect, which has its own sub-properties +var bucket = Bucket(self, "MyBucket", new BucketProps { + WebsiteRedirect = new WebsiteRedirect { + HostName = "aws.amazon.com" + }}); +``` + +------ +#### [ Go ] + +To create a construct in Go, call the function `NewXxxxxx` where `Xxxxxxx` is the name of the construct\. The constructs' properties are defined as a struct\. + +In Go, all construct parameters are pointers, including values like numbers, Booleans, and strings\. Use the convenience functions like `jsii.String` to create these pointers\. + +``` + // Instantiate default Bucket + bucket := awss3.NewBucket(stack, jsii.String("MyBucket"), nil) + + // Instantiate Bucket with BucketName and Versioned properties + bucket1 := awss3.NewBucket(stack, jsii.String("MyBucket"), &awss3.BucketProps{ + BucketName: jsii.String("my-bucket"), + Versioned: jsii.Bool(true), + }) + + // Instantiate Bucket with WebsiteRedirect, which has its own sub-properties + bucket2 := awss3.NewBucket(stack, jsii.String("MyBucket"), &awss3.BucketProps{ + WebsiteRedirect: &awss3.RedirectTarget{ + HostName: jsii.String("aws.amazon.com"), + }}) +``` + +------ + +## Accessing members<a name="multiple_languages_members"></a> + +It is common to refer to attributes or properties of constructs and other AWS CDK classes and use these values as, for example, inputs to build other constructs\. The naming differences described previously for methods apply here also\. Furthermore, in Java, it is not possible to access members directly\. Instead, a getter method is provided\. + +------ +#### [ TypeScript/JavaScript ] + +Names are `camelCase`\. + +``` +bucket.bucketArn +``` + +------ + +------ +#### [ Python ] + +Names are `snake_case`\. + +``` +bucket.bucket_arn +``` + +------ +#### [ Java ] + +A getter method is provided for each property; these names are `camelCase`\. + +``` +bucket.getBucketArn() +``` + +------ +#### [ C\# ] + +Names are `PascalCase`\. + +``` +bucket.BucketArn +``` + +------ +#### [ Go ] + +Names are `PascalCase`\. + +``` +bucket.BucketArn +``` + +------ + +## Enum constants<a name="multiple_languages_enums"></a> + +Enum constants are scoped to a class, and have uppercase names with underscores in all languages \(sometimes referred to as `SCREAMING_SNAKE_CASE`\)\. Since class names also use the same casing in all supported languages except Go, qualified enum names are also the same in these languages\. + +``` +s3.BucketEncryption.KMS_MANAGED +``` + +In Go, enum constants are attributes of the module namespace and are written as follows\. + +``` +awss3.BucketEncryption_KMS_MANAGED +``` + +## Object interfaces<a name="multiple_languages_object"></a> + +The AWS CDK uses TypeScript object interfaces to indicate that a class implements an expected set of methods and properties\. You can recognize an object interface because its name starts with `I`\. A concrete class indicates the interfaces that it implements by using the `implements` keyword\. + +------ +#### [ TypeScript/JavaScript ] + +**Note** +JavaScript doesn't have an interface feature\. You can ignore the `implements` keyword and the class names following it\. + +``` +import { IAspect, IConstruct } from 'aws-cdk-lib'; + +class MyAspect implements IAspect { + public visit(node: IConstruct) { + console.log('Visited', node.node.path); + } +} +``` + +------ + +------ +#### [ Python ] + +Python doesn't have an interface feature\. However, for the AWS CDK you can indicate interface implementation by decorating your class with `@jsii.implements(interface)`\. + +``` +from aws_cdk import IAspect, IConstruct +import jsii + +@jsii.implements(IAspect) +class MyAspect(): + def visit(self, node: IConstruct) -> None: + print("Visited", node.node.path) +``` + +------ +#### [ Java ] + +``` +import software.amazon.awscdk.IAspect; +import software.amazon.awscdk.IConstruct; + +public class MyAspect implements IAspect { + public void visit(IConstruct node) { + System.out.format("Visited %s", node.getNode().getPath()); + } +} +``` + +------ +#### [ C\# ] + +``` +using Amazon.CDK; + +public class MyAspect : IAspect +{ + public void Visit(IConstruct node) + { + System.Console.WriteLine($"Visited ${node.Node.Path}"); + } +} +``` + +------ +#### [ Go ] + +Go structs do not need to explicitly declare which interfaces they implement\. The Go compiler determines implementation based on the methods and properties available on the structure\. For example, in the following code, `MyAspect` implements the `IAspect` interface because it provides a `Visit` method that takes a construct\. + +``` +type MyAspect struct { +} + +func (a MyAspect) Visit(node constructs.IConstruct) { + fmt.Println("Visited", *node.Node().Path()) +} +``` + +------ \ No newline at end of file diff --git a/v2/parameters.md b/v2/parameters.md new file mode 100644 index 00000000..65721b05 --- /dev/null +++ b/v2/parameters.md @@ -0,0 +1,208 @@ +# Parameters<a name="parameters"></a> + +AWS CloudFormation templates can contain [parameters](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html)—custom values that are supplied at deployment time and incorporated into the template\. Because the AWS CDK synthesizes AWS CloudFormation templates, it also offers support for deployment\-time parameters\. + +Using the AWS CDK, you can define parameters, which can then be used in the properties of constructs you create\. You can also deploy stacks that contain parameters\. + +When deploying the AWS CloudFormation template using the AWS CDK Toolkit, you provide the parameter values on the command line\. If you deploy the template through the AWS CloudFormation console, you are prompted for the parameter values\. + +In general, we recommend against using AWS CloudFormation parameters with the AWS CDK\. The usual ways to pass values into AWS CDK apps are [context values](context.md) and environment variables\. Because they are not available at synthesis time, parameter values cannot be easily used for flow control and other purposes in your CDK app\. + +**Note** +To do control flow with parameters, you can use [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.CfnCondition.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.CfnCondition.html) constructs, although this is awkward compared to native `if` statements\. + +Using parameters requires you to be mindful of how the code you're writing behaves at deployment time, and also at synthesis time\. This makes it harder to understand and reason about your AWS CDK application, in many cases for little benefit\. + +Generally, it's better to have your CDK app accept necessary information in a well\-defined way and use it directly to declare constructs in your CDK app\. An ideal AWS CDK\-generated AWS CloudFormation template is concrete, with no values remaining to be specified at deployment time\. + +There are, however, use cases to which AWS CloudFormation parameters are uniquely suited\. If you have separate teams defining and deploying infrastructure, for example, you can use parameters to make the generated templates more widely useful\. Also, because the AWS CDK supports AWS CloudFormation parameters, you can use the AWS CDK with AWS services that use AWS CloudFormation templates \(such as AWS Service Catalog\)\. These AWS services use parameters to configure the template that's being deployed\. + +## Defining parameters<a name="parameters_define"></a> + +Use the [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.CfnParameter.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.CfnParameter.html) class to define a parameter\. You'll want to specify at least a type and a description for most parameters, though both are technically optional\. The description appears when the user is prompted to enter the parameter's value in the AWS CloudFormation console\. For more information on the available types, see [Types](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html#parameters-section-structure-properties-type)\. + +**Note** +You can define parameters in any scope\. However, we recommend defining parameters at the stack level so that their logical ID doesn't change when you refactor your code\. + +------ +#### [ TypeScript ] + +``` +const uploadBucketName = new CfnParameter(this, "uploadBucketName", { + type: "String", + description: "The name of the Amazon S3 bucket where uploaded files will be stored."}); +``` + +------ +#### [ JavaScript ] + +``` +const uploadBucketName = new CfnParameter(this, "uploadBucketName", { + type: "String", + description: "The name of the Amazon S3 bucket where uploaded files will be stored."}); +``` + +------ +#### [ Python ] + +``` +upload_bucket_name = CfnParameter(self, "uploadBucketName", type="String", + description="The name of the Amazon S3 bucket where uploaded files will be stored.") +``` + +------ +#### [ Java ] + +``` +CfnParameter uploadBucketName = CfnParameter.Builder.create(this, "uploadBucketName") + .type("String") + .description("The name of the Amazon S3 bucket where uploaded files will be stored") + .build(); +``` + +------ +#### [ C\# ] + +``` +var uploadBucketName = new CfnParameter(this, "uploadBucketName", new CfnParameterProps +{ + Type = "String", + Description = "The name of the Amazon S3 bucket where uploaded files will be stored" +}); +``` + +------ + +## Using parameters<a name="parameters_use"></a> + +A `CfnParameter` instance exposes its value to your AWS CDK app via a [token](tokens.md)\. Like all tokens, the parameter's token is resolved at synthesis time\. But it resolves to a reference to the parameter defined in the AWS CloudFormation template \(which will be resolved at deploy time\), rather than to a concrete value\. + +You can retrieve the token as an instance of the `Token` class, or in string, string list, or numeric encoding\. Your choice depends on the kind of value required by the class or method that you want to use the parameter with\. + +------ +#### [ TypeScript ] + + +| Property | kind of value | +| --- |--- | +| value | Token class instance | +| valueAsList | The token represented as a string list | +| valueAsNumber | The token represented as a number | +| valueAsString | The token represented as a string | + +------ +#### [ JavaScript ] + + +| Property | kind of value | +| --- |--- | +| value | Token class instance | +| valueAsList | The token represented as a string list | +| valueAsNumber | The token represented as a number | +| valueAsString | The token represented as a string | + +------ +#### [ Python ] + + +| Property | kind of value | +| --- |--- | +| value | Token class instance | +| value\_as\_list | The token represented as a string list | +| value\_as\_number | The token represented as a number | +| value\_as\_string | The token represented as a string | + +------ +#### [ Java ] + + +| Property | kind of value | +| --- |--- | +| getValue\(\) | Token class instance | +| getValueAsList\(\) | The token represented as a string list | +| getValueAsNumber\(\) | The token represented as a number | +| getValueAsString\(\) | The token represented as a string | + +------ +#### [ C\# ] + + +| Property | kind of value | +| --- |--- | +| Value | Token class instance | +| ValueAsList | The token represented as a string list | +| ValueAsNumber | The token represented as a number | +| ValueAsString | The token represented as a string | + +------ + +For example, to use a parameter in a `Bucket` definition: + +------ +#### [ TypeScript ] + +``` +const bucket = new Bucket(this, "myBucket", + { bucketName: uploadBucketName.valueAsString}); +``` + +------ +#### [ JavaScript ] + +``` +const bucket = new Bucket(this, "myBucket", + { bucketName: uploadBucketName.valueAsString}); +``` + +------ +#### [ Python ] + +``` +bucket = Bucket(self, "myBucket", + bucket_name=upload_bucket_name.value_as_string) +``` + +------ +#### [ Java ] + +``` +Bucket bucket = Bucket.Builder.create(this, "myBucket") + .bucketName(uploadBucketName.getValueAsString()) + .build(); +``` + +------ +#### [ C\# ] + +``` +var bucket = new Bucket(this, "myBucket") +{ + BucketName = uploadBucketName.ValueAsString +}; +``` + +------ + +## Deploying with parameters<a name="parameters_deploy"></a> + +A generated template containing parameters can be deployed in the usual way through the AWS CloudFormation console\. You are prompted for the values of each parameter\. + +The AWS CDK Toolkit \(`cdk` command line tool\) also supports specifying parameters at deployment\. You provide these on the command line following the `--parameters` flag\. You might deploy a stack that uses the `uploadBucketName` parameter, like the following example\. + +``` +cdk deploy MyStack --parameters uploadBucketName=uploadbucket +``` + +To define multiple parameters, use multiple `--parameters` flags\. + +``` +cdk deploy MyStack --parameters uploadBucketName=upbucket --parameters downloadBucketName=downbucket +``` + +If you are deploying multiple stacks, you can specify a different value of each parameter for each stack\. To do so, prefix the name of the parameter with the stack name and a colon\. + +``` +cdk deploy MyStack YourStack --parameters MyStack:uploadBucketName=uploadbucket --parameters YourStack:uploadBucketName=upbucket +``` + +By default, the AWS CDK retains values of parameters from previous deployments and uses them in subsequent deployments if they are not specified explicitly\. Use the `--no-previous-parameters` flag to require all parameters to be specified\. \ No newline at end of file diff --git a/v2/permissions.md b/v2/permissions.md new file mode 100644 index 00000000..a5806904 --- /dev/null +++ b/v2/permissions.md @@ -0,0 +1,522 @@ +# Permissions<a name="permissions"></a> + +The AWS Construct Library uses a few common, widely implemented idioms to manage access and permissions\. The IAM module provides you with the tools you need to use these idioms\. + +## Principals<a name="permissions_principals"></a> + +An IAM principal is an authenticated AWS entity representing a user, service, or application that can call AWS APIs\. The AWS Construct Library supports specifying principals in several flexible ways to grant them access your AWS resources\. + +In security contexts, the term "principal" refers specifically to authenticated entities such as users\. Objects like groups and roles do not *represent* users \(and other authenticated entities\) but rather *identify* them indirectly for the purpose of granting permissions\. + +For example, if you create an IAM group, you can grant the group \(and thus its members\) write access to an Amazon RDS table\. However, the group itself is not a principal because it doesn't represent a single entity \(also, you cannot log in to a group\)\. + +In the CDK's IAM library, classes that directly or indirectly identify principals implement the [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.IPrincipal.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.IPrincipal.html) interface, allowing these objects to be used interchangeably in access policies\. However, not all of them are principals in the security sense\. These objects include: + +1. IAM resources such as `[Role](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html)`, `[User](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.User.html)`, and `[Group](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Group.html)` + +1. Service principals \(`new iam.[ServicePrincipal](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.ServicePrincipal.html)('service.amazonaws.com')`\) + +1. Federated principals \(`new iam.[FederatedPrincipal](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.FederatedPrincipal.html)('cognito-identity.amazonaws.com')`\) + +1. Account principals \(`new iam.[AccountPrincipal](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.AccountPrincipal.html)('0123456789012'))` + +1. Canonical user principals \(`new iam.[CanonicalUserPrincipal](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.CanonicalUserPrincipal.html)('79a59d[...]7ef2be')`\) + +1. AWS Organizations principals \(`new iam.[OrganizationPrincipal](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.OrganizationPrincipal.html)('org-id')`\) + +1. Arbitrary ARN principals \(`new iam.[ArnPrincipal](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.ArnPrincipal.html)(res.arn)`\) + +1. An `iam.[CompositePrincipal](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.CompositePrincipal.html)(principal1, principal2, ...)` to trust multiple principals + +## Grants<a name="permissions_grants"></a> + +Every construct that represents a resource that can be accessed, such as an Amazon S3 bucket or Amazon DynamoDB table, has methods that grant access to another entity\. All such methods have names starting with **grant**\. + +For example, Amazon S3 buckets have the methods `[grantRead](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html#grantwbrreadidentity-objectskeypattern)` and `[grantReadWrite](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html#grantwbrreadwbrwriteidentity-objectskeypattern)` \(Python: `grant_read`, `grant_read_write`\) to enable read and read/write access, respectively, from an entity to the bucket\. The entity doesn't have to know exactly which Amazon S3 IAM permissions are required to perform these operations\. + +The first argument of a **grant** method is always of type [IGrantable](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.IGrantable.html)\. This interface represents entities that can be granted permissions\. That is, it represents resources with roles, such as the IAM objects `[Role](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html)`, `[User](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.User.html)`, and `[Group](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.User.html)`\. + +Other entities can also be granted permissions\. For example, later in this topic, we show how to grant a CodeBuild project access to an Amazon S3 bucket\. Generally, the associated role is obtained via a `role` property on the entity being granted access\. + +Resources that use execution roles, such as `[lambda\.Function](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.Function.html)`, also implement `IGrantable`, so you can grant them access directly instead of granting access to their role\. For example, if `bucket` is an Amazon S3 bucket, and `function` is a Lambda function, the following code grants the function read access to the bucket\. + +------ +#### [ TypeScript ] + +``` +bucket.grantRead(function); +``` + +------ +#### [ JavaScript ] + +``` +bucket.grantRead(function); +``` + +------ +#### [ Python ] + +``` +bucket.grant_read(function) +``` + +------ +#### [ Java ] + +``` +bucket.grantRead(function); +``` + +------ +#### [ C\# ] + +``` +bucket.GrantRead(function); +``` + +------ + + Sometimes permissions must be applied while your stack is being deployed\. One such case is when you grant an AWS CloudFormation custom resource access to some other resource\. The custom resource will be invoked during deployment, so it must have the specified permissions at deployment time\. + +Another case is when a service verifies that the role you pass to it has the right policies applied\. \(A number of AWS services do this to make sure that you didn't forget to set the policies\.\) In those cases, the deployment might fail if the permissions are applied too late\. + + To force the grant's permissions to be applied before another resource is created, you can add a dependency on the grant itself, as shown here\. Though the return value of grant methods is commonly discarded, every grant method in fact returns an `iam.Grant` object\. + +------ +#### [ TypeScript ] + +``` +const grant = bucket.grantRead(lambda); +const custom = new CustomResource(...); +custom.node.addDependency(grant); +``` + +------ +#### [ JavaScript ] + +``` +const grant = bucket.grantRead(lambda); +const custom = new CustomResource(...); +custom.node.addDependency(grant); +``` + +------ +#### [ Python ] + +``` +grant = bucket.grant_read(function) +custom = CustomResource(...) +custom.node.add_dependency(grant) +``` + +------ +#### [ Java ] + +``` +Grant grant = bucket.grantRead(function); +CustomResource custom = new CustomResource(...); +custom.node.addDependency(grant); +``` + +------ +#### [ C\# ] + +``` +var grant = bucket.GrantRead(function); +var custom = new CustomResource(...); +custom.node.AddDependency(grant); +``` + +------ + +## Roles<a name="permissions_roles"></a> + +The IAM package contains a `[Role](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html)` construct that represents IAM roles\. The following code creates a new role, trusting the Amazon EC2 service\. + +------ +#### [ TypeScript ] + +``` +import * as iam from 'aws-cdk-lib/aws-iam'; + +const role = new iam.Role(this, 'Role', { + assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com'), // required +}); +``` + +------ +#### [ JavaScript ] + +``` +const iam = require('aws-cdk-lib/aws-iam'); + +const role = new iam.Role(this, 'Role', { + assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com') // required +}); +``` + +------ +#### [ Python ] + +``` +import aws_cdk.aws_iam as iam + +role = iam.Role(self, "Role", + assumed_by=iam.ServicePrincipal("ec2.amazonaws.com")) # required +``` + +------ +#### [ Java ] + +``` +import software.amazon.awscdk.services.iam.Role; +import software.amazon.awscdk.services.iam.ServicePrincipal; + +Role role = Role.Builder.create(this, "Role") + .assumedBy(new ServicePrincipal("ec2.amazonaws.com")).build(); +``` + +------ +#### [ C\# ] + +``` +using Amazon.CDK.AWS.IAM; + +var role = new Role(this, "Role", new RoleProps +{ + AssumedBy = new ServicePrincipal("ec2.amazonaws.com"), // required +}); +``` + +------ + +You can add permissions to a role by calling the role's `[addToPolicy](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html#addwbrtowbrpolicystatement)` method \(Python: `add_to_policy`\), passing in a `[PolicyStatement](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.PolicyStatement.html)` that defines the rule to be added\. The statement is added to the role's default policy; if it has none, one is created\. + + The following example adds a `Deny` policy statement to the role for the actions `ec2:SomeAction` and `s3:AnotherAction` on the resources `bucket` and `otherRole` \(Python: `other_role`\), under the condition that the authorized service is AWS CodeBuild\. + +------ +#### [ TypeScript ] + +``` +role.addToPolicy(new iam.PolicyStatement({ + effect: iam.Effect.DENY, + resources: [bucket.bucketArn, otherRole.roleArn], + actions: ['ec2:SomeAction', 's3:AnotherAction'], + conditions: {StringEquals: { + 'ec2:AuthorizedService': 'codebuild.amazonaws.com', +}}})); +``` + +------ +#### [ JavaScript ] + +``` +role.addToPolicy(new iam.PolicyStatement({ + effect: iam.Effect.DENY, + resources: [bucket.bucketArn, otherRole.roleArn], + actions: ['ec2:SomeAction', 's3:AnotherAction'], + conditions: {StringEquals: { + 'ec2:AuthorizedService': 'codebuild.amazonaws.com' +}}})); +``` + +------ +#### [ Python ] + +``` +role.add_to_policy(iam.PolicyStatement( + effect=iam.Effect.DENY, + resources=[bucket.bucket_arn, other_role.role_arn], + actions=["ec2:SomeAction", "s3:AnotherAction"], + conditions={"StringEquals": { + "ec2:AuthorizedService": "codebuild.amazonaws.com"}} +)) +``` + +------ +#### [ Java ] + +``` +role.addToPolicy(PolicyStatement.Builder.create() + .effect(Effect.DENY) + .resources(Arrays.asList(bucket.getBucketArn(), otherRole.getRoleArn())) + .actions(Arrays.asList("ec2:SomeAction", "s3:AnotherAction")) + .conditions(java.util.Map.of( // Map.of requires Java 9 or later + "StringEquals", java.util.Map.of( + "ec2:AuthorizedService", "codebuild.amazonaws.com"))) + .build()); +``` + +------ +#### [ C\# ] + +``` +role.AddToPolicy(new PolicyStatement(new PolicyStatementProps +{ + Effect = Effect.DENY, + Resources = new string[] { bucket.BucketArn, otherRole.RoleArn }, + Actions = new string[] { "ec2:SomeAction", "s3:AnotherAction" }, + Conditions = new Dictionary<string, object> + { + ["StringEquals"] = new Dictionary<string, string> + { + ["ec2:AuthorizedService"] = "codebuild.amazonaws.com" + } + } +})); +``` + +------ + + In the preceding example, we've created a new `[PolicyStatement](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.PolicyStatement.html)` inline with the `[addToPolicy](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html#addwbrtowbrpolicystatement)` \(Python: `add_to_policy`\) call\. You can also pass in an existing policy statement or one you've modified\. The [PolicyStatement](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.PolicyStatement.html) object has [numerous methods](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.PolicyStatement.html#methods) for adding principals, resources, conditions, and actions\. + +If you're using a construct that requires a role to function correctly, you can do one of the following: ++ Pass in an existing role when instantiating the construct object\. ++ Let the construct create a new role for you, trusting the appropriate service principal\. The following example uses such a construct: a CodeBuild project\. + +------ +#### [ TypeScript ] + +``` +import * as codebuild from 'aws-cdk-lib/aws-codebuild'; + +// imagine roleOrUndefined is a function that might return a Role object +// under some conditions, and undefined under other conditions +const someRole: iam.IRole | undefined = roleOrUndefined(); + +const project = new codebuild.Project(this, 'Project', { + // if someRole is undefined, the Project creates a new default role, + // trusting the codebuild.amazonaws.com service principal + role: someRole, +}); +``` + +------ +#### [ JavaScript ] + +``` +const codebuild = require('aws-cdk-lib/aws-codebuild'); + +// imagine roleOrUndefined is a function that might return a Role object +// under some conditions, and undefined under other conditions +const someRole = roleOrUndefined(); + +const project = new codebuild.Project(this, 'Project', { + // if someRole is undefined, the Project creates a new default role, + // trusting the codebuild.amazonaws.com service principal + role: someRole +}); +``` + +------ +#### [ Python ] + +``` +import aws_cdk.aws_codebuild as codebuild + +# imagine role_or_none is a function that might return a Role object +# under some conditions, and None under other conditions +some_role = role_or_none(); + +project = codebuild.Project(self, "Project", +# if role is None, the Project creates a new default role, +# trusting the codebuild.amazonaws.com service principal +role=some_role) +``` + +------ +#### [ Java ] + +``` +import software.amazon.awscdk.services.iam.Role; +import software.amazon.awscdk.services.codebuild.Project; + +// imagine roleOrNull is a function that might return a Role object +// under some conditions, and null under other conditions +Role someRole = roleOrNull(); + +// if someRole is null, the Project creates a new default role, +// trusting the codebuild.amazonaws.com service principal +Project project = Project.Builder.create(this, "Project") + .role(someRole).build(); +``` + +------ +#### [ C\# ] + +``` +using Amazon.CDK.AWS.CodeBuild; + +// imagine roleOrNull is a function that might return a Role object +// under some conditions, and null under other conditions +var someRole = roleOrNull(); + +// if someRole is null, the Project creates a new default role, +// trusting the codebuild.amazonaws.com service principal +var project = new Project(this, "Project", new ProjectProps +{ + Role = someRole +}); +``` + +------ + +Once the object is created, the role \(whether the role passed in or the default one created by the construct\) is available as the property `role`\. However, this property is not available on external resources\. Therefore, these constructs have an `addToRolePolicy` \(Python: `add_to_role_policy`\) method\. + +The method does nothing if the construct is an external resource, and it calls the `addToPolicy` \(Python: `add_to_policy`\) method of the `role` property otherwise\. This saves you the trouble of handling the undefined case explicitly\. + +The following example demonstrates: + +------ +#### [ TypeScript ] + +``` +// project is imported into the CDK application +const project = codebuild.Project.fromProjectName(this, 'Project', 'ProjectName'); + +// project is imported, so project.role is undefined, and this call has no effect +project.addToRolePolicy(new iam.PolicyStatement({ + effect: iam.Effect.ALLOW, // ... and so on defining the policy +})); +``` + +------ +#### [ JavaScript ] + +``` +// project is imported into the CDK application +const project = codebuild.Project.fromProjectName(this, 'Project', 'ProjectName'); + +// project is imported, so project.role is undefined, and this call has no effect +project.addToRolePolicy(new iam.PolicyStatement({ + effect: iam.Effect.ALLOW // ... and so on defining the policy +})); +``` + +------ +#### [ Python ] + +``` +# project is imported into the CDK application +project = codebuild.Project.from_project_name(self, 'Project', 'ProjectName') + +# project is imported, so project.role is undefined, and this call has no effect +project.add_to_role_policy(iam.PolicyStatement( + effect=iam.Effect.ALLOW, # ... and so on defining the policy +) +``` + +------ +#### [ Java ] + +``` +// project is imported into the CDK application +Project project = Project.fromProjectName(this, "Project", "ProjectName"); + +// project is imported, so project.getRole() is null, and this call has no effect +project.addToRolePolicy(PolicyStatement.Builder.create() + .effect(Effect.ALLOW) // .. and so on defining the policy + .build(); +``` + +------ +#### [ C\# ] + +``` +// project is imported into the CDK application +var project = Project.FromProjectName(this, "Project", "ProjectName"); + +// project is imported, so project.role is null, and this call has no effect +project.AddToRolePolicy(new PolicyStatement(new PolicyStatementProps +{ + Effect = Effect.ALLOW, // ... and so on defining the policy +})); +``` + +------ + +## Resource policies<a name="permissions_resource_policies"></a> + +A few resources in AWS, such as Amazon S3 buckets and IAM roles, also have a resource policy\. These constructs have an `addToResourcePolicy` method \(Python: `add_to_resource_policy`\), which takes a `[PolicyStatement](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.PolicyStatement.html)` as its argument\. Every policy statement added to a resource policy must specify at least one principal\. + +In the following example, the [Amazon S3 bucket](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html) `bucket` grants a role with the `s3:SomeAction` permission to itself\. + +------ +#### [ TypeScript ] + +``` +bucket.addToResourcePolicy(new iam.PolicyStatement({ + effect: iam.Effect.ALLOW, + actions: ['s3:SomeAction'], + resources: [bucket.bucketArn], + principals: [role] +})); +``` + +------ +#### [ JavaScript ] + +``` +bucket.addToResourcePolicy(new iam.PolicyStatement({ + effect: iam.Effect.ALLOW, + actions: ['s3:SomeAction'], + resources: [bucket.bucketArn], + principals: [role] +})); +``` + +------ +#### [ Python ] + +``` +bucket.add_to_resource_policy(iam.PolicyStatement( + effect=iam.Effect.ALLOW, + actions=["s3:SomeAction"], + resources=[bucket.bucket_arn], + principals=role)) +``` + +------ +#### [ Java ] + +``` +bucket.addToResourcePolicy(PolicyStatement.Builder.create() + .effect(Effect.ALLOW) + .actions(Arrays.asList("s3:SomeAction")) + .resources(Arrays.asList(bucket.getBucketArn())) + .principals(Arrays.asList(role)) + .build()); +``` + +------ +#### [ C\# ] + +``` +bucket.AddToResourcePolicy(new PolicyStatement(new PolicyStatementProps +{ + Effect = Effect.ALLOW, + Actions = new string[] { "s3:SomeAction" }, + Resources = new string[] { bucket.BucketArn }, + Principals = new IPrincipal[] { role } +})); +``` + +------ + +## Using external IAM objects<a name="permissions_existing"></a> + +If you have defined an IAM user, principal, group, or role outside your AWS CDK app, you can use that IAM object in your AWS CDK app\. To do so, create a reference to it using its ARN or its name\. \(Use the name for users, groups, and roles\.\) The returned reference can then be used to grant permissions or to construct policy statements as explained previously\. ++ For users, call `[User\.fromUserArn\(\)](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.User.html#static-fromwbruserwbrarnscope-id-userarn)` or `[User\.fromUserName\(\)](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.User.html#static-fromwbruserwbrnamescope-id-username)`\. `User.fromUserAttributes()` is also available, but currently provides the same functionality as `User.fromUserArn()`\. ++ For principals, instantiate an `[ArnPrincipal](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.ArnPrincipal.html)` object\. ++ For groups, call `[Group\.fromGroupArn\(\)](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Group.html#static-fromwbrgroupwbrarnscope-id-grouparn)` or `[Group\.fromGroupName\(\)](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Group.html#static-fromwbrgroupwbrnamescope-id-groupname)`\. ++ For roles, call `[Role\.fromRoleArn\(\)](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html#static-fromwbrrolewbrarnscope-id-rolearn-options)` or `[Role\.fromRoleName\(\)](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html#static-fromwbrrolewbrnamescope-id-rolename)`\. + +Policies \(including managed policies\) can be used in similar fashion using the following methods\. You can use references to these objects anywhere an IAM policy is required\. ++ `[Policy\.fromPolicyName](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Policy.html#static-fromwbrpolicywbrnamescope-id-policyname)` ++ `[ManagedPolicy\.fromManagedPolicyArn](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.ManagedPolicy.html#static-fromwbrmanagedwbrpolicywbrarnscope-id-managedpolicyarn)` ++ `[ManagedPolicy\.fromManagedPolicyName](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.ManagedPolicy.html#static-fromwbrmanagedwbrpolicywbrnamescope-id-managedpolicyname)` ++ `[ManagedPolicy\.fromAwsManagedPolicyName](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.ManagedPolicy.html#static-fromwbrawswbrmanagedwbrpolicywbrnamemanagedpolicyname)` + +**Note** +As with all references to external AWS resources, you cannot modify external IAM objects in your CDK app\. \ No newline at end of file diff --git a/v2/pgp-keys.md b/v2/pgp-keys.md new file mode 100644 index 00000000..05c1957b --- /dev/null +++ b/v2/pgp-keys.md @@ -0,0 +1,298 @@ +# OpenPGP keys for the AWS CDK and jsii<a name="pgp-keys"></a> + +This topic contains current and historical OpenPGP keys for the AWS CDK and jsii\. + +## Current keys<a name="pgp-keys-current"></a> + +These keys should be used to validate current releases of the AWS CDK and jsii\. + +### AWS CDK OpenPGP key<a name="cdk_pgp_key"></a> + + +| | | +| --- |--- | +| Key ID: | 0x42B9CF2286CD987A | +| Type: | RSA | +| Size: | 4096/4096 | +| Created: | 2022\-07\-05 | +| Expires: | 2026\-07\-04 | +| User ID: | AWS Cloud Development Kit <aws\-cdk@amazon\.com> | +| Key fingerprint: | 69B5 2D5B A295 1D11 FA65 413B 42B9 CF22 86CD 987A | + +Select the "Copy" icon to copy the following OpenPGP key: + +``` +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQINBGLEgOsBEADCoAMwvnszMLybJ+AD9cHhVyX6+rYIUEXYSgVnfkl6Z7qawIwv +wgd/a5fEs9Kiz2XJmfwS9Rxb4d+0+Y1ls1A+gnpw9FMLcZlqkC9KLnS2MqvuXWLB +t3z4kjZaL9fQ+58PoD4gy/M2hDg6gZrYqR3gtJuw8FcFpb/1KlkzRQUM8eAMFxf2 +TyfjP0V0tSHwcB+84oushX7fUXVMyc3+OHsCPOe/WBFMIlWgKA+n33JKIQlUUC8f +kCWBAsAFupil0lCveT6mZu5slNRlc1I3iBLjUZ3/MtLygfqAMKwUVXeawtDvRIZe +PrAFc2NyODEhly2JG6K0FW7eIcvBqR3rg8U49t9Y74ELTM0kKnfd+flvq35xWqQC +0zghnk3kDppRTN4zWBgTKiCMxBcsHXGOoGn57t4B9VY9Zy3vkeySigeiwl/Tw9nJ +PE0SRnwEc/HnjTTfX+GTG1aQVE0xSVyZ4m5ymRNCu6+rNH8lKwo5FujlXJ+GXPkp +qT+Lx6Ix/Ny7PaoweWxwtZUkLRS4pWUsg0yotZrGyIbS+X3yMEG8WBTFI9hf6HTq +0ryfi5/TsBrdrGKqWB99EC9xYEGgtHp4fKO5X0ynOagVOhf0jSe8t1uyuJPGb2Gc +MQagSys5xMhdG/ZnEY4Cb+JDtH/4jc3tca0+4Z5RQ7kF9IhCncFtrbjJbwARAQAB +tC5BV1MgQ2xvdWQgRGV2ZWxvcG1lbnQgS2l0IDxhd3MtY2RrQGFtYXpvbi5jb20+ +iQI/BBMBAgApBQJixIDrAhsvBQkHhM4ABwsJCAcDAgEGFQgCCQoLBBYCAwECHgEC +F4AACgkQQrnPIobNmHo2qg//Zt9p/kN1DevflzxWKouUX0AS7UmUtRYXu5k/EEbu +wkYNHpUr7+lZ+Me5YyjcIpt6UwuG9cW4SvwuxIfXucyKAWiwEbydCQauvnrYDxDa +J6Yr/ntk7Sii6An9re99qic3IsvX+xlUXh+qJ/34ooP/1PHziCMqykvW/DwAIyhx +2qvTXy+9+OlOWSUbhkCnNz5XKb4XQGq73DqalZX1nH4dG6fckZmYRX+dpw2njfTw +ZLdZ7bkrfiL84FI4A21RfSbEU4s4ngiV17lZ9ivilBKTbDv3da7+yc919M7C5N4J +yrlxvtyYNDoqKAD2WYZAnpEbG/shu3f56RyOJd56tXGwl9nKPh+F9y+379XthSwA +xZTURFtjWf7wWHaDZadU0DKi+Oeeszjg2f/VJaGmmS8PIg7q6GiSHHpqHqNvACHm +ZXMw12QFd3qt3xu0JMmE11ZC5VBgblwpkQTrO04Sq1rOpJwXI9ODMS/ZEhAIoYmT +OR7ouknlAx6mj9fwpavWDAAJHLdVUMYBZTXiQYFzDvx51ivvTRWkB1zTJcFdqShY +B37+Jz2jLDNdMrcHk2yfVp/VvfbxKcexg8wEwrrtQUslTUenl5jBZJouoz/wW81s +Y4U1nCPCdTK5/C7JCKzR2gVnCpe6uaxAWkkM2feQhjqJZkTC4cFVgBT+4M6WcT1r +yq4= +=ahbs +-----END PGP PUBLIC KEY BLOCK----- +``` + +### jsii OpenPGP key<a name="jsii_pgp_key"></a> + + +| | | +| --- |--- | +| Key ID: | 0x056C4E15DAE3D8D9 | +| Type: | RSA | +| Size: | 4096/4096 | +| Created: | 2022\-07\-05 | +| Expires: | 2026\-07\-04 | +| User ID: | AWS JSII Team <aws\-jsii@amazon\.com> | +| Key fingerprint: | 1E07 31D4 57E5 FE87 87E5 530A 056C 4E15 DAE3 D8D9 | + +Select the "Copy" icon to copy the following OpenPGP key: + +``` +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQINBGLEgOkBEAD27EPVG9g2mHQ3+M6tF6le+tfhARJ2EV7m7NKIrTdSlCZATLWn +AVLlxG1unW34NlkKZbcbR86gAxRnnAhuEhPuloU/S5wAqPGbRiFl58YjYZDNJw6U +1SSMpE4O1sfjxv9yAbiRihLYtvksyHHZmaDhYner2aK1PdeWu+BKq/tjfm3Yzsd2 +uuVEduJ72YoQk/29dEiGOHfT+2kUKxUX+0tJSJ9MGlEf4NtQE4WLzrT6Xqb2SG4+ +alIiIVxIEi0XKDn7n8ZLjFwfJwOYxVYLtEUkqFWM8e8vgoc9/nYc+vDXZVED2g3Z +FWrwSnDSXbQpnMa2cLhD4xLpDHUS3i2p7r3dkJQGLo/5JGOopLibrOAbYZ72izhu +H/TuPFogSz0mNFPglrWdnLF04UIjIq420+06V4WQZC9n55Zjcbki/OhnC3B9pAdU +tiy8zg070bWq45dPGf5STkPPn7G8A2zmKefyO51iLIi26ZzW78siB+FvcGRhdg25 +39sHJ1cmrTeC+B+k4KeV5sQ/m3UucimrZnk1xdaiVp8mWzRqWb8bB6Rs8K9RMrMV +tFBOKOBAT2QxOQtRGAantVgm193E1T1cmNpD0FKAKkDdPs64rKBEwFiHxccXHbah +eMd1weVwn3AKFD6uAm8ZRMV+dyssfcQxqpo/kfT1XpA6cQeOmGDOcKBfdwARAQAB +tCNBV1MgSlNJSSBUZWFtIDxhd3MtanNpaUBhbWF6b24uY29tPokCPwQTAQIAKQUC +YsSA6QIbLwUJB4TOAAcLCQgHAwIBBhUIAgkKCwQWAgMBAh4BAheAAAoJEAVsThXa +49jZjU4QANoyqOJUT4gRrXshE3N0mW5Ad4i8Ke09GA62HyvTtfbsA+2nkNVGJpXm +sFMzdaFO95Q65RkLS9vW4nhhjXBEc2XYNCt2AnARudA/41ykjDPwU112z9ZTB9he +y4ItIeNGpHvMWr51fihl0y2nkpODOBeiv44jscLbHyOmZfki1f5fuIu2U2IbUGK3 +5FtYyeHcgRHnpYkzLuzK4PfayOywqQPJ7M9DWrHf+v5Cu4ZCZDOIKfzF+ew7MWwc +6KaoWHCYbFpX8jxFppbGsSFOQ8Sl2quoP0TLz9Wsq70Khi6C2P8JI6lm0HRLO+1M +jFbQxNOwAcN3k4HSwunAjXBlmT/6oc1RsdBdpXBaZ2AWseIXwSYZqNXp+5L179uZ +vSiD3DSSUqLJbdQRVOsJi3/87V5QU59byq2dToHveRjtSbVnK0TkTx9ZlgkcpjvM +BwHNqWhratV6af2Upjq2YQ0fdSB42f3pgopInxNJPMvlAb+cCfr0Pfwu7ge7UooQ +WHTxbpCvwtn/HNctMGpWscO02WsWgoYVjnVFay/XphE77pQ9rRUkhMe6VKXfxj/n +OCZJKrydluIIwR8vvONNqO+QwZ1xDEhO7MaSZlOm1AuUZIXFPgaWQkPZHKiiwFA/ +QWnL/+shuRtMH2geTjkev198Jgb5HyXFm4SyYtZferQROyliEhik +=BuGv +-----END PGP PUBLIC KEY BLOCK----- +``` + +## Historical keys<a name="pgp-keys-expired"></a> + +These keys may be used to validate releases of the AWS CDK and jsii before 2022\-07\-05\. + +**Important** +New keys are created before the previous ones expire\. As a result, at any given moment in time, more than one key may be valid\. Keys are used to sign artifacts starting the day they are created, so use the more recently\-issued key where keys' validity overlaps\. + +### AWS CDK OpenPGP key \(2022\-04\-07\)<a name="cdk_pgp_key-2022-04-07-"></a> + +**Note** +This key was not used to sign AWS CDK artifacts after 2022\-07\-05\. + + +| | | +| --- |--- | +| Key ID: | 0x015584281F44A3C3 | +| Type: | RSA | +| Size: | 4096/4096 | +| Created: | 2022\-04\-07 | +| Expires: | 2026\-04\-06 | +| User ID: | AWS Cloud Development Kit <aws\-cdk@amazon\.com> | +| Key fingerprint: | EAE1 1A24 82B0 AA86 456E 6C67 0155 8428 1F44 A3C3 | + +Select the "Copy" icon to copy the following OpenPGP key: + +``` +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQINBGJPLgUBEADtlR5jQtxtBmROQvmWlPOViqqnJNhk0dULc3tXnq8NS/l6X81r +wHk+/CHG5kBunwvM0qaqLFRC6z9NnnNDxEHcTi47n+OAjWyDM6unxxWOPz8Dfaps +Uq/ZWa4by292ZeqRC9Ir2wdrizb69JbRjeshBwlJDAS/qtqCAqBRH/f7Zw7QSD6/ +XTxyIy+KOVjZwFPFNHMRQ/NmgUc/Rfxsa0pUjk1YAj/AkvQlwwD8DEnASoBhO0DP +QonZxouLqIpgp4LsGo8TZdQv30ocIj0C9DuYUiUXWlCPlYPgDj6IWf3rgpMQ6nB9 +wC9lx4t/L3Zg1HUD52y8aymndmbdHVn90mzlNg4XWyc58rioYrEk57YwbDnea/Kk +Hv4kVHZRfJ4/OFPyqs5ex1X3X6rb07VvA1tfLgPywO9XF2Xws8YWOWcEobaWTcnb +AzyVC6wKya8rEQzxkYJ6UkJlhDB6g6bZwIpsI2zlimG+kSBsyFvE2oRYMS0cXPqU +o+tX0+4TvxEyW3RrUQzQHIpqXrb0X1Q8Z2idPn5dwsipDEa4gsFXtrSXmbB/0Cee +eJVvKWQAsxol3+NE9L/yozq3cz5PWh0SSbmCLRcs78lMJ23MmzbMWV7BWC9DXdY+ +TywY5IkDUPjGCKlD8VlrI3TgC222bH6qaua6LYCiTtRtvpDYuJNAlUjhawARAQAB +tC5BV1MgQ2xvdWQgRGV2ZWxvcG1lbnQgS2l0IDxhd3MtY2RrQGFtYXpvbi5jb20+ +iQI/BBMBAgApBQJiTy4FAhsvBQkHhM4ABwsJCAcDAgEGFQgCCQoLBBYCAwECHgEC +F4AACgkQAVWEKB9Eo8NpbxAAiBF0kR/lVw3vuam60mk4l0iGMVsP8Xq6g/buzbEO +2MEB4Ftk04qOnoa+93S0ZiLR9PqxrwsGSp4ADDX3Vtc4uxwzUlKUi1ywEhQ1cwyL +YHQI3Hd75K1J81ozMEu6qJH+yF0TtTDZMeZHtH/XvuIYJW3Lx4o5ZFlsEegFPAgX +YCCpUS+k9qC6M8g2VjcltQJpyjGswsKm6FWaKHW+B9dfjdOHlImB9E2jaknJ8eoY +zb9zHgFANluMzpZ6rYVSiCuXiEgYmazQWCvlPcMOP7nX+1hq1z11LMqeSnfE09gX +H+OYho9cMEJkb1dzx1H9MRpylFIn9tL+2iCp4UPJjnqi6uawWyLZ2tp4G11haqQq +1yAh69u233I8GZKFUySzjHwH5qWGRgBTjrZ6FdcjSS2w/wMkVKuCPkWtdvo/TJrm +msCd1Reye8SEKYqrs0ujTwmlvWmUZmO06AdUjo1kWiBKeslTJrWEuG7Yk4pFOoA4 +dsaq83gxpOJNVCh6M3y4DLNrvl7dhF95NwTWMROPj2otw7NIjF4/cdzve2+P7YNN +pVAtyCtTJdD3eZbQPVaL3T8cf1VGqt6++pnLGnWJ0+X3TyvfmTohdJvN3TE+tq7A +7cprDX/q9c56HaXdJzVpxEzuf/YC+JuYKeHwsX3QouDhyRg3PsigdZES/02Wr8so +l6U= +=MQI4 +-----END PGP PUBLIC KEY BLOCK----- +``` + +### jsii OpenPGP key \(2022\-04\-07\)<a name="jsii_pgp_key-2022-04-07"></a> + +**Note** +This key was not used to sign jsii artifacts after 2022\-07\-05\. + + +| | | +| --- |--- | +| Key ID: | 0x985F5BC974B79356 | +| Type: | RSA | +| Size: | 4096/4096 | +| Created: | 2022\-04\-07 | +| Expires: | 2026\-04\-06 | +| User ID: | AWS JSII Team <aws\-jsii@amazon\.com> | +| Key fingerprint: | 35A7 1785 8FA6 282D C5AC CD95 985F 5BC9 74B7 9356 | + +Select the "Copy" icon to copy the following OpenPGP key: + +``` +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQINBGJPLewBEADHH4TXup/gOlHrKDZRbj8MvsMTdM6eDteA6/c32UYV/YsK9rDA +jN8Jv/xlfosOebcHrfnFpHF9VTkmjuOpN695XdwMrW/NvlEPISTGEJf21x6ZTQ2r +1xWFYzC3sl3FZmvj9XAXTmygdv+XM3TqsFgZeCaBkZVdiLbQf+FhYrovUlgotb5D +YiCQI3ofV5QTE+141jhO5Pkd3ZIoBG+P826LaT8NXhwS0o1XqVk39DCZNoFshNmR +WFZpkVCTHyv5ZhVey1NWXnD8opO375htGNV4AeSmSIH9YkURD1g5F+2t7RiosKFo +kJrfPmUjhHn8IFpReGc8qmMMZX0WaV3t+VAWfOHGGyrXDfQ4xz1VCot75C2+qypM ++qhwOAOOP0zA7CfI96ULZzSH/j8HuQk3O0DsUCybpMuKEazEMxP3tgGtRerwDaFG +jQvAlK8Rbq3v8buBI6YJuXTwSzJE8KLjleUiTFumE6WP4rsAvlP/5rBvubeMfa3n +NIMm5Rkl36Z+jt3e2Z2ZqWDPpBRta8m7QHccrZhkvqu3YC3Gl6kdnm4Vio3Xfpg2 +qtWhIQutQ6DmItewV+weQHas3hl88RPJtSrfWWIIMkpbF7Y4vbX9xcnsYCLlp2Mz +tWbbnU+EWATNSsufml/Kdnu9iEEuLmeovE11I69nwjNOq9P+GJ3r/FUb2wARAQAB +tCNBV1MgSlNJSSBUZWFtIDxhd3MtanNpaUBhbWF6b24uY29tPokCPwQTAQIAKQUC +Yk8t7AIbLwUJB4TOAAcLCQgHAwIBBhUIAgkKCwQWAgMBAh4BAheAAAoJEJhfW8l0 +t5NWo64P/2y7gcMRylLLW/wbrCjton2O4+YRocwQxKm1cBml9FVDUR5967YczNuu +EwEOfH/Pu3UAlrBfKAfxPNhKchLwYiOBNh2Wk5UUxRcldNHTLb5jn5gxCeWNAsl/ +Tc46qY+ObdBMdOf2Vu33UCOg83WLbg1bfBoA8Bm1cd0XObtLGucu606EBt1dBrKq +9UTcbJfuGivY2Xjy5r4kEiMHBoLKcFrSo2Mm7VtYlE4Mabjyj9+orqUio7qxOl60 +aa7Psa6rMvs1Ip9IOrAdG7o5Y29tQpeINH0R1/u47BrlTEAgG63Dfy49w2h/1g0G +c9KPXVuN55OWRIu0hsiySDMk/2ERsF348TU3NURZltnCOxp6pHlbPJIxRVTNa9Cn +f8tbLB3y3HfA80516g+qwNYIYiqksDdV2bz+VbvmCWcO+FellDZli831gyMGa5JJ +rq7d0lEr6nqjcnKiVwItTQXyFYmKTAXweQtVC72g1sd3oZIyqa7T8pvhWpKXxoJV +WP+OPBhGg/JEVC9sguhuv53tzVwayrNwb54JxJsD2nemfhQm1Wyvb2bPTEaJ3mrv +mhPUvXZj/I9rgsEq3L/sm2Xjy09nra4o3oe3bhEL8nOj11wkIodi17VaGP0y+H3s +I5zB5UztS6dy+cH+J7DoRaxzVzq7qtH/ZY2quClt30wwqDHUX1ef +=+iYX +-----END PGP PUBLIC KEY BLOCK----- +``` + +### AWS CDK OpenPGP key \(2018\-06\-19\)<a name="cdk_pgp_key-2018-06-19-"></a> + + +| | | +| --- |--- | +| Key ID: | 0x0566A784E17F3870 | +| Type: | RSA | +| Size: | 4096/4096 | +| Created: | 2018\-06\-19 | +| Expires: | 2022\-06\-18 | +| User ID: | AWS CDK Team <aws\-cdk@amazon\.com> | +| Key fingerprint: | E88B E3B6 F0B1 E350 9E36 4F96 0566 A784 E17F 3870 | + +Select the "Copy" icon to copy the following OpenPGP key: + +``` +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQINBFsovE8BEADEFVCHeAVPvoQgsjVu9FPUczxy9P+2zGIT/MLI3/vPLiULQwRy +IN2oxyBNDtcDToNa/fTkW3Ev0NTP4V1h+uBoKDZD/p+dTmSDRfByECMI0sGZ3UsG +Ohhyl2Of44s0sL8gdLtDnqSRLf+ZrfT3gpgUnplW7VitkwLxr78jDpW4QD8p8dZ9 +WNm3JgB55jyPgaJKqA1Ln4Vduni/1XkrG42nxrrU71uUdZPvPZ2ELLJa6n0/raG8 +jq3le+xQh45gAIs6PGaAgy7jAsfbwkGTBHjjujITAY1DwvQH5iS31OaCM9n4JNpc +xGZeJAVYTLilznf2QtS/a50t+ZOmpq67Ssp2j6qYpiumm0Lo9q3K/R4/yF0FZ8SL +1TuNX0ecXEptiMVUfTiqrLsANg18EPtLZZOYW+ZkbcVytkDpiqj7bMwA7mI7zGCJ +1gjaTbcEmOmVdQYS1G6ZptwbTtvrgA6AfnZxX1HUxLRQ7tT/wvRtABfbQKAh85Ff +a3U9W4oC3c1MP5IyhNV1Wo8Zm0flZiZc0iZnojTtSG6UbcxNNL4Q8e08FWjhungj +yxSsIBnQO1Aeo1N4BbzlI+n9iaXVDUN7Kz1QEyS4PNpjvUyrUiQ+a9C5sRA7WP+x +IEOaBBGpoAXB3oLsdTNO6AcwcDd9+r2NlXlhWC4/uH2YHQUIegPqHmPWxwARAQAB +tCFBV1MgQ0RLIFRlYW0gPGF3cy1jZGtAYW1hem9uLmNvbT6JAj8EEwEIACkFAlso +vE8CGy8FCQeEzgAHCwkIBwMCAQYVCAIJCgsEFgIDAQIeAQIXgAAKCRAFZqeE4X84 +cLGxD/0XHnhoR2xvz38GM8HQlwlZy9W1wVhQKmNDQUavw8Zx7+iRR3m7nq3xM7Qq +BDbcbKSg1lVLSBQ6H2V6vRpysOhkPSH1nN2dO8DtvSKIPcxK48+1x7lmO+ksSs/+ +oo1UvOmTDaRzOitYh3kOGXHHXk/l11GtF2FGQzYssX5iM4PHcjBsK1unThs56IMh +OJeZezEYzBaskTu/ytRJ236bPP2kZIEXfzAvhmTytuXWUXEftxOxc6fIAcYiKTha +aofG7WyR+Fvb1j5gNLcbY552QMxa23NZd5cSZH7468WEW1SGJ3AdLA7k5xvsPPOC +2YvQFD+vUOZ1JJuu6B5rHkiEMhRTLklkvqXEShTxuXiCp7iTOo6TBCmrWAT4eQr7 +htLmqlXrgKi8qPkWmRdXXG+MQBzI/UyZq2q8KC6cx2md1PhANmeefhiM7FZZfeNM +WLonWfh8gVCsNH5h8WJ9fxsQCADd3Xxx3NelS2zDYBPRoaqZEEBbgUP6LnWFprA2 +EkSlc/RoDqZCpBGgcoy1FFWvV/ZLgNU6OTQlYH6oYOWiylSJnaTDyurrktsxJI6d +4gdsFb6tqwTGecuUPvvZaEuvhWExLxAebhu780FdAPXgVTX+YCLI2zf+dWQvkFQf +80RE7ayn7BsiaLzFBVux/zz/WgvudsZX18r8tDiVQBL51ORmqw== +=0wuQ +-----END PGP PUBLIC KEY BLOCK----- +``` + +### jsii OpenPGP key \(2018\-08\-06\)<a name="jsii_pgp_key-2018-08-06"></a> + + +| | | +| --- |--- | +| Key ID: | 0x1C7ACE4CB2A1B93A | +| Type: | RSA | +| Size: | 4096/4096 | +| Created: | 2018\-08\-06 | +| Expires: | 2022\-08\-05 | +| User ID: | AWS JSII Team <aws\-jsii@amazon\.com> | +| Key fingerprint: | 85EF 6522 4CE2 1E8C 72DB 28EC 1C7A CE4C B2A1 B93A | + +Select the "Copy" icon to copy the following OpenPGP key: + +``` +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQINBFtoSs0BEAD6WweLD0B26h0F7Jo9iR6tVQ4PgQBK1Va5H/eP+A2Iqw79UyxZ +WNzHYhzQ5MjYYI1SgcPavXy5/LV1N8HJ7QzyKszybnLYpNTLPYArWE8ZM9ZmjvIR +p1GzwnVBGQfoOlxyeutE9T5ZkAn45dTS5jlno4unji4gHjnwXKf2nP1APU2CZfdK +8vDpLOgj9LeeGlerYNbx+7xtY/I+csFIQvK09FPLSNMJQLlkBhY0r6Rt9ZQG+653 +tJn+AUjyM237w0UIX1IqyYc5IONXu8HklPGu0NYuX9AY/63Ak2Cyfj0w/PZlvueQ +noQNM3j0nkOEsTOEXCyaLQw9iBKpxvLnm5RjMSODDCkj8c9uu0LHr7J4EOtgt2S1 +pem7Y/c/N+/Z+Ksg9fP8fVTfYwRPvdI1x2sCiRDfLoQSG9tdrN5VwPFi4sGV04sI +x7Al8Vf/OBjAGZrDaJgM/gVvb9SKAQUA6t3ofeP14gDrS0eYodEXZ+lamnxFglxF +Sn8NRC4JFNmkXSUaTNGUdFf//F0D69PRNT8CnFfmniGj0CphN5037PCA2LC/Buq2 +3+K6mTPkCcCHYPC/SwItp/xIDAQsGuDc1i1SfDYXrjsK7uOuwC5jLA9X6wZ/jgXQ +4umRRJBAV1aW8b1+yfaYYCO2AfXXO6caObv8IvH7Pc4leC2DoqylD3KklQARAQAB +tCNBV1MgSlNJSSBUZWFtIDxhd3MtanNpaUBhbWF6b24uY29tPokCPwQTAQgAKQUC +W2hKzQIbLwUJB4TOAAcLCQgHAwIBBhUIAgkKCwQWAgMBAh4BAheAAAoJEBx6zkyy +obk6B34P/iNb5QjKyhT0glZiq1wK7tuDDRpR6fC/sp6Jd/GhaNjO4BzlDbUPSjW5 +950VT+qwaHXbIma/QVP7EIRztfwWy7m8eOodjpiu7JyJprhwG9nocXiNsLADcMoH +BvabkDRWXWIWSurq2wbcFMlTVwxjHPIQs6kt2oojpzP985CDS/KTzyjow6/gfMim +DLdhSSbDUM34STEgew79L2sQzL7cvM/N59k+AGyEMHZDXHkEw/Bge5Ovz50YOnsp +lisH4BzPRIw7uWqPlkVPzJKwMuo2WvMjDfgbYLbyjfvs5mqDxT2GTwAx/rd2taU6 +iSqP0QmLM54BtTVVdoVXZSmJyTmXAAGlITq8ECZ/coUW9K2pUSgVuWyu63lktFP6 +MyCQYRmXPh9aSd4+ielteXM9Y39snlyLgEJBhMxioZXVO2oszwluPuhPoAp4ekwj +/umVsBf6As6PoAchg7Qzr+lRZGmV9YTJOgDn2Z7jf/7tOes0g/mdiXTQMSGtp/Fp +ggnifTBx3iXkrQhqHlwtam8XTHGHy3MvX17ZslNuB8Pjh+07hhCxv0VUVZPUHJqJ +ZsLa398LMteQ8UMxwJ3t06jwDWAd7mbr2tatIilLHtWWBFoCwBh1XLe/03ENCpDp +njZ7OsBsBK2nVVcN0H2v5ey0T1yE93o6r7xOwCwBiVp5skTCRUob +=2Tag +-----END PGP PUBLIC KEY BLOCK----- +``` \ No newline at end of file diff --git a/v2/reference.md b/v2/reference.md new file mode 100644 index 00000000..42d41645 --- /dev/null +++ b/v2/reference.md @@ -0,0 +1,55 @@ +# API reference<a name="reference"></a> + +The [API Reference](https://docs.aws.amazon.com/cdk/api/v2) contains information about the AWS Construct Library and other APIs provided by the AWS CDK\. Most of the AWS Construct Library is actually contained in a single package called `aws-cdk-lib` in NPM \(it has other names for other ecosystems\)\. The CDK API Reference is organized into submodules, one or more for each AWS service\. + +Each submodule has an overview that includes information about how to use its APIs\. For example, the [S3](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3-readme.html) overview demonstrates how to set default encryption on an Amazon S3 bucket\. + +Separate versions of the API Reference are provided for TypeScript/JavaScript, Python, Java, C\#/\.NET, and Go\. + +## Versioning<a name="versioning"></a> + +Version numbers consist of three numeric version parts: *major*\.*minor*\.*patch*, and strictly adhere to the [semantic versioning](https://semver.org) model\. This means that breaking changes to stable APIs are limited to major releases\. + +Minor and patch releases are backward compatible\. The code written in a previous version with the same major version can be upgraded to a newer version within the same major version\. It will also continue to build and run, producing the same output\. + +### AWS CDK Toolkit \(CLI\) compatibility<a name="cdk_toolkit_versioning"></a> + +The AWS CDK Toolkit \(that is, the `cdk` command line command\) is *always* compatible with construct libraries of a semantically *lower* or *equal* version number\. It is, therefore, always safe to upgrade the AWS CDK Toolkit within the same major version\. + +The AWS CDK Toolkit might be, but is *not always*, compatible with construct libraries of a semantically *higher* version\. This depends on whether the same cloud assembly schema version is employed by the two components\. The AWS CDK framework generates a cloud assembly during synthesis; the AWS CDK Toolkit consumes it for deployment\. The schema that defines the format of the cloud assembly is strictly specified and versioned\. AWS construct libraries using a given cloud assembly schema version are compatible with AWS CDK toolkit versions using that schema version or later\. This might include releases of the AWS CDK Toolkit that are *earlier than* a given construct library release\. + +When the cloud assembly version required by the construct library is not compatible with the version supported by the AWS CDK Toolkit, you receive an error message like this one\. + +``` +Cloud assembly schema version mismatch: Maximum schema version supported is 3.0.0, but found 4.0.0. + Please upgrade your CLI in order to interact with this app. +``` + +To resolve this error, update the AWS CDK Toolkit to a version compatible with the required cloud assembly version, or to the latest available version\. The alternative \(downgrading the construct library modules your app uses\) is generally not desirable\. + +**Note** +For more details on the cloud assembly schema, see [Cloud Assembly Versioning](https://github.com/aws/aws-cdk/tree/master/packages/%40aws-cdk/cloud-assembly-schema#versioning)\. + +### AWS Construct Library versioning<a name="aws_construct_lib_stability"></a> + +The modules in the AWS Construct Library move through various stages as they are developed from concept to mature API\. Different stages imply different promises for API stability in subsequent versions of the AWS CDK\. + +APIs in the main AWS CDK library, `aws-cdk-lib`, are stable, and the library is fully semantically versioned\. This package includes AWS CloudFormation \(L1\) constructs for all AWS services and all stable higher\-level \(L2 and L3\) modules\. \(It also includes the core CDK classes like `App` and `Stack`\.\) No APIs will be removed from this package \(though they may be deprecated\) until the next major release of the CDK\. No individual API will ever have breaking changes; if a breaking change is required, an entirely new API will be added\. + +New APIs under development for a service already incorporated in `aws-cdk-lib` are identified using a `BetaN` suffix, where `N` starts at 1 and is incremented with each breaking change to the new API\. `BetaN` APIs are never removed, only deprecated, so your existing app continues to work with newer versions of `aws-cdk-lib`\. When the API is deemed stable, a new API without the `BetaN` suffix is added\. + +When higher\-level \(L2 or L3\) APIs begin to be developed for an AWS service that previously had only L1 APIs, those APIs are initially distributed in a separate package\. The name of such a package has an "Alpha" suffix, and its version matches the first version of `aws-cdk-lib` it is compatible with, with an `alpha` sub\-version\. When the module supports the intended use cases, its APIs are added to `aws-cdk-lib`\. + +### Language binding stability<a name="aws_construct_lib_versioning_binding"></a> + +From time to time, we might add support to the AWS CDK for additional programming languages\. Although the API described in all the languages is the same, the way that API is expressed varies by language and might change as the language support evolves\. For this reason, language bindings are deemed experimental for a time until they are considered ready for production use\. + + +| Language | Stability | +| --- |--- | +| TypeScript | Stable | +| JavaScript | Stable | +| Python | Stable | +| Java | Stable | +| C\#/\.NET | Stable | +| Go | Stable | \ No newline at end of file diff --git a/v2/resources.md b/v2/resources.md new file mode 100644 index 00000000..0f39fddc --- /dev/null +++ b/v2/resources.md @@ -0,0 +1,1292 @@ +# Resources<a name="resources"></a> + +As described in [Constructs](constructs.md), the AWS CDK provides a rich class library of constructs, called *AWS constructs*, that represent all AWS resources\. + +To create an instance of a resource using its corresponding construct, pass in the scope as the first argument, the logical ID of the construct, and a set of configuration properties \(props\)\. For example, here's how to create an Amazon SQS queue with AWS KMS encryption using the [sqs\.Queue](https://docs.aws.amazon.com/cdk/api/v2/docs/@aws-cdk_aws-sqs.Queue.html) construct from the AWS Construct Library\. + +------ +#### [ TypeScript ] + +``` +import * as sqs from '@aws-cdk/aws-sqs'; + +new sqs.Queue(this, 'MyQueue', { + encryption: sqs.QueueEncryption.KMS_MANAGED +}); +``` + +------ +#### [ JavaScript ] + +``` +const sqs = require('@aws-cdk/aws-sqs'); + +new sqs.Queue(this, 'MyQueue', { + encryption: sqs.QueueEncryption.KMS_MANAGED +}); +``` + +------ +#### [ Python ] + +``` +import aws_cdk.aws_sqs as sqs + +sqs.Queue(self, "MyQueue", encryption=sqs.QueueEncryption.KMS_MANAGED) +``` + +------ +#### [ Java ] + +``` +import software.amazon.awscdk.services.sqs.*; + +Queue.Builder.create(this, "MyQueue").encryption( + QueueEncryption.KMS_MANAGED).build(); +``` + +------ +#### [ C\# ] + +``` +using Amazon.CDK.AWS.SQS; + +new Queue(this, "MyQueue", new QueueProps +{ + Encryption = QueueEncryption.KMS_MANAGED +}); +``` + +------ + +Some configuration props are optional, and in many cases have default values\. In some cases, all props are optional, and the last argument can be omitted entirely\. + +## Resource attributes<a name="resources_attributes"></a> + +Most resources in the AWS Construct Library expose attributes, which are resolved at deployment time by AWS CloudFormation\. Attributes are exposed in the form of properties on the resource classes with the type name as a prefix\. The following example shows how to get the URL of an Amazon SQS queue using the `queueUrl` \(Python: `queue_url`\) property\. + +------ +#### [ TypeScript ] + +``` +import * as sqs from '@aws-cdk/aws-sqs'; + +const queue = new sqs.Queue(this, 'MyQueue'); +const url = queue.queueUrl; // => A string representing a deploy-time value +``` + +------ +#### [ JavaScript ] + +``` +const sqs = require('@aws-cdk/aws-sqs'); + +const queue = new sqs.Queue(this, 'MyQueue'); +const url = queue.queueUrl; // => A string representing a deploy-time value +``` + +------ +#### [ Python ] + +``` +import aws_cdk.aws_sqs as sqs + +queue = sqs.Queue(self, "MyQueue") +url = queue.queue_url # => A string representing a deploy-time value +``` + +------ +#### [ Java ] + +``` +Queue queue = new Queue(this, "MyQueue"); +String url = queue.getQueueUrl(); // => A string representing a deploy-time value +``` + +------ +#### [ C\# ] + +``` +var queue = new Queue(this, "MyQueue"); +var url = queue.QueueUrl; // => A string representing a deploy-time value +``` + +------ + +See [Tokens](tokens.md) for information about how the AWS CDK encodes deploy\-time attributes as strings\. + +## Referencing resources<a name="resources_referencing"></a> + +Many AWS CDK classes require properties that are AWS CDK resource objects \(resources\)\. For example, an Amazon ECS resource requires a reference to the cluster on which it runs\. An Amazon CloudFront distribution requires a reference to the bucket containing the source code\. To satisfy these requirements, you can refer to a resource in one of two ways: ++ By passing a resource defined in your CDK app, either in the same stack or in a different one ++ By passing a proxy object referencing a resource defined in your AWS account, created from a unique identifier of the resource \(such as an ARN\) + +If a construct property represents another AWS construct, its type is that of the interface type of that construct\. For example, the Amazon ECS service takes a property `cluster` of type `ecs.ICluster`; the CloudFront distribution takes a property `sourceBucket` \(Python: `source_bucket`\) of type `s3.IBucket`\. + +You can directly pass any resource object of the proper type defined in the same AWS CDK app\. The following example defines an Amazon ECS cluster and then uses it to define an Amazon ECS service\. + +------ +#### [ TypeScript ] + +``` +const cluster = new ecs.Cluster(this, 'Cluster', { /*...*/ }); + +const service = new ecs.Ec2Service(this, 'Service', { cluster: cluster }); +``` + +------ +#### [ JavaScript ] + +``` +const cluster = new ecs.Cluster(this, 'Cluster', { /*...*/ }); + +const service = new ecs.Ec2Service(this, 'Service', { cluster: cluster }); +``` + +------ +#### [ Python ] + +``` +cluster = ecs.Cluster(self, "Cluster") + +service = ecs.Ec2Service(self, "Service", cluster=cluster) +``` + +------ +#### [ Java ] + +``` +Cluster cluster = new Cluster(this, "Cluster"); +Ec2Service service = new Ec2Service(this, "Service", + new Ec2ServiceProps.Builder().cluster(cluster).build()); +``` + +------ +#### [ C\# ] + +``` +var cluster = new Cluster(this, "Cluster"); +var service = new Ec2Service(this, "Service", new Ec2ServiceProps { Cluster = cluster }); +``` + +------ + +## Referencing resources in a different stack<a name="resource_stack"></a> + +You can refer to resources in a different stack as long as they are defined in the same app and are in the same AWS account and Region\. The following pattern is generally used: ++ Store a reference to the construct as an attribute of the stack that produces the resource\. \(To get a reference to the current construct's stack, use `Stack.of(this)`\.\) ++ Pass this reference to the constructor of the stack that consumes the resource as a parameter or a property\. The consuming stack then passes it as a property to any construct that needs it\. + +The following example defines a stack `stack1`\. This stack defines an Amazon S3 bucket and stores a reference to the bucket construct as an attribute of the stack\. Then the app defines a second stack, `stack2`, which accepts a bucket at instantiation\. `stack2` might, for example, define an AWS Glue Table that uses the bucket for data storage\. + +------ +#### [ TypeScript ] + +``` +const prod = { account: '123456789012', region: 'us-east-1' }; + +const stack1 = new StackThatProvidesABucket(app, 'Stack1', { env: prod }); + +// stack2 will take a property { bucket: IBucket } +const stack2 = new StackThatExpectsABucket(app, 'Stack2', { + bucket: stack1.bucket, + env: prod +}); +``` + +------ +#### [ JavaScript ] + +``` +const prod = { account: '123456789012', region: 'us-east-1' }; + +const stack1 = new StackThatProvidesABucket(app, 'Stack1', { env: prod }); + +// stack2 will take a property { bucket: IBucket } +const stack2 = new StackThatExpectsABucket(app, 'Stack2', { + bucket: stack1.bucket, + env: prod +}); +``` + +------ +#### [ Python ] + +``` +prod = core.Environment(account="123456789012", region="us-east-1") + +stack1 = StackThatProvidesABucket(app, "Stack1", env=prod) + +# stack2 will take a property "bucket" +stack2 = StackThatExpectsABucket(app, "Stack2", bucket=stack1.bucket, env=prod) +``` + +------ +#### [ Java ] + +``` +// Helper method to build an environment +static Environment makeEnv(String account, String region) { + return Environment.builder().account(account).region(region) + .build(); +} + +App app = new App(); + +Environment prod = makeEnv("123456789012", "us-east-1"); + +StackThatProvidesABucket stack1 = new StackThatProvidesABucket(app, "Stack1", + StackProps.builder().env(prod).build()); + +// stack2 will take an argument "bucket" +StackThatExpectsABucket stack2 = new StackThatExpectsABucket(app, "Stack,", + StackProps.builder().env(prod).build(), stack1.bucket); +``` + +------ +#### [ C\# ] + +``` +Amazon.CDK.Environment makeEnv(string account, string region) +{ + return new Amazon.CDK.Environment { Account = account, Region = region }; +} + +var prod = makeEnv(account: "123456789012", region: "us-east-1"); + +var stack1 = new StackThatProvidesABucket(app, "Stack1", new StackProps { Env = prod }); + +// stack2 will take a property "bucket" +var stack2 = new StackThatExpectsABucket(app, "Stack2", new StackProps { Env = prod, + bucket = stack1.Bucket}); +``` + +------ + +If the AWS CDK determines that the resource is in the same account and Region, but in a different stack, it automatically synthesizes AWS CloudFormation [exports](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-stack-exports.html) in the producing stack and an [Fn::ImportValue](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-importvalue.html) in the consuming stack to transfer that information from one stack to the other\. + +### Resolving dependency deadlocks<a name="resources_deadlock"></a> + +Referencing a resource from one stack in a different stack creates a dependency between the two stacks\. This makes sure that they're deployed in the right order\. After the stacks are deployed, this dependency is concrete\. After that, removing the use of the shared resource from the consuming stack can cause an unexpected deployment failure\. This happens if there is another dependency between the two stacks that force them to be deployed in the same order\. It can also happen without a dependency if the producing stack is simply chosen by the CDK Toolkit to be deployed first\. The AWS CloudFormation export is removed from the producing stack because it's no longer needed, but the exported resource is still being used in the consuming stack because its update is not yet deployed\. Therefore, deploying the producer stack fails\. + +To break this deadlock, remove the use of the shared resource from the consuming stack\. \(This removes the automatic export from the producing stack\.\) Next, manually add the same export to the producing stack using exactly the same logical ID as the automatically generated export\. Remove the use of the shared resource in the consuming stack and deploy both stacks\. Then, remove the manual export \(and the shared resource if it's no longer needed\) and deploy both stacks again\. The stack's `[exportValue\(\)](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html#exportwbrvalueexportedvalue-options)` method is a convenient way to create the manual export for this purpose\. \(See the example in the linked method reference\.\) + +## Referencing resources in your AWS account<a name="resources_external"></a> + +Suppose you want to use a resource already available in your AWS account in your AWS CDK app\. This might be a resource that was defined through the console, an AWS SDK, directly with AWS CloudFormation, or in a different AWS CDK application\. You can turn the resource's ARN \(or another identifying attribute, or group of attributes\) into a proxy object\. The proxy object serves as a reference to the resource by calling a static factory method on the resource's class\. + +When you create such a proxy, the external resource **does not** become a part of your AWS CDK app\. Therefore, changes you make to the proxy in your AWS CDK app do not affect the deployed resource\. The proxy can, however, be passed to any AWS CDK method that requires a resource of that type\. + +The following example shows how to reference a bucket based on an existing bucket with the ARN **arn:aws:s3:::my\-bucket\-name**, and an Amazon Virtual Private Cloud based on an existing VPC having a specific ID\. + +------ +#### [ TypeScript ] + +``` +// Construct a proxy for a bucket by its name (must be same account) +s3.Bucket.fromBucketName(this, 'MyBucket', 'my-bucket-name'); + +// Construct a proxy for a bucket by its full ARN (can be another account) +s3.Bucket.fromBucketArn(this, 'MyBucket', 'arn:aws:s3:::my-bucket-name'); + +// Construct a proxy for an existing VPC from its attribute(s) +ec2.Vpc.fromVpcAttributes(this, 'MyVpc', { + vpcId: 'vpc-1234567890abcde', +}); +``` + +------ +#### [ JavaScript ] + +``` +// Construct a proxy for a bucket by its name (must be same account) +s3.Bucket.fromBucketName(this, 'MyBucket', 'my-bucket-name'); + +// Construct a proxy for a bucket by its full ARN (can be another account) +s3.Bucket.fromBucketArn(this, 'MyBucket', 'arn:aws:s3:::my-bucket-name'); + +// Construct a proxy for an existing VPC from its attribute(s) +ec2.Vpc.fromVpcAttributes(this, 'MyVpc', { + vpcId: 'vpc-1234567890abcde' +}); +``` + +------ +#### [ Python ] + +``` +# Construct a proxy for a bucket by its name (must be same account) +s3.Bucket.from_bucket_name(self, "MyBucket", "my-bucket-name") + +# Construct a proxy for a bucket by its full ARN (can be another account) +s3.Bucket.from_bucket_arn(self, "MyBucket", "arn:aws:s3:::my-bucket-name") + +# Construct a proxy for an existing VPC from its attribute(s) +ec2.Vpc.from_vpc_attributes(self, "MyVpc", vpc_id="vpc-1234567890abcdef") +``` + +------ +#### [ Java ] + +``` +// Construct a proxy for a bucket by its name (must be same account) +Bucket.fromBucketName(this, "MyBucket", "my-bucket-name"); + +// Construct a proxy for a bucket by its full ARN (can be another account) +Bucket.fromBucketArn(this, "MyBucket", + "arn:aws:s3:::my-bucket-name"); + +// Construct a proxy for an existing VPC from its attribute(s) +Vpc.fromVpcAttributes(this, "MyVpc", VpcAttributes.builder() + .vpcId("vpc-1234567890abcdef").build()); +``` + +------ +#### [ C\# ] + +``` +// Construct a proxy for a bucket by its name (must be same account) +Bucket.FromBucketName(this, "MyBucket", "my-bucket-name"); + +// Construct a proxy for a bucket by its full ARN (can be another account) +Bucket.FromBucketArn(this, "MyBucket", "arn:aws:s3:::my-bucket-name"); + +// Construct a proxy for an existing VPC from its attribute(s) +Vpc.FromVpcAttributes(this, "MyVpc", new VpcAttributes +{ + VpcId = "vpc-1234567890abcdef" +}); +``` + +------ + +Let's take a closer look at the [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-ec2.Vpc.html#static-fromwbrlookupscope-id-options](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-ec2.Vpc.html#static-fromwbrlookupscope-id-options) method\. Because the `ec2.Vpc` construct is complex, there are many ways you might want to select the VPC to be used with your CDK app\. To address this, the VPC construct has a `fromLookup` static method \(Python: `from_lookup`\) that lets you look up the desired Amazon VPC by querying your AWS account at synthesis time\. + +To use `Vpc.fromLookup()`, the system that synthesizes the stack must have access to the account that owns the Amazon VPC\. This is because the CDK Toolkit queries the account to find the right Amazon VPC at synthesis time\. + +Furthermore, `Vpc.fromLookup()` works only in stacks that are defined with an explicit **account** and **region** \(see [Environments](environments.md)\)\. If the AWS CDK tries to look up an Amazon VPC from an [environment\-agnostic stack](stacks.md#stack_api), the CDK Toolkit doesn't know which environment to query to find the VPC\. + +You must provide `Vpc.fromLookup()` attributes sufficient to uniquely identify a VPC in your AWS account\. For example, there can only ever be one default VPC, so it's sufficient to specify the VPC as the default\. + +------ +#### [ TypeScript ] + +``` +ec2.Vpc.fromLookup(this, 'DefaultVpc', { + isDefault: true +}); +``` + +------ +#### [ JavaScript ] + +``` +ec2.Vpc.fromLookup(this, 'DefaultVpc', { + isDefault: true +}); +``` + +------ +#### [ Python ] + +``` +ec2.Vpc.from_lookup(self, "DefaultVpc", is_default=True) +``` + +------ +#### [ Java ] + +``` +Vpc.fromLookup(this, "DefaultVpc", VpcLookupOptions.builder() + .isDefault(true).build()); +``` + +------ +#### [ C\# ] + +``` +Vpc.FromLookup(this, id = "DefaultVpc", new VpcLookupOptions { IsDefault = true }); +``` + +------ + +You can also use the `tags` property to query for VPCs by tag\. You can add tags to the Amazon VPC at the time of its creation by using AWS CloudFormation or the AWS CDK\. You can edit tags at any time after creation by using the AWS Management Console, the AWS CLI, or an AWS SDK\. In addition to any tags you add yourself, the AWS CDK automatically adds the following tags to all VPCs it creates\. ++ *Name* – The name of the VPC\. ++ *aws\-cdk:subnet\-name* – The name of the subnet\. ++ *aws\-cdk:subnet\-type* – The type of the subnet: Public, Private, or Isolated\. + +------ +#### [ TypeScript ] + +``` +ec2.Vpc.fromLookup(this, 'PublicVpc', + {tags: {'aws-cdk:subnet-type': "Public"}}); +``` + +------ +#### [ JavaScript ] + +``` +ec2.Vpc.fromLookup(this, 'PublicVpc', + {tags: {'aws-cdk:subnet-type': "Public"}}); +``` + +------ +#### [ Python ] + +``` +ec2.Vpc.from_lookup(self, "PublicVpc", + tags={"aws-cdk:subnet-type": "Public"}) +``` + +------ +#### [ Java ] + +``` +Vpc.fromLookup(this, "PublicVpc", VpcLookupOptions.builder() + .tags(java.util.Map.of("aws-cdk:subnet-type", "Public")) // Java 9 or later + .build()); +``` + +------ +#### [ C\# ] + +``` +Vpc.FromLookup(this, id = "PublicVpc", new VpcLookupOptions + { Tags = new Dictionary<string, string> { ["aws-cdk:subnet-type"] = "Public" }); +``` + +------ + +Results of `Vpc.fromLookup()` are cached in the project's `cdk.context.json` file\. \(See [Runtime context](context.md)\.\) Commit this file to version control so that your app will continue to refer to the same Amazon VPC\. This works even if you later change the attributes of your VPCs in a way that would result in a different VPC being selected\. This is particularly important if you're deploying the stack in an environment that doesn't have access to the AWS account that defines the VPC, such as [CDK Pipelines](cdk_pipeline.md)\. + +Although you can use an external resource anywhere you'd use a similar resource defined in your AWS CDK app, you cannot modify it\. For example, calling `addToResourcePolicy` \(Python: `add_to_resource_policy`\) on an external `s3.Bucket` does nothing\. + +## Physical names<a name="resources_physical_names"></a> + +The logical names of resources in AWS CloudFormation are different from the names of resources that are shown in the AWS Management Console after they're deployed by AWS CloudFormation\. The AWS CDK calls these final names *physical names*\. + +For example, AWS CloudFormation might create the Amazon S3 bucket with the logical ID **Stack2MyBucket4DD88B4F** from the previous example with the physical name **stack2mybucket4dd88b4f\-iuv1rbv9z3to**\. + +You can specify a physical name when creating constructs that represent resources by using the property <resourceType>Name\. The following example creates an Amazon S3 bucket with the physical name **my\-bucket\-name**\. + +------ +#### [ TypeScript ] + +``` +const bucket = new s3.Bucket(this, 'MyBucket', { + bucketName: 'my-bucket-name', +}); +``` + +------ +#### [ JavaScript ] + +``` +const bucket = new s3.Bucket(this, 'MyBucket', { + bucketName: 'my-bucket-name' +}); +``` + +------ +#### [ Python ] + +``` +bucket = s3.Bucket(self, "MyBucket", bucket_name="my-bucket-name") +``` + +------ +#### [ Java ] + +``` +Bucket bucket = Bucket.Builder.create(this, "MyBucket") + .bucketName("my-bucket-name").build(); +``` + +------ +#### [ C\# ] + +``` +var bucket = new Bucket(this, "MyBucket", new BucketProps { BucketName = "my-bucket-name" }); +``` + +------ + +Assigning physical names to resources has some disadvantages in AWS CloudFormation\. Most importantly, any changes to deployed resources that require a resource replacement, such as changes to a resource's properties that are immutable after creation, will fail if a resource has a physical name assigned\. If you end up in that state, the only solution is to delete the AWS CloudFormation stack, then deploy the AWS CDK app again\. See the [AWS CloudFormation documentation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-name.html) for details\. + +In some cases, such as when creating an AWS CDK app with cross\-environment references, physical names are required for the AWS CDK to function correctly\. In those cases, if you don't want to bother with coming up with a physical name yourself, you can let the AWS CDK name it for you\. To do so, use the special value `PhysicalName.GENERATE_IF_NEEDED`, as follows\. + +------ +#### [ TypeScript ] + +``` +const bucket = new s3.Bucket(this, 'MyBucket', { + bucketName: core.PhysicalName.GENERATE_IF_NEEDED, +}); +``` + +------ +#### [ JavaScript ] + +``` +const bucket = new s3.Bucket(this, 'MyBucket', { + bucketName: core.PhysicalName.GENERATE_IF_NEEDED +}); +``` + +------ +#### [ Python ] + +``` +bucket = s3.Bucket(self, "MyBucket", + bucket_name=core.PhysicalName.GENERATE_IF_NEEDED) +``` + +------ +#### [ Java ] + +``` +Bucket bucket = Bucket.Builder.create(this, "MyBucket") + .bucketName(PhysicalName.GENERATE_IF_NEEDED).build(); +``` + +------ +#### [ C\# ] + +``` +var bucket = new Bucket(this, "MyBucket", new BucketProps + { BucketName = PhysicalName.GENERATE_IF_NEEDED }); +``` + +------ + +## Passing unique identifiers<a name="resources_identifiers"></a> + +Whenever possible, you should pass resources by reference, as described in the previous section\. However, there are cases where you have no other choice but to refer to a resource by one of its attributes\. Example use cases include the following: ++ When you are using low\-level AWS CloudFormation resources ++ When you need to expose resources to the runtime components of an AWS CDK application, such as when referring to Lambda functions through environment variables + +These identifiers are available as attributes on the resources, such as the following\. + +------ +#### [ TypeScript ] + +``` +bucket.bucketName +lambdaFunc.functionArn +securityGroup.groupArn +``` + +------ +#### [ JavaScript ] + +``` +bucket.bucketName +lambdaFunc.functionArn +securityGroup.groupArn +``` + +------ +#### [ Python ] + +``` +bucket.bucket_name +lambda_func.function_arn +security_group_arn +``` + +------ +#### [ Java ] + +The Java AWS CDK binding uses getter methods for attributes\. + +``` +bucket.getBucketName() +lambdaFunc.getFunctionArn() +securityGroup.getGroupArn() +``` + +------ +#### [ C\# ] + +``` +bucket.BucketName +lambdaFunc.FunctionArn +securityGroup.GroupArn +``` + +------ + +The following example shows how to pass a generated bucket name to an AWS Lambda function\. + +------ +#### [ TypeScript ] + +``` +const bucket = new s3.Bucket(this, 'Bucket'); + +new lambda.Function(this, 'MyLambda', { + // ... + environment: { + BUCKET_NAME: bucket.bucketName, + }, +}); +``` + +------ +#### [ JavaScript ] + +``` +const bucket = new s3.Bucket(this, 'Bucket'); + +new lambda.Function(this, 'MyLambda', { + // ... + environment: { + BUCKET_NAME: bucket.bucketName + } +}); +``` + +------ +#### [ Python ] + +``` +bucket = s3.Bucket(self, "Bucket") + +lambda.Function(self, "MyLambda", environment=dict(BUCKET_NAME=bucket.bucket_name)) +``` + +------ +#### [ Java ] + +``` +final Bucket bucket = new Bucket(this, "Bucket"); + +Function.Builder.create(this, "MyLambda") + .environment(java.util.Map.of( // Java 9 or later + "BUCKET_NAME", bucket.getBucketName())) + .build(); +``` + +------ +#### [ C\# ] + +``` +var bucket = new Bucket(this, "Bucket"); + +new Function(this, "MyLambda", new FunctionProps +{ + Environment = new Dictionary<string, string> + { + ["BUCKET_NAME"] = bucket.BucketName + } +}); +``` + +------ + +## Granting permissions<a name="resources_grants"></a> + +AWS constructs make least\-privilege permissions achievable by offering simple, intent\-based APIs to express permission requirements\. Many AWS constructs offer grant methods that you can use to grant an entity \(such as an IAM role or user\) permission to work with the resource, without having to manually create IAM permission statements\. + +The following example creates the permissions to allow a Lambda function's execution role to read and write objects to a particular Amazon S3 bucket\. If the Amazon S3 bucket is encrypted with an AWS KMS key, this method also grants permissions to the Lambda function's execution role to decrypt with the key\. + +------ +#### [ TypeScript ] + +``` +if (bucket.grantReadWrite(func).success) { + // ... +} +``` + +------ +#### [ JavaScript ] + +``` +if ( bucket.grantReadWrite(func).success) { + // ... +} +``` + +------ +#### [ Python ] + +``` +if bucket.grant_read_write(func).success: + # ... +``` + +------ +#### [ Java ] + +``` +if (bucket.grantReadWrite(func).getSuccess()) { + // ... +} +``` + +------ +#### [ C\# ] + +``` +if (bucket.GrantReadWrite(func).Success) +{ + // ... +} +``` + +------ + +The grant methods return an `iam.Grant` object\. Use the `success` attribute of the `Grant` object to determine whether the grant was effectively applied \(for example, it may not have been applied on [external resources](#resources_referencing)\)\. You can also use the `assertSuccess` \(Python: `assert_success`\) method of the `Grant` object to enforce that the grant was successfully applied\. + +If a specific grant method isn't available for the particular use case, you can use a generic grant method to define a new grant with a specified list of actions\. + +The following example shows how to grant a Lambda function access to the Amazon DynamoDB `CreateBackup` action\. + +------ +#### [ TypeScript ] + +``` +table.grant(func, 'dynamodb:CreateBackup'); +``` + +------ +#### [ JavaScript ] + +``` +table.grant(func, 'dynamodb:CreateBackup'); +``` + +------ +#### [ Python ] + +``` +table.grant(func, "dynamodb:CreateBackup") +``` + +------ +#### [ Java ] + +``` +table.grant(func, "dynamodb:CreateBackup"); +``` + +------ +#### [ C\# ] + +``` +table.Grant(func, "dynamodb:CreateBackup"); +``` + +------ + +Many resources, such as Lambda functions, require a role to be assumed when executing code\. A configuration property enables you to specify an `iam.IRole`\. If no role is specified, the function automatically creates a role specifically for this use\. You can then use grant methods on the resources to add statements to the role\. + +The grant methods are built using lower\-level APIs for handling with IAM policies\. Policies are modeled as [PolicyDocument](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-iam-readme.html) objects\. Add statements directly to roles \(or a construct's attached role\) using the `addToRolePolicy` method \(Python: `add_to_role_policy`\), or to a resource's policy \(such as a `Bucket` policy\) using the `addToResourcePolicy` \(Python: `add_to_resource_policy`\) method\. + +## Metrics and alarms<a name="resources_metrics"></a> + +Many resources emit CloudWatch metrics that can be used to set up monitoring dashboards and alarms\. AWS constructs have metric methods that let you access the metrics without looking up the correct name to use\. + +The following example shows how to define an alarm when the `ApproximateNumberOfMessagesNotVisible` of an Amazon SQS queue exceeds 100\. + +------ +#### [ TypeScript ] + +``` +import * as cw from '@aws-cdk/aws-cloudwatch'; +import * as sqs from '@aws-cdk/aws-sqs'; +import { Duration } from '@aws-cdk/core'; + +const queue = new sqs.Queue(this, 'MyQueue'); + +const metric = queue.metricApproximateNumberOfMessagesNotVisible({ + label: 'Messages Visible (Approx)', + period: Duration.minutes(5), + // ... +}); +metric.createAlarm(this, 'TooManyMessagesAlarm', { + comparisonOperator: cw.ComparisonOperator.GREATER_THAN_THRESHOLD, + threshold: 100, + // ... +}); +``` + +------ +#### [ JavaScript ] + +``` +const cw = require('@aws-cdk/aws-cloudwatch'); +const sqs = require('@aws-cdk/aws-sqs'); +const { Duration } = require('@aws-cdk/core'); + +const queue = new sqs.Queue(this, 'MyQueue'); + +const metric = queue.metricApproximateNumberOfMessagesNotVisible({ + label: 'Messages Visible (Approx)', + period: Duration.minutes(5) + // ... +}); +metric.createAlarm(this, 'TooManyMessagesAlarm', { + comparisonOperator: cw.ComparisonOperator.GREATER_THAN_THRESHOLD, + threshold: 100 + // ... +}); +``` + +------ +#### [ Python ] + +``` +import aws_cdk.aws_cloudwatch as cw +import aws_cdk.aws_sqs as sqs +from aws_cdk.core import Duration + +queue = sqs.Queue(self, "MyQueue") +metric = queue.metric_approximate_number_of_messages_not_visible( + label="Messages Visible (Approx)", + period=Duration.minutes(5), + # ... +) +metric.create_alarm(self, "TooManyMessagesAlarm", + comparison_operator=cw.ComparisonOperator.GREATER_THAN_THRESHOLD, + threshold=100, + # ... +) +``` + +------ +#### [ Java ] + +``` +import software.amazon.awscdk.core.Duration; +import software.amazon.awscdk.services.sqs.Queue; +import software.amazon.awscdk.services.cloudwatch.Metric; +import software.amazon.awscdk.services.cloudwatch.MetricOptions; +import software.amazon.awscdk.services.cloudwatch.CreateAlarmOptions; +import software.amazon.awscdk.services.cloudwatch.ComparisonOperator; + +Queue queue = new Queue(this, "MyQueue"); + +Metric metric = queue + .metricApproximateNumberOfMessagesNotVisible(MetricOptions.builder() + .label("Messages Visible (Approx)") + .period(Duration.minutes(5)).build()); + +metric.createAlarm(this, "TooManyMessagesAlarm", CreateAlarmOptions.builder() + .comparisonOperator(ComparisonOperator.GREATER_THAN_THRESHOLD) + .threshold(100) + // ... + .build()); +``` + +------ +#### [ C\# ] + +``` +using cdk = Amazon.CDK; +using cw = Amazon.CDK.AWS.CloudWatch; +using sqs = Amazon.CDK.AWS.SQS; + +var queue = new sqs.Queue(this, "MyQueue"); +var metric = queue.MetricApproximateNumberOfMessagesNotVisible(new cw.MetricOptions +{ + Label = "Messages Visible (Approx)", + Period = cdk.Duration.Minutes(5), + // ... +}); +metric.CreateAlarm(this, "TooManyMessagesAlarm", new cw.CreateAlarmOptions +{ + ComparisonOperator = cw.ComparisonOperator.GREATER_THAN_THRESHOLD, + Threshold = 100, + // .. +}); +``` + +------ + +If there is no method for a particular metric, you can use the general metric method to specify the metric name manually\. + +Metrics can also be added to CloudWatch dashboards\. See [CloudWatch](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_cloudwatch-readme.html)\. + +## Network traffic<a name="resources_traffic"></a> + +In many cases, you must enable permissions on a network for an application to work, such as when the compute infrastructure needs to access the persistence layer\. Resources that establish or listen for connections expose methods that enable traffic flows, including setting security group rules or network ACLs\. + +[IConnectable](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.IConnectable.html) resources have a `connections` property that is the gateway to network traffic rules configuration\. + +You enable data to flow on a given network path by using `allow` methods\. The following example enables HTTPS connections to the web and incoming connections from the Amazon EC2 Auto Scaling group `fleet2`\. + +------ +#### [ TypeScript ] + +``` +import * as asg from '@aws-cdk/aws-autoscaling'; +import * as ec2 from '@aws-cdk/aws-ec2'; + +const fleet1: asg.AutoScalingGroup = asg.AutoScalingGroup(/*...*/); + +// Allow surfing the (secure) web +fleet1.connections.allowTo(new ec2.Peer.anyIpv4(), new ec2.Port({ fromPort: 443, toPort: 443 })); + +const fleet2: asg.AutoScalingGroup = asg.AutoScalingGroup(/*...*/); +fleet1.connections.allowFrom(fleet2, ec2.Port.AllTraffic()); +``` + +------ +#### [ JavaScript ] + +``` +const asg = require('@aws-cdk/aws-autoscaling'); +const ec2 = require('@aws-cdk/aws-ec2'); + +const fleet1 = asg.AutoScalingGroup(); + +// Allow surfing the (secure) web +fleet1.connections.allowTo(new ec2.Peer.anyIpv4(), new ec2.Port({ fromPort: 443, toPort: 443 })); + +const fleet2 = asg.AutoScalingGroup(); +fleet1.connections.allowFrom(fleet2, ec2.Port.AllTraffic()); +``` + +------ +#### [ Python ] + +``` +import aws_cdk.aws_autoscaling as asg +import aws_cdk.aws_ec2 as ec2 + +fleet1 = asg.AutoScalingGroup( ... ) + +# Allow surfing the (secure) web +fleet1.connections.allow_to(ec2.Peer.any_ipv4(), + ec2.Port(PortProps(from_port=443, to_port=443))) + +fleet2 = asg.AutoScalingGroup( ... ) +fleet1.connections.allow_from(fleet2, ec2.Port.all_traffic()) +``` + +------ +#### [ Java ] + +``` +import software.amazon.awscdk.services.autoscaling.AutoScalingGroup; +import software.amazon.awscdk.services.ec2.Peer; +import software.amazon.awscdk.services.ec2.Port; + +AutoScalingGroup fleet1 = AutoScalingGroup.Builder.create(this, "MyFleet") + /* ... */.build(); + +// Allow surfing the (secure) Web +fleet1.getConnections().allowTo(Peer.anyIpv4(), + Port.Builder.create().fromPort(443).toPort(443).build()); + +AutoScalingGroup fleet2 = AutoScalingGroup.Builder.create(this, "MyFleet2") + /* ... */.build(); +fleet1.getConnections().allowFrom(fleet2, Port.allTraffic()); +``` + +------ +#### [ C\# ] + +``` +using cdk = Amazon.CDK; +using asg = Amazon.CDK.AWS.AutoScaling; +using ec2 = Amazon.CDK.AWS.EC2; + +// Allow surfing the (secure) Web +var fleet1 = new asg.AutoScalingGroup(this, "MyFleet", new asg.AutoScalingGroupProps { /* ... */ }); +fleet1.Connections.AllowTo(ec2.Peer.AnyIpv4(), new ec2.Port(new ec2.PortProps + { FromPort = 443, ToPort = 443 }); + +var fleet2 = new asg.AutoScalingGroup(this, "MyFleet2", new asg.AutoScalingGroupProps { /* ... */ }); +fleet1.Connections.AllowFrom(fleet2, ec2.Port.AllTraffic()); +``` + +------ + +Certain resources have default ports associated with them\. Examples include the listener of a load balancer on the public port, and the ports on which the database engine accepts connections for instances of an Amazon RDS database\. In such cases, you can enforce tight network control without having to manually specify the port\. To do so, use the `allowDefaultPortFrom` and `allowToDefaultPort` methods \(Python: `allow_default_port_from`, `allow_to_default_port`\)\. + +The following example shows how to enable connections from any IPV4 address, and a connection from an Auto Scaling group to access a database\. + +------ +#### [ TypeScript ] + +``` +listener.connections.allowDefaultPortFromAnyIpv4('Allow public access'); + +fleet.connections.allowToDefaultPort(rdsDatabase, 'Fleet can access database'); +``` + +------ +#### [ JavaScript ] + +``` +listener.connections.allowDefaultPortFromAnyIpv4('Allow public access'); + +fleet.connections.allowToDefaultPort(rdsDatabase, 'Fleet can access database'); +``` + +------ +#### [ Python ] + +``` +listener.connections.allow_default_port_from_any_ipv4("Allow public access") + +fleet.connections.allow_to_default_port(rds_database, "Fleet can access database") +``` + +------ +#### [ Java ] + +``` +listener.getConnections().allowDefaultPortFromAnyIpv4("Allow public access"); + +fleet.getConnections().AllowToDefaultPort(rdsDatabase, "Fleet can access database"); +``` + +------ +#### [ C\# ] + +``` +listener.Connections.AllowDefaultPortFromAnyIpv4("Allow public access"); + +fleet.Connections.AllowToDefaultPort(rdsDatabase, "Fleet can access database"); +``` + +------ + +## Event handling<a name="resources_events"></a> + +Some resources can act as event sources\. Use the `addEventNotification` method \(Python: `add_event_notification`\) to register an event target to a particular event type emitted by the resource\. In addition to this, `addXxxNotification` methods offer a simple way to register a handler for common event types\. + +The following example shows how to trigger a Lambda function when an object is added to an Amazon S3 bucket\. + +------ +#### [ TypeScript ] + +``` +import * as s3nots from '@aws-cdk/aws-s3-notifications'; + +const handler = new lambda.Function(this, 'Handler', { /*…*/ }); +const bucket = new s3.Bucket(this, 'Bucket'); +bucket.addObjectCreatedNotification(new s3nots.LambdaDestination(handler)); +``` + +------ +#### [ JavaScript ] + +``` +const s3nots = require('@aws-cdk/aws-s3-notifications'); + +const handler = new lambda.Function(this, 'Handler', { /*…*/ }); +const bucket = new s3.Bucket(this, 'Bucket'); +bucket.addObjectCreatedNotification(new s3nots.LambdaDestination(handler)); +``` + +------ +#### [ Python ] + +``` +import aws_cdk.aws_s3_notifications as s3_nots + +handler = lambda_.Function(self, "Handler", ...) +bucket = s3.Bucket(self, "Bucket") +bucket.add_object_created_notification(s3_nots.LambdaDestination(handler)) +``` + +------ +#### [ Java ] + +``` +import software.amazon.awscdk.services.s3.Bucket; +import software.amazon.awscdk.services.lambda.Function; +import software.amazon.awscdk.services.s3.notifications.LambdaDestination; + +Function handler = Function.Builder.create(this, "Handler")/* ... */.build(); +Bucket bucket = new Bucket(this, "Bucket"); +bucket.addObjectCreatedNotification(new LambdaDestination(handler)); +``` + +------ +#### [ C\# ] + +``` +using lambda = Amazon.CDK.AWS.Lambda; +using s3 = Amazon.CDK.AWS.S3; +using s3Nots = Amazon.CDK.AWS.S3.Notifications; + +var handler = new lambda.Function(this, "Handler", new lambda.FunctionProps { .. }); +var bucket = new s3.Bucket(this, "Bucket"); +bucket.AddObjectCreatedNotification(new s3Nots.LambdaDestination(handler)); +``` + +------ + +## Removal policies<a name="resources_removal"></a> + +Resources that maintain persistent data, such as databases, Amazon S3 buckets, and Amazon ECR registries, have a *removal policy*\. The removal policy indicates whether to delete persistent objects when the AWS CDK stack that contains them is destroyed\. The values specifying the removal policy are available through the `RemovalPolicy` enumeration in the AWS CDK `core` module\. + +**Note** +Resources besides those that store data persistently might also have a `removalPolicy` that is used for a different purpose\. For example, a Lambda function version uses a `removalPolicy` attribute to determine whether a given version is retained when a new version is deployed\. These have different meanings and defaults compared to the removal policy on an Amazon S3 bucket or DynamoDB table\. + + +| Value | meaning | +| --- |--- | +| RemovalPolicy\.RETAIN | Keep the contents of the resource when destroying the stack \(default\)\. The resource is orphaned from the stack and must be deleted manually\. If you attempt to re\-deploy the stack while the resource still exists, you will receive an error message due to a name conflict\. | +| RemovalPolicy\.DESTROY | The resource will be destroyed along with the stack\. | + +AWS CloudFormation does not remove Amazon S3 buckets that contain files even if their removal policy is set to `DESTROY`\. Attempting to do so is an AWS CloudFormation error\. To have the AWS CDK delete all files from the bucket before destroying it, set the bucket's `autoDeleteObjects` property to `true`\. + +Following is an example of creating an Amazon S3 bucket with `RemovalPolicy` of `DESTROY` and `autoDeleteOjbects` set to `true`\. + +------ +#### [ TypeScript ] + +``` +import * as cdk from '@aws-cdk/core'; +import * as s3 from '@aws-cdk/aws-s3'; + +export class CdkTestStack extends cdk.Stack { + constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { + super(scope, id, props); + + const bucket = new s3.Bucket(this, 'Bucket', { + removalPolicy: cdk.RemovalPolicy.DESTROY, + autoDeleteObjects: true + }); + } +} +``` + +------ +#### [ JavaScript ] + +``` +const cdk = require('@aws-cdk/core'); +const s3 = require('@aws-cdk/aws-s3'); + +class CdkTestStack extends cdk.Stack { + constructor(scope, id, props) { + super(scope, id, props); + + const bucket = new s3.Bucket(this, 'Bucket', { + removalPolicy: cdk.RemovalPolicy.DESTROY, + autoDeleteObjects: true + }); + } +} + +module.exports = { CdkTestStack } +``` + +------ +#### [ Python ] + +``` +import aws_cdk.core as cdk +import aws_cdk.aws_s3 as s3 + +class CdkTestStack(cdk.stack): + def __init__(self, scope: cdk.Construct, id: str, **kwargs): + super().__init__(scope, id, **kwargs) + + bucket = s3.Bucket(self, "Bucket", + removal_policy=cdk.RemovalPolicy.DESTROY, + auto_delete_objects=True) +``` + +------ +#### [ Java ] + +``` +software.amazon.awscdk.core.*; +import software.amazon.awscdk.services.s3.*; + +public class CdkTestStack extends Stack { + public CdkTestStack(final Construct scope, final String id) { + this(scope, id, null); + } + + public CdkTestStack(final Construct scope, final String id, final StackProps props) { + super(scope, id, props); + + Bucket.Builder.create(this, "Bucket") + .removalPolicy(RemovalPolicy.DESTROY) + .autoDeleteObjects(true).build(); + } +} +``` + +------ +#### [ C\# ] + +``` +using Amazon.CDK; +using Amazon.CDK.AWS.S3; + +public CdkTestStack(Construct scope, string id, IStackProps props) : base(scope, id, props) +{ + new Bucket(this, "Bucket", new BucketProps { + RemovalPolicy = RemovalPolicy.DESTROY, + AutoDeleteObjects = true + }); +} +``` + +------ + +You can also apply a removal policy directly to the underlying AWS CloudFormation resource via the `applyRemovalPolicy()` method\. This method is available on some stateful resources that do not have a `removalPolicy` property in their L2 resource's props\. Examples include the following: ++ AWS CloudFormation stacks ++ Amazon Cognito user pools ++ Amazon DocumentDB database instances ++ Amazon EC2 volumes ++ Amazon OpenSearch Service domains ++ Amazon FSx file systems ++ Amazon SQS queues + +------ +#### [ TypeScript ] + +``` +const resource = bucket.node.findChild('Resource') as cdk.CfnResource; +resource.applyRemovalPolicy(cdk.RemovalPolicy.DESTROY); +``` + +------ +#### [ JavaScript ] + +``` +const resource = bucket.node.findChild('Resource'); +resource.applyRemovalPolicy(cdk.RemovalPolicy.DESTROY); +``` + +------ +#### [ Python ] + +``` +resource = bucket.node.find_child('Resource') +resource.apply_removal_policy(cdk.RemovalPolicy.DESTROY); +``` + +------ +#### [ Java ] + +``` +CfnResource resource = (CfnResource)bucket.node.findChild("Resource"); +resource.applyRemovalPolicy(cdk.RemovalPolicy.DESTROY); +``` + +------ +#### [ C\# ] + +``` +var resource = (CfnResource)bucket.node.findChild('Resource'); +resource.ApplyRemovalPolicy(cdk.RemovalPolicy.DESTROY); +``` + +------ + +**Note** +The AWS CDK's `RemovalPolicy` translates to AWS CloudFormation's `DeletionPolicy`\. However, the default in AWS CDK is to retain the data, which is the opposite of the AWS CloudFormation default\. \ No newline at end of file diff --git a/v2/sam.md b/v2/sam.md new file mode 100644 index 00000000..e61e0367 --- /dev/null +++ b/v2/sam.md @@ -0,0 +1,3 @@ +# AWS SAM integration<a name="sam"></a> + +The AWS CDK and the AWS Serverless Application Model \(AWS SAM\) can work together to let you to locally build and test serverless applications defined in the CDK\. For complete information, see [AWS Cloud Development Kit \(AWS CDK\)](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-cdk.html) in the AWS SAM Developer Guide\. To install the SAM CLI, see [Installing the AWS SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html)\. \ No newline at end of file diff --git a/v2/security-iam.md b/v2/security-iam.md new file mode 100644 index 00000000..55f220ba --- /dev/null +++ b/v2/security-iam.md @@ -0,0 +1,11 @@ +# Identity and access management for the AWS Cloud Development Kit \(AWS CDK\)<a name="security-iam"></a> + +AWS Identity and Access Management \(IAM\) is an Amazon Web Services \(AWS\) service that helps an administrator securely control access to AWS resources\. IAM administrators control who can be *authenticated* \(signed in\) and *authorized* \(have permissions\) to use resources in AWS services\. IAM is an AWS service that you can use with no additional charge\. + +To use the AWS CDK to access AWS, you need an AWS account and AWS credentials\. To increase the security of your AWS account, we recommend that you use an *IAM user* to provide access credentials instead of using your AWS account credentials\. + +For details about working with IAM, see [AWS Identity and Access Management](https://aws.amazon.com/iam/)\. + +For an overview of IAM users and why they are important for the security of your account, see [AWS Security Credentials](https://docs.aws.amazon.com/general/latest/gr/aws-security-credentials.html) in the [Amazon Web Services General Reference](https://docs.aws.amazon.com/general/latest/gr/)\. + +The AWS CDK follows the [shared responsibility model](https://aws.amazon.com/compliance/shared-responsibility-model/) through the specific Amazon Web Services \(AWS\) services it supports\. For AWS service security information, see the [AWS service security documentation page](https://docs.aws.amazon.com/security/?id=docs_gateway#aws-security) and [AWS services that are in scope of AWS compliance efforts by compliance program](https://aws.amazon.com/compliance/services-in-scope/)\. \ No newline at end of file diff --git a/v2/security.md b/v2/security.md new file mode 100644 index 00000000..bf319928 --- /dev/null +++ b/v2/security.md @@ -0,0 +1,15 @@ +# Security for the AWS Cloud Development Kit \(AWS CDK\)<a name="security"></a> + +Cloud security at Amazon Web Services \(AWS\) is the highest priority\. As an AWS customer, you benefit from a data center and network architecture that is built to meet the requirements of the most security\-sensitive organizations\. Security is a shared responsibility between AWS and you\. The [Shared Responsibility Model](https://aws.amazon.com/compliance/shared-responsibility-model/) describes this as Security of the Cloud and Security in the Cloud\. + +**Security of the Cloud** – AWS is responsible for protecting the infrastructure that runs all of the services offered in the AWS Cloud and providing you with services that you can use securely\. Our security responsibility is the highest priority at AWS, and the effectiveness of our security is regularly tested and verified by third\-party auditors as part of the [AWS Compliance Programs](https://aws.amazon.com/compliance/programs/)\. + +**Security in the Cloud** – Your responsibility is determined by the AWS service you are using, and other factors including the sensitivity of your data, your organization's requirements, and applicable laws and regulations\. + +The AWS CDK follows the [shared responsibility model](https://aws.amazon.com/compliance/shared-responsibility-model/) through the specific Amazon Web Services \(AWS\) services it supports\. For AWS service security information, see the [AWS service security documentation page](https://docs.aws.amazon.com/security/?id=docs_gateway#aws-security) and [AWS services that are in scope of AWS compliance efforts by compliance program](https://aws.amazon.com/compliance/services-in-scope/)\. + +**Topics** ++ [Identity and access management](security-iam.md) ++ [Compliance validation](compliance-validation.md) ++ [Resilience](disaster-recovery-resiliency.md) ++ [Infrastructure security](infrastructure-security.md) \ No newline at end of file diff --git a/v2/serverless_example.md b/v2/serverless_example.md new file mode 100644 index 00000000..4e551396 --- /dev/null +++ b/v2/serverless_example.md @@ -0,0 +1,805 @@ +# Creating a serverless application using the AWS CDK<a name="serverless_example"></a> + +This example walks you through creating the resources for a simple widget dispensing service\. \(For the purpose of this example, a widget is just a name or identifier that can be added to, retrieved from, and deleted from a collection\.\) The example includes: ++ An AWS Lambda function\. ++ An Amazon API Gateway API to call the Lambda function\. ++ An Amazon S3 bucket that holds the widgets\. + +This tutorial contains the following steps\. + +1. Create an AWS CDK app + +1. Create a Lambda function that gets a list of widgets with HTTP GET / + +1. Create the service that calls the Lambda function + +1. Add the service to the AWS CDK app + +1. Test the app + +1. Add Lambda functions to do the following: + + Create a widget with POST /\{name\} + + Get a widget by name with GET /\{name\} + + Delete a widget by name with DELETE /\{name\} + +1. Tear everything down when you're finished + +## Create an AWS CDK app<a name="serverless_example_create_app"></a> + +Create the app **MyWidgetService** in the current folder\. + +------ +#### [ TypeScript ] + +``` +mkdir MyWidgetService +cd MyWidgetService +cdk init --language typescript +``` + +------ +#### [ JavaScript ] + +``` +mkdir MyWidgetService +cd MyWidgetService +cdk init --language javascript +``` + +------ +#### [ Python ] + +``` +mkdir MyWidgetService +cd MyWidgetService +cdk init --language python +source .venv/bin/activate +pip install -r requirements.txt +``` + +------ +#### [ Java ] + +``` +mkdir MyWidgetService +cd MyWidgetService +cdk init --language java +``` + +You may now import the Maven project into your IDE\. + +------ +#### [ C\# ] + +``` +mkdir MyWidgetService +cd MyWidgetService +cdk init --language csharp +``` + +You may now open `src/MyWidgetService.sln` in Visual Studio\. + +------ + +**Note** +The CDK names source files and classes based on the name of the project directory\. If you don't use the name `MyWidgetService` as shown previously, it might be difficult to follow the rest of the steps\. Some of the files that the instructions tell you to modify wont' be there, because they will have different names\. + +The important files in the blank project are as follows\. \(We will also be adding a couple of new files\.\) + +------ +#### [ TypeScript ] ++ `bin/my_widget_service.ts` – Main entry point for the application ++ `lib/my_widget_service-stack.ts` – Defines the widget service stack + +------ +#### [ JavaScript ] ++ `bin/my_widget_service.js` – Main entry point for the application ++ `lib/my_widget_service-stack.js` – Defines the widget service stack + +------ +#### [ Python ] ++ `app.py` – Main entry point for the application ++ `my_widget_service/my_widget_service_stack.py` – Defines the widget service stack + +------ +#### [ Java ] ++ `src/main/java/com/myorg/MyWidgetServiceApp.java` – Main entry point for the application ++ `src/main/java/com/myorg/MyWidgetServiceStack.java` – Defines the widget service stack + +------ +#### [ C\# ] ++ `src/MyWidgetService/Program.cs` – Main entry point for the application ++ `src/MyWidgetService/MyWidgetServiceStack.cs` – Defines the widget service stack + +------ + +Run the app and note that it synthesizes an empty stack\. + +``` +cdk synth +``` + +You should see output beginning with YAML code like the following\. + +``` +Resources: + CDKMetadata: + Type: AWS::CDK::Metadata + Properties: + ... +``` + +## Create a Lambda function to list all widgets<a name="serverless_example_create_iam_function"></a> + +The next step is to create a Lambda function to list all of the widgets in our Amazon S3 bucket\. We will provide the Lambda function's code in JavaScript\. + +Create the `resources` directory in the project's main directory\. + +``` +mkdir resources +``` + +Create the following JavaScript file, `widgets.js`, in the `resources` directory\. + +``` +/* +This code uses callbacks to handle asynchronous function responses. +It currently demonstrates using an async-await pattern. +AWS supports both the async-await and promises patterns. +For more information, see the following: +https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function +https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises +https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/calling-services-asynchronously.html +https://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-handler.html +*/ +const AWS = require('aws-sdk'); +const S3 = new AWS.S3(); + +const bucketName = process.env.BUCKET; + +exports.main = async function(event, context) { + try { + var method = event.httpMethod; + + if (method === "GET") { + if (event.path === "/") { + const data = await S3.listObjectsV2({ Bucket: bucketName }).promise(); + var body = { + widgets: data.Contents.map(function(e) { return e.Key }) + }; + return { + statusCode: 200, + headers: {}, + body: JSON.stringify(body) + }; + } + } + + // We only accept GET for now + return { + statusCode: 400, + headers: {}, + body: "We only accept GET /" + }; + } catch(error) { + var body = error.stack || JSON.stringify(error, null, 2); + return { + statusCode: 400, + headers: {}, + body: JSON.stringify(body) + } + } +} +``` + +Save it and be sure the project still results in an empty stack\. We haven't yet wired the Lambda function to the AWS CDK app, so the Lambda asset doesn't appear in the output\. + +``` +cdk synth +``` + +## Create a widget service<a name="serverless_example_create_widget_service"></a> + +Create a new source file to define the widget service with the source code shown below\. + +------ +#### [ TypeScript ] + +File: `lib/widget_service.ts` + +``` +import * as cdk from "aws-cdk-lib"; +import { Construct } from "constructs"; +import * as apigateway from "aws-cdk-lib/aws-apigateway"; +import * as lambda from "aws-cdk-lib/aws-lambda"; +import * as s3 from "aws-cdk-lib/aws-s3"; + +export class WidgetService extends Construct { + constructor(scope: Construct, id: string) { + super(scope, id); + + const bucket = new s3.Bucket(this, "WidgetStore"); + + const handler = new lambda.Function(this, "WidgetHandler", { + runtime: lambda.Runtime.NODEJS_14_X, // So we can use async in widget.js + code: lambda.Code.fromAsset("resources"), + handler: "widgets.main", + environment: { + BUCKET: bucket.bucketName + } + }); + + bucket.grantReadWrite(handler); // was: handler.role); + + const api = new apigateway.RestApi(this, "widgets-api", { + restApiName: "Widget Service", + description: "This service serves widgets." + }); + + const getWidgetsIntegration = new apigateway.LambdaIntegration(handler, { + requestTemplates: { "application/json": '{ "statusCode": "200" }' } + }); + + api.root.addMethod("GET", getWidgetsIntegration); // GET / + } +} +``` + +------ +#### [ JavaScript ] + +File: `lib/widget_service.js` + +``` +const cdk = require("aws-cdk-lib"); +const { Construct } = require("constructs"); +const apigateway = require("aws-cdk-lib/aws-apigateway"); +const lambda = require("aws-cdk-lib/aws-lambda"); +const s3 = require("aws-cdk-lib/aws-s3"); + +class WidgetService extends Construct { + constructor(scope, id) { + super(scope, id); + + const bucket = new s3.Bucket(this, "WidgetStore"); + + const handler = new lambda.Function(this, "WidgetHandler", { + runtime: lambda.Runtime.NODEJS_14_X, // So we can use async in widget.js + code: lambda.Code.fromAsset("resources"), + handler: "widgets.main", + environment: { + BUCKET: bucket.bucketName + } + }); + + bucket.grantReadWrite(handler); // was: handler.role); + + const api = new apigateway.RestApi(this, "widgets-api", { + restApiName: "Widget Service", + description: "This service serves widgets." + }); + + const getWidgetsIntegration = new apigateway.LambdaIntegration(handler, { + requestTemplates: { "application/json": '{ "statusCode": "200" }' } + }); + + api.root.addMethod("GET", getWidgetsIntegration); // GET / + } +} + +module.exports = { WidgetService } +``` + +------ +#### [ Python ] + +File: `my_widget_service/widget_service.py` + +``` +import aws_cdk as cdk +from constructs import Construct +from aws_cdk import (aws_apigateway as apigateway, + aws_s3 as s3, + aws_lambda as lambda_) + +class WidgetService(Construct): + def __init__(self, scope: Construct, id: str): + super().__init__(scope, id) + + bucket = s3.Bucket(self, "WidgetStore") + + handler = lambda_.Function(self, "WidgetHandler", + runtime=lambda_.Runtime.NODEJS_14_X, + code=lambda_.Code.from_asset("resources"), + handler="widgets.main", + environment=dict( + BUCKET=bucket.bucket_name) + ) + + bucket.grant_read_write(handler) + + api = apigateway.RestApi(self, "widgets-api", + rest_api_name="Widget Service", + description="This service serves widgets.") + + get_widgets_integration = apigateway.LambdaIntegration(handler, + request_templates={"application/json": '{ "statusCode": "200" }'}) + + api.root.add_method("GET", get_widgets_integration) # GET / +``` + +------ +#### [ Java ] + +File: `src/src/main/java/com/myorg/WidgetService.java` + +``` +package com.myorg; + +import java.util.HashMap; + +import software.constructs.Construct; +import software.amazon.awscdk.services.apigateway.LambdaIntegration; +import software.amazon.awscdk.services.apigateway.Resource; +import software.amazon.awscdk.services.apigateway.RestApi; +import software.amazon.awscdk.services.lambda.Code; +import software.amazon.awscdk.services.lambda.Function; +import software.amazon.awscdk.services.lambda.Runtime; +import software.amazon.awscdk.services.s3.Bucket; + +public class WidgetService extends Construct { + + @SuppressWarnings("serial") + public WidgetService(Construct scope, String id) { + super(scope, id); + + Bucket bucket = new Bucket(this, "WidgetStore"); + + Function handler = Function.Builder.create(this, "WidgetHandler") + .runtime(Runtime.NODEJS_14_X) + .code(Code.fromAsset("resources")) + .handler("widgets.main") + .environment(java.util.Map.of( // Java 9 or later + "BUCKET", bucket.getBucketName()) + .build(); + + bucket.grantReadWrite(handler); + + RestApi api = RestApi.Builder.create(this, "Widgets-API") + .restApiName("Widget Service").description("This service services widgets.") + .build(); + + LambdaIntegration getWidgetsIntegration = LambdaIntegration.Builder.create(handler) + .requestTemplates(java.util.Map.of( // Map.of is Java 9 or later + "application/json", "{ \"statusCode\": \"200\" }")) + .build(); + + api.getRoot().addMethod("GET", getWidgetsIntegration); + } +} +``` + +------ +#### [ C\# ] + +File: `src/MyWidgetService/WidgetService.cs` + +``` +using Amazon.CDK; +using Amazon.CDK.AWS.APIGateway; +using Amazon.CDK.AWS.Lambda; +using Amazon.CDK.AWS.S3; +using System.Collections.Generic; +using constructs; + +namespace MyWidgetService +{ + + public class WidgetService : Construct + { + public WidgetService(Construct scope, string id) : base(scope, id) + { + var bucket = new Bucket(this, "WidgetStore"); + + var handler = new Function(this, "WidgetHandler", new FunctionProps + { + Runtime = Runtime.NODEJS_14_X, + Code = Code.FromAsset("resources"), + Handler = "widgets.main", + Environment = new Dictionary<string, string> + { + ["BUCKET"] = bucket.BucketName + } + }); + + bucket.GrantReadWrite(handler); + + var api = new RestApi(this, "Widgets-API", new RestApiProps + { + RestApiName = "Widget Service", + Description = "This service services widgets." + }); + + var getWidgetsIntegration = new LambdaIntegration(handler, new LambdaIntegrationOptions + { + RequestTemplates = new Dictionary<string, string> + { + ["application/json"] = "{ \"statusCode\": \"200\" }" + } + }); + + api.Root.AddMethod("GET", getWidgetsIntegration); + + } + } +} +``` + +------ + +**Tip** +We're using a `[lambda\.Function](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.Function.html)` in to deploy this function because it supports a wide variety of programming languages\. For JavaScript and TypeScript specifically, you might consider a `[lambda\-nodejs\.NodejsFunction](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda_nodejs.NodejsFunction.html)`\. The latter uses esbuild to bundle up the script and converts code written in TypeScript automatically\. + +Save the app and make sure it still synthesizes an empty stack\. + +``` +cdk synth +``` + +## Add the service to the app<a name="serverless_example_add_service"></a> + +To add the widget service to our AWS CDK app, we'll need to modify the source file that defines the stack to instantiate the service construct\. + +------ +#### [ TypeScript ] + +File: `lib/my_widget_service-stack.ts` + +Add the following line of code after the existing `import` statement\. + +``` +import * as widget_service from '../lib/widget_service'; +``` + +Replace the comment in the constructor with the following line of code\. + +``` + new widget_service.WidgetService(this, 'Widgets'); +``` + +------ +#### [ JavaScript ] + +File: `lib/my_widget_service-stack.js` + +Add the following line of code after the existing `require()` line\. + +``` +const widget_service = require('../lib/widget_service'); +``` + +Replace the comment in the constructor with the following line of code\. + +``` + new widget_service.WidgetService(this, 'Widgets'); +``` + +------ +#### [ Python ] + +File: `my_widget_service/my_widget_service_stack.py` + +Add the following line of code after the existing `import` statement\. + +``` +from . import widget_service +``` + +Replace the comment in the constructor with the following line of code\. + +``` + widget_service.WidgetService(self, "Widgets") +``` + +------ +#### [ Java ] + +File: `src/src/main/java/com/myorg/MyWidgetServiceStack.java` + +Replace the comment in the constructor with the following line of code\. + +``` +new WidgetService(this, "Widgets"); +``` + +------ +#### [ C\# ] + +File: `src/MyWidgetService/MyWidgetServiceStack.cs` + +Replace the comment in the constructor with the following line of code\. + +``` +new WidgetService(this, "Widgets"); +``` + +------ + +Be sure the app runs and synthesizes a stack \(we won't show the stack here: it's over 250 lines\)\. + +``` +cdk synth +``` + +## Deploy and test the app<a name="serverless_example_deploy_and_test"></a> + +Before you can deploy your first AWS CDK app, you must bootstrap your AWS environment\. Among other resources, this creates a staging bucket that the AWS CDK uses to deploy stacks containing assets\. For details, see [Bootstrapping your AWS environment](cli.md#cli-bootstrap)\. If you've already bootstrapped, you'll get a warning and nothing will change\. + +``` +cdk bootstrap aws://ACCOUNT-NUMBER/REGION +``` + +Now we're ready to deploy the app as follows\. + +``` +cdk deploy +``` + +If the deployment succeeds, save the URL for your server\. This URL appears in one of the last lines in the window, where *GUID* is an alphanumeric GUID and *REGION* is your AWS Region\. + +``` +https://GUID.execute-api-REGION.amazonaws.com/prod/ +``` + +Test your app by getting the list of widgets \(currently empty\) by navigating to this URL in a browser, or use the following command\. + +``` +curl -X GET 'https://GUID.execute-api.REGION.amazonaws.com/prod' +``` + +You can also test the app by completing the following steps: + +1. Open the AWS Management Console\. + +1. Navigate to the API Gateway service\. + +1. Find **Widget Service** in the list\. + +1. Select **GET** and **Test** to test the function\. + +Because we haven't stored any widgets yet, the output should be similar to the following\. + +``` +{ "widgets": [] } +``` + +## Add the individual widget functions<a name="serverless_example_add_widget_functions"></a> + +The next step is to create Lambda functions to create, show, and delete individual widgets\. + +Replace the code in `widgets.js` \(in `resources`\) with the following\. + +``` +const AWS = require('aws-sdk'); +const S3 = new AWS.S3(); + +const bucketName = process.env.BUCKET; + +/* +This code uses callbacks to handle asynchronous function responses. +It currently demonstrates using an async-await pattern. +AWS supports both the async-await and promises patterns. +For more information, see the following: +https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function +https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises +https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/calling-services-asynchronously.html +https://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-handler.html +*/ +exports.main = async function(event, context) { + try { + var method = event.httpMethod; + // Get name, if present + var widgetName = event.path.startsWith('/') ? event.path.substring(1) : event.path; + + if (method === "GET") { + // GET / to get the names of all widgets + if (event.path === "/") { + const data = await S3.listObjectsV2({ Bucket: bucketName }).promise(); + var body = { + widgets: data.Contents.map(function(e) { return e.Key }) + }; + return { + statusCode: 200, + headers: {}, + body: JSON.stringify(body) + }; + } + + if (widgetName) { + // GET /name to get info on widget name + const data = await S3.getObject({ Bucket: bucketName, Key: widgetName}).promise(); + var body = data.Body.toString('utf-8'); + + return { + statusCode: 200, + headers: {}, + body: JSON.stringify(body) + }; + } + } + + if (method === "POST") { + // POST /name + // Return error if we do not have a name + if (!widgetName) { + return { + statusCode: 400, + headers: {}, + body: "Widget name missing" + }; + } + + // Create some dummy data to populate object + const now = new Date(); + var data = widgetName + " created: " + now; + + var base64data = new Buffer(data, 'binary'); + + await S3.putObject({ + Bucket: bucketName, + Key: widgetName, + Body: base64data, + ContentType: 'application/json' + }).promise(); + + return { + statusCode: 200, + headers: {}, + body: data + }; + } + + if (method === "DELETE") { + // DELETE /name + // Return an error if we do not have a name + if (!widgetName) { + return { + statusCode: 400, + headers: {}, + body: "Widget name missing" + }; + } + + await S3.deleteObject({ + Bucket: bucketName, Key: widgetName + }).promise(); + + return { + statusCode: 200, + headers: {}, + body: "Successfully deleted widget " + widgetName + }; + } + + // We got something besides a GET, POST, or DELETE + return { + statusCode: 400, + headers: {}, + body: "We only accept GET, POST, and DELETE, not " + method + }; + } catch(error) { + var body = error.stack || JSON.stringify(error, null, 2); + return { + statusCode: 400, + headers: {}, + body: body + } + } +} +``` + +Wire up these functions to your API Gateway code at the end of the `WidgetService` constructor\. + +------ +#### [ TypeScript ] + +File: `lib/widget_service.ts` + +``` + const widget = api.root.addResource("{id}"); + + const widgetIntegration = new apigateway.LambdaIntegration(handler); + + widget.addMethod("POST", widgetIntegration); // POST /{id} + widget.addMethod("GET", widgetIntegration); // GET /{id} + widget.addMethod("DELETE", widgetIntegration); // DELETE /{id} +``` + +------ +#### [ JavaScript ] + +File: `lib/widget_service.js` + +``` + const widget = api.root.addResource("{id}"); + + const widgetIntegration = new apigateway.LambdaIntegration(handler); + + widget.addMethod("POST", widgetIntegration); // POST /{id} + widget.addMethod("GET", widgetIntegration); // GET /{id} + widget.addMethod("DELETE", widgetIntegration); // DELETE /{id} +``` + +------ +#### [ Python ] + +File: `my_widget_service/widget_service.py` + +``` + widget = api.root.add_resource("{id}") + + widget_integration = apigateway.LambdaIntegration(handler) + + widget.add_method("POST", widget_integration); # POST /{id} + widget.add_method("GET", widget_integration); # GET /{id} + widget.add_method("DELETE", widget_integration); # DELETE /{id} +``` + +------ +#### [ Java ] + +File: `src/src/main/java/com/myorg/WidgetService.java` + +``` + Resource widget = api.getRoot().addResource("{id}"); + + LambdaIntegration widgetIntegration = new LambdaIntegration(handler); + + widget.addMethod("POST", widgetIntegration); // POST /{id} + widget.addMethod("GET", widgetIntegration); // GET /{id} + widget.addMethod("DELETE", widgetIntegration); // DELETE /{id} +``` + +------ +#### [ C\# ] + +File: `src/MyWidgetService/WidgetService.cs` + +``` + var widget = api.Root.AddResource("{id}"); + + var widgetIntegration = new LambdaIntegration(handler); + + widget.AddMethod("POST", widgetIntegration); // POST /{id} + widget.AddMethod("GET", widgetIntegration); // GET /{id} + widget.AdMethod("DELETE", widgetIntegration); // DELETE /{id} +``` + +------ + +Save and deploy the app\. + +``` +cdk deploy +``` + +We can now store, show, or delete an individual widget\. Use the following commands to list the widgets, create the widget **example**, list all of the widgets, show the contents of **example** \(it should show today's date\), delete **example**, and then show the list of widgets again\. + +``` +curl -X GET 'https://GUID.execute-api.REGION.amazonaws.com/prod' +curl -X POST 'https://GUID.execute-api.REGION.amazonaws.com/prod/example' +curl -X GET 'https://GUID.execute-api.REGION.amazonaws.com/prod' +curl -X GET 'https://GUID.execute-api.REGION.amazonaws.com/prod/example' +curl -X DELETE 'https://GUID.execute-api.REGION.amazonaws.com/prod/example' +curl -X GET 'https://GUID.execute-api.REGION.amazonaws.com/prod' +``` + +You can also use the API Gateway console to test these functions\. Set the **name** value to the name of a widget, such as **example**\. + +## Clean up<a name="serverless_example_destroy"></a> + +To avoid unexpected AWS charges, destroy your AWS CDK stack after you're done with this exercise\. + +``` +cdk destroy +``` \ No newline at end of file diff --git a/v2/guide/how-tos/create-multiple-stacks.adoc b/v2/stack_how_to_create_multiple_stacks.md similarity index 62% rename from v2/guide/how-tos/create-multiple-stacks.adoc rename to v2/stack_how_to_create_multiple_stacks.md index 42224032..c31fe24c 100644 --- a/v2/guide/how-tos/create-multiple-stacks.adoc +++ b/v2/stack_how_to_create_multiple_stacks.md @@ -1,102 +1,85 @@ -include::../attributes.txt[] +# Create an app with multiple stacks<a name="stack_how_to_create_multiple_stacks"></a> -// Attributes +Most of the code examples in the *AWS CDK Developer Guide* involve only a single stack\. However, you can create apps containing any number of stacks\. Each stack results in its own AWS CloudFormation template\. Stacks are the *unit of deployment:* each stack in an app can be synthesized and deployed individually using the `cdk deploy` command\. -[.topic] -[#stack-how-to-create-multiple-stacks] -= Example: Create a CDK app with multiple stacks -:info_titleabbrev: Example: CDK app with multiple stacks +This topic illustrates the following: ++ How to extend the `Stack` class to accept new properties or arguments ++ How to use these properties to affect what resources the stack contains and their configuration ++ How to instantiate multiple stacks from this class -// Content start +The example uses a Boolean property, named `encryptBucket` \(Python: `encrypt_bucket`\)\. It indicates whether an Amazon S3 bucket should be encrypted\. If so, the stack enables encryption using a key managed by AWS Key Management Service \(AWS KMS\)\. The app creates two instances of this stack, one with encryption and one without\. -You can create an {aws} Cloud Development Kit ({aws} CDK) application containing multiple xref:stacks[stacks]. When you deploy the {aws} CDK app, each stack becomes its own {aws} CloudFormation template. You can also synthesize and deploy each stack individually using the {aws} CDK CLI `cdk deploy` command. +## Before you begin<a name="cdk-how-to-create-multiple-stacks-prereqs"></a> -In this example, we cover the following: +First, install Node\.js and the AWS CDK command line tools, if you haven't already\. See [Getting started with the AWS CDK](getting_started.md) for details\. -* How to extend the `Stack` class to accept new properties or arguments. -* How to use properties to determine which resources the stack contains and their configuration. -* How to instantiate multiple stacks from this class. +Next, create an AWS CDK project by entering the following commands at the command line\. -The example in this topic uses a Boolean property, named `encryptBucket` (Python: `encrypt_bucket`). It indicates whether an Amazon S3 bucket should be encrypted. If so, the stack enables encryption using a key managed by {aws} Key Management Service ({aws} KMS). The app creates two instances of this stack, one with encryption and one without. +------ +#### [ TypeScript ] -[#cdk-how-to-create-multiple-stacks-prereqs] -== Prerequisites - -This example assumes that all xref:getting-started[getting started] steps have been completed. - -[#cdk-how-to-create-multiple-stacks-create] -== Create a CDK project - -First, we create a CDK project using the CDK CLI: - -==== -[role="tablist"] -TypeScript:: -+ -[source,none,subs="verbatim,attributes"] ----- +``` mkdir multistack cd multistack cdk init --language=typescript ----- +``` + +------ +#### [ JavaScript ] -JavaScript:: -+ -[source,none,subs="verbatim,attributes"] ----- +``` mkdir multistack cd multistack cdk init --language=javascript ----- +``` + +------ +#### [ Python ] -Python:: -+ -[source,none,subs="verbatim,attributes"] ----- +``` mkdir multistack cd multistack cdk init --language=python -source .venv/bin/activate # On Windows, run '.\venv\Scripts\activate' instead +source .venv/bin/activate pip install -r requirements.txt ----- +``` -Java:: -+ -[source,none,subs="verbatim,attributes"] ----- +------ +#### [ Java ] + +``` mkdir multistack cd multistack cdk init --language=java ----- -+ -You can import the resulting Maven project into your Java IDE. - -C#:: -+ -[source,none,subs="verbatim,attributes"] ----- +``` + +You can import the resulting Maven project into your Java IDE\. + +------ +#### [ C\# ] + +``` mkdir multistack cd multistack cdk init --language=csharp ----- -+ -You can open the file `src/Pipeline.sln` in Visual Studio. -==== +``` + +You can open the file `src/Pipeline.sln` in Visual Studio\. + +------ -[#cdk-how-to-create-multiple-stacks-extend-stackprops] -== Add an optional parameter +## Add optional parameter<a name="cdk-how-to-create-multiple-stacks-extend-stackprops"></a> -The `props` argument of the `Stack` constructor fulfills the interface `StackProps`. In this example, we want the stack to accept an additional property to tell us whether to encrypt the Amazon S3 bucket. To do this, we create an interface or class that includes the property. This allows the compiler to make sure that the property has a Boolean value and enables auto-completion for it in your IDE. +The `props` argument of the `Stack` constructor fulfills the interface `StackProps`\. In this example, we want the stack to accept an additional property to tell us whether to encrypt the Amazon S3 bucket\. We should create an interface or class that includes the property\. This allows the compiler to make sure that the property has a Boolean value and enables autocompletion for it in your IDE\. -We open our _stack file_ in our IDE or editor and add the new interface, class, or argument. New lines are highlighted in bold: +So open the indicated source file in your IDE or editor and add the new interface, class, or argument\. The code should look like this after the changes\. The lines we added are shown in bold\. + +------ +#### [ TypeScript ] -==== -[role="tablist"] -TypeScript:: File: `lib/multistack-stack.ts` -+ -[source,javascript,subs="verbatim,attributes"] ----- + +``` import * as cdk from 'aws-cdk-lib'; import { Construct } from 'constructs'; @@ -108,38 +91,40 @@ export class MultistackStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: MultiStackProps) { super(scope, id, props); - // The code that defines our stack goes here + // The code that defines your stack goes here } } ----- +``` + +------ +#### [ JavaScript ] -JavaScript:: File: `lib/multistack-stack.js` -+ -JavaScript doesn't have an interface feature; we don't need to add any code. -+ -[source,javascript,subs="verbatim,attributes"] ----- + +JavaScript doesn't have an interface feature; we don't need to add any code\. + +``` const cdk = require('aws-cdk-stack'); class MultistackStack extends cdk.Stack { constructor(scope, id, props) { super(scope, id, props); - // The code that defines our stack goes here + // The code that defines your stack goes here } } module.exports = { MultistackStack } ----- +``` + +------ +#### [ Python ] -Python:: File: `multistack/multistack_stack.py` -+ -Python does not have an interface feature, so we'll extend our stack to accept the new property by adding a keyword argument. -+ -[source,python,subs="verbatim,attributes"] ----- + +Python does not have an interface feature, so we'll extend our stack to accept the new property by adding a keyword argument\. + +``` import aws_cdk as cdk from constructs import Construct @@ -151,16 +136,17 @@ class MultistackStack(cdk.Stack): **kwargs) -> None: super().__init__(scope, id, **kwargs) - # The code that defines our stack goes here ----- + # The code that defines your stack goes here +``` + +------ +#### [ Java ] -Java:: File: `src/main/java/com/myorg/MultistackStack.java` -+ -It's more complicated than we really want to get into to extend a props type in Java. Instead, write the stack's constructor to accept an optional Boolean parameter. Because `props` is an optional argument, we'll write an additional constructor that lets you skip it. It will default to `false`. -+ -[source,java,subs="verbatim,attributes"] ----- + +It's more complicated than we really want to get into to extend a props type in Java\. Instead, write the stack's constructor to accept an optional Boolean parameter\. Because `props` is an optional argument, we'll write an additional constructor that lets you skip it\. It will default to `false`\. + +``` package com.myorg; import software.amazon.awscdk.Stack; @@ -183,16 +169,17 @@ public class MultistackStack extends Stack { final boolean encryptBucket) { super(scope, id, props); - // The code that defines our stack goes here + // The code that defines your stack goes here } } ----- +``` + +------ +#### [ C\# ] -C#:: File: `src/Multistack/MultistackStack.cs` -+ -[source,csharp,subs="verbatim,attributes"] ----- + +``` using Amazon.CDK; using constructs; @@ -210,27 +197,26 @@ namespace Multistack { public MultistackStack(Construct scope, string id, MultiStackProps props) : base(scope, id, props) { - // The code that defines our stack goes here + // The code that defines your stack goes here } } } ----- -==== +``` + +------ + +The new property is optional\. If `encryptBucket` \(Python: `encrypt_bucket`\) is not present, its value is `undefined`, or the local equivalent\. The bucket will be unencrypted by default\. -The new property is optional. If `encryptBucket` (Python: `encrypt_bucket`) is not present, its value is `undefined`, or the local equivalent. The bucket will be unencrypted by default. +## Define the stack class<a name="cdk-how-to-create-multiple-stacks-define-stack"></a> -[#cdk-how-to-create-multiple-stacks-define-stack] -== Define the stack class + Now let's define our stack class, using our new property\. Make the code look like the following\. The code you need to add or change is shown in bold\. -Next, we define our stack class, using our new property. New code is highlighted in bold: +------ +#### [ TypeScript ] -==== -[role="tablist"] -TypeScript:: File: `lib/multistack-stack.ts` -+ -[source,javascript,subs="verbatim,attributes"] ----- + +``` import * as cdk from 'aws-cdk-lib'; import { Construct } from constructs; import * as s3 from 'aws-cdk-lib/aws-s3'; @@ -257,13 +243,14 @@ export class MultistackStack extends cdk.Stack { } } } ----- +``` + +------ +#### [ JavaScript ] -JavaScript:: File: `lib/multistack-stack.js` -+ -[source,javascript,subs="verbatim,attributes"] ----- + +``` const cdk = require('aws-cdk-lib'); const s3 = require('aws-cdk-lib/aws-s3'); @@ -287,13 +274,14 @@ class MultistackStack extends cdk.Stack { } module.exports = { MultistackStack } ----- +``` + +------ +#### [ Python ] -Python:: File: `multistack/multistack_stack.py` -+ -[source,python,subs="verbatim,attributes"] ----- + +``` import aws_cdk as cdk from constructs import Construct from aws_cdk import aws_s3 as s3 @@ -316,13 +304,14 @@ class MultistackStack(cdk.Stack): else: s3.Bucket(self, "MyGroovyBucket", removal_policy=cdk.RemovalPolicy.DESTROY) ----- +``` + +------ +#### [ Java ] -Java:: File: `src/main/java/com/myorg/MultistackStack.java` -+ -[source,java,subs="verbatim,attributes"] ----- + +``` package com.myorg; import software.amazon.awscdk.Stack; @@ -362,15 +351,16 @@ public class MultistackStack extends Stack { } } } ----- +``` + +------ +#### [ C\# ] -C#:: File: `src/Multistack/MultistackStack.cs` -+ -[source,csharp,subs="verbatim,attributes"] ----- + +``` using Amazon.CDK; -using Amazon.CDK.{aws}.S3; +using Amazon.CDK.AWS.S3; namespace Multistack { @@ -405,21 +395,20 @@ namespace Multistack } } } ----- -==== +``` -[#stack-how-to-create-multiple-stacks-create-stacks] -== Create two stack instances +------ -In our _application file_, we add the code to instantiate two separate stacks. We delete the existing `MultistackStack` definition and define our two stacks. New code is highlight in bold: +## Create two stack instances<a name="stack_how_to_create_multiple_stacks-create-stacks"></a> + +Now we'll add the code to instantiate two separate stacks\. As before, the lines of code shown in bold are the ones you need to add\. Delete the existing `MultistackStack` definition\. + +------ +#### [ TypeScript ] -==== -[role="tablist"] -TypeScript:: File: `bin/multistack.ts` -+ -[source,javascript,subs="verbatim,attributes"] ----- + +``` #!/usr/bin/env node import 'source-map-support/register'; import * as cdk from 'aws-cdk-lib'; @@ -438,13 +427,14 @@ new MultistackStack(app, "MyEastCdkStack", { }); app.synth(); ----- +``` + +------ +#### [ JavaScript ] -JavaScript:: File: `bin/multistack.js` -+ -[source,javascript,subs="verbatim,attributes"] ----- + +``` #!/usr/bin/env node const cdk = require('aws-cdk-lib'); const { MultistackStack } = require('../lib/multistack-stack'); @@ -462,13 +452,14 @@ new MultistackStack(app, "MyEastCdkStack", { }); app.synth(); ----- +``` + +------ +#### [ Python ] -Python:: File: `./app.py` -+ -[source,python,subs="verbatim,attributes"] ----- + +``` #!/usr/bin/env python3 import aws_cdk as cdk @@ -485,13 +476,14 @@ MultistackStack(app, "MyEastCdkStack", encrypt_bucket=True) app.synth() ----- +``` + +------ +#### [ Java ] -Java:: File: `src/main/java/com/myorg/MultistackApp.java` -+ -[source,java,subs="verbatim,attributes"] ----- + +``` package com.myorg; import software.amazon.awscdk.App; @@ -517,13 +509,14 @@ public class MultistackApp { app.synth(); } } ----- +``` + +------ +#### [ C\# ] + +File: src/Multistack/Program\.cs -C#:: -File: src/Multistack/Program.cs -+ -[source,csharp,subs="verbatim,attributes"] ----- +``` using Amazon.CDK; namespace Multistack @@ -550,44 +543,38 @@ namespace Multistack } } } ----- -==== +``` -This code uses the new `encryptBucket` (Python: `encrypt_bucket`) property on the `MultistackStack` class to instantiate the following: +------ -* One stack with an encrypted Amazon S3 bucket in the `us-east-1` {aws} Region. -* One stack with an unencrypted Amazon S3 bucket in the `us-west-1` {aws} Region. + This code uses the new `encryptBucket` \(Python: `encrypt_bucket`\) property on the `MultistackStack` class to instantiate the following: ++ One stack with an encrypted Amazon S3 bucket in the `us-east-1` AWS Region\. ++ One stack with an unencrypted Amazon S3 bucket in the `us-west-1` AWS Region\. -[#cdk-how-to-create-multiple-stacks-synth-deploy] -== Synthesize and deploy the stack +## Synthesize and deploy the stack<a name="cdk-how-to-create-multiple-stacks-synth-deploy"></a> -Next, we can deploy stacks from the app. First, we synthesize an {aws} CloudFormation template for `MyEastCdkStack`. This is the stack in `us-east-1` with the encrypted Amazon S3 bucket. +Now you can deploy stacks from the app\. First, synthesize an AWS CloudFormation template for `MyEastCdkStack`—the stack in `us-east-1`\. This is the stack with the encrypted S3 bucket\. -[source,none,subs="verbatim,attributes"] ----- +``` $ cdk synth MyEastCdkStack ----- +``` -To deploy this stack to our {aws} environment, we can issue one of the following commands. The first command uses our default {aws} profile to obtain the credentials to deploy the stack. The second uses a profile that we specify. For `PROFILE_NAME`, we can substitute the name of an {aws} CLI profile that contains appropriate credentials for deploying to the `us-east-1` {aws} Region. +To deploy this stack to your AWS account, issue one of the following commands\. The first command uses your default AWS profile to obtain the credentials to deploy the stack\. The second uses a profile that you specify\. For *PROFILE\_NAME*, substitute the name of an AWS CLI profile that contains appropriate credentials for deploying to the `us-east-1` AWS Region\. -[source,none,subs="verbatim,attributes"] ----- -$ cdk deploy MyEastCdkStack ----- +``` +cdk deploy MyEastCdkStack +``` -[source,none,subs="verbatim,attributes"] ----- -$ cdk deploy MyEastCdkStack --profile=<PROFILE_NAME> ----- +``` +cdk deploy MyEastCdkStack --profile=PROFILE_NAME +``` -[#cdk-how-to-create-multiple-stacks-destroy-stack] -== Clean up +## Clean up<a name="cdk-how-to-create-multiple-stacks-destroy-stack"></a> -To avoid charges for resources that we deployed, we destroy the stack using the following command: +To avoid charges for resources that you deployed, destroy the stack using the following command\. -[source,none,subs="verbatim,attributes"] ----- +``` cdk destroy MyEastCdkStack ----- +``` -The destroy operation fails if there is anything stored in the stack's bucket. There shouldn't be, since we only created the bucket. If we did put something in the bucket, we must delete the bucket contents before destroying the stack. We can use the {aws} Management Console or the {aws} CLI to delete the bucket contents. \ No newline at end of file +The destroy operation fails if there is anything stored in the stack's bucket\. There shouldn't be if you've only followed the instructions in this topic\. But if you did put something in the bucket, you must delete the bucket contents before destroying the stack\. \(Do not delete the bucket itself\.\) Use the AWS Management Console or the AWS CLI to delete the bucket contents\. \ No newline at end of file diff --git a/v2/stacks.md b/v2/stacks.md new file mode 100644 index 00000000..7b542e3c --- /dev/null +++ b/v2/stacks.md @@ -0,0 +1,385 @@ +# Stacks<a name="stacks"></a> + +The unit of deployment in the AWS CDK is called a *stack*\. All AWS resources defined within the scope of a stack, either directly or indirectly, are provisioned as a single unit\. + +Because AWS CDK stacks are implemented through AWS CloudFormation stacks, they have the same limitations as in [AWS CloudFormation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cloudformation-limits.html)\. + +You can define any number of stacks in your AWS CDK app\. Any instance of the `Stack` construct represents a stack\. This can be defined in one of the following ways: ++ Directly within the scope of the app, like the `MyFirstStack` example shown previously ++ Indirectly by any construct within the tree + +For example, the following code defines an AWS CDK app with two stacks\. + +------ +#### [ TypeScript ] + +``` +const app = new App(); + +new MyFirstStack(app, 'stack1'); +new MySecondStack(app, 'stack2'); + +app.synth(); +``` + +------ +#### [ JavaScript ] + +``` +const app = new App(); + +new MyFirstStack(app, 'stack1'); +new MySecondStack(app, 'stack2'); + +app.synth(); +``` + +------ +#### [ Python ] + +``` +app = App() + +MyFirstStack(app, 'stack1') +MySecondStack(app, 'stack2') + +app.synth() +``` + +------ +#### [ Java ] + +``` +App app = new App(); + +new MyFirstStack(app, "stack1"); +new MySecondStack(app, "stack2"); + +app.synth(); +``` + +------ +#### [ C\# ] + +``` +var app = new App(); + +new MyFirstStack(app, "stack1"); +new MySecondStack(app, "stack2"); + +app.Synth(); +``` + +------ + +To list all the stacks in an AWS CDK app, run the cdk ls command, which for the previous AWS CDK app would have the following output\. + +``` +stack1 +stack2 +``` + +When you run the cdk synth command for an app with multiple stacks, the cloud assembly includes a separate template for each stack instance\. Even if the two stacks are instances of the same class, the AWS CDK emits them as two individual templates\. + +You can synthesize each template by specifying the stack name in the cdk synth command\. The following example synthesizes the template for **stack1**\. + +``` +cdk synth stack1 +``` + +This approach is conceptually different from how AWS CloudFormation templates are normally used, where a template can be deployed multiple times and parameterized through [AWS CloudFormation parameters](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html)\. Although AWS CloudFormation parameters can be defined in the AWS CDK, they are generally discouraged because AWS CloudFormation parameters are resolved only during deployment\. This means that you cannot determine their value in your code\. + +For example, to conditionally include a resource in your app based on a parameter value, you must set up an [AWS CloudFormation condition](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/conditions-section-structure.html) and tag the resource with it\. The AWS CDK takes an approach where concrete templates are resolved at synthesis time\. Therefore, you can use an **if** statement to check the value to determine whether a resource should be defined or some behavior should be applied\. + +**Note** +The AWS CDK provides as much resolution as possible during synthesis time to enable idiomatic and natural usage of your programming language\. + +Like any other construct, stacks can be composed together into groups\. The following code shows an example of a service that consists of three stacks: a control plane, a data plane, and monitoring stacks\. The service construct is defined twice: once for the beta environment and once for the production environment\. + +------ +#### [ TypeScript ] + +``` +import { App, Stack } from 'aws-cdk-lib'; +import { Construct } from 'constructs'; + +interface EnvProps { + prod: boolean; +} + +// imagine these stacks declare a bunch of related resources +class ControlPlane extends Stack {} +class DataPlane extends Stack {} +class Monitoring extends Stack {} + +class MyService extends Construct { + + constructor(scope: Construct, id: string, props?: EnvProps) { + + super(scope, id); + + // we might use the prod argument to change how the service is configured + new ControlPlane(this, "cp"); + new DataPlane(this, "data"); + new Monitoring(this, "mon"); } +} + +const app = new App(); +new MyService(app, "beta"); +new MyService(app, "prod", { prod: true }); + +app.synth(); +``` + +------ +#### [ JavaScript ] + +``` +const { App, Stack } = require('aws-cdk-lib'); +const { Construct } = require('constructs'); + +// imagine these stacks declare a bunch of related resources +class ControlPlane extends Stack {} +class DataPlane extends Stack {} +class Monitoring extends Stack {} + +class MyService extends Construct { + + constructor(scope, id, props) { + + super(scope, id); + + // we might use the prod argument to change how the service is configured + new ControlPlane(this, "cp"); + new DataPlane(this, "data"); + new Monitoring(this, "mon"); + } +} + +const app = new App(); +new MyService(app, "beta"); +new MyService(app, "prod", { prod: true }); + +app.synth(); +``` + +------ +#### [ Python ] + +``` +from aws_cdk import App, Stack +from constructs import Construct + +# imagine these stacks declare a bunch of related resources +class ControlPlane(Stack): pass +class DataPlane(Stack): pass +class Monitoring(Stack): pass + +class MyService(Construct): + + def __init__(self, scope: Construct, id: str, *, prod=False): + + super().__init__(scope, id) + + # we might use the prod argument to change how the service is configured + ControlPlane(self, "cp") + DataPlane(self, "data") + Monitoring(self, "mon") + +app = App(); +MyService(app, "beta") +MyService(app, "prod", prod=True) + +app.synth() +``` + +------ +#### [ Java ] + +``` +package com.myorg; + +import software.amazon.awscdk.App; +import software.amazon.awscdk.Stack; +import software.constructs.Construct; + +public class MyApp { + + // imagine these stacks declare a bunch of related resources + static class ControlPlane extends Stack { + ControlPlane(Construct scope, String id) { + super(scope, id); + } + } + + static class DataPlane extends Stack { + DataPlane(Construct scope, String id) { + super(scope, id); + } + } + + static class Monitoring extends Stack { + Monitoring(Construct scope, String id) { + super(scope, id); + } + } + + static class MyService extends Construct { + MyService(Construct scope, String id) { + this(scope, id, false); + } + + MyService(Construct scope, String id, boolean prod) { + super(scope, id); + + // we might use the prod argument to change how the service is configured + new ControlPlane(this, "cp"); + new DataPlane(this, "data"); + new Monitoring(this, "mon"); + } + } + + public static void main(final String argv[]) { + App app = new App(); + + new MyService(app, "beta"); + new MyService(app, "prod", true); + + app.synth(); + } +} +``` + +------ +#### [ C\# ] + +``` +using Amazon.CDK; +using Constructs; + +// imagine these stacks declare a bunch of related resources +public class ControlPlane : Stack { + public ControlPlane(Construct scope, string id=null) : base(scope, id) { } +} + +public class DataPlane : Stack { + public DataPlane(Construct scope, string id=null) : base(scope, id) { } +} + +public class Monitoring : Stack +{ + public Monitoring(Construct scope, string id=null) : base(scope, id) { } +} + +public class MyService : Construct +{ + public MyService(Construct scope, string id, Boolean prod=false) : base(scope, id) + { + // we might use the prod argument to change how the service is configured + new ControlPlane(this, "cp"); + new DataPlane(this, "data"); + new Monitoring(this, "mon"); + } +} + +class Program +{ + static void Main(string[] args) + { + + var app = new App(); + new MyService(app, "beta"); + new MyService(app, "prod", prod: true); + app.Synth(); + } +} +``` + +------ + +This AWS CDK app eventually consists of six stacks, three for each environment: + +``` +$ cdk ls + +betacpDA8372D3 +betadataE23DB2BA +betamon632BD457 +prodcp187264CE +proddataF7378CE5 +prodmon631A1083 +``` + +The physical names of the AWS CloudFormation stacks are automatically determined by the AWS CDK based on the stack's construct path in the tree\. By default, a stack's name is derived from the construct ID of the `Stack` object\. However, you can specify an explicit name by using the `stackName` prop \(in Python, `stack_name`\), as follows\. + +------ +#### [ TypeScript ] + +``` +new MyStack(this, 'not:a:stack:name', { stackName: 'this-is-stack-name' }); +``` + +------ +#### [ JavaScript ] + +``` +new MyStack(this, 'not:a:stack:name', { stackName: 'this-is-stack-name' }); +``` + +------ +#### [ Python ] + +``` +MyStack(self, "not:a:stack:name", stack_name="this-is-stack-name") +``` + +------ +#### [ Java ] + +``` +new MyStack(this, "not:a:stack:name", StackProps.builder() + .StackName("this-is-stack-name").build()); +``` + +------ +#### [ C\# ] + +``` +new MyStack(this, "not:a:stack:name", new StackProps +{ + StackName = "this-is-stack-name" +}); +``` + +------ + +## Stack API<a name="stack_api"></a> + +The [Stack](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html) object provides a rich API, including the following: ++ `Stack.of(construct)` – A static method that returns the **Stack** in which a construct is defined\. This is useful if you need to interact with a stack from within a reusable construct\. The call fails if a stack cannot be found in scope\. ++ `stack.stackName` \(Python: `stack_name`\) – Returns the physical name of the stack\. As mentioned previously, all AWS CDK stacks have a physical name that the AWS CDK can resolve during synthesis\. ++ `stack.region` and `stack.account` – Return the AWS Region and account, respectively, into which this stack will be deployed\. These properties return one of the following: + + The account or Region explicitly specified when the stack was defined + + A string\-encoded token that resolves to the AWS CloudFormation pseudo parameters for account and Region to indicate that this stack is environment agnostic + + For information about how environments are determined for stacks, see [Environments](environments.md)\. ++ `stack.addDependency(stack)` \(Python: `stack.add_dependency(stack)` – Can be used to explicitly define dependency order between two stacks\. This order is respected by the cdk deploy command when deploying multiple stacks at once\. ++ `stack.tags` – Returns a [TagManager](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.TagManager.html) that you can use to add or remove stack\-level tags\. This tag manager tags all resources within the stack, and also tags the stack itself when it's created through AWS CloudFormation\. ++ `stack.partition`, `stack.urlSuffix` \(Python: `url_suffix`\), `stack.stackId` \(Python: `stack_id`\), and `stack.notificationArn` \(Python: `notification_arn`\) – Return tokens that resolve to the respective AWS CloudFormation pseudo parameters, such as `{ "Ref": "AWS::Partition" }`\. These tokens are associated with the specific stack object so that the AWS CDK framework can identify cross\-stack references\. ++ `stack.availabilityZones` \(Python: `availability_zones`\) – Returns the set of Availability Zones available in the environment in which this stack is deployed\. For environment\-agnostic stacks, this always returns an array with two Availability Zones\. For environment\-specific stacks, the AWS CDK queries the environment and returns the exact set of Availability Zones available in the Region that you specified\. ++ `stack.parseArn(arn)` and `stack.formatArn(comps)` \(Python: `parse_arn`, `format_arn`\) – Can be used to work with Amazon Resource Names \(ARNs\)\. ++ `stack.toJsonString(obj)` \(Python: `to_json_string`\) – Can be used to format an arbitrary object as a JSON string that can be embedded in an AWS CloudFormation template\. The object can include tokens, attributes, and references, which are only resolved during deployment\. ++ `stack.templateOptions` \(Python: `template_options`\) – Use to specify AWS CloudFormation template options, such as Transform, Description, and Metadata, for your stack\. + +## Nested stacks<a name="stack_nesting"></a> + +The [NestedStack](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.NestedStack.html) construct offers a way around the AWS CloudFormation 500\-resource limit for stacks\. A nested stack counts as only one resource in the stack that contains it\. However, it can contain up to 500 resources, including additional nested stacks\. + +The scope of a nested stack must be a `Stack` or `NestedStack` construct\. The nested stack doesn't need to be declared lexically inside its parent stack\. It is necessary only to pass the parent stack as the first parameter \(`scope`\) when instantiating the nested stack\. Aside from this restriction, defining constructs in a nested stack works exactly the same as in an ordinary stack\. + +At synthesis time, the nested stack is synthesized to its own AWS CloudFormation template, which is uploaded to the AWS CDK staging bucket at deployment\. Nested stacks are bound to their parent stack and are not treated as independent deployment artifacts\. They aren't listed by `cdk list`, and they can't be deployed by `cdk deploy`\. + +References between parent stacks and nested stacks are automatically translated to stack parameters and outputs in the generated AWS CloudFormation templates, as with any [cross\-stack reference](resources.md#resource_stack)\. + +**Warning** +Changes in security posture are not displayed before deployment for nested stacks\. This information is displayed only for top\-level stacks\. \ No newline at end of file diff --git a/v2/tagging.md b/v2/tagging.md new file mode 100644 index 00000000..ab2db769 --- /dev/null +++ b/v2/tagging.md @@ -0,0 +1,544 @@ +# Tagging<a name="tagging"></a> + +Tags are informational key\-value elements that you can add to constructs in your AWS CDK app\. A tag applied to a given construct also applies to all of its taggable children\. Tags are included in the AWS CloudFormation template synthesized from your app and are applied to the AWS resources it deploys\. You can use tags to identify and categorize resources for the following purposes: ++ Simplifying management ++ Cost allocation ++ Access control ++ Any other purposes that you devise + +**Tip** +For more information about how you can use tags with your AWS resources, see the whitepaper [Tagging Best Practices](https://d1.awsstatic.com/whitepapers/aws-tagging-best-practices.pdf) \(PDF\)\. + +The [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Tags.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Tags.html) class includes the static method `of()`, through which you can add tags to, or remove tags from, the specified construct\. ++ [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Tags.html#addkey-value-props](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Tags.html#addkey-value-props) applies a new tag to the given construct and all of its children\. ++ [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Tags.html#removekey-props](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Tags.html#removekey-props) removes a tag from the given construct and any of its children, including tags a child construct may have applied to itself\. + +**Note** +Tagging is implemented using [Aspects](aspects.md)\. Aspects are a way to apply an operation \(such as tagging\) to all constructs in a given scope\. + +The following example applies the tag **key** with the value **value** to a construct\. + +------ +#### [ TypeScript ] + +``` +Tags.of(myConstruct).add('key', 'value'); +``` + +------ +#### [ JavaScript ] + +``` +Tags.of(myConstruct).add('key', 'value'); +``` + +------ +#### [ Python ] + +``` +Tags.of(my_construct).add("key", "value") +``` + +------ +#### [ Java ] + +``` +Tags.of(myConstruct).add("key", "value"); +``` + +------ +#### [ C\# ] + +``` +Tags.Of(myConstruct).Add("key", "value"); +``` + +------ + +The following example deletes the tag **key** from a construct\. + +------ +#### [ TypeScript ] + +``` +Tags.of(myConstruct).remove('key'); +``` + +------ +#### [ JavaScript ] + +``` +Tags.of(myConstruct).remove('key'); +``` + +------ +#### [ Python ] + +``` +Tags.of(my_construct).remove("key") +``` + +------ +#### [ Java ] + +``` +Tags.of(myConstruct).remove("key"); +``` + +------ +#### [ C\# ] + +``` +Tags.Of(myConstruct).Remove("key"); +``` + +------ + +If you are using `Stage` constructs, apply the tag at the `Stage` level or below\. Tags are not applied across `Stage` boundaries\. + +## Tag priorities<a name="w55aac23c26c25"></a> + +The AWS CDK applies and removes tags recursively\. If there are conflicts, the tagging operation with the highest priority wins\. \(Priorities are set using the optional `priority` property\.\) If the priorities of two operations are the same, the tagging operation closest to the bottom of the construct tree wins\. By default, applying a tag has a priority of 100 \(except for tags added directly to an AWS CloudFormation resource, which has a priority of 50\)\. The default priority for removing a tag is 200\. + +The following applies a tag with a priority of 300 to a construct\. + +------ +#### [ TypeScript ] + +``` +Tags.of(myConstruct).add('key', 'value', { + priority: 300 +}); +``` + +------ +#### [ JavaScript ] + +``` +Tags.of(myConstruct).add('key', 'value', { + priority: 300 +}); +``` + +------ +#### [ Python ] + +``` +Tags.of(my_construct).add("key", "value", priority=300) +``` + +------ +#### [ Java ] + +``` +Tags.of(myConstruct).add("key", "value", TagProps.builder() + .priority(300).build()); +``` + +------ +#### [ C\# ] + +``` +Tags.Of(myConstruct).Add("key", "value", new TagProps { Priority = 300 }); +``` + +------ + +## Optional properties<a name="tagging_props"></a> + +Tags support [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.TagProps.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.TagProps.html) that fine\-tune how tags are applied to, or removed from, resources\. All properties are optional\. + +`applyToLaunchedInstances` \(Python: `apply_to_launched_instances`\) +Available for add\(\) only\. By default, tags are applied to instances launched in an Auto Scaling group\. Set this property to **false** to ignore instances launched in an Auto Scaling group\. + +`includeResourceTypes`/`excludeResourceTypes` \(Python: `include_resource_types`/`exclude_resource_types`\) +Use these to manipulate tags only on a subset of resources, based on AWS CloudFormation resource types\. By default, the operation is applied to all resources in the construct subtree, but this can be changed by including or excluding certain resource types\. Exclude takes precedence over include, if both are specified\. + +`priority` +Use this to set the priority of this operation with respect to other `Tags.add()` and `Tags.remove()` operations\. Higher values take precedence over lower values\. The default is 100 for add operations \(50 for tags applied directly to AWS CloudFormation resources\) and 200 for remove operations\. + +The following example applies the tag **tagname** with the value **value** and priority **100** to resources of type **AWS::Xxx::Yyy** in the construct\. It doesn't apply the tag to instances launched in an Amazon EC2 Auto Scaling group or to resources of type **AWS::Xxx::Zzz**\. \(These are placeholders for two arbitrary but different AWS CloudFormation resource types\.\) + +------ +#### [ TypeScript ] + +``` +Tags.of(myConstruct).add('tagname', 'value', { + applyToLaunchedInstances: false, + includeResourceTypes: ['AWS::Xxx::Yyy'], + excludeResourceTypes: ['AWS::Xxx::Zzz'], + priority: 100, +}); +``` + +------ +#### [ JavaScript ] + +``` +Tags.of(myConstruct).add('tagname', 'value', { + applyToLaunchedInstances: false, + includeResourceTypes: ['AWS::Xxx::Yyy'], + excludeResourceTypes: ['AWS::Xxx::Zzz'], + priority: 100 +}); +``` + +------ +#### [ Python ] + +``` +Tags.of(my_construct).add("tagname", "value", + apply_to_launched_instances=False, + include_resource_types=["AWS::Xxx::Yyy"], + exclude_resource_types=["AWS::Xxx::Zzz"], + priority=100) +``` + +------ +#### [ Java ] + +``` +Tags.of(myConstruct).add("key", "value", TagProps.builder() + .applyToLaunchedInstances(false) + .includeResourceTypes(Arrays.asList("AWS::Xxx::Yyy")) + .excludeResourceTypes(Arrays.asList("AWS::Xxx::Zzz")) + .priority(100).build()); +``` + +------ +#### [ C\# ] + +``` +Tags.Of(myConstruct).Add("tagname", "value", new TagProps +{ + ApplyToLaunchedInstances = false, + IncludeResourceTypes = ["AWS::Xxx::Yyy"], + ExcludeResourceTypes = ["AWS::Xxx::Zzz"], + Priority = 100 +}); +``` + +------ + +The following example removes the tag **tagname** with priority **200** from resources of type **AWS::Xxx::Yyy** in the construct, but not from resources of type **AWS::Xxx::Zzz**\. + +------ +#### [ TypeScript ] + +``` +Tags.of(myConstruct).remove('tagname', { + includeResourceTypes: ['AWS::Xxx::Yyy'], + excludeResourceTypes: ['AWS::Xxx::Zzz'], + priority: 200, +}); +``` + +------ +#### [ JavaScript ] + +``` +Tags.of(myConstruct).remove('tagname', { + includeResourceTypes: ['AWS::Xxx::Yyy'], + excludeResourceTypes: ['AWS::Xxx::Zzz'], + priority: 200 +}); +``` + +------ +#### [ Python ] + +``` +Tags.of(my_construct).remove("tagname", + include_resource_types=["AWS::Xxx::Yyy"], + exclude_resource_types=["AWS::Xxx::Zzz"], + priority=200,) +``` + +------ +#### [ Java ] + +``` +Tags.of((myConstruct).remove("tagname", TagProps.builder() + .includeResourceTypes(Arrays.asList("AWS::Xxx::Yyy")) + .excludeResourceTypes(Arrays.asList("AWS::Xxx::Zzz")) + .priority(100).build()); +``` + +------ +#### [ C\# ] + +``` +Tags.Of(myConstruct).Remove("tagname", new TagProps +{ + IncludeResourceTypes = ["AWS::Xxx::Yyy"], + ExcludeResourceTypes = ["AWS::Xxx::Zzz"], + Priority = 100 +}); +``` + +------ + +## Example<a name="tagging_example"></a> + +The following example adds the tag key **StackType** with value **TheBest** to any resource created within the `Stack` named `MarketingSystem`\. Then it removes it again from all resources except Amazon EC2 VPC subnets\. The result is that only the subnets have the tag applied\. + +------ +#### [ TypeScript ] + +``` +import { App, Stack, Tags } from 'aws-cdk-lib'; + +const app = new App(); +const theBestStack = new Stack(app, 'MarketingSystem'); + +// Add a tag to all constructs in the stack +Tags.of(theBestStack).add('StackType', 'TheBest'); + +// Remove the tag from all resources except subnet resources +Tags.of(theBestStack).remove('StackType', { + excludeResourceTypes: ['AWS::EC2::Subnet'] +}); +``` + +------ +#### [ JavaScript ] + +``` +const { App, Stack, Tags } = require('aws-cdk-lib'); + +const app = new App(); +const theBestStack = new Stack(app, 'MarketingSystem'); + +// Add a tag to all constructs in the stack +Tags.of(theBestStack).add('StackType', 'TheBest'); + +// Remove the tag from all resources except subnet resources +Tags.of(theBestStack).remove('StackType', { + excludeResourceTypes: ['AWS::EC2::Subnet'] +}); +``` + +------ +#### [ Python ] + +``` +from aws_cdk import App, Stack, Tags + +app = App(); +the_best_stack = Stack(app, 'MarketingSystem') + +# Add a tag to all constructs in the stack +Tags.of(the_best_stack).add("StackType", "TheBest") + +# Remove the tag from all resources except subnet resources +Tags.of(the_best_stack).remove("StackType", + exclude_resource_types=["AWS::EC2::Subnet"]) +``` + +------ +#### [ Java ] + +``` +import software.amazon.awscdk.App; +import software.amazon.awscdk.Tags; + +// Add a tag to all constructs in the stack +Tags.of(theBestStack).add("StackType", "TheBest"); + +// Remove the tag from all resources except subnet resources +Tags.of(theBestStack).remove("StackType", TagProps.builder() + .excludeResourceTypes(Arrays.asList("AWS::EC2::Subnet")) + .build()); +``` + +------ +#### [ C\# ] + +``` +using Amazon.CDK; + +var app = new App(); +var theBestStack = new Stack(app, 'MarketingSystem'); + +// Add a tag to all constructs in the stack +Tags.Of(theBestStack).Add("StackType", "TheBest"); + +// Remove the tag from all resources except subnet resources +Tags.Of(theBestStack).Remove("StackType", new TagProps +{ + ExcludeResourceTypes = ["AWS::EC2::Subnet"] +}); +``` + +------ + +The following code achieves the same result\. Consider which approach \(inclusion or exclusion\) makes your intent clearer\. + +------ +#### [ TypeScript ] + +``` +Tags.of(theBestStack).add('StackType', 'TheBest', + { includeResourceTypes: ['AWS::EC2::Subnet']}); +``` + +------ +#### [ JavaScript ] + +``` +Tags.of(theBestStack).add('StackType', 'TheBest', + { includeResourceTypes: ['AWS::EC2::Subnet']}); +``` + +------ +#### [ Python ] + +``` +Tags.of(the_best_stack).add("StackType", "TheBest", + include_resource_types=["AWS::EC2::Subnet"]) +``` + +------ +#### [ Java ] + +``` +Tags.of(theBestStack).add("StackType", "TheBest", TagProps.builder() + .includeResourceTypes(Arrays.asList("AWS::EC2::Subnet")) + .build()); +``` + +------ +#### [ C\# ] + +``` +Tags.Of(theBestStack).Add("StackType", "TheBest", new TagProps { + IncludeResourceTypes = ["AWS::EC2::Subnet"] +}); +``` + +------ + +## Tagging single constructs<a name="tagging_single"></a> + +`Tags.of(scope).add(key, value)` is the standard way to add tags to constructs in the AWS CDK\. Its tree\-walking behavior, which recursively tags all taggable resources under the given scope, is almost always what you want\. Sometimes, however, you need to tag a specific, arbitrary construct \(or constructs\)\. + +One such case involves applying tags whose value is derived from some property of the construct being tagged\. The standard tagging approach recursively applies the same key and value to all matching resources in the scope\. However, here the value could be different for each tagged construct\. + +Tags are implemented using [aspects](aspects.md), and the CDK calls the tag's `visit()` method for each construct under the scope you specified using `Tags.of(scope)`\. We can call `Tag.visit()` directly to apply a tag to a single construct\. + +------ +#### [ TypeScript ] + +``` +new cdk.Tag(key, value).visit(scope); +``` + +------ +#### [ JavaScript ] + +``` +new cdk.Tag(key, value).visit(scope); +``` + +------ +#### [ Python ] + +``` +cdk.Tag(key, value).visit(scope) +``` + +------ +#### [ Java ] + +``` +Tag.Builder.create(key, value).build().visit(scope); +``` + +------ +#### [ C\# ] + +``` +new Tag(key, value).Visit(scope); +``` + +------ + +You can tag all constructs under a scope but let the values of the tags derive from properties of each construct\. To do so, write an aspect and apply the tag in the aspect's `visit()` method as shown in the preceding example\. Then, add the aspect to the desired scope using `Aspects.of(scope).add(aspect)`\. + +The following example applies a tag to each resource in a stack containing the resource's path\. + +------ +#### [ TypeScript ] + +``` +class PathTagger implements cdk.IAspect { + visit(node: IConstruct) { + new cdk.Tag("aws-cdk-path", node.node.path).visit(node); + } +} + +stack = new MyStack(app); +cdk.Aspects.of(stack).add(new PathTagger()) +``` + +------ +#### [ JavaScript ] + +``` +class PathTagger { + visit(node) { + new cdk.Tag("aws-cdk-path", node.node.path).visit(node); + } +} + +stack = new MyStack(app); +cdk.Aspects.of(stack).add(new PathTagger()) +``` + +------ +#### [ Python ] + +``` +@jsii.implements(cdk.IAspect) +class PathTagger: + def visit(self, node: IConstruct): + cdk.Tag("aws-cdk-path", node.node.path).visit(node) + +stack = MyStack(app) +cdk.Aspects.of(stack).add(PathTagger()) +``` + +------ +#### [ Java ] + +``` +final class PathTagger implements IAspect { + public void visit(IConstruct node) { + Tag.Builder.create("aws-cdk-path", node.getNode().getPath()).build().visit(node); + } +} + +stack stack = new MyStack(app); +Aspects.of(stack).add(new PathTagger()); +``` + +------ +#### [ C\# ] + +``` +public class PathTagger : IAspect +{ + public void Visit(IConstruct node) + { + new Tag("aws-cdk-path", node.Node.Path).Visit(node); + } +} + +var stack = new MyStack(app); +Aspects.Of(stack).Add(new PathTagger); +``` + +------ + +**Tip** +The logic of conditional tagging, including priorities, resource types, and so on, is built into the `Tag` class\. You can use these features when applying tags to arbitrary resources; the tag is not applied if the conditions aren't met\. Also, the `Tag` class only tags taggable resources, so you don't need to test whether a construct is taggable before applying a tag\. \ No newline at end of file diff --git a/v2/guide/testing/testing.adoc b/v2/testing.md similarity index 66% rename from v2/guide/testing/testing.adoc rename to v2/testing.md index ed8c4502..06abe244 100644 --- a/v2/guide/testing/testing.adoc +++ b/v2/testing.md @@ -1,65 +1,43 @@ -include::../attributes.txt[] +# Testing constructs<a name="testing"></a> -// Attributes +With the AWS CDK, your infrastructure can be as testable as any other code you write\. The standard approach to testing AWS CDK apps uses the AWS CDK's [assertions](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.assertions-readme.html) module and popular test frameworks like [Jest](https://jestjs.io/) for TypeScript and JavaScript or [Pytest](https://docs.pytest.org/en/6.2.x/) for Python\. -:https---docs-aws-amazon-com-cdk-api-v2-docs-aws-cdk-lib-assertions-Match-html-methods: https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.assertions.Match.html#methods -[.topic] -[#testing] -= Test {aws} CDK applications +There are two categories of tests that you can write for AWS CDK apps\. ++ **Fine\-grained assertions** test specific aspects of the generated AWS CloudFormation template, such as "this resource has this property with this value\." These tests can detect regressions\. They're also useful when you're developing new features using test\-driven development\. \(You can write a test first, then make it pass by writing a correct implementation\.\) Fine\-grained assertions are the most frequently used tests\. ++ **Snapshot tests** test the synthesized AWS CloudFormation template against a previously stored baseline template\. Snapshot tests let you refactor freely, since you can be sure that the refactored code works exactly the same way as the original\. If the changes were intentional, you can accept a new baseline for future tests\. However, CDK upgrades can also cause synthesized templates to change, so you can't rely only on snapshots to make sure that your implementation is correct\. -// Content start +**Note** +Complete versions of the TypeScript, Python, and Java apps used as examples in this topic are [available on GitHub](https://github.com/cdklabs/aws-cdk-testing-examples/)\. -With the {aws} CDK, your infrastructure can be as testable as any other code you write. You can test in the cloud and locally. This topic addresses how to test in the cloud. For guidance on local testing see xref:testing-locally[Locally test and build {aws} CDK applications with the {aws} SAM CLI]. The standard approach to testing {aws} CDK apps uses the {aws} CDK's https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.assertions-readme.html[assertions] module and popular test frameworks like https://jestjs.io/[Jest] for TypeScript and JavaScript or https://docs.pytest.org/en/6.2.x/[Pytest] for Python. +## Getting started<a name="testing_getting_started"></a> -There are two categories of tests that you can write for {aws} CDK apps. +To illustrate how to write these tests, we'll create a stack that contains an AWS Step Functions state machine and an AWS Lambda function\. The Lambda function is subscribed to an Amazon SNS topic and simply forwards the message to the state machine\. -* *Fine-grained assertions* test specific aspects of the generated {aws} CloudFormation template, such as "this resource has this property with this value." These tests can detect regressions. They're also useful when you're developing new features using test-driven development. (You can write a test first, then make it pass by writing a correct implementation.) Fine-grained assertions are the most frequently used tests. -* *Snapshot tests* test the synthesized {aws} CloudFormation template against a previously stored baseline template. Snapshot tests let you refactor freely, since you can be sure that the refactored code works exactly the same way as the original. If the changes were intentional, you can accept a new baseline for future tests. However, CDK upgrades can also cause synthesized templates to change, so you can't rely only on snapshots to make sure that your implementation is correct. +First, create an empty CDK application project using the CDK Toolkit and installing the libraries we'll need\. The constructs we'll use are all in the main CDK package, which is a default dependency in projects created with the CDK Toolkit\. However, you must install your testing framework\. -[NOTE] -==== +------ +#### [ TypeScript ] -Complete versions of the TypeScript, Python, and Java apps used as examples in this topic are https://github.com/cdklabs/aws-cdk-testing-examples/[available on GitHub]. +``` +mkdir state-machine && cd state-machine +cdk init --language=typescript +npm install --save-dev jest @types/jest +``` -==== +Create a directory for your tests\. -[#testing-getting-started] -== Getting started +``` +mkdir test +``` -To illustrate how to write these tests, we'll create a stack that contains an {aws} Step Functions state machine and an {aws} Lambda function. The Lambda function is subscribed to an Amazon SNS topic and simply forwards the message to the state machine. +Edit the project's `package.json` to tell NPM how to run Jest, and to tell Jest what kinds of files to collect\. The necessary changes are as follows\. ++ Add a new `test` key to the `scripts` section ++ Add Jest and its types to the `devDependencies` section ++ Add a new `jest` top\-level key with a `moduleFileExtensions` declaration -First, create an empty CDK application project using the CDK Toolkit and installing the libraries we'll need. The constructs we'll use are all in the main CDK package, which is a default dependency in projects created with the CDK Toolkit. However, you must install your testing framework. +These changes are shown in the following outline\. Place the new text where indicated in `package.json`\. The "\.\.\." placeholders indicate existing parts of the file that should not be changed\. -==== -[role="tablist"] -TypeScript:: -+ -[source,none,subs="verbatim,attributes"] ----- -$ mkdir state-machine && cd state-machine -cdk init --language=typescript -npm install --save-dev jest @types/jest ----- -+ -Create a directory for your tests. -+ -[source,none,subs="verbatim,attributes"] ----- -$ mkdir test ----- -+ -Edit the project's `package.json` to tell NPM how to run Jest, and to tell Jest what kinds of files to collect. The necessary changes are as follows. -+ --- -* Add a new `test` key to the `scripts` section -* Add Jest and its types to the `devDependencies` section -* Add a new `jest` top-level key with a `moduleFileExtensions` declaration --- -+ -These changes are shown in the following outline. Place the new text where indicated in `package.json`. The "..." placeholders indicate existing parts of the file that should not be changed. -+ -[source,json,subs="verbatim,attributes"] ----- +``` { ... "scripts": { @@ -75,36 +53,31 @@ These changes are shown in the following outline. Place the new text where indic "moduleFileExtensions": ["js"] } } ----- - -JavaScript:: -+ -[source,none,subs="verbatim,attributes"] ----- -$ mkdir state-machine && cd state-machine -$ cdk init --language=javascript -$ npm install --save-dev jest ----- -+ -Create a directory for your tests. -+ -[source,none,subs="verbatim,attributes"] ----- -$ mkdir test ----- -+ -Edit the project's `package.json` to tell NPM how to run Jest, and to tell Jest what kinds of files to collect. The necessary changes are as follows. -+ --- -* Add a new `test` key to the `scripts` section -* Add Jest to the `devDependencies` section -* Add a new `jest` top-level key with a `moduleFileExtensions` declaration --- -+ -These changes are shown in the following outline. Place the new text where indicated in `package.json`. The "..." placeholders indicate existing parts of the file that shouldn't be changed. -+ -[source,json,subs="verbatim,attributes"] ----- +``` + +------ +#### [ JavaScript ] + +``` +mkdir state-machine && cd state-machine +cdk init --language=javascript +npm install --save-dev jest +``` + +Create a directory for your tests\. + +``` +mkdir test +``` + +Edit the project's `package.json` to tell NPM how to run Jest, and to tell Jest what kinds of files to collect\. The necessary changes are as follows\. ++ Add a new `test` key to the `scripts` section ++ Add Jest to the `devDependencies` section ++ Add a new `jest` top\-level key with a `moduleFileExtensions` declaration + +These changes are shown in the following outline\. Place the new text where indicated in `package.json`\. The "\.\.\." placeholders indicate existing parts of the file that shouldn't be changed\. + +``` { ... "scripts": { @@ -119,59 +92,57 @@ These changes are shown in the following outline. Place the new text where indic "moduleFileExtensions": ["js"] } } ----- - -Python:: -+ -[source,none,subs="verbatim,attributes"] ----- -$ mkdir state-machine && cd state-machine -$ cdk init --language=python -$ source .venv/bin/activate # On Windows, run '.\venv\Scripts\activate' instead -$ python -m pip install -r requirements.txt -$ python -m pip install -r requirements-dev.txt ----- - -Java:: -+ -[source,none,subs="verbatim,attributes"] ----- -$ mkdir state-machine && cd-state-machine -$ cdk init --language=java ----- -+ -Open the project in your preferred Java IDE. (In Eclipse, use *File* > *Import* > Existing Maven Projects.) - -C#:: -+ -[source,none,subs="verbatim,attributes"] ----- -$ mkdir state-machine && cd-state-machine -$ cdk init --language=csharp ----- -+ -Open `src\StateMachine.sln` in Visual Studio. -+ -Right-click the solution in Solution Explorer and choose *Add* > **New Project**. Search for MSTest C# and add an *MSTest Test Project* for C#. (The default name `TestProject1`is fine.) -+ -Right-click `TestProject1` and choose *Add* > **Project Reference**, and add the `StateMachine` project as a reference. -==== - -[#testing-app] -== The example stack - -Here's the stack that will be tested in this topic. As we've previously described, it contains a Lambda function and a Step Functions state machine, and accepts one or more Amazon SNS topics. The Lambda function is subscribed to the Amazon SNS topics and forwards them to the state machine. - -You don't have to do anything special to make the app testable. In fact, this CDK stack is not different in any important way from the other example stacks in this Guide. - -==== -[role="tablist"] -TypeScript:: -+ -Place the following code in `lib/state-machine-stack.ts`: -+ -[source,javascript,subs="verbatim,attributes"] ----- +``` + +------ +#### [ Python ] + +``` +mkdir state-machine && cd state-machine +cdk init --language=python +source .venv/bin/activate +python -m pip install -r requirements.txt +python -m pip install -r requirements-dev.txt +``` + +------ +#### [ Java ] + +``` +mkdir state-machine && cd-state-machine +cdk init --language=java +``` + +Open the project in your preferred Java IDE\. \(In Eclipse, use **File** > **Import** > Existing Maven Projects\.\) + +------ +#### [ C\# ] + +``` +mkdir state-machine && cd-state-machine +cdk init --language=csharp +``` + +Open `src\StateMachine.sln` in Visual Studio\. + +Right\-click the solution in Solution Explorer and choose **Add** > **New Project**\. Search for MSTest C\# and add an **MSTest Test Project** for C\#\. \(The default name `TestProject1`is fine\.\) + +Right\-click `TestProject1` and choose **Add** > **Project Reference**, and add the `StateMachine` project as a reference\. + +------ + +## The example stack<a name="testing_app"></a> + +Here's the stack that will be tested in this topic\. As we've previously described, it contains a Lambda function and a Step Functions state machine, and accepts one or more Amazon SNS topics\. The Lambda function is subscribed to the Amazon SNS topics and forwards them to the state machine\. + +You don't have to do anything special to make the app testable\. In fact, this CDK stack is not different in any important way from the other example stacks in this Guide\. + +------ +#### [ TypeScript ] + +Place the following code in `lib/state-machine-stack.ts`: + +``` import * as cdk from "aws-cdk-lib"; import * as sns from "aws-cdk-lib/aws-sns"; import * as sns_subscriptions from "aws-cdk-lib/aws-sns-subscriptions"; @@ -194,7 +165,7 @@ export class StateMachineStack extends cdk.Stack { // This Lambda function starts the state machine. const func = new lambda.Function(this, "LambdaFunction", { - runtime: lambda.Runtime.NODEJS_18_X, + runtime: lambda.Runtime.NODEJS_14_X, handler: "handler", code: lambda.Code.fromAsset("./start-state-machine"), environment: { @@ -209,14 +180,14 @@ export class StateMachineStack extends cdk.Stack { } } } ----- - -JavaScript:: -+ -Place the following code in `lib/state-machine-stack.js`: -+ -[source,javascript,subs="verbatim,attributes"] ----- +``` + +------ +#### [ JavaScript ] + +Place the following code in `lib/state-machine-stack.js`: + +``` const cdk = require("aws-cdk-lib"); const sns = require("aws-cdk-lib/aws-sns"); const sns_subscriptions = require("aws-cdk-lib/aws-sns-subscriptions"); @@ -234,7 +205,7 @@ class StateMachineStack extends cdk.Stack { // This Lambda function starts the state machine. const func = new lambda.Function(this, "LambdaFunction", { - runtime: lambda.Runtime.NODEJS_18_X, + runtime: lambda.Runtime.NODEJS_14_X, handler: "handler", code: lambda.Code.fromAsset("./start-state-machine"), environment: { @@ -251,14 +222,14 @@ class StateMachineStack extends cdk.Stack { } module.exports = { StateMachineStack } ----- +``` + +------ +#### [ Python ] -Python:: -+ Place the following code in `state_machine/state_machine_stack.py`: -+ -[source,python,subs="verbatim,attributes"] ----- + +``` from typing import List import aws_cdk.aws_lambda as lambda_ @@ -287,7 +258,7 @@ class StateMachineStack(cdk.Stack): func = lambda_.Function( self, "LambdaFunction", - runtime=lambda_.Runtime.NODEJS_18_X, + runtime=lambda_.Runtime.NODEJS_14_X, handler="handler", code=lambda_.Code.from_asset("./start-state-machine"), environment={ @@ -299,12 +270,12 @@ class StateMachineStack(cdk.Stack): subscription = sns_subscriptions.LambdaSubscription(func) for topic in topics: topic.add_subscription(subscription) ----- +``` + +------ +#### [ Java ] -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- +``` package software.amazon.samples.awscdkassertionssamples; import software.constructs.Construct; @@ -337,7 +308,7 @@ public class StateMachineStack extends Stack { // This Lambda function starts the state machine. final Function func = Function.Builder.create(this, "LambdaFunction") - .runtime(Runtime.NODEJS_18_X) + .runtime(Runtime.NODEJS_14_X) .handler("handler") .code(Code.fromAsset("./start-state-machine")) .environment(Collections.singletonMap("STATE_MACHINE_ARN", stateMachine.getStateMachineArn())) @@ -350,17 +321,17 @@ public class StateMachineStack extends Stack { } } } ----- +``` -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- +------ +#### [ C\# ] + +``` using Amazon.CDK; -using Amazon.CDK.{aws}.Lambda; -using Amazon.CDK.{aws}.StepFunctions; -using Amazon.CDK.{aws}.SNS; -using Amazon.CDK.{aws}.SNS.Subscriptions; +using Amazon.CDK.AWS.Lambda; +using Amazon.CDK.AWS.StepFunctions; +using Amazon.CDK.AWS.SNS; +using Amazon.CDK.AWS.SNS.Subscriptions; using Constructs; using System.Collections.Generic; @@ -386,7 +357,7 @@ namespace AwsCdkAssertionSamples // This Lambda function starts the state machine. var func = new Function(this, "LambdaFunction", new FunctionProps { - Runtime = Runtime.NODEJS_18_X, + Runtime = Runtime.NODEJS_14_X, Handler = "handler", Code = Code.FromAsset("./start-state-machine"), Environment = new Dictionary<string, string> @@ -404,19 +375,18 @@ namespace AwsCdkAssertionSamples } } } ----- -==== +``` + +------ -We'll modify the app's main entry point so that we don't actually instantiate our stack. We don't want to accidentally deploy it. Our tests will create an app and an instance of the stack for testing. This is a useful tactic when combined with test-driven development: make sure that the stack passes all tests before you enable deployment. +We'll modify the app's main entry point so that we don't actually instantiate our stack\. We don't want to accidentally deploy it\. Our tests will create an app and an instance of the stack for testing\. This is a useful tactic when combined with test\-driven development: make sure that the stack passes all tests before you enable deployment\. + +------ +#### [ TypeScript ] -==== -[role="tablist"] -TypeScript:: -+ In `bin/state-machine.ts`: -+ -[source,javascript,subs="verbatim,attributes"] ----- + +``` #!/usr/bin/env node import * as cdk from "aws-cdk-lib"; @@ -424,14 +394,14 @@ const app = new cdk.App(); // Stacks are intentionally not created here -- this application isn't meant to // be deployed. ----- +``` + +------ +#### [ JavaScript ] -JavaScript:: -+ In `bin/state-machine.js`: -+ -[source,javascript,subs="verbatim,attributes"] ----- + +``` #!/usr/bin/env node const cdk = require("aws-cdk-lib"); @@ -439,14 +409,14 @@ const app = new cdk.App(); // Stacks are intentionally not created here -- this application isn't meant to // be deployed. ----- +``` + +------ +#### [ Python ] -Python:: -+ In `app.py`: -+ -[source,python,subs="verbatim,attributes"] ----- + +``` #!/usr/bin/env python3 import os @@ -458,12 +428,12 @@ app = cdk.App() # be deployed. app.synth() ----- +``` -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- +------ +#### [ Java ] + +``` package software.amazon.samples.awscdkassertionssamples; import software.amazon.awscdk.App; @@ -477,12 +447,12 @@ public class SampleApp { app.synth(); } } ----- +``` + +------ +#### [ C\# ] -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- +``` using Amazon.CDK; namespace AwsCdkAssertionSamples @@ -499,88 +469,81 @@ namespace AwsCdkAssertionSamples } } } ----- -==== - -[#testing-lambda] -== The Lambda function - -Our example stack includes a Lambda function that starts our state machine. We must provide the source code for this function so the CDK can bundle and deploy it as part of creating the Lambda function resource. - -* Create the folder `start-state-machine` in the app's main directory. -* In this folder, create at least one file. For example, you can save the following code in `start-state-machines/index.js`. -+ -[source,javascript,subs="verbatim,attributes"] ----- -exports.handler = async function (event, context) { - return 'hello world'; -}; ----- -+ -However, any file will work, since we won't actually be deploying the stack. - -[#testing-running-tests] -== Running tests - -For reference, here are the commands you use to run tests in your {aws} CDK app. These are the same commands that you'd use to run the tests in any project using the same testing framework. For languages that require a build step, include that to make sure that your tests have compiled. - -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -$ tsc && npm test ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- -$ npm test ----- - -Python:: -+ -[source,none,subs="verbatim,attributes"] ----- -$ python -m pytest ----- - -Java:: -+ -[source,none,subs="verbatim,attributes"] ----- -$ mvn compile && mvn test ----- - -C#:: -+ -Build your solution (F6) to discover the tests, then run the tests (**Test** > **Run All Tests**). To choose which tests to run, open Test Explorer (**Test** > **Test Explorer**). -+ +``` + +------ + +## The Lambda function<a name="testing_lambda"></a> + +Our example stack includes a Lambda function that starts our state machine\. We must provide the source code for this function so the CDK can bundle and deploy it as part of creating the Lambda function resource\. ++ Create the folder `start-state-machine` in the app's main directory\. ++ In this folder, create at least one file\. For example, you can save the following code in `start-state-machines/index.js`\. + + ``` + exports.handler = async function (event, context) { + return 'hello world'; + }; + ``` + + However, any file will work, since we won't actually be deploying the stack\. + +## Running tests<a name="testing_running_tests"></a> + +For reference, here are the commands you use to run tests in your AWS CDK app\. These are the same commands that you'd use to run the tests in any project using the same testing framework\. For languages that require a build step, include that to make sure that your tests have compiled\. + +------ +#### [ TypeScript ] + +``` +tsc && npm test +``` + +------ +#### [ JavaScript ] + +``` +npm test +``` + +------ +#### [ Python ] + +``` +python -m pytest +``` + +------ +#### [ Java ] + +``` +mvn compile && mvn test +``` + +------ +#### [ C\# ] + +Build your solution \(F6\) to discover the tests, then run the tests \(**Test** > **Run All Tests**\)\. To choose which tests to run, open Test Explorer \(**Test** > **Test Explorer**\)\. + Or: -+ -[source,none,subs="verbatim,attributes"] ----- -$ dotnet test src ----- -==== -[#testing-fine-grained] -== Fine-grained assertions +``` +dotnet test src +``` + +------ -The first step for testing a stack with fine-grained assertions is to synthesize the stack, because we're writing assertions against the generated {aws} CloudFormation template. +## Fine\-grained assertions<a name="testing_fine_grained"></a> -Our `StateMachineStackStack` requires that we pass it the Amazon SNS topic to be forwarded to the state machine. So in our test, we'll create a separate stack to contain the topic. +The first step for testing a stack with fine\-grained assertions is to synthesize the stack, because we're writing assertions against the generated AWS CloudFormation template\. -Ordinarily, when writing a CDK app, you can subclass `Stack` and instantiate the Amazon SNS topic in the stack's constructor. In our test, we instantiate `Stack` directly, then pass this stack as the ``Topic``'s scope, attaching it to the stack. This is functionally equivalent and less verbose. It also helps make stacks that are used only in tests "look different" from the stacks that you intend to deploy. +Our `StateMachineStackStack` requires that we pass it the Amazon SNS topic to be forwarded to the state machine\. So in our test, we'll create a separate stack to contain the topic\. -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +Ordinarily, when writing a CDK app, you can subclass `Stack` and instantiate the Amazon SNS topic in the stack's constructor\. In our test, we instantiate `Stack` directly, then pass this stack as the `Topic`'s scope, attaching it to the stack\. This is functionally equivalent and less verbose\. It also helps make stacks that are used only in tests "look different" from the stacks that you intend to deploy\. + +------ +#### [ TypeScript ] + +``` import { Capture, Match, Template } from "aws-cdk-lib/assertions"; import * as cdk from "aws-cdk-lib"; import * as sns from "aws-cdk-lib/aws-sns"; @@ -606,14 +569,15 @@ describe("StateMachineStack", () => { // Prepare the stack for assertions. const template = Template.fromStack(stateMachineStack); - }) -}) ----- - -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- + + +} +``` + +------ +#### [ JavaScript ] + +``` const { Capture, Match, Template } = require("aws-cdk-lib/assertions"); const cdk = require("aws-cdk-lib"); const sns = require("aws-cdk-lib/aws-sns"); @@ -639,14 +603,12 @@ describe("StateMachineStack", () => { // Prepare the stack for assertions. const template = Template.fromStack(stateMachineStack); - }) -}) ----- - -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- +``` + +------ +#### [ Python ] + +``` from aws_cdk import aws_sns as sns import aws_cdk as cdk from aws_cdk.assertions import Template @@ -672,12 +634,12 @@ def test_synthesizes_properly(): # Prepare the stack for assertions. template = Template.from_stack(state_machine_stack) ----- +``` + +------ +#### [ Java ] -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- +``` package software.amazon.samples.awscdkassertionssamples; import org.junit.jupiter.api.Test; @@ -714,18 +676,16 @@ public class StateMachineStackTest { // Prepare the stack for assertions. final Template template = Template.fromStack(stateMachineStack) - } -} ----- +``` -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- +------ +#### [ C\# ] + +``` using Microsoft.VisualStudio.TestTools.UnitTesting; using Amazon.CDK; -using Amazon.CDK.{aws}.SNS; +using Amazon.CDK.AWS.SNS; using Amazon.CDK.Assertions; using AwsCdkAssertionSamples; @@ -763,48 +723,47 @@ namespace TestProject1 } } } ----- -==== +``` + +------ -Now we can assert that the Lambda function and the Amazon SNS subscription were created. +Now we can assert that the Lambda function and the Amazon SNS subscription were created\. -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +------ +#### [ TypeScript ] + +``` // Assert it creates the function with the correct properties... - template.hasResourceProperties("{aws}::Lambda::Function", { + template.hasResourceProperties("AWS::Lambda::Function", { Handler: "handler", Runtime: "nodejs14.x", }); // Creates the subscription... - template.resourceCountIs("{aws}::SNS::Subscription", 1); ----- + template.resourceCountIs("AWS::SNS::Subscription", 1); +``` + +------ +#### [ JavaScript ] -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +``` // Assert it creates the function with the correct properties... - template.hasResourceProperties("{aws}::Lambda::Function", { + template.hasResourceProperties("AWS::Lambda::Function", { Handler: "handler", Runtime: "nodejs14.x", }); // Creates the subscription... - template.resourceCountIs("{aws}::SNS::Subscription", 1); ----- + template.resourceCountIs("AWS::SNS::Subscription", 1); +``` -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- +------ +#### [ Python ] + +``` # Assert that we have created the function with the correct properties template.has_resource_properties( - "{aws}::Lambda::Function", + "AWS::Lambda::Function", { "Handler": "handler", "Runtime": "nodejs14.x", @@ -812,61 +771,59 @@ Python:: ) # Assert that we have created a subscription - template.resource_count_is("{aws}::SNS::Subscription", 1) ----- + template.resource_count_is("AWS::SNS::Subscription", 1) +``` + +------ +#### [ Java ] -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- +``` // Assert it creates the function with the correct properties... - template.hasResourceProperties("{aws}::Lambda::Function", Map.of( + template.hasResourceProperties("AWS::Lambda::Function", Map.of( "Handler", "handler", "Runtime", "nodejs14.x" )); // Creates the subscription... - template.resourceCountIs("{aws}::SNS::Subscription", 1); ----- + template.resourceCountIs("AWS::SNS::Subscription", 1); +``` -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- +------ +#### [ C\# ] + +``` // Prepare the stack for assertions. var template = Template.FromStack(stateMachineStack); // Assert it creates the function with the correct properties... - template.HasResourceProperties("{aws}::Lambda::Function", new StringDict { + template.HasResourceProperties("AWS::Lambda::Function", new StringDict { { "Handler", "handler"}, { "Runtime", "nodejs14x" } }); // Creates the subscription... - template.ResourceCountIs("{aws}::SNS::Subscription", 1); ----- -==== - -Our Lambda function test asserts that two particular properties of the function resource have specific values. By default, the `hasResourceProperties` method performs a partial match on the resource's properties as given in the synthesized CloudFormation template. This test requires that the provided properties exist and have the specified values, but the resource can also have other properties, which are not tested. - -Our Amazon SNS assertion asserts that the synthesized template contains a subscription, but nothing about the subscription itself. We included this assertion mainly to illustrate how to assert on resource counts. The `Template` class offers more specific methods to write assertions against the `Resources`, `Outputs`, and `Mapping` sections of the CloudFormation template. - -[#testing-fine-grained-matchers] -*Matchers*:: -+ -The default partial matching behavior of `hasResourceProperties` can be changed using _matchers_ from the `link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.assertions.Match.html#methods[Match]` class. -+ -Matchers range from lenient (`Match.anyValue`) to strict (`Match.objectEquals`). They can be nested to apply different matching methods to different parts of the resource properties. Using `Match.objectEquals` and `Match.anyValue` together, for example, we can test the state machine's IAM role more fully, while not requiring specific values for properties that may change. -+ -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- + template.ResourceCountIs("AWS::SNS::Subscription", 1); +``` + +------ + +Our Lambda function test asserts that two particular properties of the function resource have specific values\. By default, the `hasResourceProperties` method performs a partial match on the resource's properties as given in the synthesized CloudFormation template\. This test requires that the provided properties exist and have the specified values, but the resource can also have other properties, which are not tested\. + +Our Amazon SNS assertion asserts that the synthesized template contains a subscription, but nothing about the subscription itself\. We included this assertion mainly to illustrate how to assert on resource counts\. The `Template` class offers more specific methods to write assertions against the `Resources`, `Outputs`, and `Mapping` sections of the CloudFormation template\. + +### Matchers<a name="testing_fine_grained_matchers"></a> + +The default partial matching behavior of `hasResourceProperties` can be changed using *matchers* from the [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.assertions.Match.html#methods](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.assertions.Match.html#methods) class\. + +Matchers range from lenient \(`Match.anyValue`\) to strict \(`Match.objectEquals`\)\. They can be nested to apply different matching methods to different parts of the resource properties\. Using `Match.objectEquals` and `Match.anyValue` together, for example, we can test the state machine's IAM role more fully, while not requiring specific values for properties that may change\. + +------ +#### [ TypeScript ] + +``` // Fully assert on the state machine's IAM role with matchers. template.hasResourceProperties( - "{aws}::IAM::Role", + "AWS::IAM::Role", Match.objectEquals({ AssumeRolePolicyDocument: { Version: "2012-10-17", @@ -887,15 +844,15 @@ TypeScript:: }, }) ); ----- +``` + +------ +#### [ JavaScript ] -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +``` // Fully assert on the state machine's IAM role with matchers. template.hasResourceProperties( - "{aws}::IAM::Role", + "AWS::IAM::Role", Match.objectEquals({ AssumeRolePolicyDocument: { Version: "2012-10-17", @@ -916,17 +873,17 @@ JavaScript:: }, }) ); ----- +``` -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- +------ +#### [ Python ] + +``` from aws_cdk.assertions import Match # Fully assert on the state machine's IAM role with matchers. template.has_resource_properties( - "{aws}::IAM::Role", + "AWS::IAM::Role", Match.object_equals( { "AssumeRolePolicyDocument": { @@ -953,14 +910,14 @@ from aws_cdk.assertions import Match } ), ) ----- +``` + +------ +#### [ Java ] -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- +``` // Fully assert on the state machine's IAM role with matchers. - template.hasResourceProperties("{aws}::IAM::Role", Match.objectEquals( + template.hasResourceProperties("AWS::IAM::Role", Match.objectEquals( Collections.singletonMap("AssumeRolePolicyDocument", Map.of( "Version", "2012-10-17", "Statement", Collections.singletonList(Map.of( @@ -977,14 +934,14 @@ Java:: )) )) )); ----- +``` -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- +------ +#### [ C\# ] + +``` // Fully assert on the state machine's IAM role with matchers. - template.HasResource("{aws}::IAM::Role", Match.ObjectEquals(new ObjectDict + template.HasResource("AWS::IAM::Role", Match.ObjectEquals(new ObjectDict { { "AssumeRolePolicyDocument", new ObjectDict { @@ -1017,22 +974,21 @@ C#:: } } })); ----- -==== -+ -Many CloudFormation resources include serialized JSON objects represented as strings. The `Match.serializedJson()` matcher can be used to match properties inside this JSON. -+ -For example, Step Functions state machines are defined using a string in the JSON-based https://docs.aws.amazon.com/step-functions/latest/dg/concepts-amazon-states-language.html[Amazon States Language]. We'll use `Match.serializedJson()` to make sure that our initial state is the only step. Again, we'll use nested matchers to apply different kinds of matching to different parts of the object. -+ -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +``` + +------ + +Many CloudFormation resources include serialized JSON objects represented as strings\. The `Match.serializedJson()` matcher can be used to match properties inside this JSON\. + +For example, Step Functions state machines are defined using a string in the JSON\-based [Amazon States Language](https://docs.aws.amazon.com/step-functions/latest/dg/concepts-amazon-states-language.html)\. We'll use `Match.serializedJson()` to make sure that our initial state is the only step\. Again, we'll use nested matchers to apply different kinds of matching to different parts of the object\. + +------ +#### [ TypeScript ] + +``` // Assert on the state machine's definition with the Match.serializedJson() // matcher. - template.hasResourceProperties("{aws}::StepFunctions::StateMachine", { + template.hasResourceProperties("AWS::StepFunctions::StateMachine", { DefinitionString: Match.serializedJson( // Match.objectEquals() is used implicitly, but we use it explicitly // here for extra clarity. @@ -1050,15 +1006,15 @@ TypeScript:: }) ), }); ----- +``` -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +------ +#### [ JavaScript ] + +``` // Assert on the state machine's definition with the Match.serializedJson() // matcher. - template.hasResourceProperties("{aws}::StepFunctions::StateMachine", { + template.hasResourceProperties("AWS::StepFunctions::StateMachine", { DefinitionString: Match.serializedJson( // Match.objectEquals() is used implicitly, but we use it explicitly // here for extra clarity. @@ -1076,15 +1032,15 @@ JavaScript:: }) ), }); ----- +``` + +------ +#### [ Python ] -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- +``` # Assert on the state machine's definition with the serialized_json matcher. template.has_resource_properties( - "{aws}::StepFunctions::StateMachine", + "AWS::StepFunctions::StateMachine", { "DefinitionString": Match.serialized_json( # Match.object_equals() is the default, but specify it here for clarity @@ -1105,14 +1061,14 @@ Python:: ), }, ) ----- +``` -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- +------ +#### [ Java ] + +``` // Assert on the state machine's definition with the Match.serializedJson() matcher. - template.hasResourceProperties("{aws}::StepFunctions::StateMachine", Collections.singletonMap( + template.hasResourceProperties("AWS::StepFunctions::StateMachine", Collections.singletonMap( "DefinitionString", Match.serializedJson( // Match.objectEquals() is used implicitly, but we use it explicitly here for extra clarity. Match.objectEquals(Map.of( @@ -1129,14 +1085,14 @@ Java:: )) ) )); ----- +``` + +------ +#### [ C\# ] -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- +``` // Assert on the state machine's definition with the Match.serializedJson() matcher - template.HasResourceProperties("{aws}::StepFunctions::StateMachine", new ObjectDict + template.HasResourceProperties("AWS::StepFunctions::StateMachine", new ObjectDict { { "DefinitionString", Match.SerializedJson( // Match.objectEquals() is used implicitly, but we use it explicitly here for extra clarity. @@ -1154,28 +1110,26 @@ C#:: }} }) )}}); ----- -==== - -[#testing-fine-grained-capture] -*Capturing*:: -+ -It's often useful to test properties to make sure they follow specific formats, or have the same value as another property, without needing to know their exact values ahead of time. The `assertions` module provides this capability in its `link:https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.assertions.Capture.html[Capture]` class. -+ -By specifying a `Capture` instance in place of a value in `hasResourceProperties`, that value is retained in the `Capture` object. The actual captured value can be retrieved using the object's `as` methods, including `asNumber()`, `asString()`, and ``asObject``, and subjected to test. Use `Capture` with a matcher to specify the exact location of the value to be captured within the resource's properties, including serialized JSON properties. -+ -The following example tests to make sure that the starting state of our state machine has a name beginning with `Start`. It also tests that this state is present within the list of states in the machine. -+ -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +``` + +------ + +### Capturing<a name="testing_fine_grained_capture"></a> + +It's often useful to test properties to make sure they follow specific formats, or have the same value as another property, without needing to know their exact values ahead of time\. The `assertions` module provides this capability in its [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.assertions.Capture.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.assertions.Capture.html) class\. + +By specifying a `Capture` instance in place of a value in `hasResourceProperties`, that value is retained in the `Capture` object\. The actual captured value can be retrieved using the object's `as` methods, including `asNumber()`, `asString()`, and `asObject`, and subjected to test\. Use `Capture` with a matcher to specify the exact location of the value to be captured within the resource's properties, including serialized JSON properties\. + +The following example tests to make sure that the starting state of our state machine has a name beginning with `Start`\. It also tests that this state is present within the list of states in the machine\. + +------ +#### [ TypeScript ] + +``` // Capture some data from the state machine's definition. const startAtCapture = new Capture(); const statesCapture = new Capture(); - template.hasResourceProperties("{aws}::StepFunctions::StateMachine", { + template.hasResourceProperties("AWS::StepFunctions::StateMachine", { DefinitionString: Match.serializedJson( Match.objectLike({ StartAt: startAtCapture, @@ -1190,16 +1144,16 @@ TypeScript:: // Assert that the start state actually exists in the states object of the // state machine definition. expect(statesCapture.asObject()).toHaveProperty(startAtCapture.asString()); ----- +``` + +------ +#### [ JavaScript ] -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +``` // Capture some data from the state machine's definition. const startAtCapture = new Capture(); const statesCapture = new Capture(); - template.hasResourceProperties("{aws}::StepFunctions::StateMachine", { + template.hasResourceProperties("AWS::StepFunctions::StateMachine", { DefinitionString: Match.serializedJson( Match.objectLike({ StartAt: startAtCapture, @@ -1214,12 +1168,12 @@ JavaScript:: // Assert that the start state actually exists in the states object of the // state machine definition. expect(statesCapture.asObject()).toHaveProperty(startAtCapture.asString()); ----- +``` -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- +------ +#### [ Python ] + +``` import re from aws_cdk.assertions import Capture @@ -1230,7 +1184,7 @@ import re start_at_capture = Capture() states_capture = Capture() template.has_resource_properties( - "{aws}::StepFunctions::StateMachine", + "AWS::StepFunctions::StateMachine", { "DefinitionString": Match.serialized_json( Match.object_like( @@ -1249,16 +1203,16 @@ import re # Assert that the start state actually exists in the states object of the # state machine definition. assert start_at_capture.as_string() in states_capture.as_object() ----- +``` + +------ +#### [ Java ] -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- +``` // Capture some data from the state machine's definition. final Capture startAtCapture = new Capture(); final Capture statesCapture = new Capture(); - template.hasResourceProperties("{aws}::StepFunctions::StateMachine", Collections.singletonMap( + template.hasResourceProperties("AWS::StepFunctions::StateMachine", Collections.singletonMap( "DefinitionString", Match.serializedJson( Match.objectLike(Map.of( "StartAt", startAtCapture, @@ -1272,16 +1226,16 @@ Java:: // Assert that the start state actually exists in the states object of the state machine definition. assertThat(statesCapture.asObject()).containsKey(startAtCapture.asString()); ----- +``` -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- +------ +#### [ C\# ] + +``` // Capture some data from the state machine's definition. var startAtCapture = new Capture(); var statesCapture = new Capture(); - template.HasResourceProperties("{aws}::StepFunctions::StateMachine", new ObjectDict + template.HasResourceProperties("AWS::StepFunctions::StateMachine", new ObjectDict { { "DefinitionString", Match.SerializedJson( new ObjectDict @@ -1294,26 +1248,24 @@ C#:: Assert.IsTrue(startAtCapture.ToString().StartsWith("Start")); Assert.IsTrue(statesCapture.AsObject().ContainsKey(startAtCapture.ToString())); ----- -==== +``` + +------ -[#testing-snapshot] -== Snapshot tests +## Snapshot tests<a name="testing_snapshot"></a> -In _snapshot testing_, you compare the entire synthesized CloudFormation template against a previously stored baseline (often called a "master") template. Unlike fine-grained assertions, snapshot testing isn't useful in catching regressions. This is because snapshot testing applies to the entire template, and things besides code changes can cause small (or not-so-small) differences in synthesis results. These changes may not even affect your deployment, but they will still cause a snapshot test to fail. +In *snapshot testing*, you compare the entire synthesized CloudFormation template against a previously stored baseline \(often called a "master"\) template\. Unlike fine\-grained assertions, snapshot testing isn't useful in catching regressions\. This is because snapshot testing applies to the entire template, and things besides code changes can cause small \(or not\-so\-small\) differences in synthesis results\. These changes may not even affect your deployment, but they will still cause a snapshot test to fail\. -For example, you might update a CDK construct to incorporate a new best practice, which can cause changes to the synthesized resources or how they're organized. Alternatively, you might update the CDK Toolkit to a version that reports additional metadata. Changes to context values can also affect the synthesized template. +For example, you might update a CDK construct to incorporate a new best practice, which can cause changes to the synthesized resources or how they're organized\. Alternatively, you might update the CDK Toolkit to a version that reports additional metadata\. Changes to context values can also affect the synthesized template\. -Snapshot tests can be of great help in refactoring, though, as long as you hold constant all other factors that might affect the synthesized template. You will know immediately if a change you made has unintentionally changed the template. If the change is intentional, simply accept the new template as the baseline. +Snapshot tests can be of great help in refactoring, though, as long as you hold constant all other factors that might affect the synthesized template\. You will know immediately if a change you made has unintentionally changed the template\. If the change is intentional, simply accept the new template as the baseline\. For example, if we have this `DeadLetterQueue` construct: -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +------ +#### [ TypeScript ] + +``` export class DeadLetterQueue extends sqs.Queue { public readonly messagesInQueueAlarm: cloudwatch.IAlarm; @@ -1329,12 +1281,12 @@ export class DeadLetterQueue extends sqs.Queue { }); } } ----- +``` + +------ +#### [ JavaScript ] -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +``` class DeadLetterQueue extends sqs.Queue { constructor(scope, id) { @@ -1351,12 +1303,12 @@ class DeadLetterQueue extends sqs.Queue { } module.exports = { DeadLetterQueue } ----- +``` -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- +------ +#### [ Python ] + +``` class DeadLetterQueue(sqs.Queue): def __init__(self, scope: Construct, id: str): super().__init__(scope, id) @@ -1369,12 +1321,12 @@ class DeadLetterQueue(sqs.Queue): threshold=1, metric=self.metric_approximate_number_of_messages_visible(), ) ----- +``` + +------ +#### [ Java ] -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- +``` public class DeadLetterQueue extends Queue { private final IAlarm messagesInQueueAlarm; @@ -1393,12 +1345,12 @@ public class DeadLetterQueue extends Queue { return messagesInQueueAlarm; } } ----- +``` -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- +------ +#### [ C\# ] + +``` namespace AwsCdkAssertionSamples { public class DeadLetterQueue : Queue @@ -1417,17 +1369,16 @@ namespace AwsCdkAssertionSamples } } } ----- -==== +``` + +------ We can test it like this: -==== -[role="tablist"] -TypeScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +------ +#### [ TypeScript ] + +``` import { Match, Template } from "aws-cdk-lib/assertions"; import * as cdk from "aws-cdk-lib"; import { DeadLetterQueue } from "../lib/dead-letter-queue"; @@ -1441,12 +1392,12 @@ describe("DeadLetterQueue", () => { expect(template.toJSON()).toMatchSnapshot(); }); }); ----- +``` + +------ +#### [ JavaScript ] -JavaScript:: -+ -[source,javascript,subs="verbatim,attributes"] ----- +``` const { Match, Template } = require("aws-cdk-lib/assertions"); const cdk = require("aws-cdk-lib"); const { DeadLetterQueue } = require("../lib/dead-letter-queue"); @@ -1460,12 +1411,12 @@ describe("DeadLetterQueue", () => { expect(template.toJSON()).toMatchSnapshot(); }); }); ----- +``` -Python:: -+ -[source,python,subs="verbatim,attributes"] ----- +------ +#### [ Python ] + +``` import aws_cdk_lib as cdk from aws_cdk_lib.assertions import Match, Template @@ -1477,12 +1428,12 @@ def snapshot_test(): template = Template.from_stack(stack) assert template.to_json() == snapshot ----- +``` + +------ +#### [ Java ] -Java:: -+ -[source,java,subs="verbatim,attributes"] ----- +``` package software.amazon.samples.awscdkassertionssamples; import org.junit.jupiter.api.Test; @@ -1504,12 +1455,12 @@ public class DeadLetterQueueTest { expect.toMatchSnapshot(template.toJSON()); } } ----- +``` + +------ +#### [ C\# ] -C#:: -+ -[source,csharp,subs="verbatim,attributes"] ----- +``` using Microsoft.VisualStudio.TestTools.UnitTesting; using Amazon.CDK; @@ -1539,16 +1490,14 @@ namespace TestProject1 } } } ----- -==== +``` -[#testing-tips] -== Tips for tests +------ -Remember, your tests will live just as long as the code they test, and they will be read and modified just as often. Therefore, it pays to take a moment to consider how best to write them. +## Tips for tests<a name="testing_tips"></a> -Don't copy and paste setup lines or common assertions. Instead, refactor this logic into fixtures or helper functions. Use good names that reflect what each test actually tests. +Remember, your tests will live just as long as the code they test, and they will be read and modified just as often\. Therefore, it pays to take a moment to consider how best to write them\. -Don't try to do too much in one test. Preferably, a test should test one and only one behavior. If you accidentally break that behavior, exactly one test should fail, and the name of the test should tell you what failed. This is more an ideal to be striven for, however; sometimes you will unavoidably (or inadvertently) write tests that test more than one behavior. Snapshot tests are, for reasons we've already described, especially prone to this problem, so use them sparingly. +Don't copy and paste setup lines or common assertions\. Instead, refactor this logic into fixtures or helper functions\. Use good names that reflect what each test actually tests\. -include::testing-locally.adoc[leveloffset=+1] \ No newline at end of file +Don't try to do too much in one test\. Preferably, a test should test one and only one behavior\. If you accidentally break that behavior, exactly one test should fail, and the name of the test should tell you what failed\. This is more an ideal to be striven for, however; sometimes you will unavoidably \(or inadvertently\) write tests that test more than one behavior\. Snapshot tests are, for reasons we've already described, especially prone to this problem, so use them sparingly\. \ No newline at end of file diff --git a/v2/tokens.md b/v2/tokens.md new file mode 100644 index 00000000..faa745bd --- /dev/null +++ b/v2/tokens.md @@ -0,0 +1,426 @@ +# Tokens<a name="tokens"></a> + +Tokens represent values that can only be resolved at a later time in the lifecycle of an app \(see [App lifecycle](apps.md#lifecycle)\)\. For example, the name of an Amazon S3 bucket that you define in your AWS CDK app is only allocated when the AWS CloudFormation template is synthesized\. If you print the `bucket.bucketName` attribute, which is a string, you see it contains something like the following\. + +``` +${TOKEN[Bucket.Name.1234]} +``` + +This is how the AWS CDK encodes a token whose value is not yet known at construction time, but will become available later\. The AWS CDK calls these placeholders *tokens*\. In this case, it's a token encoded as a string\. + +You can pass this string around as if it was the name of the bucket\. In the following example, the bucket name is specified as an environment variable to an AWS Lambda function\. + +------ +#### [ TypeScript ] + +``` +const bucket = new s3.Bucket(this, 'MyBucket'); + +const fn = new lambda.Function(stack, 'MyLambda', { + // ... + environment: { + BUCKET_NAME: bucket.bucketName, + } +}); +``` + +------ +#### [ JavaScript ] + +``` +const bucket = new s3.Bucket(this, 'MyBucket'); + +const fn = new lambda.Function(stack, 'MyLambda', { + // ... + environment: { + BUCKET_NAME: bucket.bucketName + } +}); +``` + +------ +#### [ Python ] + +``` +bucket = s3.Bucket(self, "MyBucket") + +fn = lambda_.Function(stack, "MyLambda", + environment=dict(BUCKET_NAME=bucket.bucket_name)) +``` + +------ +#### [ Java ] + +``` +final Bucket bucket = new Bucket(this, "MyBucket"); + +Function fn = Function.Builder.create(this, "MyLambda") + .environment(java.util.Map.of( // Map.of requires Java 9+ + "BUCKET_NAME", bucket.getBucketName())) + .build(); +``` + +------ +#### [ C\# ] + +``` +var bucket = new s3.Bucket(this, "MyBucket"); + +var fn = new Function(this, "MyLambda", new FunctionProps { + Environment = new Dictionary<string, string> + { + ["BUCKET_NAME"] = bucket.BucketName + } +}); +``` + +------ + +When the AWS CloudFormation template is finally synthesized, the token is rendered as the AWS CloudFormation intrinsic `{ "Ref": "MyBucket" }`\. At deployment time, AWS CloudFormation replaces this intrinsic with the actual name of the bucket that was created\. + +## Tokens and token encodings<a name="tokens_encoding"></a> + +Tokens are objects that implement the [IResolvable](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.IResolvable.html) interface, which contains a single `resolve` method\. The AWS CDK calls this method during synthesis to produce the final value for the AWS CloudFormation template\. Tokens participate in the synthesis process to produce arbitrary values of any type\. + +**Note** +You'll hardly ever work directly with the `IResolvable` interface\. You will most likely only see string\-encoded versions of tokens\. + +Other functions typically only accept arguments of basic types, such as `string` or `number`\. To use tokens in these cases, you can encode them into one of three types by using static methods on the [cdk\.Token](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Token.html) class\. ++ [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Token.html#static-aswbrstringvalue-options](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Token.html#static-aswbrstringvalue-options) to generate a string encoding \(or call `.toString()` on the token object\) ++ [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Token.html#static-aswbrlistvalue-options](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Token.html#static-aswbrlistvalue-options) to generate a list encoding ++ [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Token.html#static-aswbrnumbervalue](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Token.html#static-aswbrnumbervalue) to generate a numeric encoding + +These take an arbitrary value, which can be an `IResolvable`, and encode them into a primitive value of the indicated type\. + +**Important** +Because any one of the previous types can potentially be an encoded token, be careful when you parse or try to read their contents\. For example, if you attempt to parse a string to extract a value from it, and the string is an encoded token, your parsing fails\. Similarly, if you try to query the length of an array or perform math operations with a number, you must first verify that they aren't encoded tokens\. + +To check whether a value has an unresolved token in it, call the `Token.isUnresolved` \(Python: `is_unresolved`\) method\. + +The following example validates that a string value, which could be a token, is no more than 10 characters long\. + +------ +#### [ TypeScript ] + +``` +if (!Token.isUnresolved(name) && name.length > 10) { + throw new Error(`Maximum length for name is 10 characters`); +} +``` + +------ +#### [ JavaScript ] + +``` +if ( !Token.isUnresolved(name) && name.length > 10) { + throw ( new Error(`Maximum length for name is 10 characters`)); +} +``` + +------ +#### [ Python ] + +``` +if not Token.is_unresolved(name) and len(name) > 10: + raise ValueError("Maximum length for name is 10 characters") +``` + +------ +#### [ Java ] + +``` +if (!Token.isUnresolved(name) && name.length() > 10) + throw new IllegalArgumentException("Maximum length for name is 10 characters"); +``` + +------ +#### [ C\# ] + +``` +if (!Token.IsUnresolved(name) && name.Length > 10) + throw new ArgumentException("Maximum length for name is 10 characters"); +``` + +------ + +If **name** is a token, validation isn't performed, and an error could still occur in a later stage in the lifecycle, such as during deployment\. + +**Note** +You can use token encodings to escape the type system\. For example, you could string\-encode a token that produces a number value at synthesis time\. If you use these functions, it's your responsibility to make sure that your template resolves to a usable state after synthesis\. + +## String\-encoded tokens<a name="tokens_string"></a> + +String\-encoded tokens look like the following\. + +``` +${TOKEN[Bucket.Name.1234]} +``` + +They can be passed around like regular strings, and can be concatenated, as shown in the following example\. + +------ +#### [ TypeScript ] + +``` +const functionName = bucket.bucketName + 'Function'; +``` + +------ +#### [ JavaScript ] + +``` +const functionName = bucket.bucketName + 'Function'; +``` + +------ +#### [ Python ] + +``` +function_name = bucket.bucket_name + "Function" +``` + +------ +#### [ Java ] + +``` +String functionName = bucket.getBucketName().concat("Function"); +``` + +------ +#### [ C\# ] + +``` +string functionName = bucket.BucketName + "Function"; +``` + +------ + +You can also use string interpolation, if your language supports it, as shown in the following example\. + +------ +#### [ TypeScript ] + +``` +const functionName = `${bucket.bucketName}Function`; +``` + +------ +#### [ JavaScript ] + +``` +const functionName = `${bucket.bucketName}Function`; +``` + +------ +#### [ Python ] + +``` +function_name = f"{bucket.bucket_name}Function" +``` + +------ +#### [ Java ] + +``` +String functionName = String.format("%sFunction". bucket.getBucketName()); +``` + +------ +#### [ C\# ] + +``` +string functionName = $"${bucket.bucketName}Function"; +``` + +------ + +Avoid manipulating the string in other ways\. For example, taking a substring of a string is likely to break the string token\. + +## List\-encoded tokens<a name="tokens_list"></a> + +List\-encoded tokens look like the following: + +``` +["#{TOKEN[Stack.NotificationArns.1234]}"] +``` + +The only safe thing to do with these lists is pass them directly to other constructs\. Tokens in string list form cannot be concatenated, nor can an element be taken from the token\. The only safe way to manipulate them is by using AWS CloudFormation intrinsic functions like [Fn\.select](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-select.html)\. + +## Number\-encoded tokens<a name="tokens_number"></a> + +Number\-encoded tokens are a set of tiny negative floating\-point numbers that look like the following\. + +``` +-1.8881545897087626e+289 +``` + +As with list tokens, you cannot modify the number value, as doing so is likely to break the number token\. The only allowed operation is to pass the value around to another construct\. + +## Lazy values<a name="tokens_lazy"></a> + +In addition to representing deploy\-time values, such as AWS CloudFormation [parameters](parameters.md), tokens are also commonly used to represent synthesis\-time lazy values\. These are values for which the final value will be determined before synthesis has completed, but not at the point where the value is constructed\. Use tokens to pass a literal string or number value to another construct, while the actual value at synthesis time might depend on some calculation that has yet to occur\. + +You can construct tokens representing synth\-time lazy values using static methods on the `Lazy` class, such as [Lazy\.string](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Lazy.html#static-stringproducer-options) and [Lazy\.number](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Lazy.html#static-numberproducer)\. These methods accept an object whose `produce` property is a function that accepts a context argument and returns the final value when called\. + +The following example creates an Auto Scaling group whose capacity is determined after its creation\. + +------ +#### [ TypeScript ] + +``` +let actualValue: number; + +new AutoScalingGroup(this, 'Group', { + desiredCapacity: Lazy.numberValue({ + produce(context) { + return actualValue; + } + }) +}); + +// At some later point +actualValue = 10; +``` + +------ +#### [ JavaScript ] + +``` +let actualValue; + +new AutoScalingGroup(this, 'Group', { + desiredCapacity: Lazy.numberValue({ + produce(context) { + return (actualValue); + } + }) +}); + +// At some later point +actualValue = 10; +``` + +------ +#### [ Python ] + +``` +class Producer: + def __init__(self, func): + self.produce = func + +actual_value = None + +AutoScalingGroup(self, "Group", + desired_capacity=Lazy.number_value(Producer(lambda context: actual_value)) +) + +# At some later point +actual_value = 10 +``` + +------ +#### [ Java ] + +``` +double actualValue = 0; + +class ProduceActualValue implements INumberProducer { + + @Override + public Number produce(IResolveContext context) { + return actualValue; + } +} + +AutoScalingGroup.Builder.create(this, "Group") + .desiredCapacity(Lazy.numberValue(new ProduceActualValue())).build(); + +// At some later point +actualValue = 10; +``` + +------ +#### [ C\# ] + +``` +public class NumberProducer : INumberProducer +{ + Func<Double> function; + + public NumberProducer(Func<Double> function) + { + this.function = function; + } + + public Double Produce(IResolveContext context) + { + return function(); + } +} + +double actualValue = 0; + +new AutoScalingGroup(this, "Group", new AutoScalingGroupProps +{ + DesiredCapacity = Lazy.NumberValue(new NumberProducer(() => actualValue)) +}); + +// At some later point +actualValue = 10; +``` + +------ + +## Converting to JSON<a name="tokens_json"></a> + +Sometimes you want to produce a JSON string of arbitrary data, and you may not know whether the data contains tokens\. To properly JSON\-encode any data structure, regardless of whether it contains tokens, use the method [stack\.toJsonString](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html#towbrjsonwbrstringobj-space), as shown in the following example\. + +------ +#### [ TypeScript ] + +``` +const stack = Stack.of(this); +const str = stack.toJsonString({ + value: bucket.bucketName +}); +``` + +------ +#### [ JavaScript ] + +``` +const stack = Stack.of(this); +const str = stack.toJsonString({ + value: bucket.bucketName +}); +``` + +------ +#### [ Python ] + +``` +stack = Stack.of(self) +string = stack.to_json_string(dict(value=bucket.bucket_name)) +``` + +------ +#### [ Java ] + +``` +Stack stack = Stack.of(this); +String stringVal = stack.toJsonString(java.util.Map.of( // Map.of requires Java 9+ + put("value", bucket.getBucketName()))); +``` + +------ +#### [ C\# ] + +``` +var stack = Stack.Of(this); +var stringVal = stack.ToJsonString(new Dictionary<string, string> +{ + ["value"] = bucket.BucketName +}); +``` + +------ \ No newline at end of file diff --git a/v2/tools.md b/v2/tools.md new file mode 100644 index 00000000..4eef2d2e --- /dev/null +++ b/v2/tools.md @@ -0,0 +1,8 @@ +# AWS CDK tools<a name="tools"></a> + +This section contains information about the AWS CDK tools listed below\. + +**Topics** ++ [AWS CDK Toolkit \(`cdk` command\)](cli.md) ++ [AWS Toolkit for Visual Studio Code](vscode.md) ++ [AWS SAM integration](sam.md) \ No newline at end of file diff --git a/v2/troubleshooting.md b/v2/troubleshooting.md new file mode 100644 index 00000000..ae142217 --- /dev/null +++ b/v2/troubleshooting.md @@ -0,0 +1,254 @@ +# Troubleshooting common AWS CDK issues<a name="troubleshooting"></a><a name="troubleshooting_top"></a> + +This topic describes how to troubleshoot the following issues with the AWS CDK\. ++ [After updating the AWS CDK, the AWS CDK Toolkit \(CLI\) reports a mismatch with the AWS Construct Library](#troubleshooting_toolkit) ++ [When deploying my AWS CDK stack, I receive a `NoSuchBucket` error](#troubleshooting_nobucket) ++ [When deploying my AWS CDK stack, I receive a `forbidden: null` message](#troubleshooting_forbidden_null) ++ [When synthesizing an AWS CDK stack, I get the message `--app is required either in command-line, in cdk.json or in ~/.cdk.json`](#troubleshooting_app_required) ++ [When synthesizing an AWS CDK stack, I receive an error because the AWS CloudFormation template contains too many resources](#troubleshooting_resource_count) ++ [I specified three \(or more\) Availability Zones for my Auto Scaling group or VPC, but it was only deployed in two](#troubleshooting_availability_zones) ++ [My S3 bucket, DynamoDB table, or other resource is not deleted when I issue `cdk destroy`](#troubleshooting_resource_not_deleted)<a name="troubleshooting_toolkit"></a> + +**After updating the AWS CDK, the AWS CDK Toolkit \(CLI\) reports a mismatch with the AWS Construct Library** +The version of the AWS CDK Toolkit \(which provides the `cdk` command\) must be at least equal to the version of the main AWS Construct Library module, `aws-cdk-lib`\. The Toolkit is intended to be backward compatible\. The latest 2\.x version of the toolkit can be used with any 1\.x or 2\.x release of the library\. For this reason, we recommend you install this component globally and keep it up to date\. + +``` +npm update -g aws-cdk +``` + +If you need to work with multiple versions of the AWS CDK Toolkit, install a specific version of the toolkit locally in your project folder\. + +If you are using TypeScript or JavaScript, your project directory already contains a versioned local copy of the CDK Toolkit\. + +If you are using another language, use `npm` to install the AWS CDK Toolkit, omitting the `-g` flag and specifying the desired version\. For example: + +``` +npm install aws-cdk@2.0 +``` + +To run a locally installed AWS CDK Toolkit, use the command `npx aws-cdk` instead of only `cdk`\. For example: + +``` +npx aws-cdk deploy MyStack +``` + +`npx aws-cdk` runs the local version of the AWS CDK Toolkit if one exists\. It falls back to the global version when a project doesn't have a local installation\. You may find it convenient to set up a shell alias to make sure `cdk` is always invoked this way\. + +------ +#### [ macOS/Linux ] + +``` +alias cdk="npx aws-cdk" +``` + +------ +#### [ Windows ] + +``` +doskey cdk=npx aws-cdk $* +``` + +------ + +\([back to list](#troubleshooting_top)\)<a name="troubleshooting_nobucket"></a> + +**When deploying my AWS CDK stack, I receive a `NoSuchBucket` error** +Your AWS environment has not been bootstrapped, and so does not have an Amazon S3 bucket to hold resources during deployment\. You can create the staging bucket and other required resources with the following command: + +``` +cdk bootstrap aws://ACCOUNT-NUMBER/REGION +``` + +To avoid generating unexpected AWS charges, the AWS CDK does not automatically bootstrap any environment\. You must explicitly bootstrap each environment into which you will deploy\. + +By default, the bootstrap resources are created in the Region or Regions that are used by stacks in the current AWS CDK application\. Alternatively, they are created in the Region specified in your local AWS profile \(set by `aws configure`\), using that profile's account\. You can specify a different account and Region on the command line as follows\. \(You must specify the account and Region if you are not in an app's directory\.\) + +``` +cdk bootstrap aws://ACCOUNT-NUMBER/REGION +``` + +For more information, see [Bootstrapping](bootstrapping.md)\. + +\([back to list](#troubleshooting_top)\)<a name="troubleshooting_forbidden_null"></a> + +**When deploying my AWS CDK stack, I receive a `forbidden: null` message** +You are deploying a stack that requires bootstrap resources, but are using an IAM role or account that lacks permission to write to it\. \(The staging bucket is used when deploying stacks that contain assets or that synthesize an AWS CloudFormation template larger than 50K\.\) Use an account or role that has permission to perform the action `s3:*` against the bucket mentioned in the error message\. + +\([back to list](#troubleshooting_top)\)<a name="troubleshooting_app_required"></a> + +**When synthesizing an AWS CDK stack, I get the message `--app is required either in command-line, in cdk.json or in ~/.cdk.json`** +This message usually means that you aren't in the main directory of your AWS CDK project when you issue `cdk synth`\. The file `cdk.json` in this directory, created by the `cdk init` command, contains the command line needed to run \(and thereby synthesize\) your AWS CDK app\. For a TypeScript app, for example, the default `cdk.json` looks something like this: + +``` +{ + "app": "npx ts-node bin/my-cdk-app.ts" +} +``` + + We recommend issuing `cdk` commands only in your project's main directory, so the AWS CDK toolkit can find `cdk.json` there and successfully run your app\. + + If this isn't practical for some reason, the AWS CDK Toolkit looks for the app's command line in two other locations: ++ In `cdk.json` in your home directory ++ On the `cdk synth` command itself using the `-a` option + +For example, you might synthesize a stack from a TypeScript app as follows\. + +``` +cdk synth --app "npx ts-node my-cdk-app.ts" MyStack +``` + +\([back to list](#troubleshooting_top)\)<a name="troubleshooting_resource_count"></a> + +**When synthesizing an AWS CDK stack, I receive an error because the AWS CloudFormation template contains too many resources** +The AWS CDK generates and deploys AWS CloudFormation templates\. AWS CloudFormation has a hard limit on the number of resources a stack can contain\. With the AWS CDK, you can run up against this limit more quickly than you might expect\. + +**Note** +The AWS CloudFormation resource limit is 500 at this writing\. See [AWS CloudFormation quotas](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cloudformation-limits.html) for the current resource limit\. + +The AWS Construct Library's higher\-level, intent\-based constructs automatically provision any auxiliary resources that are needed for logging, key management, authorization, and other purposes\. For example, granting one resource access to another generates any IAM objects needed for the relevant services to communicate\. + +In our experience, real\-world use of intent\-based constructs results in 1–5 AWS CloudFormation resources per construct, though this can vary\. For serverless applications, 5–8 AWS resources per API endpoint is typical\. + +Patterns, which represent a higher level of abstraction, let you define even more AWS resources with even less code\. The AWS CDK code in [Creating an AWS Fargate service using the AWS CDK](ecs_example.md), for example, generates more than 50 AWS CloudFormation resources while defining only three constructs\! + +Exceeding the AWS CloudFormation resource limit is an error during AWS CloudFormation synthesis\. The AWS CDK issues a warning if your stack exceeds 80% of the limit\. You can use a different limit by setting the `maxResources` property on your stack, or disable validation by setting `maxResources` to 0\. + +**Tip** +You can get an exact count of the resources in your synthesized output using the following utility script\. \(Since every AWS CDK developer needs Node\.js, the script is written in JavaScript\.\) + +``` +// rescount.js - count the resources defined in a stack +// invoke with: node rescount.js <path-to-stack-json> +// e.g. node rescount.js cdk.out/MyStack.template.json + +import * as fs from 'fs'; +const path = process.argv[2]; + +if (path) fs.readFile(path, 'utf8', function(err, contents) { + console.log(err ? `${err}` : + `${Object.keys(JSON.parse(contents).Resources).length} resources defined in ${path}`); +}); else console.log("Please specify the path to the stack's output .json file"); +``` + +As your stack's resource count approaches the limit, consider re\-architecting to reduce the number of resources your stack contains: for example, by combining some Lambda functions, or by breaking your stack into multiple stacks\. The CDK supports [references between stacks](resources.md#resource_stack), so you can separate your app's functionality into different stacks in whatever way makes the most sense to you\. + +**Note** +AWS CloudFormation experts often suggest the use of nested stacks as a solution to the resource limit\. The AWS CDK supports this approach via the [`NestedStack`](stacks.md#stack_nesting) construct\. + +\([back to list](#troubleshooting_top)\)<a name="troubleshooting_availability_zones"></a> + +**I specified three \(or more\) Availability Zones for my Auto Scaling group or VPC, but it was only deployed in two** +To get the number of Availability Zones that you request, specify the account and Region in the stack's `env` property\. If you do not specify both, the AWS CDK, by default, synthesizes the stack as environment\-agnostic\. You can then deploy the stack to a specific Region using AWS CloudFormation\. Because some Regions have only two Availability Zones, an environment\-agnostic template doesn't use more than two\. + +**Note** +In the past, Regions have occasionally launched with only one Availability Zone\. Environment\-agnostic AWS CDK stacks cannot be deployed to such Regions\. At this writing, however, all AWS Regions have at least two AZs\. + +You can change this behavior by overriding your stack's [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html#availabilityzones](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html#availabilityzones) \(Python: `availability_zones`\) property to explicitly specify the zones that you want to use\. + +For more information about specifying a stack's account and region at synthesis time, while retaining the flexibility to deploy to any region, see [Environments](environments.md)\. + +\([back to list](#troubleshooting_top)\)<a name="troubleshooting_resource_not_deleted"></a> + +**My S3 bucket, DynamoDB table, or other resource is not deleted when I issue `cdk destroy`** +By default, resources that can contain user data have a `removalPolicy` \(Python: `removal_policy`\) property of `RETAIN`, and the resource is not deleted when the stack is destroyed\. Instead, the resource is orphaned from the stack\. You must then delete the resource manually after the stack is destroyed\. Until you do, redeploying the stack fails\. This is because the name of the new resource being created during deployment conflicts with the name of the orphaned resource\. + +If you set a resource's removal policy to `DESTROY`, that resource will be deleted when the stack is destroyed\. + +------ +#### [ TypeScript ] + +``` +import * as cdk from 'aws-cdk-lib'; +import { Construct } from 'constructs'; +import * as s3 from 'aws-cdk-lib/aws-s3'; + +export class CdkTestStack extends cdk.Stack { + constructor(scope: Construct, id: string, props?: cdk.StackProps) { + super(scope, id, props); + + const bucket = new s3.Bucket(this, 'Bucket', { + removalPolicy: cdk.RemovalPolicy.DESTROY, + }); + } +} +``` + +------ +#### [ JavaScript ] + +``` +const cdk = require('aws-cdk-lib'); +const s3 = require('aws-cdk-lib/aws-s3'); + +class CdkTestStack extends cdk.Stack { + constructor(scope, id, props) { + super(scope, id, props); + + const bucket = new s3.Bucket(this, 'Bucket', { + removalPolicy: cdk.RemovalPolicy.DESTROY + }); + } +} + +module.exports = { CdkTestStack } +``` + +------ +#### [ Python ] + +``` +import aws_cdk as cdk +from constructs import Construct +import aws_cdk.aws_s3 as s3 + +class CdkTestStack(cdk.stack): + def __init__(self, scope: Construct, id: str, **kwargs): + super().__init__(scope, id, **kwargs) + + bucket = s3.Bucket(self, "Bucket", + removal_policy=cdk.RemovalPolicy.DESTROY) +``` + +------ +#### [ Java ] + +``` +software.amazon.awscdk.*; +import software.amazon.awscdk.services.s3.*; +import software.constructs; + +public class CdkTestStack extends Stack { + public CdkTestStack(final Construct scope, final String id) { + this(scope, id, null); + } + + public CdkTestStack(final Construct scope, final String id, final StackProps props) { + super(scope, id, props); + + Bucket.Builder.create(this, "Bucket") + .removalPolicy(RemovalPolicy.DESTROY).build(); + } +} +``` + +------ +#### [ C\# ] + +``` +using Amazon.CDK; +using Amazon.CDK.AWS.S3; + +public CdkTestStack(Construct scope, string id, IStackProps props) : base(scope, id, props) +{ + new Bucket(this, "Bucket", new BucketProps { + RemovalPolicy = RemovalPolicy.DESTROY + }); +} +``` + +------ + +**Note** +AWS CloudFormation cannot delete a non\-empty Amazon S3 bucket\. If you set an Amazon S3 bucket's removal policy to `DESTROY`, and it contains data, attempting to destroy the stack will fail because the bucket cannot be deleted\. You can have the AWS CDK delete the objects in the bucket before attempting to destroy it by setting the bucket's `autoDeleteObjects` prop to `true`\. + +\([back to list](#troubleshooting_top)\) \ No newline at end of file diff --git a/v2/use_cfn_public_registry.md b/v2/use_cfn_public_registry.md new file mode 100644 index 00000000..ea1c70e3 --- /dev/null +++ b/v2/use_cfn_public_registry.md @@ -0,0 +1,112 @@ +# Using resources from the AWS CloudFormation Public Registry<a name="use_cfn_public_registry"></a> + + The AWS CloudFormation Public Registry is a collection of AWS CloudFormation extensions from both AWS and third parties\. The extensions are available for use by all AWS customers\. You can also publish your own extension for others to use\. Extensions are of two types: resources and modules\. You can use public resource extensions in your AWS CDK app using the [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.CfnResource.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.CfnResource.html) construct\. + +All public extensions published by AWS are available to all accounts in all Regions without any action on your part\. However, you must activate each third\-party extension you want to use, in each account and Region where you want to use it\. + +**Note** +When you use AWS CloudFormation with third\-party resource types, you will incur charges\. Charges are based on the number of handler operations you run per month and handler operation duration\. See [CloudFormation pricing](http://aws.amazon.com/cloudformation/pricing/) for complete details\. + +See [Using public extensions in CloudFormation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/registry-public.html) for complete documentation of this feature from the AWS CloudFormation side\. + +## Activating a third\-party resource in your account and Region<a name="use_cfn_public_registry_activate"></a> + +Extensions published by AWS do not require activation; they are always available in every account and Region\. You can activate a third\-party extension through the AWS Management Console, via the AWS Command Line Interface, or by deploying a special AWS CloudFormation resource\. + +To activate a third\-party extension through the AWS Management Console, or to see what resources are available, follow these steps\. + +![\[Image NOT FOUND\]](http://docs.aws.amazon.com/cdk/v2/guide/images/activate-cfn-extension.png) + +1. Sign in to the AWS account in which you want to use the extension, then switch to the Region where you want to use it\. + +1. Navigate to the CloudFormation console via the **Services** menu\. + +1. Choose **Public extensions** on the navigation bar, then activate the **Third party** radio button under **Publisher**\. A list of the available third\-party public extensions appears\. \(You may also choose **AWS** to see a list of the public extensions published by AWS, though you don't need to activate them\.\) + +1. Browse the list and find the extension you want to activate\. Alternatively, search for it, then activate the radio button in the upper right corner of the extension's card\. + +1. Choose the **Activate** button at the top of the list to activate the selected extension\. The extension's **Activate** page appears\. + +1. In the **Activate** page, you can override the extension's default name and specify an execution role and logging configuration\. You can also choose whether to automatically update the extension when a new version is released\. When you have set these options as you like, choose **Activate extension** at the bottom of the page\. + +To activate a third\-party extension using the AWS CLI, use the `activate-type `command\. Substitute the ARN of the custom type you want to use where indicated\. + +``` +aws cloudformation activate-type --public-type-arn public_extension_ARN --auto-update-activated +``` + +To activate an extension through CloudFormation or the CDK, deploy a resource of type `AWS::CloudFormation::TypeActivation`, specifying the following properties\. ++ `TypeName` \- The name of the type, such as `AWSQS::EKS::Cluster`\. ++ `MajorVersion` \- The major version number of the extension that you want\. Omit if you want the latest version\. ++ `AutoUpdate` \- Whether to automatically update this extension when a new minor version is released by the publisher\. \(Major version updates require explicitly changing the `MajorVersion` property\.\) ++ `ExecutionRoleArn` \- The ARN of the IAM role under which this extension will run\. ++ `LoggingConfig` \- The logging configuration for the extension\. + +The `TypeActivation` resource can be deployed by the CDK using the [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.CfnResource.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.CfnResource.html) construct\. This is shown for the actual extensions in the following section\. + +## Adding a resource from the AWS CloudFormation Public Registry to your CDK app<a name="use_cfn_public_registry_add"></a> + + Use the [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.CfnResource.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.CfnResource.html) construct to include a resource from the AWS CloudFormation Public Registry in your application\. This construct is in the CDK's `aws-cdk-lib` module\. + +For example, suppose that there is a public resource named `MY::S5::UltimateBucket` that you want to use in your AWS CDK application\. This resource takes one property: the bucket name\. The corresponding `CfnResource` instantiation looks like this\. + +------ +#### [ TypeScript ] + +``` +const ubucket = new CfnResource(this, 'MyUltimateBucket', { + type: 'MY::S5::UltimateBucket::MODULE', + properties: { + BucketName: 'UltimateBucket' + } +}); +``` + +------ +#### [ JavaScript ] + +``` +const ubucket = new CfnResource(this, 'MyUltimateBucket', { + type: 'MY::S5::UltimateBucket::MODULE', + properties: { + BucketName: 'UltimateBucket' + } +}); +``` + +------ +#### [ Python ] + +``` +ubucket = CfnResource(self, "MyUltimateBucket", + type="MY::S5::UltimateBucket::MODULE", + properties=dict( + BucketName="UltimateBucket")) +``` + +------ +#### [ Java ] + +``` +CfnResource.Builder.create(this, "MyUltimateBucket") + .type("MY::S5::UltimateBucket::MODULE") + .properties(java.util.Map.of( // Map.of requires Java 9+ + "BucketName", "UltimateBucket")) + .build(); +``` + +------ +#### [ C\# ] + +``` +new CfnResource(this, "MyUltimateBucket", new CfnResourceProps +{ + Type = "MY::S5::UltimateBucket::MODULE", + Properties = new Dictionary<string, object> + { + ["BucketName"] = "UltimateBucket" + } +}); +``` + +------ \ No newline at end of file diff --git a/v2/use_cfn_template.md b/v2/use_cfn_template.md new file mode 100644 index 00000000..1dc1e90f --- /dev/null +++ b/v2/use_cfn_template.md @@ -0,0 +1,666 @@ +# Import or migrate an existing AWS CloudFormation template<a name="use_cfn_template"></a> + +The [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.cloudformation_include-readme.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.cloudformation_include-readme.html) construct converts the resources in an imported AWS CloudFormation template to AWS CDK L1 constructs\. You can work with these in your app in the same way that you would if they were defined in AWS CDK code\. You can use these L1 constructs within higher\-level AWS CDK constructs\. For example, this can let you use the L2 permission grant methods with the resources they define\. + +This construct essentially adds an AWS CDK API wrapper to any resource in the template\. Use this capability to migrate your existing AWS CloudFormation templates to the AWS CDK a piece at a time\. This way, you can take advantage of the AWS CDK's convenient higher\-level abstractions\. You can also use this feature to vend your AWS CloudFormation templates to AWS CDK developers by providing an AWS CDK construct API\. + +**Note** +AWS CDK v1 also included [https://docs.aws.amazon.com/cdk/api/latest/docs/aws-cdk-lib.CfnInclude.html](https://docs.aws.amazon.com/cdk/api/latest/docs/aws-cdk-lib.CfnInclude.html), which was previously used for the same general purpose\. However, it lacks much of the functionality of `cloudformation-include.CfnInclude`\. + +## Importing an AWS CloudFormation template<a name="w55aac33b9b9"></a> + + Here is a simple AWS CloudFormation template to use for the examples in this topic\. Save it as `my-template.json`\. After you've tried these examples with the provided template, you might explore further using a template for an actual stack you've already deployed\. You can get this template from the AWS CloudFormation console\. + +**Tip** +You can use either a JSON or YAML template\. We recommend JSON if available, since YAML parsers can vary slightly in what they accept\. + +``` +{ + "Resources": { + "MyBucket": { + "Type": "AWS::S3::Bucket", + "Properties": { + "BucketName": "MyBucket", + } + } + } +} +``` + +And here's how you import it into your stack using `cloudformation-include`\. + +------ +#### [ TypeScript ] + +``` +import * as cdk from 'aws-cdk-lib'; +import * as cfninc from 'aws-cdk-lib/cloudformation-include'; +import { Construct } from 'constructs'; + +export class MyStack extends cdk.Stack { + constructor(scope: Construct, id: string, props?: cdk.StackProps) { + super(scope, id, props); + + const template = new cfninc.CfnInclude(this, 'Template', { + templateFile: 'my-template.json', + }); + } +} +``` + +------ +#### [ JavaScript ] + +``` +const cdk = require('aws-cdk-lib'); +const cfninc = require('aws-cdk-lib/cloudformation-include'); + +class MyStack extends cdk.Stack { + constructor(scope, id, props) { + super(scope, id, props); + + const template = new cfninc.CfnInclude(this, 'Template', { + templateFile: 'my-template.json', + }); + } +} + +module.exports = { MyStack } +``` + +------ +#### [ Python ] + +``` +import aws_cdk as cdk +from aws_cdk import cloudformation_include as cfn_inc +from constructs import Construct + +class MyStack(cdk.Stack): + + def __init__(self, scope: Construct, id: str, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + template = cfn_inc.CfnInclude(self, "Template", + template_file="my-template.json") +``` + +------ +#### [ Java ] + +``` +import software.amazon.awscdk.Stack; +import software.amazon.awscdk.StackProps; +import software.amazon.awscdk.cloudformation.include.CfnInclude; +import software.constructs.Construct; + +public class MyStack extends Stack { + public MyStack(final Construct scope, final String id) { + this(scope, id, null); + } + + public MyStack(final Construct scope, final String id, final StackProps props) { + super(scope, id, props); + + CfnInclude template = CfnInclude.Builder.create(this, "Template") + .templateFile("my-template.json") + .build(); + } +} +``` + +------ +#### [ C\# ] + +``` +using Amazon.CDK; +using Constructs; +using cfnInc = Amazon.CDK.CloudFormation.Include; + +namespace MyApp +{ + public class MyStack : Stack + { + internal MyStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) + { + var template = new cfnInc.CfnInclude(this, "Template", new cfnInc.CfnIncludeProps + { + TemplateFile = "my-template.json" + }); + } + } +} +``` + +------ + +By default, importing a resource preserves the resource's original logical ID from the template\. This behavior is suitable for migrating an AWS CloudFormation template to the AWS CDK, where the logical IDs must be retained\. AWS CloudFormation needs this to recognize these as the same resources from the AWS CloudFormation template\. + +You might instead be developing an AWS CDK construct wrapper for the template so it can be used by AWS CDK developers \("vending"\)\. If you're doing this, have the AWS CDK generate new resource IDs instead\. That way, the construct can be used multiple times in a stack without name conflicts\. To do this, set the `preserveLogicalIds` property to `false` when importing the template\. + +------ +#### [ TypeScript ] + +``` +const template = new cfninc.CfnInclude(this, 'MyConstruct', { + templateFile: 'my-template.json', + preserveLogicalIds: false +}); +``` + +------ +#### [ JavaScript ] + +``` +const template = new cfninc.CfnInclude(this, 'MyConstruct', { + templateFile: 'my-template.json', + preserveLogicalIds: false +}); +``` + +------ +#### [ Python ] + +``` +template = cfn_inc.CfnInclude(self, "Template", + template_file="my-template.json", + preserve_logical_ids=False) +``` + +------ +#### [ Java ] + +``` +CfnInclude template = CfnInclude.Builder.create(this, "Template") + .templateFile("my-template.json") + .preserveLogicalIds(false) + .build(); +``` + +------ +#### [ C\# ] + +``` +var template = new cfnInc.CfnInclude(this, "Template", new cfn_inc.CfnIncludeProps +{ + TemplateFile = "my-template.json", + PreserveLogicalIds = false +}); +``` + +------ + +To put the imported resources under the control of your AWS CDK app, add the stack to the `App` as usual\. + +------ +#### [ TypeScript ] + +``` +import * as cdk from 'aws-cdk-lib'; +import { MyStack } from '../lib/my-stack'; + +const app = new cdk.App(); +new MyStack(app, 'MyStack'); +``` + +------ +#### [ JavaScript ] + +``` +const cdk = require('aws-cdk-lib'); +const { MyStack } = require('../lib/my-stack'); + +const app = new cdk.App(); +new MyStack(app, 'MyStack'); +``` + +------ +#### [ Python ] + +``` +import aws_cdk as cdk +from mystack.my_stack import MyStack + +app = cdk.App() +MyStack(app, "MyStack") +``` + +------ +#### [ Java ] + +``` +import software.amazon.awscdk.App; + +public class MyApp { + public static void main(final String[] args) { + App app = new App(); + + new MyStack(app, "MyStack"); + } +} +``` + +------ +#### [ C\# ] + +``` +using Amazon.CDK; + +namespace CdkApp +{ + sealed class Program + { + public static void Main(string[] args) + { + var app = new App(); + new MyStack(app, "MyStack"); + } + } +} +``` + +------ + +To verify that there will be no unintended changes to the AWS resources in the stack, perform a diff, omitting the AWS CDK\-specific metadata\. + +``` +cdk diff --no-version-reporting --no-path-metadata --no-asset-metadata +``` + +When you `cdk deploy` the stack, your AWS CDK app becomes the source of truth for the stack\. In the future, make changes to the AWS CDK app, not to the AWS CloudFormation template\. + +## Accessing imported resources<a name="use_cfn_template_cfninclude_access"></a> + +The name `template` in the example code represents the imported AWS CloudFormation template\. To access a resource from it, use this object's [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.cloudformation_include.CfnInclude.html#getwbrresourcelogicalid](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.cloudformation_include.CfnInclude.html#getwbrresourcelogicalid) method\. To access the returned resource as a specific kind of resource, cast the result to the desired type\. \(Casting is not necessary in Python and JavaScript\.\) + +------ +#### [ TypeScript ] + +``` +const cfnBucket = template.getResource('MyBucket') as s3.CfnBucket; +``` + +------ +#### [ JavaScript ] + +``` +const cfnBucket = template.getResource('MyBucket'); +``` + +------ +#### [ Python ] + +``` +cfn_bucket = template.get_resource("MyBucket") +``` + +------ +#### [ Java ] + +``` +CfnBucket cfnBucket = (CfnBucket)template.getResource("MyBucket"); +``` + +------ +#### [ C\# ] + +``` +var cfnBucket = (CfnBucket)template.GetResource("MyBucket"); +``` + +------ + +In our example, `cfnBucket` is now an instance of the [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html) class, a L1 construct that exactly represents the corresponding AWS CloudFormation resource\. You can treat it like any other resource of its type, for example getting its ARN by way of the `bucket.attrArn` property\. + +To wrap the L1 `CfnBucket` resource in a L2 [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html) instance instead, use the static methods [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html#static-fromwbrbucketwbrarnscope-id-bucketarn](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html#static-fromwbrbucketwbrarnscope-id-bucketarn), [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html#static-fromwbrbucketwbrattributesscope-id-attrs](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html#static-fromwbrbucketwbrattributesscope-id-attrs), or [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html#static-fromwbrbucketwbrnamescope-id-bucketname](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html#static-fromwbrbucketwbrnamescope-id-bucketname)\. Usually the `fromBucketName()` method is the most convenient\. For example: + +------ +#### [ TypeScript ] + +``` +const bucket = s3.Bucket.fromBucketName(this, 'Bucket', cfnBucket.ref); +``` + +------ +#### [ JavaScript ] + +``` +const bucket = s3.Bucket.fromBucketName(this, 'Bucket', cfnBucket.ref); +``` + +------ +#### [ Python ] + +``` +bucket = s3.Bucket.from_bucket_name(self, "Bucket", cfn_bucket.ref) +``` + +------ +#### [ Java ] + +``` +Bucket bucket = (Bucket)Bucket.fromBucketName(this, "Bucket", cfnBucket.getRef()); +``` + +------ +#### [ C\# ] + +``` +var bucket = (Bucket)Bucket.FromBucketName(this, "Bucket", cfnBucket.Ref); +``` + +------ + +Other L2 constructs have similar methods for creating the construct from an existing resource\. + +Constructing the `Bucket` this way doesn't create a second Amazon S3 bucket; instead, the new `Bucket` instance encapsulates the existing `CfnBucket`\. + +In the example, `bucket` is now an L2 `Bucket` construct that you can use as you would one you declared yourself\. For example, let's say that `lambdaFunc` is an AWS Lambda function, and you want to grant it write access to the bucket\. To do so, use the bucket's convenient [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html#grantwbrwriteidentity-objectskeypattern](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html#grantwbrwriteidentity-objectskeypattern) method\. You don't need to construct the necessary IAM policy yourself\. + +------ +#### [ TypeScript ] + +``` +bucket.grantWrite(lambdaFunc); +``` + +------ +#### [ JavaScript ] + +``` +bucket.grantWrite(lambdaFunc); +``` + +------ +#### [ Python ] + +``` +bucket.grant_write(lambda_func) +``` + +------ +#### [ Java ] + +``` +bucket.grantWrite(lambdaFunc); +``` + +------ +#### [ C\# ] + +``` +bucket.GrantWrite(lambdaFunc); +``` + +------ + +## Replacing parameters<a name="use_cfn_template_cfninclude_params"></a> + +If your included AWS CloudFormation template has parameters, you can replace these with build\-time values when you import the template, using the `parameters` property\. In the following example, we replace the `UploadBucket` parameter with the ARN of a bucket defined elsewhere in our AWS CDK code\. + +------ +#### [ TypeScript ] + +``` +const template = new cfninc.CfnInclude(this, 'Template', { + templateFile: 'my-template.json', + parameters: { + 'UploadBucket': bucket.bucketArn, + }, +}); +``` + +------ +#### [ JavaScript ] + +``` +const template = new cfninc.CfnInclude(this, 'Template', { + templateFile: 'my-template.json', + parameters: { + 'UploadBucket': bucket.bucketArn, + }, +}); +``` + +------ +#### [ Python ] + +``` +template = cfn_inc.CfnInclude(self, "Template", + template_file="my-template.json", + parameters=dict(UploadBucket=bucket.bucket_arn) +) +``` + +------ +#### [ Java ] + +``` +CfnInclude template = CfnInclude.Builder.create(this, "Template") + .templateFile("my-template.json") + .parameters(java.util.Map.of( // Map.of requires Java 9+ + "UploadBucket", bucket.getBucketArn())) + .build(); +``` + +------ +#### [ C\# ] + +``` +var template = new cfnInc.CfnInclude(this, "Template", new cfnInc.CfnIncludeProps +{ + TemplateFile = "my-template.json", + Parameters = new Dictionary<string, string> + { + { "UploadBucket", bucket.BucketArn } + } +}); +``` + +------ + +## Other template elements<a name="use_cfn_template_cfninclude_other"></a> + +You can import any AWS CloudFormation template element, not only resources\. The imported elements become part of the AWS CDK stack\. To import these elements, use the following methods of the `CfnInclude` object\. ++ [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.cloudformation_include.CfnInclude.html#getwbrconditionconditionname](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.cloudformation_include.CfnInclude.html#getwbrconditionconditionname) \- AWS CloudFormation [conditions](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/conditions-section-structure.html) ++ [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.cloudformation_include.CfnInclude.html#getwbrhookhooklogicalid](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.cloudformation_include.CfnInclude.html#getwbrhookhooklogicalid) \- AWS CloudFormation [hooks](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/blue-green.html) for blue/green deployments ++ [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.cloudformation_include.CfnInclude.html#getwbrmappingmappingname](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.cloudformation_include.CfnInclude.html#getwbrmappingmappingname) \- AWS CloudFormation [mappings](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/mappings-section-structure.html) ++ [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.cloudformation_include.CfnInclude.html#getwbroutputlogicalid](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.cloudformation_include.CfnInclude.html#getwbroutputlogicalid) \- AWS CloudFormation [outputs](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html) ++ [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.cloudformation_include.CfnInclude.html#getwbrparameterparametername](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.cloudformation_include.CfnInclude.html#getwbrparameterparametername) \- AWS CloudFormation [parameters](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html) ++ [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.cloudformation_include.CfnInclude.html#getwbrrulerulename](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.cloudformation_include.CfnInclude.html#getwbrrulerulename) \- AWS CloudFormation [rules](https://docs.aws.amazon.com/servicecatalog/latest/adminguide/reference-template_constraint_rules.html) for AWS Service Catalog templates + +Each of these methods returns an instance of a class representing the specific type of AWS CloudFormation element\. These objects are mutable; changes that you make to them will appear in the template generated from the AWS CDK stack\. The following code, for example, imports a parameter from the template and modifies its default\. + +------ +#### [ TypeScript ] + +``` +const param = template.getParameter('MyParameter'); +param.default = "AWS CDK" +``` + +------ +#### [ JavaScript ] + +``` +const param = template.getParameter('MyParameter'); +param.default = "AWS CDK" +``` + +------ +#### [ Python ] + +``` +param = template.get_parameter("MyParameter") +param.default = "AWS CDK" +``` + +------ +#### [ Java ] + +``` +CfnParameter param = template.getParameter("MyParameter"); +param.setDefaultValue("AWS CDK") +``` + +------ +#### [ C\# ] + +``` +var cfnBucket = (CfnBucket)template.GetResource("MyBucket"); +var param = template.GetParameter("MyParameter"); +param.Default = "AWS CDK"; +``` + +------ + +## Nested stacks<a name="use_cfn_template_cfninclude_nested"></a> + +You may import [nested stacks](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-nested-stacks.html) by specifying them either when you import their main template, or at some later point\. The nested template must be stored in a local file, but referenced as a `NestedStack` resource in the main template\. Also, the resource name used in the AWS CDK code must match the name used for the nested stack in the main template\. + +Given this resource definition in the main template, the following code shows how to import the referenced nested stack both ways\. + +``` +"NestedStack": { + "Type": "AWS::CloudFormation::Stack", + "Properties": { + "TemplateURL": "https://my-s3-template-source.s3.amazonaws.com/nested-stack.json" + } +``` + +------ +#### [ TypeScript ] + +``` +// include nested stack when importing main stack +const mainTemplate = new cfninc.CfnInclude(this, 'MainStack', { + templateFile: 'main-template.json', + loadNestedStacks: { + 'NestedStack': { + templateFile: 'nested-template.json', + }, + }, +}); + +// or add it some time after importing the main stack +const nestedTemplate = mainTemplate.loadNestedStack('NestedTemplate', { + templateFile: 'nested-template.json', +}); +``` + +------ +#### [ JavaScript ] + +``` +// include nested stack when importing main stack +const mainTemplate = new cfninc.CfnInclude(this, 'MainStack', { + templateFile: 'main-template.json', + loadNestedStacks: { + 'NestedStack': { + templateFile: 'nested-template.json', + }, + }, +}); + +// or add it some time after importing the main stack +const nestedTemplate = mainTemplate.loadNestedStack('NestedStack', { + templateFile: 'my-nested-template.json', +}); +``` + +------ +#### [ Python ] + +``` +# include nested stack when importing main stack +main_template = cfn_inc.CfnInclude(self, "MainStack", + template_file="main-template.json", + load_nested_stacks=dict(NestedStack= + cfn_inc.CfnIncludeProps(template_file="nested-template.json"))) + +# or add it some time after importing the main stack +nested_template = main_template.load_nested_stack("NestedStack", + template_file="nested-template.json") +``` + +------ +#### [ Java ] + +``` +CfnInclude mainTemplate = CfnInclude.Builder.create(this, "MainStack") + .templateFile("main-template.json") + .loadNestedStacks(java.util.Map.of( // Map.of requires Java 9+ + "NestedStack", CfnIncludeProps.builder() + .templateFile("nested-template.json").build())) + .build(); + +// or add it some time after importing the main stack +IncludedNestedStack nestedTemplate = mainTemplate.loadNestedStack("NestedTemplate", CfnIncludeProps.builder() + .templateFile("nested-template.json") + .build()); +``` + +------ +#### [ C\# ] + +``` +// include nested stack when importing main stack +var mainTemplate = new cfnInc.CfnInclude(this, "MainStack", new cfnInc.CfnIncludeProps +{ + TemplateFile = "main-template.json", + LoadNestedStacks = new Dictionary<string, cfnInc.ICfnIncludeProps> + { + { "NestedStack", new cfnInc.CfnIncludeProps { TemplateFile = "nested-template.json" } } + } +}); + +// or add it some time after importing the main stack +var nestedTemplate = mainTemplate.LoadNestedStack("NestedTemplate", new cfnInc.CfnIncludeProps { + TemplateFile = 'nested-template.json' +}); +``` + +------ + +You can import multiple nested stacks with either or both methods\. When importing the main template, you provide a mapping between the resource name of each nested stack and its template file\. This mapping can contain any number of entries\. To do it after the initial import, call `loadNestedStack()` once for each nested stack\. + +After importing a nested stack, you can access it using the main template's [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.cloudformation_include.CfnInclude.html#getwbrnestedwbrstacklogicalid](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.cloudformation_include.CfnInclude.html#getwbrnestedwbrstacklogicalid) method\. + +------ +#### [ TypeScript ] + +``` +const nestedStack = mainTemplate.getNestedStack('NestedStack').stack; +``` + +------ +#### [ JavaScript ] + +``` +const nestedStack = mainTemplate.getNestedStack('NestedStack').stack; +``` + +------ +#### [ Python ] + +``` +nested_stack = main_template.get_nested_stack("NestedStack").stack +``` + +------ +#### [ Java ] + +``` +NestedStack nestedStack = mainTemplate.getNestedStack("NestedStack").getStack(); +``` + +------ +#### [ C\# ] + +``` +var nestedStack = mainTemplate.GetNestedStack("NestedStack").Stack; +``` + +------ + +The `getNestedStack()` method returns an [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.cloudformation_include.CfnInclude.html#getwbrnestedwbrstacklogicalid](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.cloudformation_include.CfnInclude.html#getwbrnestedwbrstacklogicalid) instance\. From this instance, you can access the AWS CDK [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.NestedStack.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.NestedStack.html) instance via the `stack` property \(as shown in the example\)\. You can also access the original AWS CloudFormation template object via `includedTemplate`, from which you can load resources and other AWS CloudFormation elements\. \ No newline at end of file diff --git a/v2/videos.md b/v2/videos.md new file mode 100644 index 00000000..61b0dd42 --- /dev/null +++ b/v2/videos.md @@ -0,0 +1,16 @@ +# Videos<a name="videos"></a> + +Enjoy these videos presented by members of the AWS CDK team\. + +**Note** +Since the AWS CDK is always evolving, some of the code presented in these videos may not work quite the same way it did when the video was recorded\. This is especially true for modules that were under active development at the time\. It's also possible that we've since added a better way to achieve the same result\. Consult this Developer Guide and the [AWS CDK API Reference](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-construct-library.html) for up\-to\-date information\. + +## Infrastructure *is* Code with the AWS CDK<a name="videos-infrastructure-is-code"></a> + +## Deep dive into AWS Cloud Development Kit \(AWS CDK\)<a name="videos-deep-dive"></a> + +## Contributing to the AWS Construct Library<a name="videos-contributing"></a> + +## Faster deployments with CDK Pipelines<a name="videos-pipeliens"></a> + +## How to contribute to the AWS CDK using GitPod<a name="videos-gitpod"></a> \ No newline at end of file diff --git a/v2/vscode.md b/v2/vscode.md new file mode 100644 index 00000000..fc236ba9 --- /dev/null +++ b/v2/vscode.md @@ -0,0 +1,3 @@ +# AWS Toolkit for Visual Studio Code<a name="vscode"></a> + +The [AWS Toolkit for Visual Studio Code](https://aws.amazon.com/visualstudiocode/) is an open source plugin for Visual Studio Code that makes it easier to create, debug, and deploy applications on AWS\. The toolkit provides an integrated experience for developing AWS CDK applications\. It includes the AWS CDK Explorer feature to list your AWS CDK projects and browse the various components of the CDK application\. [Install the AWS Toolkit](https://docs.aws.amazon.com/toolkit-for-vscode/latest/userguide/setup-toolkit.html) and learn more about [using the AWS CDK Explorer](https://docs.aws.amazon.com/toolkit-for-vscode/latest/userguide/cdk-explorer.html)\. \ No newline at end of file diff --git a/v2/work-with-cdk-csharp.md b/v2/work-with-cdk-csharp.md new file mode 100644 index 00000000..40bd2dda --- /dev/null +++ b/v2/work-with-cdk-csharp.md @@ -0,0 +1,184 @@ +# Working with the AWS CDK in C\#<a name="work-with-cdk-csharp"></a> + +\.NET is a fully\-supported client language for the AWS CDK and is considered stable\. C\# is the main \.NET language for which we provide examples and support\. You can choose to write AWS CDK applications in other \.NET languages, such as Visual Basic or F\#, but AWS offers limited support for using these languages with the CDK\. + +You can develop AWS CDK applications in C\# using familiar tools including Visual Studio, Visual Studio Code, the `dotnet` command, and the NuGet package manager\. The modules comprising the AWS Construct Library are distributed via [nuget\.org](https://www.nuget.org/packages?q=amazon.cdk.aws)\. + +We suggest using [Visual Studio 2019](https://visualstudio.microsoft.com/downloads/) \(any edition\) on Windows to develop AWS CDK apps in C\#\. + +## Prerequisites<a name="csharp-prerequisites"></a> + +To work with the AWS CDK, you must have an AWS account and credentials and have installed Node\.js and the AWS CDK Toolkit\. See [AWS CDK Prerequisites](work-with.md#work-with-prerequisites)\. + +C\# AWS CDK applications require \.NET Core v3\.1 or later, [available here](https://dotnet.microsoft.com/download/dotnet-core/3.1)\. + +**Note** +Third\-party language deprecation: language version is only supported until its EOL \(End Of Life\) shared by the vendor or community and is subject to change with prior notice\. + +The \.NET toolchain includes `dotnet`, a command\-line tool for building and running \.NET applications and managing NuGet packages\. Even if you work mainly in Visual Studio, this command can be useful for batch operations and for installing AWS Construct Library packages\. + +## Creating a project<a name="csharp-newproject"></a> + +You create a new AWS CDK project by invoking `cdk init` in an empty directory\. + +``` +mkdir my-project +cd my-project +cdk init app --language csharp +``` + +`cdk init` uses the name of the project folder to name various elements of the project, including classes, subfolders, and files\. Hyphens in the folder name are converted to underscores\. However, the name should otherwise follow the form of a C\# identifier; for example, it should not start with a number or contain spaces\. + +The resulting project includes a reference to the `Amazon.CDK.Lib` NuGet package\. It and its dependencies are installed automatically by NuGet\. + +## Managing AWS Construct Library modules<a name="csharp-managemodules"></a> + +The \.NET ecosystem uses the NuGet package manager\. The main CDK package, which contains the core classes and all stable service constructs, is `Amazon.CDK.Lib`\. Experimental modules, where new functionality is under active development, are named like `Amazon.CDK.AWS.SERVICE-NAME.Alpha`, where the service name is a short name without an AWS or Amazon prefix\. For example, the NuGet package name for the AWS IoT module is `Amazon.CDK.AWS.IoT.Alpha`\. If you can't find a package you want, [search Nuget\.org](https://www.nuget.org/packages?q=amazon.cdk.aws)\. + +**Note** +The [\.NET edition of the CDK API Reference](https://docs.aws.amazon.com/cdk/api/latest/dotnet/api/index.html) also shows the package names\. + +Some services' AWS Construct Library support is in more than one module\. For example, AWS IoT has a second module named `Amazon.CDK.AWS.IoT.Actions.Alpha`\. + +The AWS CDK's main module, which you'll need in most AWS CDK apps, is imported in C\# code as `Amazon.CDK`\. Modules for the various services in the AWS Construct Library live under `Amazon.CDK.AWS`\. For example, the Amazon S3 module's namespace is `Amazon.CDK.AWS.S3`\. + +We recommend writing C\# `using` directives for the CDK core constructs and for each AWS service you use in each of your C\# source files\. You may find it convenient to use an alias for a namespace or type to help resolve name conflicts\. You can always use a type's fully\-qualfiied name \(including its namespace\) without a `using` statement\. + +NuGet has four standard, mostly\-equivalent interfaces; you can use the one that suits your needs and working style\. You can also use compatible tools, such as [Paket](https://fsprojects.github.io/Paket/) or [MyGet](https://www.myget.org/)\. + +### The Visual Studio NuGet GUI<a name="csharp-vs-nuget-gui"></a> + +Visual Studio's NuGet tools are accessible from **Tools** > **NuGet Package Manager** > **Manage NuGet Packages for Solution**\. Use the **Browse** tab to find the AWS Construct Library packages you want to install\. You can choose the desired version, including pre\-release versions of your modules and add them to any of the open projects\. + +**Note** +All AWS Construct Library modules deemed "experimental" \(see [Versioning](reference.md#versioning)\) are flagged as pre\-release in NuGet and have an `alpha` name suffix\. + +![\[Image NOT FOUND\]](http://docs.aws.amazon.com/cdk/v2/guide/images/visual-studio-nuget.png) + +Look on the **Updates** page to install new versions of your packages\. + +### The NuGet console<a name="csharp-vs-nuget-console"></a> + +The NuGet console is a PowerShell\-based interface to NuGet that works in the context of a Visual Studio project\. You can open it in Visual Studio by choosing **Tools** > **NuGet Package Manager** > **Package Manager Console**\. For more information about using this tool, see [Install and Manage Packages with the Package Manager Console in Visual Studio](https://docs.microsoft.com/en-us/nuget/consume-packages/install-use-packages-powershell)\. + +### The `dotnet` command<a name="csharp-vs-dotnet-command"></a> + +The `dotnet` command is the primary command\-line tool for working with Visual Studio C\# projects\. You can invoke it from any Windows command prompt\. Among its many capabilities, `dotnet` can add NuGet dependencies to a Visual Studio project\. + +Assuming you're in the same directory as the Visual Studio project \(`.csproj`\) file, issue a command like the following to install a package\. Note that since the main CDK library is included when you create a project, you should ever only need to explictly install experimental modules\. Experimental modules require you to specify an explicit version number\. + +``` +dotnet add package Amazon.CDK.AWS.IoT.Alpha -v VERSION-NUMBER +``` + +You may issue the command from another directory by including the path to the project file, or to the directory that contains it, after the `add` keyword\. The following example assumes that you are in your AWS CDK project's main directory\. + +``` +dotnet add src/PROJECT-DIR package Amazon.CDK.AWS.IoT.Alpha -v VERSION-NUMBER +``` + +To install a specific version of a package, include the `-v` flag and the desired version\. + +To update a package, issue the same `dotnet add` command you used to install it\. For experimental modules, again, you must specify an explicit version number\. + +For more information about managing packages using the `dotnet` command, see [Install and Manage Packages Using the dotnet CLI](https://docs.microsoft.com/en-us/nuget/consume-packages/install-use-packages-dotnet-cli)\. + +### The `nuget` command<a name="csharp-vs-nuget-command"></a> + +The `nuget` command line tool can install and update NuGet packages\. However, it requires your Visual Studio project to be set up differently from the way `cdk init` sets up projects\. \(Technical details: `nuget` works with `Packages.config` projects, while `cdk init` creates a newer\-style `PackageReference` project\.\) + +We do not recommend the use of the `nuget` tool with AWS CDK projects created by `cdk init`\. If you are using another type of project, and want to use `nuget`, see the [NuGet CLI Reference](https://docs.microsoft.com/en-us/nuget/reference/nuget-exe-cli-reference)\. + +## AWS CDK idioms in C\#<a name="csharp-cdk-idioms"></a> + +### Props<a name="csharp-props"></a> + +All AWS Construct Library classes are instantiated using three arguments: the *scope* in which the construct is being defined \(its parent in the construct tree\), an *id*, and *props*, a bundle of key/value pairs that the construct uses to configure the resources it creates\. Other classes and methods also use the "bundle of attributes" pattern for arguments\. + +In C\#, props are expressed using a props type\. In idiomatic C\# fashion, we can use an object initializer to set the various properties\. Here we're creating an Amazon S3 bucket using the `Bucket` construct; its corresponding props type is `BucketProps`\. + +``` +var bucket = new Bucket(this, "MyBucket", new BucketProps { + Versioned = true +}); +``` + +**Tip** +Add the package `Amazon.JSII.Analyzers` to your project to get required\-values checking in your props definitions inside Visual Studio\. + +When extending a class or overriding a method, you may want to accept additional props for your own purposes that are not understood by the parent class\. To do this, subclass the appropriate props type and add the new attributes\. + +``` +// extend BucketProps for use with MimeBucket +class MimeBucketProps : BucketProps { + public string MimeType { get; set; } +} + +// hypothetical bucket that enforces MIME type of objects inside it +class MimeBucket : Bucket { + public MimeBucket( readonly Construct scope, readonly string id, readonly MimeBucketProps props=null) : base(scope, id, props) { + // ... + } +} + +// instantiate our MimeBucket class +var bucket = new MimeBucket(this, "MyBucket", new MimeBucketProps { + Versioned = true, + MimeType = "image/jpeg" +}); +``` + +When calling the parent class's initializer or overridden method, you can generally pass the props you received\. The new type is compatible with its parent, and extra props you added are ignored\. + +A future release of the AWS CDK could coincidentally add a new property with a name you used for your own property\. This won't cause any technical issues using your construct or method \(since your property isn't passed "up the chain," the parent class or overridden method will simply use a default value\) but it may cause confusion for your construct's users\. You can avoid this potential problem by naming your properties so they clearly belong to your construct\. If there are many new properties, bundle them into an appropriately\-named class and pass them as a single property\. + +### Generic structures<a name="csharp-generic-structures"></a> + +In some APIs, the AWS CDK uses JavaScript arrays or untyped objects as input to a method\. \(See, for example, AWS CodeBuild's [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_codebuild.BuildSpec.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_codebuild.BuildSpec.html) method\.\) In C\#, these objects are represented as `System.Collections.Generic.Dictionary<String, Object>`\. In cases where the values are all strings, you can use `Dictionary<String, String>`\. JavaScript arrays are represented as `object[]` or `string[]` array types in C\#\. + +**Tip** +You might define short aliases to make it easier to work with these specific dictionary types\. + +``` +using StringDict = System.Collections.Generic.Dictionary<string, string>; +using ObjectDict = System.Collections.Generic.Dictionary<string, object>; +``` + +### Missing values<a name="csharp-missing-values"></a> + +In C\#, missing values in AWS CDK objects such as props are represented by `null`\. The null\-conditional member access operator `?.` and the null coalescing operator `??` are convenient for working with these values\. + +``` +// mimeType is null if props is null or if props.MimeType is null +string mimeType = props?.MimeType; + +// mimeType defaults to text/plain. either props or props.MimeType can be null +string MimeType = props?.MimeType ?? "text/plain"; +``` + +## Building, synthesizing, and deploying<a name="csharp-running"></a> + +The AWS CDK automatically compiles your app before running it\. However, it can be useful to build your app manually to check for errors and run tests\. You can do this by pressing F6 in Visual Studio or by issuing `dotnet build src` from the command line, where `src` is the directory in your project directory that contains the Visual Studio Solution \(`.sln`\) file\. + +The [stacks](stacks.md) defined in your AWS CDK app can be synthesized and deployed individually or together using the commands below\. Generally, you should be in your project's main directory when you issue them\. ++ `cdk synth`: Synthesizes a AWS CloudFormation template from one or more of the stacks in your AWS CDK app\. ++ `cdk deploy`: Deploys the resources defined by one or more of the stacks in your AWS CDK app to AWS\. + +You can specify the names of multiple stacks to be synthesized or deployed in a single command\. If your app defines only one stack, you do not need to specify it\. + +``` +cdk synth # app defines single stack +cdk deploy Happy Grumpy # app defines two or more stacks; two are deployed +``` + +You may also use the wildcards \* \(any number of characters\) and ? \(any single character\) to identify stacks by pattern\. When using wildcards, enclose the pattern in quotes\. Otherwise, the shell may try to expand it to the names of files in the current directory before they are passed to the AWS CDK Toolkit\. + +``` +cdk synth "Stack?" # Stack1, StackA, etc. +cdk deploy "*Stack" # PipeStack, LambdaStack, etc. +``` + +**Tip** +You don't need to explicitly synthesize stacks before deploying them; `cdk deploy` performs this step for you to make sure your latest code gets deployed\. + +For full documentation of the `cdk` command, see [AWS CDK Toolkit \(`cdk` command\)](cli.md)\. \ No newline at end of file diff --git a/v2/work-with-cdk-go.md b/v2/work-with-cdk-go.md new file mode 100644 index 00000000..90c17cdd --- /dev/null +++ b/v2/work-with-cdk-go.md @@ -0,0 +1,134 @@ +# Working with the AWS CDK in Go<a name="work-with-cdk-go"></a> + +Go is a fully\-supported client language for the AWS CDK and is considered stable\. Working with the AWS CDK in Go uses familiar tools\. The Go version of the AWS CDK even uses Go\-style identifiers\. + +Unlike the other languages the CDK supports, Go is not a traditional object\-oriented programming language\. Go uses composition where other languages often leverage inheritance\. We have tried to employ idiomatic Go approaches as much as possible, but there are places where the CDK charts its own course\. + +This topic explains the ins and outs of working with the AWS CDK in Go\. See the [announcement blog post](https://aws.amazon.com/blogs/developer/getting-started-with-the-aws-cloud-development-kit-and-go/) for a walkthrough of a simple Go project for the AWS CDK\. + +## Prerequisites<a name="go-prerequisites"></a> + +To work with the AWS CDK, you must have an AWS account and credentials and have installed Node\.js and the AWS CDK Toolkit\. See [AWS CDK Prerequisites](work-with.md#work-with-prerequisites)\. + +The Go bindings for the AWS CDK use the standard [Go toolchain](https://golang.org/dl/), v1\.18 or later\. You can use the editor of your choice\. + +**Note** +Third\-party language deprecation: language version is only supported until its EOL \(End Of Life\) shared by the vendor or community and is subject to change with prior notice\. + +## Creating a project<a name="go-newproject"></a> + +You create a new AWS CDK project by invoking `cdk init` in an empty directory\. + +``` +mkdir my-project +cd my-project +cdk init app --language go +``` + +`cdk init` uses the name of the project folder to name various elements of the project, including classes, subfolders, and files\. Hyphens in the folder name are converted to underscores\. However, the name should otherwise follow the form of a Go identifier; for example, it should not start with a number or contain spaces\. + +The resulting project includes a reference to the core AWS CDK Go module, `github.com/aws/aws-cdk-go/awscdk/v2`, in `go.mod`\. Issue go get to install this and other required modules\. + +## Managing AWS Construct Library modules<a name="go-managemodules"></a> + +In most AWS CDK documentation and examples, the word "module" is often used to refer to AWS Construct Library modules, one or more per AWS service, which differs from idiomatic Go usage of the term\. The CDK Construct Library is provided in one Go module with the individual Construct Library modules, which support the various AWS services, provided as Go packages within that module\. + +Some services' AWS Construct Library support is in more than one Construct Library module \(Go package\)\. For example, Amazon Route 53 has three Construct Library modules in addition to the main `awsroute53` package, named `awsroute53patterns`, `awsroute53resolver`, and `awsroute53targets`\. + +The AWS CDK's core package, which you'll need in most AWS CDK apps, is imported in Go code as `github.com/aws/aws-cdk-go/awscdk/v2`\. Packages for the various services in the AWS Construct Library live under `github.com/aws/aws-cdk-go/awscdk/v2`\. For example, the Amazon S3 module's namespace is `github.com/aws/aws-cdk-go/awscdk/v2/awss3`\. + +``` +import ( + "github.com/aws/aws-cdk-go/awscdk/v2/awss3" + // ... +) +``` + +Once you have imported the Construct Library modules \(Go packages\) for the services you want to use in your app, you access constructs in that module using, for example, `awss3.Bucket`\. + +## AWS CDK idioms in Go<a name="go-cdk-idioms"></a> + +### Field and method names<a name="go-naming"></a> + +Field and method names use camel casing \(`likeThis`\) in TypeScript, the CDK's language of origin\. In Go, these follow Go conventions, so are Pascal\-cased \(`LikeThis`\)\. + +### Cleaning up<a name="go-cdk-jsii-close"></a> + +In your `main` method, use `defer jsii.Close()` to make sure your CDK app cleans up after itself\. + +### Field and method names<a name="go-naming"></a> + +Field and method names use camel casing \(`likeThis`\) in TypeScript, the CDK's language of origin\. In Go, these follow Go conventions, so are Pascal\-cased \(`LikeThis`\)\. + +### Missing values and pointer conversion<a name="go-missing-values"></a> + +In Go, missing values in AWS CDK objects such as property bundles are represented by `nil`\. Go doesn't have nullable types; the only type that can contain `nil` is a pointer\. To allow values to be optional, then, all CDK properties, arguments, and return values are pointers, even for primitive types\. This applies to required values as well as optional ones, so if a required value later becomes optional, no breaking change in type is needed\. + +When passing literal values or expressions, use the following helper functions to create pointers to the values\. ++ `jsii.String` ++ `jsii.Number` ++ `jsii.Bool` ++ `jsii.Time` + +For consistency, we recommend that you use pointers similarly when defining your own constructs, even though it may seem more convenient to, for example, receive your construct's `id` as a string rather than a pointer to a string\. + +When dealing with optional AWS CDK values, including primitive values as well as complex types, you should explicitly test pointers to make sure they are not `nil` before doing anything with them\. Go does not have "syntactic sugar" to help handle empty or missing values as some other languages do\. However, required values in property bundles and similar structures are guaranteed to exist \(construction fails otherwise\), so these values need not be `nil`\-checked\. + +### Constructs and Props<a name="go-props"></a> + +Constructs, which represent one or more AWS resources and their associated attributes, are represented in Go as interfaces\. For example, `awss3.Bucket` is an interface\. Every construct has a factory function, such as `awss3.NewBucket`, to return a struct that implements the corresponding interface\. + +All factory functions take three arguments: the `scope` in which the construct is being defined \(its parent in the construct tree\), an `id`, and `props`, a bundle of key/value pairs that the construct uses to configure the resources it creates\. The "bundle of attributes" pattern is also used elsewhere in the AWS CDK\. + +In Go, props are represented by a specific struct type for each construct\. For example, an `awss3.Bucket` takes a props argument of type `awss3.BucketProps`\. Use a struct literal to write props arguments\. + +``` +var bucket = awss3.NewBucket(stack, jsii.String("MyBucket"), &awss3.BucketProps{ + Versioned: jsii.Bool(true), +}) +``` + +### Generic structures<a name="go-generic-structures"></a> + +In some places, the AWS CDK uses JavaScript arrays or untyped objects as input to a method\. \(See, for example, AWS CodeBuild's [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_codebuild.BuildSpec.html#static-fromwbrobjectvalue](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_codebuild.BuildSpec.html#static-fromwbrobjectvalue) method\.\) In Go, these objects are represented as slices and an empty interface, respectively\. + +The CDK provides variadic helper functions such as `jsii.Strings` for building slices containing primitive types\. + +``` +jsii.Strings("One", "Two", "Three") +``` + +### Developing custom constructs<a name="go-writing-constructs"></a> + +In Go, it is usually more straightforward to write a new construct than to extend an existing one\. First, define a new struct type, anonymously embedding one or more existing types if extension\-like semantics are desired\. Write methods for any new functionality you're adding and the fields necessary to hold the data they need\. Define a props interface if your construct needs one\. Finally, write a factory function `NewMyConstruct()` to return an instance of your construct\. + +If you are simply changing some default values on an existing construct or adding a simple behavior at instantiation, you don't need all that plumbing\. Instead, write a factory function that calls the factory function of the construct you're "extending\." In other CDK languages, for example, you might create a `TypedBucket` construct that enforces the type of objects in an Amazon S3 bucket by overriding the `s3.Bucket` type and, in your new type's initializer, adding a bucket policy that allows only specified filename extensions to be added to the bucket\. In Go, it is easier to simply write a `NewTypedBucket` that returns an `s3.Bucket` \(instantiated using `s3.NewBucket`\) to which you have added an appropriate bucket policy\. No new construct type is necessary because the functionality is already available in the standard bucket construct; the new "construct" just provides a simpler way to configure it\. + +## Building, synthesizing, and deploying<a name="go-running"></a> + +The AWS CDK automatically compiles your app before running it\. However, it can be useful to build your app manually to check for errors and to run tests\. You can do this by issuing `go build` at a command prompt while in your project's root directory\. + +Run any tests you've written by running `go test` at a command prompt\. + +The [stacks](stacks.md) defined in your AWS CDK app can be synthesized and deployed individually or together using the commands below\. Generally, you should be in your project's main directory when you issue them\. ++ `cdk synth`: Synthesizes a AWS CloudFormation template from one or more of the stacks in your AWS CDK app\. ++ `cdk deploy`: Deploys the resources defined by one or more of the stacks in your AWS CDK app to AWS\. + +You can specify the names of multiple stacks to be synthesized or deployed in a single command\. If your app defines only one stack, you do not need to specify it\. + +``` +cdk synth # app defines single stack +cdk deploy Happy Grumpy # app defines two or more stacks; two are deployed +``` + +You may also use the wildcards \* \(any number of characters\) and ? \(any single character\) to identify stacks by pattern\. When using wildcards, enclose the pattern in quotes\. Otherwise, the shell may try to expand it to the names of files in the current directory before they are passed to the AWS CDK Toolkit\. + +``` +cdk synth "Stack?" # Stack1, StackA, etc. +cdk deploy "*Stack" # PipeStack, LambdaStack, etc. +``` + +**Tip** +You don't need to explicitly synthesize stacks before deploying them; `cdk deploy` performs this step for you to make sure your latest code gets deployed\. + +For full documentation of the `cdk` command, see [AWS CDK Toolkit \(`cdk` command\)](cli.md)\. \ No newline at end of file diff --git a/v2/work-with-cdk-java.md b/v2/work-with-cdk-java.md new file mode 100644 index 00000000..78f841e4 --- /dev/null +++ b/v2/work-with-cdk-java.md @@ -0,0 +1,147 @@ +# Working with the AWS CDK in Java<a name="work-with-cdk-java"></a> + +Java is a fully\-supported client language for the AWS CDK and is considered stable\. You can develop AWS CDK applications in Java using familiar tools, including the JDK \(Oracle's, or an OpenJDK distribution such as Amazon Corretto\) and Apache Maven\. + +The AWS CDK supports Java 8 and later\. We recommend using the latest version you can, however, because later versions of the language include improvements that are particularly convenient for developing AWS CDK applications\. For example, Java 9 introduces the `Map.of()` method \(a convenient way to declare hashmaps that would be written as object literals in TypeScript\)\. Java 10 introduces local type inference using the `var` keyword\. + +**Note** +Most code examples in this Developer Guide work with Java 8\. A few examples use `Map.of()`; these examples include comments noting that they require Java 9\. + +You can use any text editor, or a Java IDE that can read Maven projects, to work on your AWS CDK apps\. We provide [Eclipse](https://www.eclipse.org/downloads/) hints in this Guide, but IntelliJ IDEA, NetBeans, and other IDEs can import Maven projects and can be used for developing AWS CDK applications in Java\. + +It is possible to write AWS CDK applications in JVM\-hosted languages other than Java \(for example, Kotlin, Groovy, Clojure, or Scala\), but the experience may not be particularly idiomatic, and we are unable to provide any support for these languages\. + +## Prerequisites<a name="java-prerequisites"></a> + +To work with the AWS CDK, you must have an AWS account and credentials and have installed Node\.js and the AWS CDK Toolkit\. See [AWS CDK Prerequisites](work-with.md#work-with-prerequisites)\. + +Java AWS CDK applications require Java 8 \(v1\.8\) or later\. We recommend [Amazon Corretto](https://aws.amazon.com/corretto/), but you can use any OpenJDK distribution or [Oracle's JDK](https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html)\. You will also need [Apache Maven](https://maven.apache.org/download.cgi) 3\.5 or later\. You can also use tools such as Gradle, but the application skeletons generated by the AWS CDK Toolkit are Maven projects\. + +**Note** +Third\-party language deprecation: language version is only supported until its EOL \(End Of Life\) shared by the vendor or community and is subject to change with prior notice\. + +## Creating a project<a name="java-newproject"></a> + +You create a new AWS CDK project by invoking `cdk init` in an empty directory\. + +``` +mkdir my-project +cd my-project +cdk init app --language java +``` + +`cdk init` uses the name of the project folder to name various elements of the project, including classes, subfolders, and files\. Hyphens in the folder name are converted to underscores\. However, the name should otherwise follow the form of a Java identifier; for example, it should not start with a number or contain spaces\. + +The resulting project includes a reference to the `software.amazon.awscdk` Maven package\. It and its dependencies are automatically installed by Maven\. + +If you are using an IDE, you can now open or import the project\. In Eclipse, for example, choose **File** > **Import** > **Maven** > **Existing Maven Projects**\. Make sure that the project settings are set to use Java 8 \(1\.8\)\. + +## Managing AWS Construct Library modules<a name="java-managemodules"></a> + +Use Maven to install AWS Construct Library packages, which are in the group `software.amazon.awscdk`\. Most constructs are in the artifact `aws-cdk-lib`, which is added to new Java projects by default\. Modules for services whose higher\-level CDK support is still being developed are in separate "experimental" packages, named with a short version \(no AWS or Amazon prefix\) of their service's name\. [Search the Maven Central Repository](https://search.maven.org/search?q=software.amazon.awscdk) to find the names of all AWS CDK and AWS Construct Module libraries\. + +**Note** +The [Java edition of the CDK API Reference](https://docs.aws.amazon.com/cdk/api/v2/java/index.html) also shows the package names\. + +Some services' AWS Construct Library support is in more than one namespace\. For example, Amazon Route 53 has its functionality divided into `software.amazon.awscdk.route53`, `route53-patterns`, `route53resolver`, and `route53-targets`\. + +The main AWS CDK package is imported in Java code as `software.amazon.awscdk`\. Modules for the various services in the AWS Construct Library live under `software.amazon.awscdk.services` and are named similarly to their Maven package name\. For example, the Amazon S3 module's namespace is `software.amazon.awscdk.services.s3`\. + +We recommend writing a separate Java `import` statement for each AWS Construct Library class you use in each of your Java source files, and avoiding wildcard imports\. You can always use a type's fully\-qualified name \(including its namespace\) without an `import` statement\. + +If your application depends on an experimental package, edit your project's `pom.xml` and add a new `<dependency>` element in the `<dependencies>` container\. For example, the following `<dependency>` element specifies the CodeStar experimental construct library module: + +``` +<dependency> + <groupId>software.amazon.awscdk</groupId> + <artifactId>codestar-alpha</artifactId> + <version>2.0.0-alpha.10</version> +</dependency> +``` + +**Tip** +If you use a Java IDE, it probably has features for managing Maven dependencies\. We recommend editing `pom.xml` directly, however, unless you are absolutely sure the IDE's functionality matches what you'd do by hand\. + +## AWS CDK idioms in Java<a name="java-cdk-idioms"></a> + +### Props<a name="java-props"></a> + +All AWS Construct Library classes are instantiated using three arguments: the *scope* in which the construct is being defined \(its parent in the construct tree\), an *id*, and *props*, a bundle of key/value pairs that the construct uses to configure the resources it creates\. Other classes and methods also use the "bundle of attributes" pattern for arguments\. + +In Java, props are expressed using the [Builder pattern](https://en.wikipedia.org/wiki/Builder_pattern)\. Each construct type has a corresponding props type; for example, the `Bucket` construct \(which represents an Amazon S3 bucket\) takes as its props an instance of `BucketProps`\. + +The `BucketProps` class \(like every AWS Construct Library props class\) has an inner class called `Builder`\. The `BucketProps.Builder` type offers methods to set the various properties of a `BucketProps` instance\. Each method returns the `Builder` instance, so the method calls can be chained to set multiple properties\. At the end of the chain, you call `build()` to actually produce the `BucketProps` object\. + +``` +Bucket bucket = new Bucket(this, "MyBucket", new BucketProps.Builder() + .versioned(true) + .encryption(BucketEncryption.KMS_MANAGED) + .build()); +``` + +Constructs, and other classes that take a props\-like object as their final argument, offer a shortcut\. The class has a `Builder` of its own that instantiates it and its props object in one step\. This way, you don't need to explicitly instantiate \(for example\) both `BucketProps` and a `Bucket`—and you don't need an import for the props type\. + +``` +Bucket bucket = Bucket.Builder.create(this, "MyBucket") + .versioned(true) + .encryption(BucketEncryption.KMS_MANAGED) + .build(); +``` + +When deriving your own construct from an existing construct, you may want to accept additional properties\. We recommend that you follow these builder patterns\. However, this isn't as simple as subclassing a construct class\. You must provide the moving parts of the two new `Builder` classes yourself\. You may prefer to simply have your construct accept one or more additional arguments\. You should provide additional constructors when an argument is optional\. + +### Generic structures<a name="java-generic-structures"></a> + +In some APIs, the AWS CDK uses JavaScript arrays or untyped objects as input to a method\. \(See, for example, AWS CodeBuild's [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_codebuild.BuildSpec.html#static-fromwbrobjectvalue](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_codebuild.BuildSpec.html#static-fromwbrobjectvalue) method\.\) In Java, these objects are represented as `java.util.Map<String, Object>`\. In cases where the values are all strings, you can use `Map<String, String>`\. + +Java does not provide a way to write literals for such containers like some other languages do\. In Java 9 and later, you can use [https://docs.oracle.com/javase/9/docs/api/java/util/Map.html#ofEntries-java.util.Map.Entry...-](https://docs.oracle.com/javase/9/docs/api/java/util/Map.html#ofEntries-java.util.Map.Entry...-) to conveniently define maps of up to ten entries inline with one of these calls\. + +``` +java.util.Map.of( + "base-directory", "dist", + "files", "LambdaStack.template.json" + ) +``` + +To create maps with more than ten entries, use [https://docs.oracle.com/javase/9/docs/api/java/util/Map.html#ofEntries-java.util.Map.Entry...-](https://docs.oracle.com/javase/9/docs/api/java/util/Map.html#ofEntries-java.util.Map.Entry...-)\. + +If you are using Java 8, you could provide your own methods similar to to these\. + +JavaScript arrays are represented as `List<Object>` or `List<String>` in Java\. The method `java.util.Arrays.asList` is convenient for defining short `List`s\. + +``` +List<String> cmds = Arrays.asList("cd lambda", "npm install", "npm install typescript") +``` + +### Missing values<a name="java-missing-values"></a> + +In Java, missing values in AWS CDK objects such as props are represented by `null`\. You must explicitly test any value that could be `null` to make sure it contains a value before doing anything with it\. Java does not have "syntactic sugar" to help handle null values as some other languages do\. You may find Apache ObjectUtil's [defaultIfNull](https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/ObjectUtils.html#defaultIfNull-T-T-) and [firstNonNull](https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/ObjectUtils.html#firstNonNull-T...-) useful in some situations\. Alternatively, write your own static helper methods to make it easier to handle potentially null values and make your code more readable\. + +## Building, synthesizing, and deploying<a name="java-running"></a> + +The AWS CDK automatically compiles your app before running it\. However, it can be useful to build your app manually to check for errors and to run tests\. You can do this in your IDE \(for example, press Control\-B in Eclipse\) or by issuing `mvn compile` at a command prompt while in your project's root directory\. + +Run any tests you've written by running `mvn test` at a command prompt\. + +The [stacks](stacks.md) defined in your AWS CDK app can be synthesized and deployed individually or together using the commands below\. Generally, you should be in your project's main directory when you issue them\. ++ `cdk synth`: Synthesizes a AWS CloudFormation template from one or more of the stacks in your AWS CDK app\. ++ `cdk deploy`: Deploys the resources defined by one or more of the stacks in your AWS CDK app to AWS\. + +You can specify the names of multiple stacks to be synthesized or deployed in a single command\. If your app defines only one stack, you do not need to specify it\. + +``` +cdk synth # app defines single stack +cdk deploy Happy Grumpy # app defines two or more stacks; two are deployed +``` + +You may also use the wildcards \* \(any number of characters\) and ? \(any single character\) to identify stacks by pattern\. When using wildcards, enclose the pattern in quotes\. Otherwise, the shell may try to expand it to the names of files in the current directory before they are passed to the AWS CDK Toolkit\. + +``` +cdk synth "Stack?" # Stack1, StackA, etc. +cdk deploy "*Stack" # PipeStack, LambdaStack, etc. +``` + +**Tip** +You don't need to explicitly synthesize stacks before deploying them; `cdk deploy` performs this step for you to make sure your latest code gets deployed\. + +For full documentation of the `cdk` command, see [AWS CDK Toolkit \(`cdk` command\)](cli.md)\. \ No newline at end of file diff --git a/v2/work-with-cdk-javascript.md b/v2/work-with-cdk-javascript.md new file mode 100644 index 00000000..e7bee1bf --- /dev/null +++ b/v2/work-with-cdk-javascript.md @@ -0,0 +1,291 @@ +# Working with the AWS CDK in JavaScript<a name="work-with-cdk-javascript"></a> + +JavaScript is a fully\-supported client language for the AWS CDK and is considered stable\. Working with the AWS CDK in JavaScript uses familiar tools, including [Node\.js](https://nodejs.org/) and the Node Package Manager \(`npm`\)\. You may also use [Yarn](https://yarnpkg.com/) if you prefer, though the examples in this Guide use NPM\. The modules comprising the AWS Construct Library are distributed via the NPM repository, [npmjs\.org](https://www.npmjs.com/)\. + +You can use any editor or IDE\. Many AWS CDK developers use [Visual Studio Code](https://code.visualstudio.com/) \(or its open\-source equivalent [VSCodium](https://vscodium.com/)\), which has good support for JavaScript\. + +## Prerequisites<a name="javascript-prerequisites"></a> + +To work with the AWS CDK, you must have an AWS account and credentials and have installed Node\.js and the AWS CDK Toolkit\. See [AWS CDK Prerequisites](work-with.md#work-with-prerequisites)\. + +JavaScript AWS CDK applications require no additional prerequisites beyond these\. + +**Note** +Third\-party language deprecation: language version is only supported until its EOL \(End Of Life\) shared by the vendor or community and is subject to change with prior notice\. + +## Creating a project<a name="javascript-newproject"></a> + +You create a new AWS CDK project by invoking `cdk init` in an empty directory\. + +``` +mkdir my-project +cd my-project +cdk init app --language javascript +``` + +Creating a project also installs the [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib-readme.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib-readme.html) module and its dependencies\. + +`cdk init` uses the name of the project folder to name various elements of the project, including classes, subfolders, and files\. Hyphens in the folder name are converted to underscores\. However, the name should otherwise follow the form of a JavaScript identifier; for example, it should not start with a number or contain spaces\. + +## Using local `cdk`<a name="typescript-local"></a> + +For the most part, this guide assumes you install the CDK Toolkit globally \(`npm install -g aws-cdk`\), and the provided command examples \(such as `cdk synth`\) follow this assumption\. This approach makes it easy to keep the CDK Toolkit up to date, and since the CDK takes a strict approach to backward compatibility, there is generally little risk in always using the latest version\. + +Some teams prefer to specify all dependencies within each project, including tools like the CDK Toolkit\. This practice lets you pin such components to specific versions and ensure that all developers on your team \(and your CI/CD environment\) use exactly those versions\. This eliminates a possible source of change, helping to make builds and deployments more consistent and repeatable\. + +The CDK includes a dependency for the CDK Toolkit in the JavaScript project template's `package.json`, so if you want to use this approach, you don't need to make any changes to your project\. All you need to do is use slightly different commands for building your app and for issuing `cdk` commands\. + +| Operation | Use global CDK Toolkit | Use local CDK Toolkit | +| --- |--- |--- | +| Initialize project | `cdk init --language javascript` | `npx aws-cdk init --language javascript` | +| --- |--- |--- | +| Run CDK Toolkit command | `cdk ...` | `npm run cdk ...` or `npx aws-cdk ...` | +| --- |--- |--- | + +`npx aws-cdk` runs the version of the CDK Toolkit installed locally in the current project, if one exists, falling back to the global installation, if any\. If no global installation exists, `npx` downloads a temporary copy of the CDK Toolkit and runs that\. You may specify an arbitrary version of the CDK Toolkit using the `@` syntax: `npx aws-cdk@1.120 --version` prints `1.120.0`\. + +**Tip** +Set up an alias so you can use the `cdk` command with a local CDK Toolkit installation\. + +``` +alias cdk="npx aws-cdk" +``` + +``` +doskey cdk=npx aws-cdk $* +``` + +## Managing AWS Construct Library modules<a name="javascript-managemodules"></a> + +Use the Node Package Manager \(`npm`\) to install and update AWS Construct Library modules for use by your apps, as well as other packages you need\. \(You may use `yarn` instead of `npm` if you prefer\.\) `npm` also installs the dependencies for those modules automatically\. + +Most AWS CDK constructs are in the main CDK package, named `aws-cdk-lib`, which is a default dependency in new projects created by cdk init\. "Experimental" AWS Construct Library modules, where higher\-level constructs are still under development, are named like `aws-cdk-lib/SERVICE-NAME-alpha`\. The service name has an *aws\-* prefix\. If you're unsure of a module's name, [search for it on NPM](https://www.npmjs.com/search?q=%40aws-cdk)\. + +**Note** +The [CDK API Reference](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-construct-library.html) also shows the package names\. + +For example, the command below installs the experimental module for AWS CodeStar\. + +``` +npm install @aws-cdk/aws-codestar-alpha +``` + +Some services' Construct Library support is in more than one namespace\. For example, besides `aws-route53`, there are three additional Amazon Route 53 namespaces, `aws-route53-targets`, `aws-route53-patterns`, and `aws-route53resolver`\. + +Your project's dependencies are maintained in `package.json`\. You can edit this file to lock some or all of your dependencies to a specific version or to allow them to be updated to newer versions under certain criteria\. To update your project's NPM dependencies to the latest permitted version according to the rules you specified in `package.json`: + +``` +npm update +``` + +In JavaScript, you import modules into your code under the same name you use to install them using NPM\. We recommend the following practices when importing AWS CDK classes and AWS Construct Library modules in your applications\. Following these guidelines will help make your code consistent with other AWS CDK applications as well as easier to understand\. ++ Use `require()`, not ES6\-style `import` directives\. Older versions of Node\.js do not support ES6 imports, so using the older syntax is more widely compatible\. \(If you really want to use ES6 imports, use [esm](https://www.npmjs.com/package/esm) to ensure your project is compatible with all supported versions of Node\.js\.\) ++ Generally, import individual classes from `aws-cdk-lib`\. + + ``` + const { App, Stack } = require('aws-cdk-lib'); + ``` ++ If you need many classes from `aws-cdk-lib`, you may use a namespace alias of `cdk` instead of importing the individual classes\. Avoid doing both\. + + ``` + const cdk = require('aws-cdk-lib'); + ``` ++ Generally, import AWS Construct Libraries using short namespace aliases\. + + ``` + const { s3 } = require('aws-cdk-lib/aws-s3'); + ``` + +## AWS CDK idioms in JavaScript<a name="javascript-cdk-idioms"></a> + +### Props<a name="javascript-props"></a> + +All AWS Construct Library classes are instantiated using three arguments: the *scope* in which the construct is being defined \(its parent in the construct tree\), an *id*, and *props*, a bundle of key/value pairs that the construct uses to configure the AWS resources it creates\. Other classes and methods also use the "bundle of attributes" pattern for arguments\. + +Using an IDE or editor that has good JavaScript autocomplete will help avoid misspelling property names\. If a construct is expecting an `encryptionKeys` property, and you spell it `encryptionkeys`, when instantiating the construct, you haven't passed the value you intended\. This can cause an error at synthesis time if the property is required, or cause the property to be silently ignored if it is optional\. In the latter case, you may get a default behavior you intended to override\. Take special care here\. + +When subclassing an AWS Construct Library class \(or overriding a method that takes a props\-like argument\), you may want to accept additional properties for your own use\. These values will be ignored by the parent class or overridden method, because they are never accessed in that code, so you can generally pass on all the props you received\. + +A future release of the AWS CDK could coincidentally add a new property with a name you used for your own property\. Passing the value you receive up the inheritance chain can then cause unexpected behavior\. It's safer to pass a shallow copy of the props you received with your property removed or set to `undefined`\. For example: + +``` +super(scope, name, {...props, encryptionKeys: undefined}); +``` + +Alternatively, name your properties so that it is clear that they belong to your construct\. This way, it is unlikely they will collide with properties in future AWS CDK releases\. If there are many of them, use a single appropriately\-named object to hold them\. + +### Missing values<a name="javascript-missing-values"></a> + +Missing values in an object \(such as `props`\) have the value `undefined` in JavaScript\. The usual techniques apply for dealing with these\. For example, a common idiom for accessing a property of a value that may be undefined is as follows: + +``` +// a may be undefined, but if it is not, it may have an attribute b +// c is undefined if a is undefined, OR if a doesn't have an attribute b +let c = a && a.b; +``` + +However, if `a` could have some other "falsy" value besides `undefined`, it is better to make the test more explicit\. Here, we'll take advantage of the fact that `null` and `undefined` are equal to test for them both at once: + +``` +let c = a == null ? a : a.b; +``` + +**Tip** +Node\.js 14\.0 and later support new operators that can simplify the handling of undefined values\. For more information, see the [optional chaining](https://github.com/tc39/proposal-optional-chaining/blob/master/README.md) and [nullish coalescing](https://github.com/tc39/proposal-nullish-coalescing/blob/master/README.md) proposals\. + +## Synthesizing and deploying<a name="javascript-running"></a> + +The [stacks](stacks.md) defined in your AWS CDK app can be synthesized and deployed individually or together using the commands below\. Generally, you should be in your project's main directory when you issue them\. ++ `cdk synth`: Synthesizes a AWS CloudFormation template from one or more of the stacks in your AWS CDK app\. ++ `cdk deploy`: Deploys the resources defined by one or more of the stacks in your AWS CDK app to AWS\. + +You can specify the names of multiple stacks to be synthesized or deployed in a single command\. If your app defines only one stack, you do not need to specify it\. + +``` +cdk synth # app defines single stack +cdk deploy Happy Grumpy # app defines two or more stacks; two are deployed +``` + +You may also use the wildcards \* \(any number of characters\) and ? \(any single character\) to identify stacks by pattern\. When using wildcards, enclose the pattern in quotes\. Otherwise, the shell may try to expand it to the names of files in the current directory before they are passed to the AWS CDK Toolkit\. + +``` +cdk synth "Stack?" # Stack1, StackA, etc. +cdk deploy "*Stack" # PipeStack, LambdaStack, etc. +``` + +**Tip** +You don't need to explicitly synthesize stacks before deploying them; `cdk deploy` performs this step for you to make sure your latest code gets deployed\. + +For full documentation of the `cdk` command, see [AWS CDK Toolkit \(`cdk` command\)](cli.md)\. + +## Using TypeScript examples with JavaScript<a name="javascript-using-typescript-examples"></a> + +[TypeScript](https://www.typescriptlang.org/) is the language we use to develop the AWS CDK, and it was the first language supported for developing applications, so many available AWS CDK code examples are written in TypeScript\. These code examples can be a good resource for JavaScript developers; you just need to remove the TypeScript\-specific parts of the code\. + +TypeScript snippets often use the newer ECMAScript `import` and `export` keywords to import objects from other modules and to declare the objects to be made available outside the current module\. Node\.js has just begun supporting these keywords in its latest releases\. Depending on the version of Node\.js you're using \(or wish to support\), you might rewrite imports and exports to use the older syntax\. + +Imports can be replaced with calls to the `require()` function\. + +------ +#### [ TypeScript ] + +``` +import * as cdk from 'aws-cdk-lib'; +import { Bucket, BucketPolicy } from 'aws-cdk-lib/aws-s3'; +``` + +------ +#### [ JavaScript ] + +``` +const cdk = require('aws-cdk-lib'); +const { Bucket, BucketPolicy } = require('aws-cdk-lib/aws-s3'); +``` + +------ + +Exports can be assigned to the `module.exports` object\. + +------ +#### [ TypeScript ] + +``` +export class Stack1 extends cdk.Stack { + // ... +} + +export class Stack2 extends cdk.Stack { + // ... +} +``` + +------ +#### [ JavaScript ] + +``` +class Stack1 extends cdk.Stack { + // ... +} + +class Stack2 extends cdk.Stack { + // ... +} + +module.exports = { Stack1, Stack2 } +``` + +------ + +**Note** +An alternative to using the old\-style imports and exports is to use the [https://www.npmjs.com/package/esm](https://www.npmjs.com/package/esm) module\. + +Once you've got the imports and exports sorted, you can dig into the actual code\. You may run into these commonly\-used TypeScript features: ++ Type annotations ++ Interface definitions ++ Type conversions/casts ++ Access modifiers + +Type annotations may be provided for variables, class members, function parameters, and function return types\. For variables, parameters, and members, types are specified by following the identifier with a colon and the type\. Function return values follow the function signature and consist of a colon and the type\. + +To convert type\-annotated code to JavaScript, remove the colon and the type\. Class members must have some value in JavaScript; set them to `undefined` if they only have a type annotation in TypeScript\. + +------ +#### [ TypeScript ] + +``` +var encrypted: boolean = true; + +class myStack extends cdk.Stack { + bucket: s3.Bucket; + // ... +} + +function makeEnv(account: string, region: string) : object { + // ... +} +``` + +------ +#### [ JavaScript ] + +``` +var encrypted = true; + +class myStack extends cdk.Stack { + bucket = undefined; + // ... +} + +function makeEnv(account, region) { + // ... +} +``` + +------ + +In TypeScript, interfaces are used to give bundles of required and optional properties, and their types, a name\. You can then use the interface name as a type annotation\. TypeScript will make sure that the object you use as, for example, an argument to a function has the required properties of the right types\. + +``` +interface myFuncProps { + code: lambda.Code, + handler?: string +} +``` + +JavaScript does not have an interface feature, so once you've removed the type annotations, delete the interface declarations entirely\. + +When a function or method returns a general\-purpose type \(such as `object`\), but you want to treat that value as a more specific child type to access properties or methods that are not part of the more general type's interface, TypeScript lets you *cast* the value using `as` followed by a type or interface name\. JavaScript doesn't support \(or need\) this, so simply remove `as` and the following identifier\. A less\-common cast syntax is to use a type name in brackets, `<LikeThis>`; these casts, too, must be removed\. + +Finally, TypeScript supports the access modifiers `public`, `protected`, and `private` for members of classes\. All class members in JavaScript are public\. Simply remove these modifiers wherever you see them\. + +Knowing how to identify and remove these TypeScript features goes a long way toward adapting short TypeScript snippets to JavaScript\. But it may be impractical to convert longer TypeScript examples in this fashion, since they are more likely to use other TypeScript features\. For these situations, we recommend [Sucrase](https://github.com/alangpierce/sucrase)\. Sucrase won't complain if code uses an undefined variable, for example, as `tsc` would\. If it is syntactically valid, then with few exceptions, Sucrase can translate it to JavaScript\. This makes it particularly valuable for converting snippets that may not be runnable on their own\. + +## Migrating to TypeScript<a name="javascript-to-typescript"></a> + +Many JavaScript developers move to [TypeScript](https://www.typescriptlang.org/) as their projects get larger and more complex\. TypeScript is a superset of JavaScript—all JavaScript code is valid TypeScript code, so no changes to your code are required—and it is also a supported AWS CDK language\. Type annotations and other TypeScript features are optional and can be added to your AWS CDK app as you find value in them\. TypeScript also gives you early access to new JavaScript features, such as optional chaining and nullish coalescing, before they're finalized—and without requiring that you upgrade Node\.js\. + +TypeScript's "shape\-based" interfaces, which define bundles of required and optional properties \(and their types\) within an object, allow common mistakes to be caught while you're writing the code, and make it easier for your IDE to provide robust autocomplete and other real\-time coding advice\. + +Coding in TypeScript does involve an additional step: compiling your app with the TypeScript compiler, `tsc`\. For typical AWS CDK apps, compilation requires a few seconds at most\. + +The easiest way to migrate an existing JavaScript AWS CDK app to TypeScript is to create a new TypeScript project using `cdk init app --language typescript`, then copy your source files \(and any other necessary files, such as assets like AWS Lambda function source code\) to the new project\. Rename your JavaScript files to end in `.ts` and begin developing in TypeScript\. \ No newline at end of file diff --git a/v2/work-with-cdk-python.md b/v2/work-with-cdk-python.md new file mode 100644 index 00000000..379a6a96 --- /dev/null +++ b/v2/work-with-cdk-python.md @@ -0,0 +1,219 @@ +# Working with the AWS CDK in Python<a name="work-with-cdk-python"></a> + +Python is a fully\-supported client language for the AWS CDK and is considered stable\. Working with the AWS CDK in Python uses familiar tools, including the standard Python implementation \(CPython\), virtual environments with `virtualenv`, and the Python package installer `pip`\. The modules comprising the AWS Construct Library are distributed via [pypi\.org](https://pypi.org/search/?q=aws-cdk)\. The Python version of the AWS CDK even uses Python\-style identifiers \(for example, `snake_case` method names\)\. + +You can use any editor or IDE\. Many AWS CDK developers use [Visual Studio Code](https://code.visualstudio.com/) \(or its open\-source equivalent [VSCodium](https://vscodium.com/)\), which has good support for Python via an [official extension](https://marketplace.visualstudio.com/items?itemName=ms-python.python)\. The IDLE editor included with Python will suffice to get started\. The Python modules for the AWS CDK do have type hints, which are useful for a linting tool or an IDE that supports type validation\. + +## Prerequisites<a name="python-prerequisites"></a> + +To work with the AWS CDK, you must have an AWS account and credentials and have installed Node\.js and the AWS CDK Toolkit\. See [AWS CDK Prerequisites](work-with.md#work-with-prerequisites)\. + +Python AWS CDK applications require Python 3\.6 or later\. If you don't already have it installed, [download a compatible version](https://www.python.org/downloads/) for your operating system at [python\.org](https://www.python.org/)\. If you run Linux, your system may have come with a compatible version, or you may install it using your distro's package manager \(`yum`, `apt`, etc\.\)\. Mac users may be interested in [Homebrew](https://brew.sh/), a Linux\-style package manager for macOS\. + +**Note** +Third\-party language deprecation: language version is only supported until its EOL \(End Of Life\) shared by the vendor or community and is subject to change with prior notice\. + +The Python package installer, `pip`, and virtual environment manager, `virtualenv`, are also required\. Windows installations of compatible Python versions include these tools\. On Linux, `pip` and `virtualenv` may be provided as separate packages in your package manager\. Alternatively, you may install them with the following commands: + +``` +python -m ensurepip --upgrade +python -m pip install --upgrade pip +python -m pip install --upgrade virtualenv +``` + +If you encounter a permission error, run the above commands with the `--user` flag so that the modules are installed in your user directory, or use `sudo` to obtain the permissions to install the modules system\-wide\. + +**Note** +It is common for Linux distros to use the executable name `python3` for Python 3\.x, and have `python` refer to a Python 2\.x installation\. Some distros have an optional package you can install that makes the `python` command refer to Python 3\. Failing that, you can adjust the command used to run your application by editing `cdk.json` in the project's main directory\. + +**Note** +On Windows, you may want to invoke Python \(and pip\) using the py executable, the [>Python launcher for Windows](https://docs.python.org/3/using/windows.html#launcher)\. Among other things, the launcher allows you to easily specify which installed version of Python you want to use\. +If typing python at the command line results in a message about installing Python from the Windows Store, even after installing a Windows version of Python, open Windows' Manage App Execution Aliases settings panel and turn off the two App Installer entries for Python\. + +## Creating a project<a name="python-newproject"></a> + +You create a new AWS CDK project by invoking `cdk init` in an empty directory\. + +``` +mkdir my-project +cd my-project +cdk init app --language python +``` + +`cdk init` uses the name of the project folder to name various elements of the project, including classes, subfolders, and files\. Hyphens in the folder name are converted to underscores\. However, the name should otherwise follow the form of a Python identifier; for example, it should not start with a number or contain spaces\. + +To work with the new project, activate its virtual environment\. This allows the project's dependencies to be installed locally in the project folder, instead of globally\. + +``` +source .venv/bin/activate +``` + +**Note** +You may recognize this as the Mac/Linux command to activate a virtual environment\. The Python templates include a batch file, `source.bat`, that allows the same command to be used on Windows\. The traditional Windows command, `.venv\Scripts\activate.bat`, works, too\. +If you initialized your AWS CDK project using CDK Toolkit v1\.70\.0 or earlier, your virtual environment is in the `.env` directory instead of `.venv`\. + +**Important** +Activate the project's virtual environment whenever you start working on it\. Otherwise, you won't have access to the modules installed there, and modules you install will go in the Python global module directory \(or will result in a permission error\)\. + +After activating your virtual environment for the first time, install the app's standard dependencies: + +``` +python -m pip install -r requirements.txt +``` + +## Managing AWS Construct Library modules<a name="python-managemodules"></a> + +Use the Python package installer, pip, to install and update AWS Construct Library modules for use by your apps, as well as other packages you need\. pip also installs the dependencies for those modules automatically\. If your system does not recognize pip as a standalone command, invoke pip as a Python module, like this: + +``` +python -m pip PIP-COMMAND +``` + +Most AWS CDK constructs are in `aws-cdk-lib`\. Experimental modules are in separate modules named like `aws-cdk.SERVICE-NAME.alpha`\. The service name includes an *aws* prefix\. If you're unsure of a module's name, [search for it at PyPI](https://pypi.org/search/?q=aws-cdk)\. For example, the command below installs the AWS CodeStar library\. + +``` +python -m pip install aws-cdk.aws-codestar-alpha +``` + +Some services' constructs are in more than one namespace\. For example, besides `aws-cdk.aws-route53`, there are three additional Amazon Route 53 namespaces, named `aws-route53-targets`, `aws-route53-patterns`, and `aws-route53resolver`\. + +**Note** +The [Python edition of the CDK API Reference](https://docs.aws.amazon.com/cdk/api/v2/python/index.html) also shows the package names\. + +The names used for importing AWS Construct Library modules into your Python code look like the following\. + +``` +import aws_cdk.aws_s3 as s3 +import aws_cdk.aws_lambda as lambda_ +``` + +We recommend the following practices when importing AWS CDK classes and AWS Construct Library modules in your applications\. Following these guidelines will help make your code consistent with other AWS CDK applications as well as easier to understand\. ++ Generally, import individual classes from top\-level `aws_cdk`\. + + ``` + from aws_cdk import App, Construct + ``` ++ If you need many classes from the `aws_cdk`, you may use a namespace alias of `cdk` instead of importing individual classes\. Avoid doing both\. + + ``` + import aws_cdk as cdk + ``` ++ Generally, import AWS Construct Libraries using short namespace aliases\. + + ``` + import aws_cdk.aws_s3 as s3 + ``` + +After installing a module, update your project's `requirements.txt` file, which lists your project's dependencies\. It is best to do this manually rather than using `pip freeze`\. `pip freeze` captures the current versions of all modules installed in your Python virtual environment, which can be useful when bundling up a project to be run elsewhere\. + +Usually, though, your `requirements.txt` should list only top\-level dependencies \(modules that your app depends on directly\) and not the dependencies of those libraries\. This strategy makes updating your dependencies simpler\. + +You can edit `requirements.txt` to allow upgrades; simply replace the `==` preceding a version number with `~=` to allow upgrades to a higher compatible version, or remove the version requirement entirely to specify the latest available version of the module\. + +With `requirements.txt` edited appropriately to allow upgrades, issue this command to upgrade your project's installed modules at any time: + +``` +pip install --upgrade -r requirements.txt +``` + +## AWS CDK idioms in Python<a name="python-cdk-idioms"></a> + +### Language conflicts<a name="python-keywords"></a> + +In Python, `lambda` is a language keyword, so you cannot use it as a name for the AWS Lambda construct library module or Lambda functions\. The Python convention for such conflicts is to use a trailing underscore, as in `lambda_`, in the variable name\. + +By convention, the second argument to AWS CDK constructs is named `id`\. When writing your own stacks and constructs, calling a parameter `id` "shadows" the Python built\-in function `id()`, which returns an object's unique identifier\. This function isn't used very often, but if you should happen to need it in your construct, rename the argument, for example `construct_id`\. + +### Arguments and properties<a name="python-props"></a> + +All AWS Construct Library classes are instantiated using three arguments: the *scope* in which the construct is being defined \(its parent in the construct tree\), an *id*, and *props*, a bundle of key/value pairs that the construct uses to configure the resources it creates\. Other classes and methods also use the "bundle of attributes" pattern for arguments\. + +*scope* and *id* should always be passed as positional arguments, not keyword arguments, because their names change if the construct accepts a property named *scope* or *id*\. + +In Python, props are expressed as keyword arguments\. If an argument contains nested data structures, these are expressed using a class which takes its own keyword arguments at instantiation\. The same pattern is applied to other method calls that take a structured argument\. + +For example, in a Amazon S3 bucket's `add_lifecycle_rule` method, the `transitions` property is a list of `Transition` instances\. + +``` +bucket.add_lifecycle_rule( + transitions=[ + Transition( + storage_class=StorageClass.GLACIER, + transition_after=Duration.days(10) + ) + ] +) +``` + +When extending a class or overriding a method, you may want to accept additional arguments for your own purposes that are not understood by the parent class\. In this case you should accept the arguments you don't care about using the `**kwargs` idiom, and use keyword\-only arguments to accept the arguments you're interested in\. When calling the parent's constructor or the overridden method, pass only the arguments it is expecting \(often just `**kwargs`\)\. Passing arguments that the parent class or method doesn't expect results in an error\. + +``` +class MyConstruct(Construct): + def __init__(self, id, *, MyProperty=42, **kwargs): + super().__init__(self, id, **kwargs) + # ... +``` + +A future release of the AWS CDK could coincidentally add a new property with a name you used for your own property\. This won't cause any technical issues for users of your construct or method \(since your property isn't passed "up the chain," the parent class or overridden method will simply use a default value\) but it may cause confusion\. You can avoid this potential problem by naming your properties so they clearly belong to your construct\. If there are many new properties, bundle them into an appropriately\-named class and pass it as a single keyword argument\. + +### Missing values<a name="python-missing-values"></a> + +The AWS CDK uses `None` to represent missing or undefined values\. When working with `**kwargs`, use the dictionary's `get()` method to provide a default value if a property is not provided\. Avoid using `kwargs[...]`, as this raises `KeyError` for missing values\. + +``` +encrypted = kwargs.get("encrypted") # None if no property "encrypted" exists +encrypted = kwargs.get("encrypted", False) # specify default of False if property is missing +``` + +Some AWS CDK methods \(such as `tryGetContext()` to get a runtime context value\) may return `None`, which you will need to check explicitly\. + +### Using interfaces<a name="python-interfaces"></a> + +Python doesn't have an interface feature as some other languages do, though it does have [abstract base classes](https://docs.python.org/3/library/abc.html), which are similar\. \(If you're not familiar with interfaces, Wikipedia has [a good introduction](https://en.wikipedia.org/wiki/Interface_(computing)#In_object-oriented_languages)\.\) TypeScript, the language in which the AWS CDK is implemented, does provide interfaces, and constructs and other AWS CDK objects often require an object that adheres to a particular interface, rather than inheriting from a particular class\. So the AWS CDK provides its own interface feature as part of the [JSII](https://github.com/aws/jsii) layer\. + +To indicate that a class implements a particular interface, you can use the `@jsii.implements` decorator: + +``` +from aws_cdk import IAspect, IConstruct +import jsii + +@jsii.implements(IAspect) +class MyAspect(): + def visit(self, node: IConstruct) -> None: + print("Visited", node.node.path) +``` + +### Type pitfalls<a name="python-type-pitfalls"></a> + +Python uses dynamic typing, where all variables may refer to a value of any type\. Parameters and return values may be annotated with types, but these are "hints" and are not enforced\. This means that in Python, it is easy to pass the incorrect type of value to a AWS CDK construct\. Instead of getting a type error during build, as you would from a statically\-typed language, you may instead get a runtime error when the JSII layer \(which translates between Python and the AWS CDK's TypeScript core\) is unable to deal with the unexpected type\. + +In our experience, the type errors Python programmers make tend to fall into these categories\. ++ Passing a single value where a construct expects a container \(Python list or dictionary\) or vice versa\. ++ Passing a value of a type associated with a layer 1 \(`CfnXxxxxx`\) construct to a L2 or L3 construct, or vice versa\. + +The AWS CDK Python modules do include type annotations, so you can use tools that support them to help with types\. If you are not using an IDE that supports these, such as [PyCharm](https://www.jetbrains.com/pycharm/), you might want to call the [MyPy](http://mypy-lang.org/) type validator as a step in your build process\. There are also runtime type checkers that can improve error messages for type\-related errors\. + +## Synthesizing and deploying<a name="python-running"></a> + +The [stacks](stacks.md) defined in your AWS CDK app can be synthesized and deployed individually or together using the commands below\. Generally, you should be in your project's main directory when you issue them\. ++ `cdk synth`: Synthesizes a AWS CloudFormation template from one or more of the stacks in your AWS CDK app\. ++ `cdk deploy`: Deploys the resources defined by one or more of the stacks in your AWS CDK app to AWS\. + +You can specify the names of multiple stacks to be synthesized or deployed in a single command\. If your app defines only one stack, you do not need to specify it\. + +``` +cdk synth # app defines single stack +cdk deploy Happy Grumpy # app defines two or more stacks; two are deployed +``` + +You may also use the wildcards \* \(any number of characters\) and ? \(any single character\) to identify stacks by pattern\. When using wildcards, enclose the pattern in quotes\. Otherwise, the shell may try to expand it to the names of files in the current directory before they are passed to the AWS CDK Toolkit\. + +``` +cdk synth "Stack?" # Stack1, StackA, etc. +cdk deploy "*Stack" # PipeStack, LambdaStack, etc. +``` + +**Tip** +You don't need to explicitly synthesize stacks before deploying them; `cdk deploy` performs this step for you to make sure your latest code gets deployed\. + +For full documentation of the `cdk` command, see [AWS CDK Toolkit \(`cdk` command\)](cli.md)\. \ No newline at end of file diff --git a/v2/work-with-cdk-typescript.md b/v2/work-with-cdk-typescript.md new file mode 100644 index 00000000..41179d3f --- /dev/null +++ b/v2/work-with-cdk-typescript.md @@ -0,0 +1,163 @@ +# Working with the AWS CDK in TypeScript<a name="work-with-cdk-typescript"></a> + +TypeScript is a fully\-supported client language for the AWS CDK and is considered stable\. Working with the AWS CDK in TypeScript uses familiar tools, including Microsoft's TypeScript compiler \(`tsc`\), [Node\.js](https://nodejs.org/) and the Node Package Manager \(`npm`\)\. You may also use [Yarn](https://yarnpkg.com/) if you prefer, though the examples in this Guide use NPM\. The modules comprising the AWS Construct Library are distributed via the NPM repository, [npmjs\.org](https://www.npmjs.com/)\. + +You can use any editor or IDE\. Many AWS CDK developers use [Visual Studio Code](https://code.visualstudio.com/) \(or its open\-source equivalent [VSCodium](https://vscodium.com/)\), which has excellent support for TypeScript\. + +## Prerequisites<a name="typescript-prerequisites"></a> + +To work with the AWS CDK, you must have an AWS account and credentials and have installed Node\.js and the AWS CDK Toolkit\. See [AWS CDK Prerequisites](work-with.md#work-with-prerequisites)\. + +You also need TypeScript itself \(version 3\.8 or later\)\. If you don't already have it, you can install it using `npm`\. + +``` +npm install -g typescript +``` + +**Note** +If you get a permission error, and have administrator access on your system, try `sudo npm install -g typescript`\. + +Keep TypeScript up to date with a regular `npm update -g typescript`\. + +**Note** +Third\-party language deprecation: language version is only supported until its EOL \(End Of Life\) shared by the vendor or community and is subject to change with prior notice\. + +## Creating a project<a name="typescript-newproject"></a> + +You create a new AWS CDK project by invoking `cdk init` in an empty directory\. + +``` +mkdir my-project +cd my-project +cdk init app --language typescript +``` + +Creating a project also installs the [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib-readme.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib-readme.html) module and its dependencies\. + +`cdk init` uses the name of the project folder to name various elements of the project, including classes, subfolders, and files\. Hyphens in the folder name are converted to underscores\. However, the name should otherwise follow the form of a TypeScript identifier; for example, it should not start with a number or contain spaces\. + +## Using local `tsc` and `cdk`<a name="typescript-local"></a> + +For the most part, this guide assumes you install TypeScript and the CDK Toolkit globally \(`npm install -g typescript aws-cdk`\), and the provided command examples \(such as `cdk synth`\) follow this assumption\. This approach makes it easy to keep both components up to date, and since both take a strict approach to backward compatibility, there is generally little risk in always using the latest versions\. + +Some teams prefer to specify all dependencies within each project, including tools like the TypeScript compiler and the CDK Toolkit\. This practice lets you pin these components to specific versions and ensure that all developers on your team \(and your CI/CD environment\) use exactly those versions\. This eliminates a possible source of change, helping to make builds and deployments more consistent and repeatable\. + +The CDK includes dependencies for both TypeScript and the CDK Toolkit in the TypeScript project template's `package.json`, so if you want to use this approach, you don't need to make any changes to your project\. All you need to do is use slightly different commands for building your app and for issuing `cdk` commands\. + +| Operation | Use global tools | Use local tools | +| --- |--- |--- | +| Initialize project | `cdk init --language typescript` | `npx aws-cdk init --language typescript` | +| --- |--- |--- | +| Build | `tsc` | `npm run build` | +| --- |--- |--- | +| Run CDK Toolkit command | `cdk ...` | `npm run cdk ...` or `npx aws-cdk ...` | +| --- |--- |--- | + +`npx aws-cdk` runs the version of the CDK Toolkit installed locally in the current project, if one exists, falling back to the global installation, if any\. If no global installation exists, `npx` downloads a temporary copy of the CDK Toolkit and runs that\. You may specify an arbitrary version of the CDK Toolkit using the `@` syntax: `npx aws-cdk@2.0 --version` prints `2.0.0`\. + +**Tip** +Set up an alias so you can use the `cdk` command with a local CDK Toolkit installation\. + +``` +alias cdk="npx aws-cdk" +``` + +``` +doskey cdk=npx aws-cdk $* +``` + +## Managing AWS Construct Library modules<a name="typescript-managemodules"></a> + +Use the Node Package Manager \(`npm`\) to install and update AWS Construct Library modules for use by your apps, as well as other packages you need\. \(You may use `yarn` instead of `npm` if you prefer\.\) `npm` also installs the dependencies for those modules automatically\. + +Most AWS CDK constructs are in the main CDK package, named `aws-cdk-lib`, which is a default dependency in new projects created by cdk init\. "Experimental" AWS Construct Library modules, where higher\-level constructs are still under development, are named like `@aws-cdk/SERVICE-NAME-alpha`\. The service name has an *aws\-* prefix\. If you're unsure of a module's name, [search for it on NPM](https://www.npmjs.com/search?q=%40aws-cdk)\. + +**Note** +The [CDK API Reference](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-construct-library.html) also shows the package names\. + +For example, the command below installs the experimental module for AWS CodeStar\. + +``` +npm install @aws-cdk/aws-codestar-alpha +``` + +Some services' Construct Library support is in more than one namespace\. For example, besides `aws-route53`, there are three additional Amazon Route 53 namespaces, `aws-route53-targets`, `aws-route53-patterns`, and `aws-route53resolver`\. + +Your project's dependencies are maintained in `package.json`\. You can edit this file to lock some or all of your dependencies to a specific version or to allow them to be updated to newer versions under certain criteria\. To update your project's NPM dependencies to the latest permitted version according to the rules you specified in `package.json`: + +``` +npm update +``` + +In TypeScript, you import modules into your code under the same name you use to install them using NPM\. We recommend the following practices when importing AWS CDK classes and AWS Construct Library modules in your applications\. Following these guidelines will help make your code consistent with other AWS CDK applications as well as easier to understand\. ++ Use ES6\-style `import` directives, not `require()`\. ++ Generally, import individual classes from `aws-cdk-lib`\. + + ``` + import { App, Stack } from 'aws-cdk-lib'; + ``` ++ If you need many classes from `aws-cdk-lib`, you may use a namespace alias of `cdk` instead of importing the individual classes\. Avoid doing both\. + + ``` + import * as cdk from 'aws-cdk-lib'; + ``` ++ Generally, import AWS service constructs using short namespace aliases\. + + ``` + import { aws_s3 as s3 } from 'aws-cdk-lib'; + ``` + +## AWS CDK idioms in TypeScript<a name="typescript-cdk-idioms"></a> + +### Props<a name="typescript-props"></a> + +All AWS Construct Library classes are instantiated using three arguments: the *scope* in which the construct is being defined \(its parent in the construct tree\), an *id*, and *props*, a bundle of key/value pairs that the construct uses to configure the AWS resources it creates\. Other classes and methods also use the "bundle of attributes" pattern for arguments\. + +In TypeScript, the shape of `props` is defined using an interface that tells you the required and optional arguments and their types\. Such an interface is defined for each kind of `props` argument, usually specific to a single construct or method\. For example, the [Bucket](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html) construct \(in the `aws-cdk-lib/aws-s3 module`\) specifies a `props` argument conforming to the [BucketProps](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.BucketProps.html) interface\. + +If a property is itself an object, for example the [websiteRedirect](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.BucketProps.html#websiteredirect) property of `BucketProps`, that object will have its own interface to which its shape must conform, in this case [RedirectTarget](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.RedirectTarget.html)\. + +If you are subclassing an AWS Construct Library class \(or overriding a method that takes a props\-like argument\), you can inherit from the existing interface to create a new one that specifies any new props your code requires\. When calling the parent class or base method, generally you can pass the entire props argument you received, since any attributes provided in the object but not specified in the interface will be ignored\. + +A future release of the AWS CDK could coincidentally add a new property with a name you used for your own property\. Passing the value you receive up the inheritance chain can then cause unexpected behavior\. It's safer to pass a shallow copy of the props you received with your property removed or set to `undefined`\. For example: + +``` +super(scope, name, {...props, encryptionKeys: undefined}); +``` + +Alternatively, name your properties so that it is clear that they belong to your construct\. This way, it is unlikely they will collide with properties in future AWS CDK releases\. If there are many of them, use a single appropriately\-named object to hold them\. + +### Missing values<a name="typescript-missing-values"></a> + +Missing values in an object \(such as props\) have the value `undefined` in TypeScript\. Version 3\.7 of the language introduced operators that simplify working with these values, making it easier to specify defaults and "short\-circuit" chaining when an undefined value is reached\. For more information about these features, see the [TypeScript 3\.7 Release Notes](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html), specifically the first two features, Optional Chaining and Nullish Coalescing\. + +## Building, synthesizing, and deploying<a name="typescript-running"></a> + +Generally, you should be in the project's root directory when building and running your application\. + +Node\.js cannot run TypeScript directly; instead, your application is converted to JavaScript using the TypeScript compiler, `tsc`\. The resulting JavaScript code is then executed\. + +The AWS CDK automatically does this whenever it needs to run your app\. However, it can be useful to compile manually to check for errors and to run tests\. To compile your TypeScript app manually, issue `npm run build`\. You may also issue `npm run watch` to enter watch mode, in which the TypeScript compiler automatically rebuilds your app whenever you save changes to a source file\. + +The [stacks](stacks.md) defined in your AWS CDK app can be synthesized and deployed individually or together using the commands below\. Generally, you should be in your project's main directory when you issue them\. ++ `cdk synth`: Synthesizes a AWS CloudFormation template from one or more of the stacks in your AWS CDK app\. ++ `cdk deploy`: Deploys the resources defined by one or more of the stacks in your AWS CDK app to AWS\. + +You can specify the names of multiple stacks to be synthesized or deployed in a single command\. If your app defines only one stack, you do not need to specify it\. + +``` +cdk synth # app defines single stack +cdk deploy Happy Grumpy # app defines two or more stacks; two are deployed +``` + +You may also use the wildcards \* \(any number of characters\) and ? \(any single character\) to identify stacks by pattern\. When using wildcards, enclose the pattern in quotes\. Otherwise, the shell may try to expand it to the names of files in the current directory before they are passed to the AWS CDK Toolkit\. + +``` +cdk synth "Stack?" # Stack1, StackA, etc. +cdk deploy "*Stack" # PipeStack, LambdaStack, etc. +``` + +**Tip** +You don't need to explicitly synthesize stacks before deploying them; `cdk deploy` performs this step for you to make sure your latest code gets deployed\. + +For full documentation of the `cdk` command, see [AWS CDK Toolkit \(`cdk` command\)](cli.md)\. \ No newline at end of file diff --git a/v2/work-with.md b/v2/work-with.md new file mode 100644 index 00000000..65037ac9 --- /dev/null +++ b/v2/work-with.md @@ -0,0 +1,121 @@ +# Working with the AWS CDK<a name="work-with"></a> + +The AWS Cloud Development Kit \(AWS CDK\) lets you define your AWS cloud infrastructure in a general\-purpose programming language\. Currently, the AWS CDK supports TypeScript, JavaScript, Python, Java, C\#, and Go\. It is also possible to use other JVM and \.NET languages, though we are unable to provide support for every such language\. + +**Note** +This Guide does not currently include instructions or code examples for Go aside from [Working with the AWS CDK in Go](work-with-cdk-go.md)\. + +We develop the AWS CDK in TypeScript and use [JSII](https://github.com/aws/jsii) to provide a "native" experience in other supported languages\. For example, we distribute AWS Construct Library modules using your preferred language's standard repository, and you install them using the language's standard package manager\. Methods and properties are even named using your language's recommended naming patterns\. + +## AWS CDK prerequisites<a name="work-with-prerequisites"></a> + +To use the AWS CDK, you need an AWS account and a corresponding access key\. If you don't have an AWS account yet, see [Create and Activate an AWS Account](https://aws.amazon.com/premiumsupport/knowledge-center/create-and-activate-aws-account/)\. To find out how to obtain an access key ID and secret access key for your AWS account, see [Understanding and Getting Your Security Credentials](https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html)\. To find out how to configure your workstation so the AWS CDK uses your credentials, see [Setting Credentials in Node\.js](https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/setting-credentials-node.html)\. + +**Tip** +If you have the [AWS CLI](https://aws.amazon.com/cli/) installed, the simplest way to set up your workstation with your AWS credentials is to open a command prompt and type: + +``` +aws configure +``` + +All AWS CDK applications require Node\.js 10\.13 or later, even if you work in Python, Java, C\#, or Go\. You may download a compatible version at [nodejs\.org](https://nodejs.org/)\. We recommend the [active LTS version](https://nodejs.org/en/about/releases/)\. Node\.js versions 13\.0\.0 through 13\.6\.0 are not compatible with the AWS CDK due to compatibility issues with its dependencies\. + +After installing Node\.js, install the AWS CDK Toolkit \(the `cdk` command\): + +``` +npm install -g aws-cdk +``` + +**Note** +If you get a permission error, and have administrator access on your system, try `sudo npm install -g aws-cdk`\. + +Test the installation by issuing `cdk --version`\. + +If you get an error message at this point, try uninstalling \(`npm uninstall -g aws-cdk`\) and reinstalling\. As a last resort, delete the `node-modules` folder from the current project and also from the global `node-modules` folder\. To figure out where this folder is, issue `npm config get prefix`\. + +### Language\-specific prerequisites<a name="work-with-prerequisites-language"></a> + +The specific language you work in also has its own prerequisites, described in the corresponding topic listed here\. ++ [Working with the AWS CDK in TypeScript](work-with-cdk-typescript.md) ++ [Working with the AWS CDK in JavaScript](work-with-cdk-javascript.md) ++ [Working with the AWS CDK in Python](work-with-cdk-python.md) ++ [Working with the AWS CDK in Java](work-with-cdk-java.md) ++ [Working with the AWS CDK in C\#](work-with-cdk-csharp.md) ++ [Working with the AWS CDK in Go](work-with-cdk-go.md) + +**Note** +Third\-party Language Deprecation: language version is only supported until its EOL \(End Of Life\) shared by the vendor or community and is subject to change with prior notice\. + +## AWS Construct Library<a name="work-with-library"></a> + +The AWS CDK includes the AWS Construct Library, a collection of constructs organized by AWS service\. The library's constructs are mainly in a single module, colloquially called `aws-cdk-lib` because that's its name in TypeScript\. The actual package name of the main CDK package varies by language\. + +------ +#### [ TypeScript ] + +| Install | `npm install aws-cdk-lib` | +| --- |--- | +| Import | `const cdk = require('aws-cdk-lib');` | +| --- |--- | + +------ +#### [ JavaScript ] + +| Install | `npm install aws-cdk-lib` | +| --- |--- | +| Import | `const cdk = require('aws-cdk-lib');` | +| --- |--- | + +------ +#### [ Python ] + +| Install | `python -m pip install aws-cdk-lib` | +| --- |--- | +| Import | `import aws_cdk as cdk` | +| --- |--- | + +------ +#### [ Java ] + +| Add to `pom.xml` | Group `software.amazon.awscdk`; artifact `aws-cdk-lib` | +| --- |--- | +| Import | `import software.amazon.awscdk.App;` \(for example\) | +| --- |--- | + +------ +#### [ C\# ] + +| Install | `dotnet add package Amazon.CDK.Lib` | +| --- |--- | +| Import | `using Amazon.CDK;` | +| --- |--- | + +------ + +**Note** +Experimental constructs are provided as separate modules\. + +The [AWS CDK API Reference](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-construct-library.html) provides detailed documentation of the constructs \(and other components\) in the library\. A version of the API Reference is provided for each supported programming language\. + +Each module's reference material is broken into the following sections\. ++ *Overview*: Introductory material you'll need to know to work with the service in the AWS CDK, including concepts and examples\. ++ *Constructs*: Library classes that represent one or more concrete AWS resources\. These are the "curated" \(L2\) resources or patterns \(L3 resources\) that provide a high\-level interface with sane defaults\. ++ *Classes*: Non\-construct classes that provide functionality used by constructs in the module\. ++ *Structs*: Data structures \(attribute bundles\) that define the structure of composite values such as properties \(the `props` argument of constructs\) and options\. ++ *Interfaces*: Interfaces, whose names all begin with "I", define the absolute minimum functionality for the corresponding construct or other class\. The CDK uses construct interfaces to represent AWS resources that are defined outside your AWS CDK app and referenced by methods such as `Bucket.fromBucketArn()`\. ++ *Enums*: Collections of named values for use in specifying certain construct parameters\. Using an enumerated value allows the CDK to check these values for validity during synthesis\. ++ *CloudFormation Resources*: These L1 constructs, whose names begin with "Cfn", represent exactly the resources defined in the CloudFormation specification\. They are automatically generated from that specification with each CDK release\. Each L2 or L3 construct encapsulates one or more CloudFormation resources\. ++ *CloudFormation Property Types*: The collection of named values that define the properties for each CloudFormation Resource\. + +### Interfaces vs\. construct classes<a name="work-with-library-interfaces"></a> + +The AWS CDK uses interfaces in a specific way that might not be obvious even if you are familiar with interfaces as a programming concept\. + +The AWS CDK supports using resources defined outside CDK applications using methods such as `Bucket.fromBucketArn()`\. External resources cannot be modified and may not have all the functionality available with resources defined in your CDK app using e\.g\. the `Bucket` class\. Interfaces, then, represent the bare minimum functionality available in the CDK for a given AWS resource type, *including external resources\.* + +When instantiating resources in your CDK app, then, you should always use concrete classes such as `Bucket`\. When specifying the type of an argument you are accepting in one of your own constructs, use the interface type such as `IBucket` if you are prepared to deal with external resources \(that is, you won't need to change them\)\. If you require a CDK\-defined construct, specify the most general type you can use\. + +Some interfaces are minimum versions of properties or options bundles associated with specific classes, rather than constructs\. Such interfaces can be useful when subclassing to accept arguments that you'll pass on to your parent class\. If you require one or more additional properties, you'll want to implement or derive from this interface, or from a more specific type\. + +**Note** +Some programming languages supported by the AWS CDK don't have an interface feature\. In these languages, interfaces are just ordinary classes\. You can identify them by their names, which follow the pattern of an initial "I" followed by the name of some other construct \(e\.g\. `IBucket`\)\. The same rules apply\. \ No newline at end of file