diff --git a/CHANGELOG.md b/CHANGELOG.md index ca6ebeb1b8572..a9fe72678f70a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,43 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [1.94.1](https://github.com/aws/aws-cdk/compare/v1.94.0...v1.94.1) (2021-03-16) + + +### Bug Fixes + +* **s3:** Notifications fail to deploy due to incompatible node runtime ([#13624](https://github.com/aws/aws-cdk/issues/13624)) ([26bc3d4](https://github.com/aws/aws-cdk/commit/26bc3d4951a96a4bdf3e3e10464a4e3b80ed563f)) + +## [1.94.0](https://github.com/aws/aws-cdk/compare/v1.93.0...v1.94.0) (2021-03-16) + + +### ⚠ BREAKING CHANGES TO EXPERIMENTAL FEATURES + +* **appmesh:** Backend, backend default and Virtual Service client policies structures are being altered +* **appmesh**: you must use the backend default interface to define backend defaults in `VirtualGateway`. + The property name also changed from `backendsDefaultClientPolicy` to `backendDefaults` +* **appmesh**: you must use the backend default interface to define backend defaults in `VirtualNode`, + (the property name also changed from `backendsDefaultClientPolicy` to `backendDefaults`), + and the `Backend` class to define a backend +* **appmesh**: you can no longer attach a client policy to a `VirtualService` + +### Features + +* **appmesh:** add missing route match features ([#13350](https://github.com/aws/aws-cdk/issues/13350)) ([b71efd9](https://github.com/aws/aws-cdk/commit/b71efd9d12843ab4b495d53e565cec97d60748f3)), closes [#11645](https://github.com/aws/aws-cdk/issues/11645) +* **aws-elasticloadbalancingv2:** add protocol version for ALB TargetGroups ([#13570](https://github.com/aws/aws-cdk/issues/13570)) ([165a3d8](https://github.com/aws/aws-cdk/commit/165a3d877b7ab23f29e42e1e74ee7c5cb35b7f24)), closes [#12869](https://github.com/aws/aws-cdk/issues/12869) +* **ecs-patterns:** Add ECS deployment circuit breaker support to higher-level constructs ([#12719](https://github.com/aws/aws-cdk/issues/12719)) ([e80a98a](https://github.com/aws/aws-cdk/commit/e80a98aa8839e9b9b89701158d82b991e9ebaa65)), closes [#12534](https://github.com/aws/aws-cdk/issues/12534) [#12360](https://github.com/aws/aws-cdk/issues/12360) + + +### Bug Fixes + +* **appmesh:** Move Client Policy from Virtual Service to backend structure ([#12943](https://github.com/aws/aws-cdk/issues/12943)) ([d3f4284](https://github.com/aws/aws-cdk/commit/d3f428435976c55ca950279cfc841665fd504370)), closes [#11996](https://github.com/aws/aws-cdk/issues/11996) +* **autoscaling:** AutoScaling on percentile metrics doesn't work ([#13366](https://github.com/aws/aws-cdk/issues/13366)) ([46114bb](https://github.com/aws/aws-cdk/commit/46114bb1f4702019a8873b9162d0a9f10763bc61)), closes [#13144](https://github.com/aws/aws-cdk/issues/13144) +* **cloudwatch:** cannot create Alarms from labeled metrics that start with a digit ([#13560](https://github.com/aws/aws-cdk/issues/13560)) ([278029f](https://github.com/aws/aws-cdk/commit/278029f25b41d956091835364e5a8de91429712c)), closes [#13434](https://github.com/aws/aws-cdk/issues/13434) +* use NodeJS 14 for all packaged custom resources ([#13488](https://github.com/aws/aws-cdk/issues/13488)) ([20a2820](https://github.com/aws/aws-cdk/commit/20a2820ee4d022663fcd0928fbc0f61153ae953f)), closes [#13534](https://github.com/aws/aws-cdk/issues/13534) [#13484](https://github.com/aws/aws-cdk/issues/13484) +* **ec2:** Security Groups support all protocols ([#13593](https://github.com/aws/aws-cdk/issues/13593)) ([8c6b3eb](https://github.com/aws/aws-cdk/commit/8c6b3ebea464e27f68ffcab32857d8baec29c413)), closes [#13403](https://github.com/aws/aws-cdk/issues/13403) +* **lambda:** fromDockerBuild output is located under /asset ([#13539](https://github.com/aws/aws-cdk/issues/13539)) ([77449f6](https://github.com/aws/aws-cdk/commit/77449f61e7075fef1240fc52becb8ea60b9ea9ad)), closes [#13439](https://github.com/aws/aws-cdk/issues/13439) +* **region-info:** ap-northeast-3 data not correctly registered ([#13564](https://github.com/aws/aws-cdk/issues/13564)) ([64da84b](https://github.com/aws/aws-cdk/commit/64da84be5c60bb8132551bcc27a7ca9c7effe95d)), closes [#13561](https://github.com/aws/aws-cdk/issues/13561) + ## [1.93.0](https://github.com/aws/aws-cdk/compare/v1.92.0...v1.93.0) (2021-03-11) @@ -40,7 +77,7 @@ All notable changes to this project will be documented in this file. See [standa ## [1.92.0](https://github.com/aws/aws-cdk/compare/v1.91.0...v1.92.0) (2021-03-06) -* **ecs-patterns**: the `desiredCount` property stored on the above constructs will be optional, allowing them to be undefined. This is enabled through the `@aws-cdk/aws-ecs-patterns:removeDefaultDesiredCount` feature flag. We would recommend all CDK users to set the `@aws-cdk/aws-ecs-patterns:removeDefaultDesiredCount` flag to `true` for all of their existing applications. +* **ecs-patterns**: the `desiredCount` property stored on the above constructs will be optional, allowing them to be undefined. This is enabled through the `@aws-cdk/aws-ecs-patterns:removeDefaultDesiredCount` feature flag. We would recommend all CDK users to set the `@aws-cdk/aws-ecs-patterns:removeDefaultDesiredCount` flag to `true` for all of their existing applications. ### ⚠ BREAKING CHANGES TO EXPERIMENTAL FEATURES diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7615d7b10db4e..fab4ce03200c9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -7,40 +7,28 @@ and let us know if it's not up-to-date (even better, submit a PR with your corr - [Getting Started](#getting-started) - [Pull Requests](#pull-requests) - - [Pull Request Checklist](#pull-request-checklist) - - [Step 1: Open Issue](#step-1-open-issue) + - [Step 1: Find something to work on](#step-1-find-something-to-work-on) - [Step 2: Design (optional)](#step-2-design-optional) - [Step 3: Work your Magic](#step-3-work-your-magic) - [Step 4: Commit](#step-4-commit) - [Step 5: Pull Request](#step-5-pull-request) - [Step 6: Merge](#step-6-merge) - [Breaking Changes](#breaking-changes) +- [Documentation](#documentation) + - [rosetta](#rosetta) - [Tools](#tools) - - [Main build scripts](#main-build-scripts) - - [Partial build tools](#partial-build-tools) - - [Useful aliases](#useful-aliases) - [Linters](#linters) - [cfn2ts](#cfn2ts) - [scripts/foreach.sh](#scriptsforeachsh) - [Jetbrains support (WebStorm/IntelliJ)](#jetbrains-support-webstormintellij) -- [Workflows](#workflows) - - [Full clean build](#full-clean-build) - - [Full Docker build](#full-docker-build) - - [Partial build](#partial-build) - - [Partial pack](#partial-pack) - - [Quick Iteration](#quick-iteration) - [Linking against this repository](#linking-against-this-repository) - [Running integration tests in parallel](#running-integration-tests-in-parallel) - [Visualizing dependencies in a CloudFormation Template](#visualizing-dependencies-in-a-cloudformation-template) - - [Adding Dependencies](#adding-dependencies) - - [Finding dependency cycles between packages](#finding-dependency-cycles-between-packages) - - [Updating all Dependencies](#updating-all-dependencies) - - [Running CLI integration tests](#running-cli-integration-tests) - - [Changing the Cloud Assembly Schema](#changing-cloud-assembly-schema) - - [API Compatibility Checks](#api-compatibility-checks) - - [Examples](#examples) - - [Feature Flags](#feature-flags) - - [Versioning and Release](#versioning-and-release) + - [Find dependency cycles between packages](#find-dependency-cycles-between-packages) +- [Running CLI integration tests](#running-cli-integration-tests) +- [Changing the Cloud Assembly Schema](#changing-cloud-assembly-schema) +- [Feature Flags](#feature-flags) +- [Versioning and Release](#versioning-and-release) - [Troubleshooting](#troubleshooting) - [Debugging](#debugging) - [Connecting the VS Code Debugger](#connecting-the-vs-code-debugger) @@ -49,134 +37,183 @@ and let us know if it's not up-to-date (even better, submit a PR with your corr ## Getting Started -### Gitpod +The following steps describe how to set up the AWS CDK repository on your local machine. +The alternative is to use [Gitpod](https://www.gitpod.io/), a Cloud IDE for your development. +See [Gitpod section](#gitpod) on how to set up the CDK repo on Gitpod. -For setting up a local development environment, -we recommend using [Gitpod](http://gitpod.io) - -a service that allows you to spin up an in-browser -Visual Studio Code-compatible editor, -with everything set up and ready to go for CDK development. -Just click the button below to create your private workspace: - -[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/aws/aws-cdk) - -This will start a new Gitpod workspace, -and immediately kick off a build of the CDK code. -Once it's done (it takes around an hour, unfortunately), -you can work on any package that you want to modify, -as described in ['Quick Iteration'](#quick-iteration) below. - -Gitpod is free for 50 hours per month - -make sure to stop your workspace when you're done -(you can always resume it later, and it won't need to run the build again). - -### Local dependencies +### Setup -If you don't want to use Gitpod, -you need to have the following SDKs and tools locally: +The following tools need to be installed on your system prior to installing the CDK: - [Node.js >= 10.13.0](https://nodejs.org/download/release/latest-v10.x/) - We recommend using a version in [Active LTS](https://nodejs.org/en/about/releases/) - ⚠️ versions `13.0.0` to `13.6.0` are not supported due to compatibility issues with our dependencies. - [Yarn >= 1.19.1, < 2](https://yarnpkg.com/lang/en/docs/install) -- [Java >= OpenJDK 8, 11, 14](https://docs.aws.amazon.com/corretto/latest/corretto-8-ug/downloads-list.html) -- [Apache Maven >= 3.6.0, < 4.0](http://maven.apache.org/install.html) - [.NET Core SDK 3.1.x](https://www.microsoft.com/net/download) - [Python >= 3.6.5, < 4.0](https://www.python.org/downloads/release/python-365/) -- [Docker >= 19.03](https://docs.docker.com/get-docker/) -The basic commands to get the repository cloned and built locally follow: +Run the following commands to clone the repository locally. ```console $ git clone https://github.com/aws/aws-cdk.git $ cd aws-cdk +$ yarn install +``` + +We recommend that you use [Visual Studio Code](https://code.visualstudio.com/) to work on the CDK. +We use `eslint` to keep our consistent in terms of style and reducing defects. We recommend installing the +the [eslint extension](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) as well. + +### Repo Layout + +The AWS CDK is a [NPM](https://www.npmjs.com/about) project written in [typescript](https://www.typescriptlang.org/). +More specifically, it is a [monorepo managed using lerna](https://github.com/lerna/lerna#about). +If you're unfamiliar with any of these technologies, it is useful to learn about them and will make understanding the +AWS CDK codebase easier but strictly not necessary for simple contributions. + +The CDK uses [jsii](https://github.com/aws/jsii/) as its primary build system. jsii enables us to write +typescript-compliant source code and produce polyglot libraries, such as, in Java, .NET, Python and Go. + +The repo contains `packages/` directory that contains the CDK public modules. The source code for the IAM module in the +CDK can be found at the location `packages/@aws-cdk/aws-iam`. +The repo also contains the `tools/` directory that holds custom build tooling (modeled as private npm packages) +specific to the CDK. + +### Build + +The full build of the CDK takes a long time complete; 1-2 hours depending on the performance of the build machine. +However, most first time contributions will require changing only one CDK module, sometimes two. A full build of the +CDK is not required in these cases. + +If you want to work on the `@aws-cdk/aws-ec2` module, the following command will build just the EC2 module and any +necessary dependencies. + +```console +$ cd packages/@aws-cdk/aws-ec2 +$ ../../../scripts/buildup +``` + +Note: The `buildup` command is resumable. If your build fails, you can fix the issue and run `buildup --resume` to +resume. + +At this point, you can run build and test the `aws-ec2` module by running + +```console +$ cd packages/@aws-cdk/aws-ec2 $ yarn build +$ yarn test ``` -If you get compiler errors when building, a common cause is a globally installed typescript. Try uninstalling it. +However, if you wish to build the the entire repository, the following command will achieve this. +```console +cd +yarn build ``` -npm uninstall -g typescript + +You are now ready to start contributing to the CDK. See the [Pull Requests](#pull-requests) section on how to make your +changes and submit it as a pull request. + +### Pack + +As called out in the above sections, the AWS CDK uses jsii to produce polyglot targets. This means that each CDK module +produces artifact in all of its target languages. + +Packing involves generating CDK code in the various target languages and packaging them up to be published to their +respective package managers. Once in a while, these will need to be generated either to test the experience of a new +feature, or reproduce a packaging failure. + +To package a specific module, say the `@aws-cdk/aws-ec2` module: + +```console +$ cd +$ docker run --rm --net=host -it -v $PWD:$PWD -w $PWD jsii/superchain +docker$ cd packages/@aws-cdk/aws-ec2 +docker$ ../../../scripts/foreach.sh --up yarn run package +docker$ exit ``` -Alternatively, the [Full Docker build](#full-docker-build) workflow can be used so -that you don't have to worry about installing all those tools on your local machine -and instead only depend on having a working Docker install. +The `dist/` folder within each module contains the packaged up language artifacts. -## Pull Requests +## Docker Build (Alternative) -### Pull Request Checklist - -* [ ] Testing - - Unit test added (prefer not to modify an existing test, otherwise, it's probably a breaking change) - - __CLI change?:__ coordinate update of integration tests with team - - __cdk-init template change?:__ coordinated update of integration tests with team -* [ ] Docs - - __jsdocs__: All public APIs documented - - __README__: README and/or documentation topic updated - - __Design__: For significant features, design document added to `design` folder -* [ ] Title and Description - - __Change type__: title prefixed with **fix**, **feat** and module name in parens, which will appear in changelog - - __Title__: use lower-case and doesn't end with a period - - __Breaking?__: last paragraph: "BREAKING CHANGE: " - - __Issues__: Indicate issues fixed via: "**Fixes #xxx**" or "**Closes #xxx**" -* [ ] Sensitive Modules (requires 2 PR approvers) - - IAM Policy Document (in @aws-cdk/aws-iam) - - EC2 Security Groups and ACLs (in @aws-cdk/aws-ec2) - - Grant APIs (only if not based on official documentation with a reference) - ---- - -### Step 1: Open Issue - -If there isn't one already, open an issue describing what you intend to contribute. It's useful to communicate in -advance because if someone is already working in this space, it may be worth collaborating with them -instead of duplicating the effort. +Build the docker image: -### Step 2: Design (optional) +```console +$ docker build -t aws-cdk . +``` -In some cases, it is useful to seek feedback by iterating on a design document. This is useful -when you plan a big change or feature, or you want advice on what would be the best path forward. +This allows you to run the CDK in a CDK-compatible directory with a command like: -Sometimes, the GitHub issue is sufficient for such discussions, and can be sufficient to get -clarity on what you plan to do. Sometimes, a design document would work better, so people can provide -iterative feedback. +```console +$ docker run -v $(pwd):/app -w /app aws-cdk +``` -Before starting on a design, read through the [design guidelines](DESIGN_GUIDELINES.md) for general -patterns and tips. +## Gitpod (Alternative) -In such cases, use the GitHub issue description to collect **requirements** and -**use cases** for your feature. +You may also set up your local development environment using [Gitpod](http://gitpod.io) - +a service that allows you to spin up an in-browser Visual Studio Code-compatible editor, +with everything set up and ready to go for CDK development. +Just click the button below to create your private workspace: + +[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/aws/aws-cdk) + +This will start a new Gitpod workspace, with the CDK repository [pre-built](https://www.gitpod.io/docs/prebuilds/). +You can now work on your CDK repository, as described in the [Getting Started](#getting-started) section. -Then, create a design document in markdown format under the `design/` directory -and request feedback through a pull request. Prefix the PR title with "**RFC:**" -(request for comments). +Gitpod is free for 50 hours per month - make sure to stop your workspace when you're done +(you can always resume it later, and it won't need to run the build again). -Once the design is finalized, you can re-purpose this PR for the implementation, -or open a new PR to that end. +For Gitpod users only! The best way to supply CDK with your AWS credentials is to add them as +[persisting environment variables](https://www.gitpod.io/docs/environment-variables). +Adding them works as follows via terminal: + +```shell +eval $(gp env -e AWS_ACCESS_KEY_ID=XXXXXXXXX) +eval $(gp env -e AWS_SECRET_ACCESS_KEY=YYYYYYY) +eval $(gp env -e AWS_DEFAULT_REGION=ZZZZZZZZ) +eval $(gp env -e) +``` + +## Pull Requests + +### Step 1: Find something to work on + +If you want to contribute a specific feature or fix you have in mind, look at active [pull +requests](https://github.com/aws/aws-cdk/pulls) to see if someone else is already working on it. If not, you can start +contributing your changes. + +On the other hand, if you are here looking for an issue to work on, explore our [backlog of +issues](https://github.com/aws/aws-cdk/issues) and find something that piques your interest. We have labeled all of our +issues for easy filtration. +If you are looking for your first contribution, the ['good first issue' +label](https://github.com/aws/aws-cdk/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) will be of help. + +### Step 2: Design (optional) + +In some cases, it is useful to seek feedback by iterating on a design document. This is useful +when you plan a big change or feature, or you want advice on what would be the best path forward. + +In most cases, the GitHub issue is sufficient for such discussions, and can be sufficient to get +clarity on what you plan to do. If the changes are significant or intrusive to the existing CDK experience, +consider writing an RFC in our [RFC repository](https://github.com/aws/aws-cdk-rfcs) before jumping into our code base. ### Step 3: Work your Magic Work your magic. Here are some guidelines: -* Coding style (abbreviated): - * In general, follow the style of the code around you - * 2 space indentation - * 120 characters wide - * ATX style headings in markdown (e.g. `## H2 heading`) +* Coding style. + * If your change introduces a new construct, take a look at our [design guidelines](./docs/DESIGN_GUIDELINES.md) for + construct libraries. + We also have an [example construct library](packages/@aws-cdk/example-construct-library) that showcases a simple + construct library with a single construct. + * We have a number of linters that run during standard build that will enforce coding consistency and correctness. + Watch out for their error messages and adjust your code accordingly. * Every change requires a unit test * If you change APIs, make sure to update the module's README file * Try to maintain a single feature/bugfix per pull request. It's okay to introduce a little bit of housekeeping - changes along the way, but try to avoid conflating multiple features. Eventually, all these are going to go into a - single commit, so you can use that to frame your scope. -* If your change introduces a new construct, take a look at the our - [example Construct Library](packages/@aws-cdk/example-construct-library) for an explanation of the common patterns we use. - Feel free to start your contribution by copy&pasting files from that project, - and then edit and rename them as appropriate - - it might be easier to get started that way. -* If your change includes code examples (in the `README.md` file or as part of regular TSDoc tags), - you should probably validate those examples can be successfully compiled and trans-literated by - running `yarn rosetta:extract` (this requires other packages used by code examples are built). + changes along the way, but try to avoid conflating multiple features. Eventually, all these are going to go into a + single commit, so you can use that to frame your scope. #### Integration Tests @@ -189,17 +226,6 @@ Integration tests perform a few functions in the CDK code base - 3. (Optionally) Acts as a way to validate that constructs set up the CloudFormation resources as expected. A successful CloudFormation deployment does not mean that the resources are set up correctly. -For Gitpod users only! The best way to supply CDK with your AWS credentials is to add them as -[persisting environment variables](https://www.gitpod.io/docs/environment-variables). -Adding them works as follows via terminal: - -```shell -eval $(gp env -e AWS_ACCESS_KEY_ID=XXXXXXXXX) -eval $(gp env -e AWS_SECRET_ACCESS_KEY=YYYYYYY) -eval $(gp env -e AWS_DEFAULT_REGION=ZZZZZZZZ) -eval $(gp env -e) -``` - If you are working on a new feature that is using previously unused CloudFormation resource types, or involves configuring resource types across services, you need to write integration tests that use these resource types or features. @@ -220,6 +246,20 @@ Examples: * [integ.destinations.ts](https://github.com/aws/aws-cdk/blob/master/packages/%40aws-cdk/aws-lambda-destinations/test/integ.destinations.ts#L7) * [integ.token-authorizer.ts](https://github.com/aws/aws-cdk/blob/master/packages/%40aws-cdk/aws-apigateway/test/authorizers/integ.token-authorizer.ts#L6) +#### yarn watch (Optional) + +We've added a watch feature to the CDK that builds your code as you type it. Start this by running `yarn watch` for +each module that you are modifying. + +For example, watch the EC2 and IAM modules in a second terminal session: + +```console +$ cd packages/@aws-cdk/aws-ec2 +$ yarn watch & # runs in the background +$ cd packages/@aws-cdk/aws-iam +$ yarn watch & # runs in the background +``` + ### Step 4: Commit Create a commit with the proposed changes: @@ -250,21 +290,19 @@ BREAKING CHANGE: Description of what broke and how to achieve this behavior now ### Step 5: Pull Request -* Push to a GitHub fork or to a branch (naming convention: `/`). +* Push to a GitHub fork. + * CDK core members can push to a branch on the AWS CDK repo (naming convention: `/`). * Submit a Pull Request on GitHub. A reviewer will later be assigned by the maintainers. -* Please follow the PR checklist written below. We trust our contributors to self-check, and this helps that process! -* Discuss review comments and iterate until you get at least one “Approve”. When iterating, push new commits to the +* Discuss review comments and iterate until you get at least one "Approve". When iterating, push new commits to the same branch. Usually all these are going to be squashed when you merge to master. The commit messages should be hints for you when you finalize your merge commit message. * Make sure to update the PR title/description if things change. The PR title/description are going to be used as the commit title/message and will appear in the CHANGELOG, so maintain them all the way throughout the process. - - ### Step 6: Merge * Make sure your PR builds successfully (we have CodeBuild setup to automatically build all PRs). -* Once approved and tested, a maintainer will squash-merge to master and will use your PR title/description as the +* Once approved and tested, one of our bots will squash-merge to master and will use your PR title/description as the commit message. ## Breaking Changes @@ -275,13 +313,9 @@ programs that customers could have been writing against the current version of the CDK, that will no longer "work correctly" with the proposed new version of the CDK. -Breaking changes are not allowed in *stable* libraries¹. They are permissible -but still *highly discouraged* in experimental libraries, and require explicit -callouts in the bodies of Pull Requests that introduce them. - -> ¹) Note that starting in version 2 of the CDK, the majority of library code will be -> bundled into a single main CDK library which will be considered stable, and so -> no code in there can undergo breaking changes. +Breaking changes are not allowed in *stable* libraries. They are permitted +in experimental libraries, unless the maintainer of the module decides that it should be avoided. +Breaking changes require explicit callouts in the bodies of Pull Requests that introduce them. Breaking changes come in two flavors: @@ -327,8 +361,11 @@ $ yarn build $ yarn compat ``` -To figure out if the changes you made were breaking. See the section [API Compatibility -Checks](#api-compatibility-checks) for more information. +The only case where it is legitimate to break a public API is if the existing +API is a bug that blocked the usage of a feature. This means that by breaking +this API we will not break anyone, because they weren't able to use it. The file +`allowed-breaking-changes.txt` in the root of the repo is an exclusion file that +can be used in these cases. #### Dealing with breaking API surface changes @@ -404,57 +441,134 @@ If the new behavior is going to be breaking, the user must opt in to it, either Of these two, the first one is preferred if possible (as feature flags have non-local effects which can cause unintended effects). -## Tools +## Documentation + +Every module's README is rendered as the landing page of the official documentation. For example, this is +the README for the `aws-ec2` module - https://docs.aws.amazon.com/cdk/api/latest/docs/aws-ec2-readme.html. + +### Rosetta + +The README file contains code snippets written as typescript code. Code snippets typed in fenced code blocks +(such as `` ```ts ``) will be automatically extracted, compiled and translated to other languages when the +during the [pack](#pack) step. We call this feature 'rosetta'. -The CDK is a big project, and at the moment, all of the CDK modules are mastered in a single monolithic repository -(uses [lerna](https://github.com/lerna/lerna)). There are pros and cons to this approach, and it's especially valuable -to maintain integrity in the early stage of the project where things constantly change across the stack. In the future, -we believe many of these modules will be extracted to their own repositories. +You can run rosetta on the EC2 module (or any other module) by running: -Another complexity is that the CDK is packaged using [jsii](https://github.com/aws/jsii) to multiple programming -languages. This means that when a full build is complete, there will be a version of each module for each supported -language. +```console +$ cd packages/@aws-cdk/aws-ec2 +$ yarn rosetta:extract --strict +``` -However, in many cases, you can probably get away with just building a portion of the project, based on areas that you -want to work on. +To successfully do that, they must be compilable. The easiest way to do that is using +a *fixture*, which looks like this: -We recommend that you use [Visual Studio Code](https://code.visualstudio.com/) to work on the CDK. Be sure to install -the [eslint extension](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) for it as well, since we have -strict linting rules that will prevent your code from compiling, but with VSCode and this extension can be automatically -fixed for you by hitting `Ctrl-.` when your cursor is on a red underline. +```` +```ts fixture=with-bucket +bucket.addLifecycleTransition({ ...props }); +``` +```` -### Main build scripts +While processing the examples, the tool will look for a file called +`rosetta/with-bucket.ts-fixture` in the package directory. This file will be +treated as a regular TypeScript source file, but it must also contain the text +`/// here`, at which point the example will be inserted. The complete file must +compile properly. -The build process is divided into stages, so you can invoke them as needed from the root of the repo: +Before the `/// here` marker, the fixture should import the necessary packages +and initialize the required variables. -- __`yarn build`__: runs the `build` and `test` commands in all modules (in topological order). -- __`yarn pack`__: packages all modules to all supported languages and produces a `dist/` directory with all the outputs - (running this script requires that you installed the [toolchains](#getting-started) for all target languages on your - system). +When no fixture is specified, the fixture with the name +`rosetta/default.ts-fixture` will be used if present. `nofixture` can be used to +opt out of that behavior. -### Partial build tools +In an `@example` block, which is unfenced, the first line of the example can +contain three slashes to achieve the same effect: -There are also two useful scripts in the `scripts` directory that can help you build part of the repo: +``` +/** + * @example + * /// fixture=with-bucket + * bucket.addLifecycleTransition({ ...props }); + */ +``` -- __`scripts/buildup`__: builds the current module and all of its dependencies (in topological order). -- __`scripts/builddown`__: builds the current module and all of its consumers (in topological order). +For a practical example of how making sample code compilable works, see the +`aws-ec2` package. -### Useful aliases +#### Recommendations -You can also add a few useful aliases to your shell profile: +In order to offer a consistent documentation style throughout the AWS CDK +codebase, example code should follow the following recommendations (there may be +cases where some of those do not apply - good judgement is to be applied): -```bash -# runs an npm script via lerna for a the current module -alias lr='lerna run --stream --scope $(node -p "require(\"./package.json\").name")' +- Types from the documented module should be **un-qualified**: -# runs "yarn build" (build + test) for the current module -alias lb='lr build' -alias lt='lr test' + ```ts + // An example in the @aws-cdk/core library, which defines Duration + Duration.minutes(15); + ``` + +- Types from other modules should be **qualified**: -# runs "yarn watch" for the current module (recommended to run in a separate terminal session): -alias lw='lr watch' + ```ts + // An example in the @aws-cdk/core library, using something from @aws-cdk/aws-s3 + const bucket = new s3.Bucket(this, 'Bucket'); + // ...rest of the example... + ``` + +- Within `.ts-fixture` files, make use of `declare` statements instead of + writing a compatible value (this will make your fixtures more durable): + + ```ts + // An hypothetical 'rosetta/default.ts-fixture' file in `@aws-cdk/core` + import * as kms from '@aws-cdk/aws-kms'; + import * as s3 from '@aws-cdk/aws-s3'; + import { StackProps } from '@aws-cdk/core'; + + declare const kmsKey: kms.IKey; + declare const bucket: s3.Bucket; + + declare const props: StackProps; + ``` + +## Tools (Advanced) + +### scripts/foreach.sh + +This wonderful tool allows you to execute a command for all modules in this repo +in topological order, but has the incredible property of being stateful. This +means that if a command fails, you can fix the issue and resume from where you +left off. + +To start a session, run: + +```console +$ scripts/foreach.sh COMMAND +``` + +This will execute "COMMAND" for each module in the repo (cwd will be the directory of the module). +If a task fails, it will stop. To resume, simply run `foreach.sh` again (with or without the same command). + +To reset the session (either when all tasks finished or if you wish to run a different session), run: + +```console +$ scripts/foreach.sh --reset +``` + +If you wish to run a command only against a module's dependency closure, use: + +```console +$ cd packages/my-module +$ ../scripts/foreach.sh --up COMMAND ``` +This will execute `COMMAND` against `my-module` and all its deps (in a topological order, of course). + +Consequently, there are two useful scripts that are built on top of `foreach.sh`, and lets you build modules. + +- __`scripts/buildup`__: builds the current module and all of its dependencies (in topological order). +- __`scripts/builddown`__: builds the current module and all of its consumers (in topological order). + ### Linters All linters are executed automatically as part of the build script, `yarn build`. @@ -501,14 +615,14 @@ $ lr pkglint **awslint** is a linter for the AWS Construct Library APIs. It is executed as a part of the build of all AWS modules in the project and enforces the [AWS -Construct Library Design Guidelines](./DESIGN_GUIDELINES.md). +Construct Library Design Guidelines](./docs/DESIGN_GUIDELINES.md). For more information about this tool, see the [awslint README](./packages/awslint/README.md). Generally speaking, if you make any changes which violate an awslint rule, build will fail with appropriate messages. All rules are documented and explained in -the [guidelines](./DESIGN_GUIDELINES.md). +the [guidelines](./docs/DESIGN_GUIDELINES.md). Here are a few useful commands: @@ -520,31 +634,6 @@ Here are a few useful commands: evaluate only the rule specified [awslint README](./packages/awslint/README.md) for details on include/exclude rule patterns. - -#### jsii-rosetta - -**jsii-rosetta** can be used to verify that all code examples included in documentation for a package (including those -in `README.md`) successfully compile against the library they document. It is recommended to run it to ensure all -examples are still accurate. Successfully building examples is also necessary to ensure the best possible translation to -other supported languages (`C#`, `Java`, `Python`, ...). - -> Note that examples may use libraries that are not part of the `dependencies` or `devDependencies` of the documented -> package. For example, `@aws-cdk/core` contains many examples that leverage libraries built *on top of it* (such as -> `@aws-cdk/aws-sns`). Such libraries must be built (using `yarn build`) before **jsii-rosetta** can verify that -> examples are correct. - -To run **jsii-rosetta** in *strict* mode (so that it always fails when encountering examples that fail to compile), use -the following command: - -```console -$ yarn rosetta:extract --strict -``` - -For more information on how you can address examples that fail compiling due to missing fixtures (declarations that are -necessary for the example to compile, but which would distract the reader away from what is being demonstrated), you -might need to introduce [rosetta fixtures](https://github.com/aws/jsii/tree/main/packages/jsii-rosetta#fixtures). Refer -to the [Examples](#examples) section. - ### cfn2ts This tool is used to generate our low-level CloudFormation resources @@ -561,37 +650,6 @@ Each module also has an npm script called `cfn2ts`: * `yarn cfn2ts`: generates L1 for a specific module * `lerna run cfn2ts`: generates L1 for the entire repo -### scripts/foreach.sh - -This wonderful tool allows you to execute a command for all modules in this repo -in topological order, but has the incredible property of being stateful. This -means that if a command fails, you can fix the issue and resume from where you -left off. - -To start a session, run: - -```console -$ scripts/foreach.sh COMMAND -``` - -This will execute "COMMAND" for each module in the repo (cwd will be the directory of the module). -If a task fails, it will stop. To resume, simply run `foreach.sh` again (with or without the same command). - -To reset the session (either when all tasks finished or if you wish to run a different session), run: - -```console -$ scripts/foreach.sh --reset -``` - -If you wish to run a command only against a module's dependency closure, use: - -```console -$ cd packages/my-module -$ ../scripts/foreach.sh --up COMMAND -``` - -This will execute `COMMAND` against `my-module` and all its deps (in a topological order, of course). - ### Jetbrains support (WebStorm/IntelliJ) This project uses lerna and utilizes symlinks inside nested `node_modules` directories. You may encounter an issue during @@ -599,146 +657,19 @@ indexing where the IDE attempts to index these directories and keeps following l available memory and crashes. To fix this, you can run ```node ./scripts/jetbrains-remove-node-modules.js``` to exclude these directories. -## Workflows - -This section includes step-by-step descriptions of common workflows. - -### Full clean build - -Clone the repo: - -```console -$ git clone https://github.com/aws/aws-cdk.git -$ cd aws-cdk -``` - -If you already have a local repo and you want a fresh build, run `git clean -fdx` from the root. - -Install and build: - -```console -$ ./install.sh -$ yarn build -``` - -If you also wish to package to all languages, make sure you have all the [toolchains](#getting-started) and now run: - -``` -$ ./pack.sh -``` - -> NOTE: in local builds, pack.sh will finish but will fail with an error -> indicating the build artifacts use the marker version (`0.0.0`). This is -> normal, and you can trust the output in `dist/` despite the failure. This is a -> protection we have to make sure we don't accidentally release artifacts with -> the marker version. - -### Full Docker build - -Clone the repo: - -```console -$ git clone https://github.com/aws/aws-cdk.git -$ cd aws-cdk -``` - -If you already have a local repo and you want a fresh build, run `git clean -fdx` from the root. - -Build the docker image: - -```console -$ docker build -t aws-cdk . -``` - -This allows you to run the CDK in a CDK-compatible directory with a command like: - -```console -$ docker run -v $(pwd):/app -w /app aws-cdk -``` - -### Partial build - -In many cases, you don't really need to build the entire project. Say you want to work on the `@aws-cdk/aws-ec2` module: - -```console -$ yarn install -$ cd packages/@aws-cdk/aws-ec2 -$ ../../../scripts/buildup -``` - -Note that `buildup` uses `foreach.sh`, which means it is resumable. If your build fails and you wish to resume, just run -`buildup --resume`. If you wish to restart, run `buildup` again. - -### Partial pack - -Packing involves generating CDK code in the various target languages and packaging them up to be published to their -respective package managers. Once in a while, these will need to be generated either to test the experience of a new -feature, or reproduce a packaging failure. - -Before running this, make sure either that the CDK module and all of its dependencies are already built. See [Partial -build](#partial-build) or [Full clean build](#full-clean-build). - -To package a specific module, say the `@aws-cdk/aws-ec2` module: - -```console -$ cd -$ docker run --rm --net=host -it -v $PWD:$PWD -w $PWD jsii/superchain -docker$ cd packages/@aws-cdk/aws-ec2 -docker$ ../../../scripts/foreach.sh --up yarn run package -docker$ exit -``` - -The `dist/` folder within each module contains the packaged up language artifacts. - -### Quick Iteration - -After you've built the modules you want to work on once, use `yarn watch` for each module that you are modifying. - -Watch the EC2 and IAM modules in a second terminal session: - -```console -$ cd packages/@aws-cdk/aws-ec2 -$ yarn watch & # runs in the background -$ cd packages/@aws-cdk/aws-iam -$ yarn watch & # runs in the background -``` - -Code... - -Now to test, you can either use `yarn test` or invoke nodeunit/jest directly: - -Running nodeunit tests directly on a module: -```console -$ cd packages/@aws-cdk/aws-iam -$ nodeunit test/test.*.js - -``` - -Running jest tests directly on a module: -```console -$ cd packages/@aws-cdk/aws-iam -$ jest test/*test.js - -``` - ### Linking against this repository -The script `./link-all.sh` can be used to generate symlinks to all modules in this repository under some `node_module` -directory. This can be used to develop against this repo as a local dependency. +If you are developing your own CDK application or library and want to use the locally checked out version of the +AWS CDK, instead of the the version of npm, the `./link-all.sh` script will help here. -One can use the `postinstall` script to symlink this repo: +This script symlinks the built modules from the local AWS CDK repo under the `node_modules/` folder of the CDK app or +library. -```json -{ - "scripts": { - "postinstall": "../aws-cdk/link-all.sh" - } -} +```console +$ cd +$ /link-all.sh ``` -This assumes this repo is a sibling of the target repo and will install the CDK as a linked dependency during -`yarn install`. - ### Running integration tests in parallel Integration tests may take a long time to complete. We can speed this up by running them in parallel @@ -760,23 +691,7 @@ Use GraphViz with `template-deps-to-dot`: $ cdk -a some.app.js synth | $awscdk/scripts/template-deps-to-dot | dot -Tpng > deps.png ``` -### Adding Dependencies - -The root [package.json](./package.json) includes global devDependencies (see -[lerna docs](https://github.com/lerna/lerna#common-devdependencies)) on the topic. - - * To add a global dependency, run `yarn add --dev` at the root. - * To add a dependency for a specific module, run `yarn add ` inside the module's directory. - -Guidelines: - - * We cannot accept dependencies that use non-permissive open source licenses (Apache, MIT, etc). - * Make sure dependencies are defined using [caret - ranges](https://docs.npmjs.com/misc/semver#caret-ranges-123-025-004) (e.g. `^1.2.3`). This enables non-breaking - updates to automatically be picked up. - * Make sure `yarn.lock` is included in your commit. - -### Finding dependency cycles between packages +### Find dependency cycles between packages You can use `find-cycles` to print a list of internal dependency cycles: @@ -792,159 +707,19 @@ Cycle: @aws-cdk/aws-sns => @aws-cdk/aws-lambda => @aws-cdk/aws-codecommit => @aw Cycle: @aws-cdk/aws-sns => @aws-cdk/aws-lambda => @aws-cdk/aws-codecommit => @aws-cdk/aws-codepipeline => @aws-cdk/aws-sns ``` -### Updating all Dependencies - -To update all dependencies (without bumping major versions): - -1. Obtain a fresh clone from "master". -2. Run `yarn install` -3. Run `./scripts/update-dependencies.sh --mode full` (use `--mode semver` to avoid bumping major versions) -4. Submit a Pull Request. - -### Running CLI integration tests +## Running CLI integration tests The CLI package (`packages/aws-cdk`) has some integration tests that aren't run as part of the regular build, since they have some particular requirements. See the [CLI CONTRIBUTING.md file](packages/aws-cdk/CONTRIBUTING.md) for more information on running those tests. -### Changing Cloud Assembly Schema +## Changing Cloud Assembly Schema If you plan on making changes to the `cloud-assembly-schema` package, make sure you familiarize yourself with its own [contribution guide](./packages/@aws-cdk/cloud-assembly-schema/CONTRIBUTING.md) -### API Compatibility Checks - -All stable APIs in the CDK go through a compatibility check during build using -the [jsii-diff] tool. This tool downloads the latest released version from npm -and verifies that the APIs in the current build have not changed in a breaking -way. - -[jsii-diff]: https://www.npmjs.com/package/jsii-diff - -Compatibility checks always run as part of a full build (`yarn build`). - -You can use `yarn compat` to run compatibility checks for all modules: - -```shell -(working directory is repo root) -$ yarn build -$ yarn compat -``` - -You can also run `compat` from individual package directories: - -```shell -$ cd packages/@aws-cdk/aws-sns -$ yarn build -$ yarn compat -``` - -The only case where it is legitimate to break a public API is if the existing -API is a bug that blocked the usage of a feature. This means that by breaking -this API we will not break anyone, because they weren't able to use it. The file -`allowed-breaking-changes.txt` in the root of the repo is an exclusion file that -can be used in these cases. - -### Examples - -#### Fixture Files - -Examples typed in fenced code blocks (looking like `'''ts`, but then with backticks -instead of regular quotes) will be automatically extracted, compiled and translated -to other languages when the bindings are generated. - -To successfully do that, they must be compilable. The easiest way to do that is using -a *fixture*, which looks like this: - -``` -'''ts fixture=with-bucket -bucket.addLifecycleTransition({ ...props }); -''' -``` - -While processing the examples, the tool will look for a file called -`rosetta/with-bucket.ts-fixture` in the package directory. This file will be -treated as a regular TypeScript source file, but it must also contain the text -`/// here`, at which point the example will be inserted. The complete file must -compile properly. - -Before the `/// here` marker, the fixture should import the necessary packages -and initialize the required variables. - -If no fixture is specified, the fixture with the name -`rosetta/default.ts-fixture` will be used if present. `nofixture` can be used to -opt out of that behavior. - -In an `@example` block, which is unfenced, the first line of the example can -contain three slashes to achieve the same effect: - -``` -/** - * @example - * /// fixture=with-bucket - * bucket.addLifecycleTransition({ ...props }); - */ -``` - -When including packages in your examples (even the package you're writing the -examples for), use the full package name (e.g. `import s3 = -require('@aws-cdk/aws-s3);`). The example will be compiled in an environment -where all CDK packages are available using their public names. In this way, -it's also possible to import packages that are not in the dependency set of -the current package. - -For a practical example of how making sample code compilable works, see the -`aws-ec2` package. - -#### Recommendations - -In order to offer a consistent documentation style throughout the AWS CDK -codebase, example code should follow the following recommendations (there may be -cases where some of those do not apply - good judgement is to be applied): - -- Types from the documented module should be **un-qualified**: - - ```ts - // An example in the @aws-cdk/core library, which defines Duration - Duration.minutes(15); - ``` - -- Types from other modules should be **qualified**: - - ```ts - // An example in the @aws-cdk/core library, using something from @aws-cdk/aws-s3 - const bucket = new s3.Bucket(this, 'Bucket'); - // ...rest of the example... - ``` - -- Within `.ts-fixture` files, make use of `declare` statements instead of - writing a compatible value (this will make your fixtures more durable): - - ```ts - // An hypothetical 'rosetta/default.ts-fixture' file in `@aws-cdk/core` - import * as kms from '@aws-cdk/aws-kms'; - import * as s3 from '@aws-cdk/aws-s3'; - import { StackProps } from '@aws-cdk/core'; - - declare const kmsKey: kms.IKey; - declare const bucket: s3.Bucket; - - declare const props: StackProps; - ``` - -> Those recommendations are not verified or enforced by automated tooling. Pull -> request reviewers may however request that new sample code is edited to meet -> those requirements as needed. - -#### Checking a single package - -Examples of all packages are extracted and compiled as part of the packaging -step. If you are working on getting rid of example compilation errors of a -single package, you can run `yarn rosetta:extract --strict` in the package's -directory (see the [**jsii-rosetta**](#jsii-rosetta) section). - -### Feature Flags +## Feature Flags Sometimes we want to introduce new breaking behavior because we believe this is the correct default behavior for the CDK. The problem of course is that breaking @@ -987,7 +762,7 @@ CDK](https://github.com/aws/aws-cdk/issues/3398) we will either remove the legacy behavior or flip the logic for all these features and then reset the `FEATURE_FLAGS` map for the next cycle. -#### CDKv2 +### Feature Flags - CDKv2 We have started working on the next version of the CDK, specifically CDKv2. This is currently being maintained on a separate branch `v2-main` whereas `master` continues to track versions `1.x`. @@ -1003,59 +778,10 @@ behaviour when flags are enabled or disabled in the two major versions. [jest helper methods]: https://github.com/aws/aws-cdk/blob/master/tools/cdk-build-tools/lib/feature-flag.ts -### Versioning and Release - -The `release.json` file at the root of the repo determines which release line -this branch belongs to. - -```js -{ - "majorVersion": 1 | 2, - "releaseType": "stable" | "alpha" | "rc" -} -``` - -To reduce merge conflicts in automatic merges between version branches, the -current version number is stored under `version.vNN.json` (where `NN` is -`majorVersion`) and changelogs are stored under `CHANGELOG.NN.md` (for -historical reasons, the changelog for 1.x is under `CHANGELOG.md`). When we -fork to a new release branch (e.g. `v2-main`), we will update `release.json` in -this branch to reflect the new version line, and this information will be used -to determine how releases are cut. - -The actual `version` field in all `package.json` files should always be `0.0.0`. -This means that local development builds will use version `0.0.0` instead of the -official version from the version file. - -#### `./bump.sh` - -This script uses [standard-version] to update the version in `version.vNN.json` -to the next version. By default it will perform a **minor** bump, but `./bump.sh -patch` can be used to perform a patch release if that's needed. - -This script will also update the relevant changelog file. - -[standard-version]: https://github.com/conventional-changelog/standard-version - -#### `scripts/resolve-version.js` - -The script evaluates evaluates the configuration in `release.json` and exports an -object like this: - -```js -{ - version: '2.0.0-alpha.1', // the current version - versionFile: 'version.v2.json', // the version file - changelogFile: 'CHANGELOG.v2.md', // changelog file name - prerelease: 'alpha', // prerelease tag (undefined for stable) - marker: '0.0.0' // version marker in package.json files -} -``` - -#### scripts/align-version.sh +## Versioning and Release -In official builds, the `scripts/align-version.sh` is used to update all -`package.json` files based on the version from `version.vNN.json`. +See [release.md](./docs/release.md) for details on how CDK versions are maintained and how +to trigger a new release ## Troubleshooting diff --git a/DESIGN_GUIDELINES.md b/docs/DESIGN_GUIDELINES.md similarity index 100% rename from DESIGN_GUIDELINES.md rename to docs/DESIGN_GUIDELINES.md diff --git a/docs/release.md b/docs/release.md new file mode 100644 index 0000000000000..f7f5f9612ea23 --- /dev/null +++ b/docs/release.md @@ -0,0 +1,53 @@ +# Versioning and Release + +The `release.json` file at the root of the repo determines which release line +this branch belongs to. + +```js +{ + "majorVersion": 1 | 2, + "releaseType": "stable" | "alpha" | "rc" +} +``` + +To reduce merge conflicts in automatic merges between version branches, the +current version number is stored under `version.vNN.json` (where `NN` is +`majorVersion`) and changelogs are stored under `CHANGELOG.NN.md` (for +historical reasons, the changelog for 1.x is under `CHANGELOG.md`). When we +fork to a new release branch (e.g. `v2-main`), we will update `release.json` in +this branch to reflect the new version line, and this information will be used +to determine how releases are cut. + +The actual `version` field in all `package.json` files should always be `0.0.0`. +This means that local development builds will use version `0.0.0` instead of the +official version from the version file. + +## `./bump.sh` + +This script uses [standard-version] to update the version in `version.vNN.json` +to the next version. By default it will perform a **minor** bump, but `./bump.sh +patch` can be used to perform a patch release if that's needed. + +This script will also update the relevant changelog file. + +[standard-version]: https://github.com/conventional-changelog/standard-version + +## `scripts/resolve-version.js` + +The script evaluates evaluates the configuration in `release.json` and exports an +object like this: + +```js +{ + version: '2.0.0-alpha.1', // the current version + versionFile: 'version.v2.json', // the version file + changelogFile: 'CHANGELOG.v2.md', // changelog file name + prerelease: 'alpha', // prerelease tag (undefined for stable) + marker: '0.0.0' // version marker in package.json files +} +``` + +## scripts/align-version.sh + +In official builds, the `scripts/align-version.sh` is used to update all +`package.json` files based on the version from `version.vNN.json`. \ No newline at end of file diff --git a/package.json b/package.json index 6ddae6c7ad5d5..f82766ba1d48f 100644 --- a/package.json +++ b/package.json @@ -18,9 +18,9 @@ "fs-extra": "^9.1.0", "graceful-fs": "^4.2.6", "jest-junit": "^12.0.0", - "jsii-diff": "^1.24.0", - "jsii-pacmak": "^1.24.0", - "jsii-rosetta": "^1.24.0", + "jsii-diff": "^1.25.0", + "jsii-pacmak": "^1.25.0", + "jsii-rosetta": "^1.25.0", "lerna": "^3.22.1", "standard-version": "^9.1.1", "typescript": "~3.9.9" diff --git a/packages/@aws-cdk/app-delivery/package.json b/packages/@aws-cdk/app-delivery/package.json index 8ac9e9cae6a12..de59545369bfd 100644 --- a/packages/@aws-cdk/app-delivery/package.json +++ b/packages/@aws-cdk/app-delivery/package.json @@ -63,7 +63,7 @@ "@types/nodeunit": "^0.0.31", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", - "fast-check": "^2.13.0", + "fast-check": "^2.14.0", "nodeunit": "^0.11.3", "pkglint": "0.0.0" }, diff --git a/packages/@aws-cdk/assert/package.json b/packages/@aws-cdk/assert/package.json index 95d88e937b9d0..47152419720c9 100644 --- a/packages/@aws-cdk/assert/package.json +++ b/packages/@aws-cdk/assert/package.json @@ -25,7 +25,7 @@ "cdk-build-tools": "0.0.0", "jest": "^26.6.3", "pkglint": "0.0.0", - "ts-jest": "^26.5.3" + "ts-jest": "^26.5.4" }, "dependencies": { "@aws-cdk/cloud-assembly-schema": "0.0.0", diff --git a/packages/@aws-cdk/assets/package.json b/packages/@aws-cdk/assets/package.json index 45735a4da140f..b19a88d4a9c12 100644 --- a/packages/@aws-cdk/assets/package.json +++ b/packages/@aws-cdk/assets/package.json @@ -69,7 +69,7 @@ "devDependencies": { "@aws-cdk/assert": "0.0.0", "@types/nodeunit": "^0.0.31", - "@types/sinon": "^9.0.10", + "@types/sinon": "^9.0.11", "aws-cdk": "0.0.0", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", diff --git a/packages/@aws-cdk/aws-apigatewayv2-authorizers/README.md b/packages/@aws-cdk/aws-apigatewayv2-authorizers/README.md index 9591ecfe4ffde..ae44e5e5d97fc 100644 --- a/packages/@aws-cdk/aws-apigatewayv2-authorizers/README.md +++ b/packages/@aws-cdk/aws-apigatewayv2-authorizers/README.md @@ -1,4 +1,5 @@ # AWS APIGatewayv2 Authorizers + --- @@ -17,24 +18,105 @@ ## Table of Contents +- [Introduction](#introduction) - [HTTP APIs](#http-apis) + - [Default Authorization](#default-authorization) + - [Route Authorization](#route-authorization) - [JWT Authorizers](#jwt-authorizers) - [User Pool Authorizer](#user-pool-authorizer) -## HTTP APIs +## Introduction API Gateway supports multiple mechanisms for controlling and managing access to your HTTP API. They are mainly classified into Lambda Authorizers, JWT authorizers and standard AWS IAM roles and policies. More information is available at [Controlling and managing access to an HTTP API](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-access-control.html). +## HTTP APIs + +Access control for Http Apis is managed by restricting which routes can be invoked via. + +Authorizers, and scopes can either be applied to the api, or specifically for each route. + +### Default Authorization + +When using default authorization, all routes of the api will inherit the configuration. + +In the example below, all routes will require the `manage:books` scope present in order to invoke the integration. + +```ts +const authorizer = new HttpJwtAuthorizer({ + ... +}); + +const api = new HttpApi(stack, 'HttpApi', { + defaultAuthorizer: authorizer, + defaultAuthorizationScopes: ['manage:books'], +}); +``` + +### Route Authorization + +Authorization can also configured for each Route. When a route authorization is configured, it takes precedence over default authorization. + +The example below showcases default authorization, along with route authorization. It also shows how to remove authorization entirely for a route. + +- `GET /books` and `GET /books/{id}` use the default authorizer settings on the api +- `POST /books` will require the [write:books] scope +- `POST /login` removes the default authorizer (unauthenticated route) + +```ts +const authorizer = new HttpJwtAuthorizer({ + ... +}); + +const api = new HttpApi(stack, 'HttpApi', { + defaultAuthorizer: authorizer, + defaultAuthorizationScopes: ['read:books'], +}); + +api.addRoutes({ + ... + path: '/books', + method: 'get', +}); + +api.addRoutes({ + ... + path: '/books/{id}', + method: 'get', +}); + +api.addRoutes({ + ... + path: '/books', + method: 'post', + authorizationScopes: ['write:books'] +}); + +api.addRoutes({ + ... + path: '/login', + method: 'post', + authorizer: new NoneAuthorizer(), +}); +``` + ## JWT Authorizers JWT authorizers allow the use of JSON Web Tokens (JWTs) as part of [OpenID Connect](https://openid.net/specs/openid-connect-core-1_0.html) and [OAuth 2.0](https://oauth.net/2/) frameworks to allow and restrict clients from accessing HTTP APIs. -When configured on a route, the API Gateway service validates the JWTs submitted by the client, and allows or denies access based on its content. +When configured, API Gateway validates the JWT submitted by the client, and allows or denies access based on its content. + +The location of the token is defined by the `identitySource` which defaults to the http `Authorization` header. However it also +[supports a number of other options](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-lambda-authorizer.html#http-api-lambda-authorizer.identity-sources). +It then decodes the JWT and validates the signature and claims, against the options defined in the authorizer and route (scopes). +For more information check the [JWT Authorizer documentation](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-jwt-authorizer.html). + +Clients that fail authorization are presented with either 2 responses: -API gateway uses the `identitySource` to determine where to look for the token. By default it checks the http `Authorization` header. However it also [supports a number of other options](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-lambda-authorizer.html#http-api-lambda-authorizer.identity-sources). It then decodes the JWT and validates the signature and claims, against the options defined in the authorizer and route (scopes). For more information check the [JWT Authorizer documentation](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-jwt-authorizer.html). +- `401 - Unauthorized` - When the JWT validation fails +- `403 - Forbidden` - When the JWT validation is successful but the required scopes are not met ```ts const authorizer = new HttpJwtAuthorizer({ @@ -58,7 +140,7 @@ api.addRoutes({ User Pool Authorizer is a type of JWT Authorizer that uses a Cognito user pool and app client to control who can access your Api. After a successful authorization from the app client, the generated access token will be used as the JWT. Clients accessing an API that uses a user pool authorizer must first sign in to a user pool and obtain an identity or access token. -They must then use this token in the `Authorization` header of the API call. More information is available at [using Amazon Cognito user +They must then use this token in the specified `identitySource` for the API call. More information is available at [using Amazon Cognito user pools as authorizer](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-integrate-with-cognito.html). ```ts diff --git a/packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/integ.user-pool.expected.json b/packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/integ.user-pool.expected.json index 17e2ae9976378..c3ddc2fbc6e94 100644 --- a/packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/integ.user-pool.expected.json +++ b/packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/integ.user-pool.expected.json @@ -54,6 +54,22 @@ } } }, + "MyHttpApiGETHttpIntegration6f095b8469365f72e33fa33d9711b140516EBE31": { + "Type": "AWS::ApiGatewayV2::Integration", + "Properties": { + "ApiId": { + "Ref": "MyHttpApi8AEAAC21" + }, + "IntegrationType": "AWS_PROXY", + "IntegrationUri": { + "Fn::GetAtt": [ + "lambda8B5974B5", + "Arn" + ] + }, + "PayloadFormatVersion": "2.0" + } + }, "MyHttpApiGETE0EFC6F8": { "Type": "AWS::ApiGatewayV2::Route", "Properties": { @@ -61,7 +77,6 @@ "Ref": "MyHttpApi8AEAAC21" }, "RouteKey": "GET /", - "AuthorizationScopes": [], "AuthorizationType": "JWT", "AuthorizerId": { "Ref": "MyHttpApiUserPoolAuthorizer8754262B" @@ -79,22 +94,6 @@ } } }, - "MyHttpApiGETHttpIntegration6f095b8469365f72e33fa33d9711b140516EBE31": { - "Type": "AWS::ApiGatewayV2::Integration", - "Properties": { - "ApiId": { - "Ref": "MyHttpApi8AEAAC21" - }, - "IntegrationType": "AWS_PROXY", - "IntegrationUri": { - "Fn::GetAtt": [ - "lambda8B5974B5", - "Arn" - ] - }, - "PayloadFormatVersion": "2.0" - } - }, "MyHttpApiUserPoolAuthorizer8754262B": { "Type": "AWS::ApiGatewayV2::Authorizer", "Properties": { diff --git a/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/integ.alb.expected.json b/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/integ.alb.expected.json index e0ffbc32a3349..ae65d49847d54 100644 --- a/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/integ.alb.expected.json +++ b/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/integ.alb.expected.json @@ -608,6 +608,24 @@ "ProtocolType": "HTTP" } }, + "HttpProxyPrivateApiDefaultRouteHttpIntegration1a580b19954e4317026ffbce1f7d5ade7A32685B": { + "Type": "AWS::ApiGatewayV2::Integration", + "Properties": { + "ApiId": { + "Ref": "HttpProxyPrivateApiA55E154D" + }, + "IntegrationType": "HTTP_PROXY", + "ConnectionId": { + "Ref": "HttpProxyPrivateApiVpcLink190366CAE" + }, + "ConnectionType": "VPC_LINK", + "IntegrationMethod": "ANY", + "IntegrationUri": { + "Ref": "lblistener657ADDEC" + }, + "PayloadFormatVersion": "1.0" + } + }, "HttpProxyPrivateApiDefaultRoute1BDCA252": { "Type": "AWS::ApiGatewayV2::Route", "Properties": { @@ -615,7 +633,6 @@ "Ref": "HttpProxyPrivateApiA55E154D" }, "RouteKey": "$default", - "AuthorizationScopes": [], "Target": { "Fn::Join": [ "", @@ -647,24 +664,6 @@ "SecurityGroupIds": [] } }, - "HttpProxyPrivateApiDefaultRouteHttpIntegration1a580b19954e4317026ffbce1f7d5ade7A32685B": { - "Type": "AWS::ApiGatewayV2::Integration", - "Properties": { - "ApiId": { - "Ref": "HttpProxyPrivateApiA55E154D" - }, - "IntegrationType": "HTTP_PROXY", - "ConnectionId": { - "Ref": "HttpProxyPrivateApiVpcLink190366CAE" - }, - "ConnectionType": "VPC_LINK", - "IntegrationMethod": "ANY", - "IntegrationUri": { - "Ref": "lblistener657ADDEC" - }, - "PayloadFormatVersion": "1.0" - } - }, "HttpProxyPrivateApiDefaultStage18B3706E": { "Type": "AWS::ApiGatewayV2::Stage", "Properties": { diff --git a/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/integ.http-proxy.expected.json b/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/integ.http-proxy.expected.json index e5220fe2959b7..378e7b2395f03 100644 --- a/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/integ.http-proxy.expected.json +++ b/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/integ.http-proxy.expected.json @@ -94,6 +94,22 @@ } } }, + "LambdaProxyApiDefaultRouteHttpIntegration70df0ec52c3e3b6bbc96e64ce3a05f24EE575CBA": { + "Type": "AWS::ApiGatewayV2::Integration", + "Properties": { + "ApiId": { + "Ref": "LambdaProxyApi67594471" + }, + "IntegrationType": "AWS_PROXY", + "IntegrationUri": { + "Fn::GetAtt": [ + "AlwaysSuccess099EAB05", + "Arn" + ] + }, + "PayloadFormatVersion": "2.0" + } + }, "LambdaProxyApiDefaultRoute1EB30A46": { "Type": "AWS::ApiGatewayV2::Route", "Properties": { @@ -101,7 +117,6 @@ "Ref": "LambdaProxyApi67594471" }, "RouteKey": "$default", - "AuthorizationScopes": [], "Target": { "Fn::Join": [ "", @@ -115,22 +130,6 @@ } } }, - "LambdaProxyApiDefaultRouteHttpIntegration70df0ec52c3e3b6bbc96e64ce3a05f24EE575CBA": { - "Type": "AWS::ApiGatewayV2::Integration", - "Properties": { - "ApiId": { - "Ref": "LambdaProxyApi67594471" - }, - "IntegrationType": "AWS_PROXY", - "IntegrationUri": { - "Fn::GetAtt": [ - "AlwaysSuccess099EAB05", - "Arn" - ] - }, - "PayloadFormatVersion": "2.0" - } - }, "LambdaProxyApiDefaultStage07C38681": { "Type": "AWS::ApiGatewayV2::Stage", "Properties": { @@ -148,27 +147,6 @@ "ProtocolType": "HTTP" } }, - "HttpProxyApiDefaultRoute8AF66B5C": { - "Type": "AWS::ApiGatewayV2::Route", - "Properties": { - "ApiId": { - "Ref": "HttpProxyApiD0217C67" - }, - "RouteKey": "$default", - "AuthorizationScopes": [], - "Target": { - "Fn::Join": [ - "", - [ - "integrations/", - { - "Ref": "HttpProxyApiDefaultRouteHttpIntegration8eeecf9ecdb91f31bebf6bd54fb711a41921AB82" - } - ] - ] - } - } - }, "HttpProxyApiDefaultRouteHttpIntegration8eeecf9ecdb91f31bebf6bd54fb711a41921AB82": { "Type": "AWS::ApiGatewayV2::Integration", "Properties": { @@ -200,6 +178,26 @@ "PayloadFormatVersion": "1.0" } }, + "HttpProxyApiDefaultRoute8AF66B5C": { + "Type": "AWS::ApiGatewayV2::Route", + "Properties": { + "ApiId": { + "Ref": "HttpProxyApiD0217C67" + }, + "RouteKey": "$default", + "Target": { + "Fn::Join": [ + "", + [ + "integrations/", + { + "Ref": "HttpProxyApiDefaultRouteHttpIntegration8eeecf9ecdb91f31bebf6bd54fb711a41921AB82" + } + ] + ] + } + } + }, "HttpProxyApiDefaultStageA88F9DE3": { "Type": "AWS::ApiGatewayV2::Stage", "Properties": { diff --git a/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/integ.lambda-proxy.expected.json b/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/integ.lambda-proxy.expected.json index f5bc444d929c3..58e37b0f64e0a 100644 --- a/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/integ.lambda-proxy.expected.json +++ b/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/integ.lambda-proxy.expected.json @@ -94,6 +94,22 @@ } } }, + "LambdaProxyApiDefaultRouteHttpIntegration70df0ec52c3e3b6bbc96e64ce3a05f24EE575CBA": { + "Type": "AWS::ApiGatewayV2::Integration", + "Properties": { + "ApiId": { + "Ref": "LambdaProxyApi67594471" + }, + "IntegrationType": "AWS_PROXY", + "IntegrationUri": { + "Fn::GetAtt": [ + "AlwaysSuccess099EAB05", + "Arn" + ] + }, + "PayloadFormatVersion": "2.0" + } + }, "LambdaProxyApiDefaultRoute1EB30A46": { "Type": "AWS::ApiGatewayV2::Route", "Properties": { @@ -101,7 +117,6 @@ "Ref": "LambdaProxyApi67594471" }, "RouteKey": "$default", - "AuthorizationScopes": [], "Target": { "Fn::Join": [ "", @@ -115,22 +130,6 @@ } } }, - "LambdaProxyApiDefaultRouteHttpIntegration70df0ec52c3e3b6bbc96e64ce3a05f24EE575CBA": { - "Type": "AWS::ApiGatewayV2::Integration", - "Properties": { - "ApiId": { - "Ref": "LambdaProxyApi67594471" - }, - "IntegrationType": "AWS_PROXY", - "IntegrationUri": { - "Fn::GetAtt": [ - "AlwaysSuccess099EAB05", - "Arn" - ] - }, - "PayloadFormatVersion": "2.0" - } - }, "LambdaProxyApiDefaultStage07C38681": { "Type": "AWS::ApiGatewayV2::Stage", "Properties": { diff --git a/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/integ.nlb.expected.json b/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/integ.nlb.expected.json index 0446031c61a19..aed54a5a8395c 100644 --- a/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/integ.nlb.expected.json +++ b/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/integ.nlb.expected.json @@ -573,6 +573,24 @@ "ProtocolType": "HTTP" } }, + "HttpProxyPrivateApiDefaultRouteHttpIntegration1a580b19954e4317026ffbce1f7d5ade7A32685B": { + "Type": "AWS::ApiGatewayV2::Integration", + "Properties": { + "ApiId": { + "Ref": "HttpProxyPrivateApiA55E154D" + }, + "IntegrationType": "HTTP_PROXY", + "ConnectionId": { + "Ref": "HttpProxyPrivateApiVpcLink190366CAE" + }, + "ConnectionType": "VPC_LINK", + "IntegrationMethod": "ANY", + "IntegrationUri": { + "Ref": "lblistener657ADDEC" + }, + "PayloadFormatVersion": "1.0" + } + }, "HttpProxyPrivateApiDefaultRoute1BDCA252": { "Type": "AWS::ApiGatewayV2::Route", "Properties": { @@ -580,7 +598,6 @@ "Ref": "HttpProxyPrivateApiA55E154D" }, "RouteKey": "$default", - "AuthorizationScopes": [], "Target": { "Fn::Join": [ "", @@ -612,24 +629,6 @@ "SecurityGroupIds": [] } }, - "HttpProxyPrivateApiDefaultRouteHttpIntegration1a580b19954e4317026ffbce1f7d5ade7A32685B": { - "Type": "AWS::ApiGatewayV2::Integration", - "Properties": { - "ApiId": { - "Ref": "HttpProxyPrivateApiA55E154D" - }, - "IntegrationType": "HTTP_PROXY", - "ConnectionId": { - "Ref": "HttpProxyPrivateApiVpcLink190366CAE" - }, - "ConnectionType": "VPC_LINK", - "IntegrationMethod": "ANY", - "IntegrationUri": { - "Ref": "lblistener657ADDEC" - }, - "PayloadFormatVersion": "1.0" - } - }, "HttpProxyPrivateApiDefaultStage18B3706E": { "Type": "AWS::ApiGatewayV2::Stage", "Properties": { diff --git a/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/integ.service-discovery.expected.json b/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/integ.service-discovery.expected.json index 28b636ef54808..1aaf644336b8c 100644 --- a/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/integ.service-discovery.expected.json +++ b/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/integ.service-discovery.expected.json @@ -574,27 +574,6 @@ "ProtocolType": "HTTP" } }, - "HttpProxyPrivateApiDefaultRoute1BDCA252": { - "Type": "AWS::ApiGatewayV2::Route", - "Properties": { - "ApiId": { - "Ref": "HttpProxyPrivateApiA55E154D" - }, - "RouteKey": "$default", - "AuthorizationScopes": [], - "Target": { - "Fn::Join": [ - "", - [ - "integrations/", - { - "Ref": "HttpProxyPrivateApiDefaultRouteHttpIntegrationa5ec5390ca688d567e9449daf58afc6f6DEAA8A8" - } - ] - ] - } - } - }, "HttpProxyPrivateApiDefaultRouteHttpIntegrationa5ec5390ca688d567e9449daf58afc6f6DEAA8A8": { "Type": "AWS::ApiGatewayV2::Integration", "Properties": { @@ -616,6 +595,26 @@ "PayloadFormatVersion": "1.0" } }, + "HttpProxyPrivateApiDefaultRoute1BDCA252": { + "Type": "AWS::ApiGatewayV2::Route", + "Properties": { + "ApiId": { + "Ref": "HttpProxyPrivateApiA55E154D" + }, + "RouteKey": "$default", + "Target": { + "Fn::Join": [ + "", + [ + "integrations/", + { + "Ref": "HttpProxyPrivateApiDefaultRouteHttpIntegrationa5ec5390ca688d567e9449daf58afc6f6DEAA8A8" + } + ] + ] + } + } + }, "HttpProxyPrivateApiDefaultStage18B3706E": { "Type": "AWS::ApiGatewayV2::Stage", "Properties": { diff --git a/packages/@aws-cdk/aws-apigatewayv2/lib/http/api.ts b/packages/@aws-cdk/aws-apigatewayv2/lib/http/api.ts index b74c00e5824fb..24d250dfd6eda 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/lib/http/api.ts +++ b/packages/@aws-cdk/aws-apigatewayv2/lib/http/api.ts @@ -83,6 +83,20 @@ export interface HttpApiProps { * @default false execute-api endpoint enabled. */ readonly disableExecuteApiEndpoint?: boolean; + + /** + * Default Authorizer to applied to all routes in the gateway + * + * @default - No authorizer + */ + readonly defaultAuthorizer?: IHttpRouteAuthorizer; + + /** + * Default OIDC scopes attached to all routes in the gateway, unless explicitly configured on the route. + * + * @default - no default authorization scopes + */ + readonly defaultAuthorizationScopes?: string[]; } /** @@ -143,15 +157,20 @@ export interface AddRoutesOptions extends BatchHttpRouteOptions { /** * Authorizer to be associated to these routes. - * @default - No authorizer + * + * Use NoneAuthorizer to remove the default authorizer for the api + * + * @default - uses the default authorizer if one is specified on the HttpApi */ readonly authorizer?: IHttpRouteAuthorizer; /** * The list of OIDC scopes to include in the authorization. * - * These scopes will be merged with the scopes from the attached authorizer - * @default - no additional authorization scopes + * These scopes will override the default authorization scopes on the gateway. + * Set to [] to remove default scopes + * + * @default - uses defaultAuthorizationScopes if configured on the API, otherwise none. */ readonly authorizationScopes?: string[]; } @@ -258,6 +277,9 @@ export class HttpApi extends HttpApiBase { private readonly _apiEndpoint: string; + private readonly defaultAuthorizer?: IHttpRouteAuthorizer; + private readonly defaultAuthorizationScopes?: string[]; + constructor(scope: Construct, id: string, props?: HttpApiProps) { super(scope, id); @@ -300,6 +322,8 @@ export class HttpApi extends HttpApiBase { this.apiId = resource.ref; this.httpApiId = resource.ref; this._apiEndpoint = resource.attrApiEndpoint; + this.defaultAuthorizer = props?.defaultAuthorizer; + this.defaultAuthorizationScopes = props?.defaultAuthorizationScopes; if (props?.defaultIntegration) { new HttpRoute(this, 'DefaultRoute', { @@ -363,12 +387,16 @@ export class HttpApi extends HttpApiBase { */ public addRoutes(options: AddRoutesOptions): HttpRoute[] { const methods = options.methods ?? [HttpMethod.ANY]; - return methods.map((method) => new HttpRoute(this, `${method}${options.path}`, { - httpApi: this, - routeKey: HttpRouteKey.with(options.path, method), - integration: options.integration, - authorizer: options.authorizer, - authorizationScopes: options.authorizationScopes, - })); + return methods.map((method) => { + const authorizationScopes = options.authorizationScopes ?? this.defaultAuthorizationScopes; + + return new HttpRoute(this, `${method}${options.path}`, { + httpApi: this, + routeKey: HttpRouteKey.with(options.path, method), + integration: options.integration, + authorizer: options.authorizer ?? this.defaultAuthorizer, + authorizationScopes, + }); + }); } } diff --git a/packages/@aws-cdk/aws-apigatewayv2/lib/http/authorizer.ts b/packages/@aws-cdk/aws-apigatewayv2/lib/http/authorizer.ts index f63c2e3a96583..297abf12e78e2 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/lib/http/authorizer.ts +++ b/packages/@aws-cdk/aws-apigatewayv2/lib/http/authorizer.ts @@ -15,6 +15,9 @@ export enum HttpAuthorizerType { /** Lambda Authorizer */ LAMBDA = 'REQUEST', + + /** No authorizer */ + NONE = 'NONE' } /** @@ -145,8 +148,10 @@ export interface HttpRouteAuthorizerBindOptions { export interface HttpRouteAuthorizerConfig { /** * The authorizer id + * + * @default - No authorizer id (useful for AWS_IAM route authorizer) */ - readonly authorizerId: string; + readonly authorizerId?: string; /** * The type of authorization */ @@ -172,3 +177,14 @@ function undefinedIfNoKeys(obj: A): A | undefined { const allUndefined = Object.values(obj).every(val => val === undefined); return allUndefined ? undefined : obj; } + +/** + * Explicitly configure no authorizers on specific HTTP API routes. + */ +export class HttpNoneAuthorizer implements IHttpRouteAuthorizer { + public bind(_: HttpRouteAuthorizerBindOptions): HttpRouteAuthorizerConfig { + return { + authorizationType: HttpAuthorizerType.NONE, + }; + } +} diff --git a/packages/@aws-cdk/aws-apigatewayv2/lib/http/route.ts b/packages/@aws-cdk/aws-apigatewayv2/lib/http/route.ts index 416e9bed973a3..c3ef630abbbb5 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/lib/http/route.ts +++ b/packages/@aws-cdk/aws-apigatewayv2/lib/http/route.ts @@ -3,7 +3,7 @@ import { Construct } from 'constructs'; import { CfnRoute, CfnRouteProps } from '../apigatewayv2.generated'; import { IRoute } from '../common'; import { IHttpApi } from './api'; -import { IHttpRouteAuthorizer } from './authorizer'; +import { HttpAuthorizerType, IHttpRouteAuthorizer } from './authorizer'; import { IHttpRouteIntegration } from './integration'; /** @@ -147,21 +147,27 @@ export class HttpRoute extends Resource implements IHttpRoute { scope: this.httpApi instanceof Construct ? this.httpApi : this, // scope under the API if it's not imported }) : undefined; - let authorizationScopes = authBindResult?.authorizationScopes ?? []; + let authorizationScopes = authBindResult?.authorizationScopes; if (authBindResult && props.authorizationScopes) { authorizationScopes = Array.from(new Set([ - ...authorizationScopes, + ...authorizationScopes ?? [], ...props.authorizationScopes, ])); } + const authorizationType = authBindResult?.authorizationType === HttpAuthorizerType.NONE ? undefined : authBindResult?.authorizationType; + + if (authorizationScopes?.length === 0) { + authorizationScopes = undefined; + } + const routeProps: CfnRouteProps = { apiId: props.httpApi.apiId, routeKey: props.routeKey.key, target: `integrations/${integration.integrationId}`, authorizerId: authBindResult?.authorizerId, - authorizationType: authBindResult?.authorizationType, + authorizationType, authorizationScopes, }; diff --git a/packages/@aws-cdk/aws-apigatewayv2/test/http/api.test.ts b/packages/@aws-cdk/aws-apigatewayv2/test/http/api.test.ts index a8c5f418f7782..348d8dec9aeb4 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/test/http/api.test.ts +++ b/packages/@aws-cdk/aws-apigatewayv2/test/http/api.test.ts @@ -5,7 +5,7 @@ import * as ec2 from '@aws-cdk/aws-ec2'; import { Duration, Stack } from '@aws-cdk/core'; import { HttpApi, HttpAuthorizer, HttpAuthorizerType, HttpIntegrationType, HttpMethod, HttpRouteAuthorizerBindOptions, HttpRouteAuthorizerConfig, - HttpRouteIntegrationBindOptions, HttpRouteIntegrationConfig, IHttpRouteAuthorizer, IHttpRouteIntegration, PayloadFormatVersion, + HttpRouteIntegrationBindOptions, HttpRouteIntegrationConfig, IHttpRouteAuthorizer, IHttpRouteIntegration, HttpNoneAuthorizer, PayloadFormatVersion, } from '../../lib'; describe('HttpApi', () => { @@ -371,6 +371,121 @@ describe('HttpApi', () => { expect(() => api.apiEndpoint).toThrow(/apiEndpoint is not configured/); }); + + + describe('default authorization settings', () => { + test('can add default authorizer', () => { + const stack = new Stack(); + + const authorizer = new DummyAuthorizer(); + + const httpApi = new HttpApi(stack, 'api', { + defaultAuthorizer: authorizer, + defaultAuthorizationScopes: ['read:pets'], + }); + + httpApi.addRoutes({ + path: '/pets', + methods: [HttpMethod.GET], + integration: new DummyRouteIntegration(), + }); + + expect(stack).toHaveResource('AWS::ApiGatewayV2::Route', { + AuthorizerId: 'auth-1234', + AuthorizationType: 'JWT', + AuthorizationScopes: ['read:pets'], + }); + }); + + test('can add default authorizer, but remove it for a route', () => { + const stack = new Stack(); + const authorizer = new DummyAuthorizer(); + + const httpApi = new HttpApi(stack, 'api', { + defaultAuthorizer: authorizer, + defaultAuthorizationScopes: ['read:pets'], + }); + + httpApi.addRoutes({ + path: '/pets', + methods: [HttpMethod.GET], + integration: new DummyRouteIntegration(), + }); + + httpApi.addRoutes({ + path: '/chickens', + methods: [HttpMethod.GET], + integration: new DummyRouteIntegration(), + authorizer: new HttpNoneAuthorizer(), + }); + + expect(stack).toHaveResource('AWS::ApiGatewayV2::Route', { + RouteKey: 'GET /pets', + AuthorizerId: 'auth-1234', + }); + + expect(stack).toHaveResource('AWS::ApiGatewayV2::Route', { + RouteKey: 'GET /chickens', + AuthorizerId: ABSENT, + }); + }); + + test('can remove default scopes for a route', () => { + const stack = new Stack(); + + const authorizer = new DummyAuthorizer(); + + const httpApi = new HttpApi(stack, 'api', { + defaultAuthorizer: authorizer, + defaultAuthorizationScopes: ['read:books'], + }); + + httpApi.addRoutes({ + path: '/pets', + methods: [HttpMethod.GET, HttpMethod.PATCH], + integration: new DummyRouteIntegration(), + authorizationScopes: [], + }); + + expect(stack).toHaveResource('AWS::ApiGatewayV2::Route', { + AuthorizationScopes: ABSENT, + }); + }); + + test('can override scopes for a route', () => { + const stack = new Stack(); + + const authorizer = new DummyAuthorizer(); + + const httpApi = new HttpApi(stack, 'api', { + defaultAuthorizer: authorizer, + defaultAuthorizationScopes: ['read:pets'], + }); + + httpApi.addRoutes({ + path: '/pets', + methods: [HttpMethod.GET, HttpMethod.PATCH], + integration: new DummyRouteIntegration(), + }); + + httpApi.addRoutes({ + path: '/chickens', + methods: [HttpMethod.GET, HttpMethod.PATCH], + integration: new DummyRouteIntegration(), + authorizationScopes: ['read:chickens'], + }); + + expect(stack).toHaveResource('AWS::ApiGatewayV2::Route', { + RouteKey: 'GET /pets', + AuthorizationScopes: ['read:pets'], + }); + + expect(stack).toHaveResource('AWS::ApiGatewayV2::Route', { + RouteKey: 'GET /chickens', + AuthorizationScopes: ['read:chickens'], + }); + }); + }); }); class DummyRouteIntegration implements IHttpRouteIntegration { diff --git a/packages/@aws-cdk/aws-applicationautoscaling/package.json b/packages/@aws-cdk/aws-applicationautoscaling/package.json index 71036cd220e5f..e9566094b344a 100644 --- a/packages/@aws-cdk/aws-applicationautoscaling/package.json +++ b/packages/@aws-cdk/aws-applicationautoscaling/package.json @@ -74,7 +74,7 @@ "@types/nodeunit": "^0.0.31", "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", - "fast-check": "^2.13.0", + "fast-check": "^2.14.0", "nodeunit": "^0.11.3", "pkglint": "0.0.0" }, diff --git a/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts b/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts index 60ca92bb142ca..0fede177a113e 100644 --- a/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts +++ b/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts @@ -208,6 +208,13 @@ export class VirtualNode extends VirtualNodeBase { /** * Utility method to add an inbound listener for this VirtualNode + * + * Note: At this time, Virtual Nodes support at most one listener. Adding + * more than one will result in a failure to deploy the CloudFormation stack. + * However, the App Mesh team has plans to add support for multiple listeners + * on Virtual Nodes and Virtual Routers. + * + * @see https://github.com/aws/aws-app-mesh-roadmap/issues/120 */ public addListener(listener: VirtualNodeListener) { this.listeners.push(listener.bind(this)); diff --git a/packages/@aws-cdk/aws-autoscaling-common/package.json b/packages/@aws-cdk/aws-autoscaling-common/package.json index 644801e0dbc71..8a43f80c5b9c7 100644 --- a/packages/@aws-cdk/aws-autoscaling-common/package.json +++ b/packages/@aws-cdk/aws-autoscaling-common/package.json @@ -66,7 +66,7 @@ "@types/nodeunit": "^0.0.31", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", - "fast-check": "^2.13.0", + "fast-check": "^2.14.0", "nodeunit": "^0.11.3", "pkglint": "0.0.0" }, diff --git a/packages/@aws-cdk/aws-certificatemanager/lambda-packages/dns_validated_certificate_handler/package.json b/packages/@aws-cdk/aws-certificatemanager/lambda-packages/dns_validated_certificate_handler/package.json index 0190f7771c88e..0ccfbcc561479 100644 --- a/packages/@aws-cdk/aws-certificatemanager/lambda-packages/dns_validated_certificate_handler/package.json +++ b/packages/@aws-cdk/aws-certificatemanager/lambda-packages/dns_validated_certificate_handler/package.json @@ -29,7 +29,7 @@ "devDependencies": { "aws-sdk": "^2.596.0", "aws-sdk-mock": "^5.1.0", - "eslint": "^7.21.0", + "eslint": "^7.22.0", "eslint-config-standard": "^14.1.1", "eslint-plugin-import": "^2.22.1", "eslint-plugin-node": "^11.1.0", @@ -37,7 +37,7 @@ "eslint-plugin-standard": "^4.1.0", "jest": "^26.6.3", "lambda-tester": "^3.6.0", - "nock": "^13.0.10", - "ts-jest": "^26.5.3" + "nock": "^13.0.11", + "ts-jest": "^26.5.4" } } diff --git a/packages/@aws-cdk/aws-codedeploy/lib/server/deployment-group.ts b/packages/@aws-cdk/aws-codedeploy/lib/server/deployment-group.ts index 32a3ccb3e40d1..ce93f699537c7 100644 --- a/packages/@aws-cdk/aws-codedeploy/lib/server/deployment-group.ts +++ b/packages/@aws-cdk/aws-codedeploy/lib/server/deployment-group.ts @@ -364,7 +364,12 @@ export class ServerDeploymentGroup extends ServerDeploymentGroupBase { 'if [ $RUBY2_INSTALL -ne 0 ]; then', '$PKG_CMD install -y ruby', 'fi', - '$PKG_CMD install -y awscli', + 'AWS_CLI_PACKAGE_NAME=awscli', + 'if [[ "$PKG_CMD" = "yum" ]];', + 'then', + 'AWS_CLI_PACKAGE_NAME=aws-cli', + 'fi', + '$PKG_CMD install -y $AWS_CLI_PACKAGE_NAME', 'TMP_DIR=`mktemp -d`', 'cd $TMP_DIR', `aws s3 cp s3://aws-codedeploy-${cdk.Stack.of(this).region}/latest/install . --region ${cdk.Stack.of(this).region}`, diff --git a/packages/@aws-cdk/aws-codedeploy/test/server/integ.deployment-group.expected.json b/packages/@aws-cdk/aws-codedeploy/test/server/integ.deployment-group.expected.json index e50bc6ef02f2b..1f5d3d109128d 100644 --- a/packages/@aws-cdk/aws-codedeploy/test/server/integ.deployment-group.expected.json +++ b/packages/@aws-cdk/aws-codedeploy/test/server/integ.deployment-group.expected.json @@ -659,7 +659,7 @@ "Fn::Join": [ "", [ - "#!/bin/bash\nset +e\nPKG_CMD=`which yum 2>/dev/null`\nset -e\nif [ -z \"$PKG_CMD\" ]; then\nPKG_CMD=apt-get\nelse\nPKG=CMD=yum\nfi\n$PKG_CMD update -y\nset +e\n$PKG_CMD install -y ruby2.0\nRUBY2_INSTALL=$?\nset -e\nif [ $RUBY2_INSTALL -ne 0 ]; then\n$PKG_CMD install -y ruby\nfi\n$PKG_CMD install -y awscli\nTMP_DIR=`mktemp -d`\ncd $TMP_DIR\naws s3 cp s3://aws-codedeploy-", + "#!/bin/bash\nset +e\nPKG_CMD=`which yum 2>/dev/null`\nset -e\nif [ -z \"$PKG_CMD\" ]; then\nPKG_CMD=apt-get\nelse\nPKG=CMD=yum\nfi\n$PKG_CMD update -y\nset +e\n$PKG_CMD install -y ruby2.0\nRUBY2_INSTALL=$?\nset -e\nif [ $RUBY2_INSTALL -ne 0 ]; then\n$PKG_CMD install -y ruby\nfi\nAWS_CLI_PACKAGE_NAME=awscli\nif [[ \"$PKG_CMD\" = \"yum\" ]];\nthen\nAWS_CLI_PACKAGE_NAME=aws-cli\nfi\n$PKG_CMD install -y $AWS_CLI_PACKAGE_NAME\nTMP_DIR=`mktemp -d`\ncd $TMP_DIR\naws s3 cp s3://aws-codedeploy-", { "Ref": "AWS::Region" }, diff --git a/packages/@aws-cdk/aws-codedeploy/test/server/test.deployment-group.ts b/packages/@aws-cdk/aws-codedeploy/test/server/test.deployment-group.ts index aebb3aa8a074f..8d2dbe44cd604 100644 --- a/packages/@aws-cdk/aws-codedeploy/test/server/test.deployment-group.ts +++ b/packages/@aws-cdk/aws-codedeploy/test/server/test.deployment-group.ts @@ -62,7 +62,7 @@ export = { 'Fn::Join': [ '', [ - '#!/bin/bash\nset +e\nPKG_CMD=`which yum 2>/dev/null`\nset -e\nif [ -z "$PKG_CMD" ]; then\nPKG_CMD=apt-get\nelse\nPKG=CMD=yum\nfi\n$PKG_CMD update -y\nset +e\n$PKG_CMD install -y ruby2.0\nRUBY2_INSTALL=$?\nset -e\nif [ $RUBY2_INSTALL -ne 0 ]; then\n$PKG_CMD install -y ruby\nfi\n$PKG_CMD install -y awscli\nTMP_DIR=`mktemp -d`\ncd $TMP_DIR\naws s3 cp s3://aws-codedeploy-', + '#!/bin/bash\nset +e\nPKG_CMD=`which yum 2>/dev/null`\nset -e\nif [ -z "$PKG_CMD" ]; then\nPKG_CMD=apt-get\nelse\nPKG=CMD=yum\nfi\n$PKG_CMD update -y\nset +e\n$PKG_CMD install -y ruby2.0\nRUBY2_INSTALL=$?\nset -e\nif [ $RUBY2_INSTALL -ne 0 ]; then\n$PKG_CMD install -y ruby\nfi\nAWS_CLI_PACKAGE_NAME=awscli\nif [[ "$PKG_CMD" = "yum" ]];\nthen\nAWS_CLI_PACKAGE_NAME=aws-cli\nfi\n$PKG_CMD install -y $AWS_CLI_PACKAGE_NAME\nTMP_DIR=`mktemp -d`\ncd $TMP_DIR\naws s3 cp s3://aws-codedeploy-', { 'Ref': 'AWS::Region', }, diff --git a/packages/@aws-cdk/aws-dynamodb-global/lambda-packages/aws-global-table-coordinator/package.json b/packages/@aws-cdk/aws-dynamodb-global/lambda-packages/aws-global-table-coordinator/package.json index e2ae4352eabe5..2753afe5af09f 100644 --- a/packages/@aws-cdk/aws-dynamodb-global/lambda-packages/aws-global-table-coordinator/package.json +++ b/packages/@aws-cdk/aws-dynamodb-global/lambda-packages/aws-global-table-coordinator/package.json @@ -29,7 +29,7 @@ "devDependencies": { "aws-sdk": "^2.596.0", "aws-sdk-mock": "^5.1.0", - "eslint": "^7.21.0", + "eslint": "^7.22.0", "eslint-config-standard": "^14.1.1", "eslint-plugin-import": "^2.22.1", "eslint-plugin-node": "^11.1.0", @@ -37,6 +37,6 @@ "eslint-plugin-standard": "^4.1.0", "jest": "^26.6.3", "lambda-tester": "^3.6.0", - "nock": "^13.0.10" + "nock": "^13.0.11" } } diff --git a/packages/@aws-cdk/aws-dynamodb/package.json b/packages/@aws-cdk/aws-dynamodb/package.json index 01ce9c576c096..92939c220811d 100644 --- a/packages/@aws-cdk/aws-dynamodb/package.json +++ b/packages/@aws-cdk/aws-dynamodb/package.json @@ -81,7 +81,7 @@ "jest": "^26.6.3", "pkglint": "0.0.0", "sinon": "^9.2.4", - "ts-jest": "^26.5.3" + "ts-jest": "^26.5.4" }, "dependencies": { "@aws-cdk/aws-applicationautoscaling": "0.0.0", diff --git a/packages/@aws-cdk/aws-ec2/lib/port.ts b/packages/@aws-cdk/aws-ec2/lib/port.ts index 314c8d615b0dd..8436f3455cda1 100644 --- a/packages/@aws-cdk/aws-ec2/lib/port.ts +++ b/packages/@aws-cdk/aws-ec2/lib/port.ts @@ -2,17 +2,158 @@ import { Token } from '@aws-cdk/core'; /** * Protocol for use in Connection Rules + * + * https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml */ export enum Protocol { ALL = '-1', + HOPOPT = '0', + ICMP = 'icmp', + IGMP = '2', + GGP = '3', + IPV4 = '4', + ST = '5', TCP = 'tcp', + CBT = '7', + EGP = '8', + IGP = '9', + BBN_RCC_MON = '10', + NVP_II = '11', + PUP = '12', + EMCON = '14', + XNET = '15', + CHAOS = '16', UDP = 'udp', - ICMP = 'icmp', - ICMPV6 = '58', - ESP = 'esp', - AH = 'ah', + MUX = '18', + DCN_MEAS = '19', + HMP = '20', + PRM = '21', + XNS_IDP = '22', + TRUNK_1 = '23', + TRUNK_2 = '24', + LEAF_1 = '25', + LEAF_2 = '26', + RDP = '27', + IRTP = '28', + ISO_TP4 = '29', + NETBLT = '30', + MFE_NSP = '31', + MERIT_INP = '32', + DCCP = '33', + THREEPC = '34', + IDPR = '35', + XTP = '36', + DDP = '37', + IDPR_CMTP = '38', + TPPLUSPLUS = '39', + IL = '40', + IPV6 = '41', + SDRP = '42', + IPV6_ROUTE = '43', + IPV6_FRAG = '44', + IDRP = '45', + RSVP = '46', + GRE = '47', + DSR = '48', + BNA = '49', + ESP = '50', + AH = '51', + I_NLSP = '52', + SWIPE = '53', + NARP = '54', + MOBILE = '55', + TLSP = '56', + SKIP = '57', + ICMPV6 = 'icmpv6', + IPV6_NONXT = '59', + IPV6_OPTS = '60', + CFTP = '62', + ANY_LOCAL = '63', + SAT_EXPAK = '64', + KRYPTOLAN = '65', + RVD = '66', + IPPC = '67', + ANY_DFS = '68', + SAT_MON = '69', + VISA = '70', + IPCV = '71', + CPNX = '72', + CPHB = '73', + WSN = '74', + PVP = '75', + BR_SAT_MON = '76', + SUN_ND = '77', + WB_MON = '78', + WB_EXPAK = '79', + ISO_IP = '80', + VMTP = '81', + SECURE_VMTP = '82', + VINES = '83', + TTP = '84', + IPTM = '84', + NSFNET_IGP = '85', + DGP = '86', + TCF = '87', + EIGRP = '88', + OSPFIGP = '89', + SPRITE_RPC = '90', + LARP = '91', + MTP = '92', + AX_25 = '93', + IPIP = '94', + MICP = '95', + SCC_SP = '96', + ETHERIP = '97', + ENCAP = '98', + ANY_ENC = '99', + GMTP = '100', + IFMP = '101', + PNNI = '102', + PIM = '103', + ARIS = '104', + SCPS = '105', + QNX = '106', + A_N = '107', + IPCOMP = '108', + SNP = '109', + COMPAQ_PEER = '110', + IPX_IN_IP = '111', + VRRP = '112', + PGM = '113', + ANY_0_HOP = '114', + L2_T_P = '115', + DDX = '116', + IATP = '117', + STP = '118', + SRP = '119', + UTI = '120', + SMP = '121', + SM = '122', + PTP = '123', + ISIS_IPV4 = '124', + FIRE = '125', + CRTP = '126', + CRUDP = '127', + SSCOPMCE = '128', + IPLT = '129', + SPS = '130', + PIPE = '131', + SCTP = '132', + FC = '133', + RSVP_E2E_IGNORE = '134', + MOBILITY_HEADER = '135', + UDPLITE = '136', + MPLS_IN_IP = '137', + MANET = '138', + HIP = '139', + SHIM6 = '140', + WESP = '141', + ROHC = '142', + ETHERNET = '143', + EXPERIMENT_1 = '253', + EXPERIMENT_2 = '254', + RESERVED = '255', } - /** * Properties to create a port range */ diff --git a/packages/@aws-cdk/aws-ec2/package.json b/packages/@aws-cdk/aws-ec2/package.json index c5d5d9be6a64e..c32f701574ffc 100644 --- a/packages/@aws-cdk/aws-ec2/package.json +++ b/packages/@aws-cdk/aws-ec2/package.json @@ -314,13 +314,153 @@ "docs-public-apis:@aws-cdk/aws-ec2.AmazonLinuxStorage", "docs-public-apis:@aws-cdk/aws-ec2.OperatingSystemType.LINUX", "docs-public-apis:@aws-cdk/aws-ec2.OperatingSystemType.WINDOWS", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.AH", "docs-public-apis:@aws-cdk/aws-ec2.Protocol.ALL", - "docs-public-apis:@aws-cdk/aws-ec2.Protocol.TCP", - "docs-public-apis:@aws-cdk/aws-ec2.Protocol.UDP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.ANY_0_HOP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.ANY_DFS", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.ANY_ENC", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.ANY_LOCAL", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.ARIS", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.AX_25", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.A_N", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.BBN_RCC_MON", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.BNA", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.BR_SAT_MON", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.CBT", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.CFTP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.CHAOS", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.COMPAQ_PEER", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.CPHB", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.CPNX", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.CRTP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.CRUDP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.DCCP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.DCN_MEAS", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.DDP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.DDX", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.DGP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.DSR", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.EGP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.EIGRP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.EMCON", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.ENCAP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.ESP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.ETHERIP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.ETHERNET", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.EXPERIMENT_1", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.EXPERIMENT_2", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.FC", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.FIRE", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.GGP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.GMTP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.GRE", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.HIP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.HMP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.HOPOPT", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.IATP", "docs-public-apis:@aws-cdk/aws-ec2.Protocol.ICMP", "docs-public-apis:@aws-cdk/aws-ec2.Protocol.ICMPV6", - "docs-public-apis:@aws-cdk/aws-ec2.Protocol.ESP", - "docs-public-apis:@aws-cdk/aws-ec2.Protocol.AH", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.IDPR", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.IDPR_CMTP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.IDRP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.IFMP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.IGMP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.IGP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.IL", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.IPCOMP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.IPCV", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.IPIP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.IPLT", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.IPPC", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.IPTM", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.IPV4", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.IPV6", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.IPV6_FRAG", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.IPV6_NONXT", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.IPV6_OPTS", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.IPV6_ROUTE", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.IPX_IN_IP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.IRTP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.ISIS_IPV4", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.ISO_IP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.ISO_TP4", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.I_NLSP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.KRYPTOLAN", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.L2_T_P", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.LARP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.LEAF_1", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.LEAF_2", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.MANET", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.MERIT_INP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.MFE_NSP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.MICP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.MOBILE", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.MOBILITY_HEADER", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.MPLS_IN_IP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.MTP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.MUX", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.NARP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.NETBLT", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.NSFNET_IGP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.NVP_II", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.OSPFIGP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.PGM", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.PIM", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.PIPE", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.PNNI", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.PRM", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.PTP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.PUP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.PVP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.QNX", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.RDP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.RESERVED", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.ROHC", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.RSVP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.RSVP_E2E_IGNORE", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.RVD", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.SAT_EXPAK", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.SAT_MON", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.SCC_SP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.SCPS", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.SCTP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.SDRP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.SECURE_VMTP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.SHIM6", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.SKIP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.SM", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.SMP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.SNP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.SPRITE_RPC", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.SPS", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.SRP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.SSCOPMCE", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.ST", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.STP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.SUN_ND", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.SWIPE", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.TCF", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.TCP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.THREEPC", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.TLSP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.TPPLUSPLUS", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.TRUNK_1", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.TRUNK_2", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.TTP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.UDP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.UDPLITE", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.UTI", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.VINES", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.VISA", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.VMTP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.VRRP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.WB_EXPAK", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.WB_MON", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.WESP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.WSN", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.XNET", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.XNS_IDP", + "docs-public-apis:@aws-cdk/aws-ec2.Protocol.XTP", "docs-public-apis:@aws-cdk/aws-ec2.WindowsVersion.WINDOWS_SERVER_2008_SP2_ENGLISH_64BIT_SQL_2008_SP4_EXPRESS", "docs-public-apis:@aws-cdk/aws-ec2.WindowsVersion.WINDOWS_SERVER_2012_R2_RTM_CHINESE_SIMPLIFIED_64BIT_BASE", "docs-public-apis:@aws-cdk/aws-ec2.WindowsVersion.WINDOWS_SERVER_2012_R2_RTM_CHINESE_TRADITIONAL_64BIT_BASE", diff --git a/packages/@aws-cdk/aws-ec2/test/integ.vpc.expected.json b/packages/@aws-cdk/aws-ec2/test/integ.vpc.expected.json index 641b97b4ddbd5..8aad8918d8ace 100644 --- a/packages/@aws-cdk/aws-ec2/test/integ.vpc.expected.json +++ b/packages/@aws-cdk/aws-ec2/test/integ.vpc.expected.json @@ -567,20 +567,6 @@ "FromPort": 800, "IpProtocol": "udp", "ToPort": 801 - }, - { - "CidrIp": "0.0.0.0/0", - "Description": "from 0.0.0.0/0:ESP 50", - "FromPort": 50, - "IpProtocol": "esp", - "ToPort": 50 - }, - { - "CidrIp": "0.0.0.0/0", - "Description": "from 0.0.0.0/0:AH 51", - "FromPort": 51, - "IpProtocol": "ah", - "ToPort": 51 } ], "VpcId": { diff --git a/packages/@aws-cdk/aws-ec2/test/integ.vpc.ts b/packages/@aws-cdk/aws-ec2/test/integ.vpc.ts index 88e4dacf9839a..2ffd5653e33f4 100644 --- a/packages/@aws-cdk/aws-ec2/test/integ.vpc.ts +++ b/packages/@aws-cdk/aws-ec2/test/integ.vpc.ts @@ -16,8 +16,6 @@ const rules = [ ec2.Port.allUdp(), ec2.Port.udp(123), ec2.Port.udpRange(800, 801), - ec2.Port.esp(), - ec2.Port.ah(), ]; for (const rule of rules) { diff --git a/packages/@aws-cdk/aws-ecs-patterns/README.md b/packages/@aws-cdk/aws-ecs-patterns/README.md index a1072d47fe700..2293c129ee245 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/README.md +++ b/packages/@aws-cdk/aws-ecs-patterns/README.md @@ -394,6 +394,25 @@ const loadBalancedFargateService = new ApplicationLoadBalancedFargateService(sta }); ``` +### Deployment circuit breaker and rollback + +Amazon ECS [deployment circuit breaker](https://aws.amazon.com/tw/blogs/containers/announcing-amazon-ecs-deployment-circuit-breaker/) +automatically rolls back unhealthy service deployments without the need for manual intervention. Use `circuitBreaker` to enable +deployment circuit breaker and optionally enable `rollback` for automatic rollback. See [Using the deployment circuit breaker](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/deployment-type-ecs.html) +for more details. + +```ts +const service = new ApplicationLoadBalancedFargateService(stack, 'Service', { + cluster, + memoryLimitMiB: 1024, + desiredCount: 1, + cpu: 512, + taskImageOptions: { + image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample"), + }, + circuitBreaker: { rollback: true }, +}); +``` ### Set deployment configuration on QueueProcessingService @@ -469,7 +488,7 @@ const scheduledFargateTask = new ScheduledFargateTask(stack, 'ScheduledFargateTa ### Use the REMOVE_DEFAULT_DESIRED_COUNT feature flag -The REMOVE_DEFAULT_DESIRED_COUNT feature flag is used to override the default desiredCount that is autogenerated by the CDK. This will set the desiredCount of any service created by any of the following constructs to be undefined. +The REMOVE_DEFAULT_DESIRED_COUNT feature flag is used to override the default desiredCount that is autogenerated by the CDK. This will set the desiredCount of any service created by any of the following constructs to be undefined. * ApplicationLoadBalancedEc2Service * ApplicationLoadBalancedFargateService diff --git a/packages/@aws-cdk/aws-ecs-patterns/lib/base/application-load-balanced-service-base.ts b/packages/@aws-cdk/aws-ecs-patterns/lib/base/application-load-balanced-service-base.ts index dde07a16e114c..2593853cd0350 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/lib/base/application-load-balanced-service-base.ts +++ b/packages/@aws-cdk/aws-ecs-patterns/lib/base/application-load-balanced-service-base.ts @@ -1,6 +1,9 @@ import { Certificate, CertificateValidation, ICertificate } from '@aws-cdk/aws-certificatemanager'; import { IVpc } from '@aws-cdk/aws-ec2'; -import { AwsLogDriver, BaseService, CloudMapOptions, Cluster, ContainerImage, DeploymentController, ICluster, LogDriver, PropagatedTagSource, Secret } from '@aws-cdk/aws-ecs'; +import { + AwsLogDriver, BaseService, CloudMapOptions, Cluster, ContainerImage, DeploymentController, DeploymentCircuitBreaker, + ICluster, LogDriver, PropagatedTagSource, Secret, +} from '@aws-cdk/aws-ecs'; import { ApplicationListener, ApplicationLoadBalancer, ApplicationProtocol, ApplicationTargetGroup, IApplicationLoadBalancer, ListenerCertificate, ListenerAction, AddApplicationTargetsProps, @@ -226,6 +229,14 @@ export interface ApplicationLoadBalancedServiceBaseProps { * @default - Rolling update (ECS) */ readonly deploymentController?: DeploymentController; + + /** + * Whether to enable the deployment circuit breaker. If this property is defined, circuit breaker will be implicitly + * enabled. + * @default - disabled + */ + readonly circuitBreaker?: DeploymentCircuitBreaker; + } export interface ApplicationLoadBalancedTaskImageOptions { diff --git a/packages/@aws-cdk/aws-ecs-patterns/lib/base/network-load-balanced-service-base.ts b/packages/@aws-cdk/aws-ecs-patterns/lib/base/network-load-balanced-service-base.ts index 949b052aebbad..5872217a43f22 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/lib/base/network-load-balanced-service-base.ts +++ b/packages/@aws-cdk/aws-ecs-patterns/lib/base/network-load-balanced-service-base.ts @@ -1,5 +1,8 @@ import { IVpc } from '@aws-cdk/aws-ec2'; -import { AwsLogDriver, BaseService, CloudMapOptions, Cluster, ContainerImage, DeploymentController, ICluster, LogDriver, PropagatedTagSource, Secret } from '@aws-cdk/aws-ecs'; +import { + AwsLogDriver, BaseService, CloudMapOptions, Cluster, ContainerImage, DeploymentController, DeploymentCircuitBreaker, + ICluster, LogDriver, PropagatedTagSource, Secret, +} from '@aws-cdk/aws-ecs'; import { INetworkLoadBalancer, NetworkListener, NetworkLoadBalancer, NetworkTargetGroup } from '@aws-cdk/aws-elasticloadbalancingv2'; import { IRole } from '@aws-cdk/aws-iam'; import { ARecord, CnameRecord, IHostedZone, RecordTarget } from '@aws-cdk/aws-route53'; @@ -176,6 +179,13 @@ export interface NetworkLoadBalancedServiceBaseProps { * @default - Rolling update (ECS) */ readonly deploymentController?: DeploymentController; + + /** + * Whether to enable the deployment circuit breaker. If this property is defined, circuit breaker will be implicitly + * enabled. + * @default - disabled + */ + readonly circuitBreaker?: DeploymentCircuitBreaker; } export interface NetworkLoadBalancedTaskImageOptions { diff --git a/packages/@aws-cdk/aws-ecs-patterns/lib/base/queue-processing-service-base.ts b/packages/@aws-cdk/aws-ecs-patterns/lib/base/queue-processing-service-base.ts index 2f72c6345c469..7ec268c241249 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/lib/base/queue-processing-service-base.ts +++ b/packages/@aws-cdk/aws-ecs-patterns/lib/base/queue-processing-service-base.ts @@ -1,6 +1,9 @@ import { ScalingInterval } from '@aws-cdk/aws-applicationautoscaling'; import { IVpc } from '@aws-cdk/aws-ec2'; -import { AwsLogDriver, BaseService, Cluster, ContainerImage, DeploymentController, ICluster, LogDriver, PropagatedTagSource, Secret } from '@aws-cdk/aws-ecs'; +import { + AwsLogDriver, BaseService, Cluster, ContainerImage, DeploymentController, DeploymentCircuitBreaker, + ICluster, LogDriver, PropagatedTagSource, Secret, +} from '@aws-cdk/aws-ecs'; import { IQueue, Queue } from '@aws-cdk/aws-sqs'; import { CfnOutput, Duration, Stack } from '@aws-cdk/core'; import * as cxapi from '@aws-cdk/cx-api'; @@ -189,6 +192,13 @@ export interface QueueProcessingServiceBaseProps { * @default - Rolling update (ECS) */ readonly deploymentController?: DeploymentController; + + /** + * Whether to enable the deployment circuit breaker. If this property is defined, circuit breaker will be implicitly + * enabled. + * @default - disabled + */ + readonly circuitBreaker?: DeploymentCircuitBreaker; } /** diff --git a/packages/@aws-cdk/aws-ecs-patterns/lib/ecs/application-load-balanced-ecs-service.ts b/packages/@aws-cdk/aws-ecs-patterns/lib/ecs/application-load-balanced-ecs-service.ts index 2915fce6a48ff..ed606bb72c907 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/lib/ecs/application-load-balanced-ecs-service.ts +++ b/packages/@aws-cdk/aws-ecs-patterns/lib/ecs/application-load-balanced-ecs-service.ts @@ -133,6 +133,7 @@ export class ApplicationLoadBalancedEc2Service extends ApplicationLoadBalancedSe enableECSManagedTags: props.enableECSManagedTags, cloudMapOptions: props.cloudMapOptions, deploymentController: props.deploymentController, + circuitBreaker: props.circuitBreaker, }); this.addServiceAsTarget(this.service); } diff --git a/packages/@aws-cdk/aws-ecs-patterns/lib/ecs/network-load-balanced-ecs-service.ts b/packages/@aws-cdk/aws-ecs-patterns/lib/ecs/network-load-balanced-ecs-service.ts index 881a346c74f8a..4bae918ca67fc 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/lib/ecs/network-load-balanced-ecs-service.ts +++ b/packages/@aws-cdk/aws-ecs-patterns/lib/ecs/network-load-balanced-ecs-service.ts @@ -131,6 +131,7 @@ export class NetworkLoadBalancedEc2Service extends NetworkLoadBalancedServiceBas enableECSManagedTags: props.enableECSManagedTags, cloudMapOptions: props.cloudMapOptions, deploymentController: props.deploymentController, + circuitBreaker: props.circuitBreaker, }); this.addServiceAsTarget(this.service); } diff --git a/packages/@aws-cdk/aws-ecs-patterns/lib/ecs/queue-processing-ecs-service.ts b/packages/@aws-cdk/aws-ecs-patterns/lib/ecs/queue-processing-ecs-service.ts index 6858813dfa9cc..985a4d2390e6b 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/lib/ecs/queue-processing-ecs-service.ts +++ b/packages/@aws-cdk/aws-ecs-patterns/lib/ecs/queue-processing-ecs-service.ts @@ -114,6 +114,7 @@ export class QueueProcessingEc2Service extends QueueProcessingServiceBase { propagateTags: props.propagateTags, enableECSManagedTags: props.enableECSManagedTags, deploymentController: props.deploymentController, + circuitBreaker: props.circuitBreaker, }); this.configureAutoscalingForService(this.service); diff --git a/packages/@aws-cdk/aws-ecs-patterns/lib/fargate/application-load-balanced-fargate-service.ts b/packages/@aws-cdk/aws-ecs-patterns/lib/fargate/application-load-balanced-fargate-service.ts index fbb68aef84b2f..326a68529272b 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/lib/fargate/application-load-balanced-fargate-service.ts +++ b/packages/@aws-cdk/aws-ecs-patterns/lib/fargate/application-load-balanced-fargate-service.ts @@ -170,6 +170,7 @@ export class ApplicationLoadBalancedFargateService extends ApplicationLoadBalanc cloudMapOptions: props.cloudMapOptions, platformVersion: props.platformVersion, deploymentController: props.deploymentController, + circuitBreaker: props.circuitBreaker, securityGroups: props.securityGroups, vpcSubnets: props.taskSubnets, }); diff --git a/packages/@aws-cdk/aws-ecs-patterns/lib/fargate/network-load-balanced-fargate-service.ts b/packages/@aws-cdk/aws-ecs-patterns/lib/fargate/network-load-balanced-fargate-service.ts index 404d5429acfed..1f2618bbca314 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/lib/fargate/network-load-balanced-fargate-service.ts +++ b/packages/@aws-cdk/aws-ecs-patterns/lib/fargate/network-load-balanced-fargate-service.ts @@ -157,6 +157,7 @@ export class NetworkLoadBalancedFargateService extends NetworkLoadBalancedServic cloudMapOptions: props.cloudMapOptions, platformVersion: props.platformVersion, deploymentController: props.deploymentController, + circuitBreaker: props.circuitBreaker, vpcSubnets: props.taskSubnets, }); this.addServiceAsTarget(this.service); diff --git a/packages/@aws-cdk/aws-ecs-patterns/lib/fargate/queue-processing-fargate-service.ts b/packages/@aws-cdk/aws-ecs-patterns/lib/fargate/queue-processing-fargate-service.ts index 6444d05f81da6..cb4b8d77a8188 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/lib/fargate/queue-processing-fargate-service.ts +++ b/packages/@aws-cdk/aws-ecs-patterns/lib/fargate/queue-processing-fargate-service.ts @@ -148,6 +148,7 @@ export class QueueProcessingFargateService extends QueueProcessingServiceBase { securityGroups: props.securityGroups, vpcSubnets: props.taskSubnets, assignPublicIp: props.assignPublicIp, + circuitBreaker: props.circuitBreaker, }); this.configureAutoscalingForService(this.service); diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/ec2/test.l3s.ts b/packages/@aws-cdk/aws-ecs-patterns/test/ec2/test.l3s.ts index 6f5a4aa0b3337..d41a7684fd677 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/test/ec2/test.l3s.ts +++ b/packages/@aws-cdk/aws-ecs-patterns/test/ec2/test.l3s.ts @@ -1098,6 +1098,72 @@ export = { test.done(); }, + 'ALB with circuit breaker'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + const cluster = new ecs.Cluster(stack, 'Cluster', { vpc }); + cluster.addCapacity('DefaultAutoScalingGroup', { instanceType: new ec2.InstanceType('t2.micro') }); + + // WHEN + new ecsPatterns.ApplicationLoadBalancedEc2Service(stack, 'Service', { + cluster, + memoryLimitMiB: 1024, + taskImageOptions: { + image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), + }, + circuitBreaker: { rollback: true }, + }); + + // THEN + expect(stack).to(haveResourceLike('AWS::ECS::Service', { + DeploymentConfiguration: { + DeploymentCircuitBreaker: { + Enable: true, + Rollback: true, + }, + }, + DeploymentController: { + Type: 'ECS', + }, + })); + + test.done(); + }, + + 'NLB with circuit breaker'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + const cluster = new ecs.Cluster(stack, 'Cluster', { vpc }); + cluster.addCapacity('DefaultAutoScalingGroup', { instanceType: new ec2.InstanceType('t2.micro') }); + + // WHEN + new ecsPatterns.NetworkLoadBalancedEc2Service(stack, 'Service', { + cluster, + memoryLimitMiB: 1024, + taskImageOptions: { + image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), + }, + circuitBreaker: { rollback: true }, + }); + + // THEN + expect(stack).to(haveResourceLike('AWS::ECS::Service', { + DeploymentConfiguration: { + DeploymentCircuitBreaker: { + Enable: true, + Rollback: true, + }, + }, + DeploymentController: { + Type: 'ECS', + }, + })); + + test.done(); + }, + 'NetworkLoadbalancedEC2Service accepts previously created load balancer'(test: Test) { // GIVEN const stack = new cdk.Stack(); diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/ec2/test.queue-processing-ecs-service.ts b/packages/@aws-cdk/aws-ecs-patterns/test/ec2/test.queue-processing-ecs-service.ts index 2c410f6581b1e..77d822d443048 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/test/ec2/test.queue-processing-ecs-service.ts +++ b/packages/@aws-cdk/aws-ecs-patterns/test/ec2/test.queue-processing-ecs-service.ts @@ -209,9 +209,7 @@ export = { maxHealthyPercent: 150, serviceName: 'ecs-test-service', family: 'ecs-task-family', - deploymentController: { - type: ecs.DeploymentControllerType.CODE_DEPLOY, - }, + circuitBreaker: { rollback: true }, }); // THEN - QueueWorker is of EC2 launch type, an SQS queue is created and all optional properties are set. @@ -220,11 +218,15 @@ export = { DeploymentConfiguration: { MinimumHealthyPercent: 60, MaximumPercent: 150, + DeploymentCircuitBreaker: { + Enable: true, + Rollback: true, + }, }, LaunchType: 'EC2', ServiceName: 'ecs-test-service', DeploymentController: { - Type: 'CODE_DEPLOY', + Type: 'ECS', }, })); diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.circuit-breaker-load-balanced-fargate-service.expected.json b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.circuit-breaker-load-balanced-fargate-service.expected.json new file mode 100644 index 0000000000000..19af7964b18be --- /dev/null +++ b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.circuit-breaker-load-balanced-fargate-service.expected.json @@ -0,0 +1,702 @@ +{ + "Resources": { + "Vpc8378EB38": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "10.0.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "InstanceTenancy": "default", + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-integ/Vpc" + } + ] + } + }, + "VpcPublicSubnet1Subnet5C2D37C4": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "CidrBlock": "10.0.0.0/18", + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "AvailabilityZone": "test-region-1a", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "Name", + "Value": "aws-ecs-integ/Vpc/PublicSubnet1" + } + ] + } + }, + "VpcPublicSubnet1RouteTable6C95E38E": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-integ/Vpc/PublicSubnet1" + } + ] + } + }, + "VpcPublicSubnet1RouteTableAssociation97140677": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" + }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + } + } + }, + "VpcPublicSubnet1DefaultRoute3DA9E72A": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VpcIGWD7BA715C" + } + }, + "DependsOn": [ + "VpcVPCGWBF912B6E" + ] + }, + "VpcPublicSubnet1EIPD7E02669": { + "Type": "AWS::EC2::EIP", + "Properties": { + "Domain": "vpc", + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-integ/Vpc/PublicSubnet1" + } + ] + } + }, + "VpcPublicSubnet1NATGateway4D7517AA": { + "Type": "AWS::EC2::NatGateway", + "Properties": { + "AllocationId": { + "Fn::GetAtt": [ + "VpcPublicSubnet1EIPD7E02669", + "AllocationId" + ] + }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-integ/Vpc/PublicSubnet1" + } + ] + } + }, + "VpcPublicSubnet2Subnet691E08A3": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "CidrBlock": "10.0.64.0/18", + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "AvailabilityZone": "test-region-1b", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "Name", + "Value": "aws-ecs-integ/Vpc/PublicSubnet2" + } + ] + } + }, + "VpcPublicSubnet2RouteTable94F7E489": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-integ/Vpc/PublicSubnet2" + } + ] + } + }, + "VpcPublicSubnet2RouteTableAssociationDD5762D8": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" + }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + } + } + }, + "VpcPublicSubnet2DefaultRoute97F91067": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VpcIGWD7BA715C" + } + }, + "DependsOn": [ + "VpcVPCGWBF912B6E" + ] + }, + "VpcPublicSubnet2EIP3C605A87": { + "Type": "AWS::EC2::EIP", + "Properties": { + "Domain": "vpc", + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-integ/Vpc/PublicSubnet2" + } + ] + } + }, + "VpcPublicSubnet2NATGateway9182C01D": { + "Type": "AWS::EC2::NatGateway", + "Properties": { + "AllocationId": { + "Fn::GetAtt": [ + "VpcPublicSubnet2EIP3C605A87", + "AllocationId" + ] + }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-integ/Vpc/PublicSubnet2" + } + ] + } + }, + "VpcPrivateSubnet1Subnet536B997A": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "CidrBlock": "10.0.128.0/18", + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "AvailabilityZone": "test-region-1a", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" + }, + { + "Key": "Name", + "Value": "aws-ecs-integ/Vpc/PrivateSubnet1" + } + ] + } + }, + "VpcPrivateSubnet1RouteTableB2C5B500": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-integ/Vpc/PrivateSubnet1" + } + ] + } + }, + "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" + }, + "SubnetId": { + "Ref": "VpcPrivateSubnet1Subnet536B997A" + } + } + }, + "VpcPrivateSubnet1DefaultRouteBE02A9ED": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + } + } + }, + "VpcPrivateSubnet2Subnet3788AAA1": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "CidrBlock": "10.0.192.0/18", + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "AvailabilityZone": "test-region-1b", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" + }, + { + "Key": "Name", + "Value": "aws-ecs-integ/Vpc/PrivateSubnet2" + } + ] + } + }, + "VpcPrivateSubnet2RouteTableA678073B": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-integ/Vpc/PrivateSubnet2" + } + ] + } + }, + "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" + }, + "SubnetId": { + "Ref": "VpcPrivateSubnet2Subnet3788AAA1" + } + } + }, + "VpcPrivateSubnet2DefaultRoute060D2087": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "VpcPublicSubnet2NATGateway9182C01D" + } + } + }, + "VpcIGWD7BA715C": { + "Type": "AWS::EC2::InternetGateway", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-integ/Vpc" + } + ] + } + }, + "VpcVPCGWBF912B6E": { + "Type": "AWS::EC2::VPCGatewayAttachment", + "Properties": { + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "InternetGatewayId": { + "Ref": "VpcIGWD7BA715C" + } + } + }, + "ClusterEB0386A7": { + "Type": "AWS::ECS::Cluster" + }, + "myServiceLB168895E1": { + "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer", + "Properties": { + "LoadBalancerAttributes": [ + { + "Key": "deletion_protection.enabled", + "Value": "false" + } + ], + "Scheme": "internet-facing", + "SecurityGroups": [ + { + "Fn::GetAtt": [ + "myServiceLBSecurityGroupFE0ED608", + "GroupId" + ] + } + ], + "Subnets": [ + { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, + { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + } + ], + "Type": "application" + }, + "DependsOn": [ + "VpcPublicSubnet1DefaultRoute3DA9E72A", + "VpcPublicSubnet2DefaultRoute97F91067" + ] + }, + "myServiceLBSecurityGroupFE0ED608": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Automatically created Security Group for ELB awsecsintegmyServiceLB1F7A535D", + "SecurityGroupIngress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow from anyone on port 80", + "FromPort": 80, + "IpProtocol": "tcp", + "ToPort": 80 + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "myServiceLBSecurityGrouptoawsecsintegmyServiceSecurityGroup8DAB521180B6703B07": { + "Type": "AWS::EC2::SecurityGroupEgress", + "Properties": { + "GroupId": { + "Fn::GetAtt": [ + "myServiceLBSecurityGroupFE0ED608", + "GroupId" + ] + }, + "IpProtocol": "tcp", + "Description": "Load balancer to target", + "DestinationSecurityGroupId": { + "Fn::GetAtt": [ + "myServiceSecurityGroupC3B9D4E0", + "GroupId" + ] + }, + "FromPort": 80, + "ToPort": 80 + } + }, + "myServiceLBPublicListenerC78AE8A0": { + "Type": "AWS::ElasticLoadBalancingV2::Listener", + "Properties": { + "DefaultActions": [ + { + "TargetGroupArn": { + "Ref": "myServiceLBPublicListenerECSGroup17E9BBC1" + }, + "Type": "forward" + } + ], + "LoadBalancerArn": { + "Ref": "myServiceLB168895E1" + }, + "Port": 80, + "Protocol": "HTTP" + } + }, + "myServiceLBPublicListenerECSGroup17E9BBC1": { + "Type": "AWS::ElasticLoadBalancingV2::TargetGroup", + "Properties": { + "Port": 80, + "Protocol": "HTTP", + "TargetType": "ip", + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "myServiceTaskDefTaskRole1C1DE6CC": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ecs-tasks.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "myServiceTaskDef7FB8322A": { + "Type": "AWS::ECS::TaskDefinition", + "Properties": { + "ContainerDefinitions": [ + { + "Essential": true, + "Image": "amazon/amazon-ecs-sample", + "LogConfiguration": { + "LogDriver": "awslogs", + "Options": { + "awslogs-group": { + "Ref": "myServiceTaskDefwebLogGroupA1767F2C" + }, + "awslogs-stream-prefix": "myService", + "awslogs-region": { + "Ref": "AWS::Region" + } + } + }, + "Name": "web", + "PortMappings": [ + { + "ContainerPort": 80, + "Protocol": "tcp" + } + ] + } + ], + "Cpu": "256", + "ExecutionRoleArn": { + "Fn::GetAtt": [ + "myServiceTaskDefExecutionRole618CD311", + "Arn" + ] + }, + "Family": "awsecsintegmyServiceTaskDefA3A33D18", + "Memory": "512", + "NetworkMode": "awsvpc", + "RequiresCompatibilities": [ + "FARGATE" + ], + "TaskRoleArn": { + "Fn::GetAtt": [ + "myServiceTaskDefTaskRole1C1DE6CC", + "Arn" + ] + } + } + }, + "myServiceTaskDefwebLogGroupA1767F2C": { + "Type": "AWS::Logs::LogGroup", + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + }, + "myServiceTaskDefExecutionRole618CD311": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ecs-tasks.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "myServiceTaskDefExecutionRoleDefaultPolicyBDAEC571": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "myServiceTaskDefwebLogGroupA1767F2C", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "myServiceTaskDefExecutionRoleDefaultPolicyBDAEC571", + "Roles": [ + { + "Ref": "myServiceTaskDefExecutionRole618CD311" + } + ] + } + }, + "myServiceB0B6FAA0": { + "Type": "AWS::ECS::Service", + "Properties": { + "Cluster": { + "Ref": "ClusterEB0386A7" + }, + "DeploymentConfiguration": { + "DeploymentCircuitBreaker": { + "Enable": true, + "Rollback": true + }, + "MaximumPercent": 200, + "MinimumHealthyPercent": 50 + }, + "DeploymentController": { + "Type": "ECS" + }, + "EnableECSManagedTags": false, + "HealthCheckGracePeriodSeconds": 60, + "LaunchType": "FARGATE", + "LoadBalancers": [ + { + "ContainerName": "web", + "ContainerPort": 80, + "TargetGroupArn": { + "Ref": "myServiceLBPublicListenerECSGroup17E9BBC1" + } + } + ], + "NetworkConfiguration": { + "AwsvpcConfiguration": { + "AssignPublicIp": "DISABLED", + "SecurityGroups": [ + { + "Fn::GetAtt": [ + "myServiceSecurityGroupC3B9D4E0", + "GroupId" + ] + } + ], + "Subnets": [ + { + "Ref": "VpcPrivateSubnet1Subnet536B997A" + }, + { + "Ref": "VpcPrivateSubnet2Subnet3788AAA1" + } + ] + } + }, + "TaskDefinition": { + "Ref": "myServiceTaskDef7FB8322A" + } + }, + "DependsOn": [ + "myServiceLBPublicListenerECSGroup17E9BBC1", + "myServiceLBPublicListenerC78AE8A0" + ] + }, + "myServiceSecurityGroupC3B9D4E0": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "aws-ecs-integ/myService/Service/SecurityGroup", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "myServiceSecurityGroupfromawsecsintegmyServiceLBSecurityGroupFA544FE5800A81885C": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "IpProtocol": "tcp", + "Description": "Load balancer to target", + "FromPort": 80, + "GroupId": { + "Fn::GetAtt": [ + "myServiceSecurityGroupC3B9D4E0", + "GroupId" + ] + }, + "SourceSecurityGroupId": { + "Fn::GetAtt": [ + "myServiceLBSecurityGroupFE0ED608", + "GroupId" + ] + }, + "ToPort": 80 + } + } + }, + "Outputs": { + "myServiceLoadBalancerDNS3A083E9F": { + "Value": { + "Fn::GetAtt": [ + "myServiceLB168895E1", + "DNSName" + ] + } + }, + "myServiceServiceURL1258C56B": { + "Value": { + "Fn::Join":[ + "", + [ + "http://", + { + "Fn::GetAtt": [ + "myServiceLB168895E1", + "DNSName" + ] + } + ] + ] + } + } + } +} diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.circuit-breaker-load-balanced-fargate-service.ts b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.circuit-breaker-load-balanced-fargate-service.ts new file mode 100644 index 0000000000000..57eeb8db17d5b --- /dev/null +++ b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.circuit-breaker-load-balanced-fargate-service.ts @@ -0,0 +1,21 @@ +import { Vpc } from '@aws-cdk/aws-ec2'; +import { Cluster, ContainerImage } from '@aws-cdk/aws-ecs'; +import { App, Stack } from '@aws-cdk/core'; + +import { ApplicationLoadBalancedFargateService } from '../../lib'; + +const app = new App(); +const stack = new Stack(app, 'aws-ecs-integ'); +const vpc = new Vpc(stack, 'Vpc', { maxAzs: 2 }); +const cluster = new Cluster(stack, 'Cluster', { vpc }); + +new ApplicationLoadBalancedFargateService(stack, 'myService', { + cluster, + memoryLimitMiB: 512, + taskImageOptions: { + image: ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), + }, + circuitBreaker: { rollback: true }, +}); + +app.synth(); diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.circuit-breaker-queue-processing-fargate-service.expected.json b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.circuit-breaker-queue-processing-fargate-service.expected.json new file mode 100644 index 0000000000000..3b8fad89fcf97 --- /dev/null +++ b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.circuit-breaker-queue-processing-fargate-service.expected.json @@ -0,0 +1,848 @@ +{ + "Resources": { + "VPCB9E5F0B4": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "10.0.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "InstanceTenancy": "default", + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-patterns-queue/VPC" + } + ] + } + }, + "VPCPublicSubnet1SubnetB4246D30": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "CidrBlock": "10.0.0.0/18", + "VpcId": { + "Ref": "VPCB9E5F0B4" + }, + "AvailabilityZone": "test-region-1a", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "Name", + "Value": "aws-ecs-patterns-queue/VPC/PublicSubnet1" + } + ] + } + }, + "VPCPublicSubnet1RouteTableFEE4B781": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "VPCB9E5F0B4" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-patterns-queue/VPC/PublicSubnet1" + } + ] + } + }, + "VPCPublicSubnet1RouteTableAssociation0B0896DC": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VPCPublicSubnet1RouteTableFEE4B781" + }, + "SubnetId": { + "Ref": "VPCPublicSubnet1SubnetB4246D30" + } + } + }, + "VPCPublicSubnet1DefaultRoute91CEF279": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VPCPublicSubnet1RouteTableFEE4B781" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VPCIGWB7E252D3" + } + }, + "DependsOn": [ + "VPCVPCGW99B986DC" + ] + }, + "VPCPublicSubnet1EIP6AD938E8": { + "Type": "AWS::EC2::EIP", + "Properties": { + "Domain": "vpc", + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-patterns-queue/VPC/PublicSubnet1" + } + ] + } + }, + "VPCPublicSubnet1NATGatewayE0556630": { + "Type": "AWS::EC2::NatGateway", + "Properties": { + "AllocationId": { + "Fn::GetAtt": [ + "VPCPublicSubnet1EIP6AD938E8", + "AllocationId" + ] + }, + "SubnetId": { + "Ref": "VPCPublicSubnet1SubnetB4246D30" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-patterns-queue/VPC/PublicSubnet1" + } + ] + } + }, + "VPCPublicSubnet2Subnet74179F39": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "CidrBlock": "10.0.64.0/18", + "VpcId": { + "Ref": "VPCB9E5F0B4" + }, + "AvailabilityZone": "test-region-1b", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "Name", + "Value": "aws-ecs-patterns-queue/VPC/PublicSubnet2" + } + ] + } + }, + "VPCPublicSubnet2RouteTable6F1A15F1": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "VPCB9E5F0B4" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-patterns-queue/VPC/PublicSubnet2" + } + ] + } + }, + "VPCPublicSubnet2RouteTableAssociation5A808732": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VPCPublicSubnet2RouteTable6F1A15F1" + }, + "SubnetId": { + "Ref": "VPCPublicSubnet2Subnet74179F39" + } + } + }, + "VPCPublicSubnet2DefaultRouteB7481BBA": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VPCPublicSubnet2RouteTable6F1A15F1" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VPCIGWB7E252D3" + } + }, + "DependsOn": [ + "VPCVPCGW99B986DC" + ] + }, + "VPCPublicSubnet2EIP4947BC00": { + "Type": "AWS::EC2::EIP", + "Properties": { + "Domain": "vpc", + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-patterns-queue/VPC/PublicSubnet2" + } + ] + } + }, + "VPCPublicSubnet2NATGateway3C070193": { + "Type": "AWS::EC2::NatGateway", + "Properties": { + "AllocationId": { + "Fn::GetAtt": [ + "VPCPublicSubnet2EIP4947BC00", + "AllocationId" + ] + }, + "SubnetId": { + "Ref": "VPCPublicSubnet2Subnet74179F39" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-patterns-queue/VPC/PublicSubnet2" + } + ] + } + }, + "VPCPrivateSubnet1Subnet8BCA10E0": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "CidrBlock": "10.0.128.0/18", + "VpcId": { + "Ref": "VPCB9E5F0B4" + }, + "AvailabilityZone": "test-region-1a", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" + }, + { + "Key": "Name", + "Value": "aws-ecs-patterns-queue/VPC/PrivateSubnet1" + } + ] + } + }, + "VPCPrivateSubnet1RouteTableBE8A6027": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "VPCB9E5F0B4" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-patterns-queue/VPC/PrivateSubnet1" + } + ] + } + }, + "VPCPrivateSubnet1RouteTableAssociation347902D1": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VPCPrivateSubnet1RouteTableBE8A6027" + }, + "SubnetId": { + "Ref": "VPCPrivateSubnet1Subnet8BCA10E0" + } + } + }, + "VPCPrivateSubnet1DefaultRouteAE1D6490": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VPCPrivateSubnet1RouteTableBE8A6027" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "VPCPublicSubnet1NATGatewayE0556630" + } + } + }, + "VPCPrivateSubnet2SubnetCFCDAA7A": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "CidrBlock": "10.0.192.0/18", + "VpcId": { + "Ref": "VPCB9E5F0B4" + }, + "AvailabilityZone": "test-region-1b", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" + }, + { + "Key": "Name", + "Value": "aws-ecs-patterns-queue/VPC/PrivateSubnet2" + } + ] + } + }, + "VPCPrivateSubnet2RouteTable0A19E10E": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "VPCB9E5F0B4" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-patterns-queue/VPC/PrivateSubnet2" + } + ] + } + }, + "VPCPrivateSubnet2RouteTableAssociation0C73D413": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VPCPrivateSubnet2RouteTable0A19E10E" + }, + "SubnetId": { + "Ref": "VPCPrivateSubnet2SubnetCFCDAA7A" + } + } + }, + "VPCPrivateSubnet2DefaultRouteF4F5CFD2": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VPCPrivateSubnet2RouteTable0A19E10E" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "VPCPublicSubnet2NATGateway3C070193" + } + } + }, + "VPCIGWB7E252D3": { + "Type": "AWS::EC2::InternetGateway", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-patterns-queue/VPC" + } + ] + } + }, + "VPCVPCGW99B986DC": { + "Type": "AWS::EC2::VPCGatewayAttachment", + "Properties": { + "VpcId": { + "Ref": "VPCB9E5F0B4" + }, + "InternetGatewayId": { + "Ref": "VPCIGWB7E252D3" + } + } + }, + "QueueProcessingServiceEcsProcessingDeadLetterQueueD47A7C6B": { + "Type": "AWS::SQS::Queue", + "Properties": { + "MessageRetentionPeriod": 1209600 + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "QueueProcessingServiceEcsProcessingQueue552F0B37": { + "Type": "AWS::SQS::Queue", + "Properties": { + "RedrivePolicy": { + "deadLetterTargetArn": { + "Fn::GetAtt": [ + "QueueProcessingServiceEcsProcessingDeadLetterQueueD47A7C6B", + "Arn" + ] + }, + "maxReceiveCount": 3 + } + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "QueueProcessingServiceQueueProcessingTaskDefTaskRole782B79A6": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ecs-tasks.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "QueueProcessingServiceQueueProcessingTaskDefTaskRoleDefaultPolicyAE808B19": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "sqs:ReceiveMessage", + "sqs:ChangeMessageVisibility", + "sqs:GetQueueUrl", + "sqs:DeleteMessage", + "sqs:GetQueueAttributes" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "QueueProcessingServiceEcsProcessingQueue552F0B37", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "QueueProcessingServiceQueueProcessingTaskDefTaskRoleDefaultPolicyAE808B19", + "Roles": [ + { + "Ref": "QueueProcessingServiceQueueProcessingTaskDefTaskRole782B79A6" + } + ] + } + }, + "QueueProcessingServiceQueueProcessingTaskDef4982F68B": { + "Type": "AWS::ECS::TaskDefinition", + "Properties": { + "ContainerDefinitions": [ + { + "Environment": [ + { + "Name": "QUEUE_NAME", + "Value": { + "Fn::GetAtt": [ + "QueueProcessingServiceEcsProcessingQueue552F0B37", + "QueueName" + ] + } + } + ], + "Essential": true, + "Image": { + "Fn::Join": [ + "", + [ + { + "Ref": "AWS::AccountId" + }, + ".dkr.ecr.", + { + "Ref": "AWS::Region" + }, + ".", + { + "Ref": "AWS::URLSuffix" + }, + "/aws-cdk/assets:3a8ba3ad06ed212b075efa3157fb407649c5996812bc64eeb5209e220aab4be5" + ] + ] + }, + "LogConfiguration": { + "LogDriver": "awslogs", + "Options": { + "awslogs-group": { + "Ref": "QueueProcessingServiceQueueProcessingTaskDefQueueProcessingContainerLogGroupCC92448A" + }, + "awslogs-stream-prefix": "QueueProcessingService", + "awslogs-region": { + "Ref": "AWS::Region" + } + } + }, + "Name": "QueueProcessingContainer" + } + ], + "Cpu": "256", + "ExecutionRoleArn": { + "Fn::GetAtt": [ + "QueueProcessingServiceQueueProcessingTaskDefExecutionRole37838985", + "Arn" + ] + }, + "Family": "awsecspatternsqueueQueueProcessingServiceQueueProcessingTaskDef2D9F8C2B", + "Memory": "512", + "NetworkMode": "awsvpc", + "RequiresCompatibilities": [ + "FARGATE" + ], + "TaskRoleArn": { + "Fn::GetAtt": [ + "QueueProcessingServiceQueueProcessingTaskDefTaskRole782B79A6", + "Arn" + ] + } + } + }, + "QueueProcessingServiceQueueProcessingTaskDefQueueProcessingContainerLogGroupCC92448A": { + "Type": "AWS::Logs::LogGroup", + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + }, + "QueueProcessingServiceQueueProcessingTaskDefExecutionRole37838985": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ecs-tasks.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "QueueProcessingServiceQueueProcessingTaskDefExecutionRoleDefaultPolicyA83D332D": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "ecr:BatchCheckLayerAvailability", + "ecr:GetDownloadUrlForLayer", + "ecr:BatchGetImage" + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":ecr:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":repository/aws-cdk/assets" + ] + ] + } + }, + { + "Action": "ecr:GetAuthorizationToken", + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "QueueProcessingServiceQueueProcessingTaskDefQueueProcessingContainerLogGroupCC92448A", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "QueueProcessingServiceQueueProcessingTaskDefExecutionRoleDefaultPolicyA83D332D", + "Roles": [ + { + "Ref": "QueueProcessingServiceQueueProcessingTaskDefExecutionRole37838985" + } + ] + } + }, + "QueueProcessingServiceQueueProcessingFargateService0340DB9F": { + "Type": "AWS::ECS::Service", + "Properties": { + "Cluster": { + "Ref": "EcsDefaultClusterMnL3mNNYNVPC9C1EC7A3" + }, + "DeploymentConfiguration": { + "DeploymentCircuitBreaker": { + "Enable": true, + "Rollback": true + }, + "MaximumPercent": 200, + "MinimumHealthyPercent": 50 + }, + "DeploymentController": { + "Type": "ECS" + }, + "EnableECSManagedTags": false, + "LaunchType": "FARGATE", + "NetworkConfiguration": { + "AwsvpcConfiguration": { + "AssignPublicIp": "DISABLED", + "SecurityGroups": [ + { + "Fn::GetAtt": [ + "QueueProcessingServiceQueueProcessingFargateServiceSecurityGroup8FDF413D", + "GroupId" + ] + } + ], + "Subnets": [ + { + "Ref": "VPCPrivateSubnet1Subnet8BCA10E0" + }, + { + "Ref": "VPCPrivateSubnet2SubnetCFCDAA7A" + } + ] + } + }, + "TaskDefinition": { + "Ref": "QueueProcessingServiceQueueProcessingTaskDef4982F68B" + } + } + }, + "QueueProcessingServiceQueueProcessingFargateServiceSecurityGroup8FDF413D": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "aws-ecs-patterns-queue/QueueProcessingService/QueueProcessingFargateService/SecurityGroup", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "QueueProcessingServiceQueueProcessingFargateServiceTaskCountTargetA9D54444": { + "Type": "AWS::ApplicationAutoScaling::ScalableTarget", + "Properties": { + "MaxCapacity": 2, + "MinCapacity": 1, + "ResourceId": { + "Fn::Join": [ + "", + [ + "service/", + { + "Ref": "EcsDefaultClusterMnL3mNNYNVPC9C1EC7A3" + }, + "/", + { + "Fn::GetAtt": [ + "QueueProcessingServiceQueueProcessingFargateService0340DB9F", + "Name" + ] + } + ] + ] + }, + "RoleARN": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":role/aws-service-role/ecs.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_ECSService" + ] + ] + }, + "ScalableDimension": "ecs:service:DesiredCount", + "ServiceNamespace": "ecs" + } + }, + "QueueProcessingServiceQueueProcessingFargateServiceTaskCountTargetCpuScaling330150E9": { + "Type": "AWS::ApplicationAutoScaling::ScalingPolicy", + "Properties": { + "PolicyName": "awsecspatternsqueueQueueProcessingServiceQueueProcessingFargateServiceTaskCountTargetCpuScaling374CE648", + "PolicyType": "TargetTrackingScaling", + "ScalingTargetId": { + "Ref": "QueueProcessingServiceQueueProcessingFargateServiceTaskCountTargetA9D54444" + }, + "TargetTrackingScalingPolicyConfiguration": { + "PredefinedMetricSpecification": { + "PredefinedMetricType": "ECSServiceAverageCPUUtilization" + }, + "TargetValue": 50 + } + } + }, + "QueueProcessingServiceQueueProcessingFargateServiceTaskCountTargetQueueMessagesVisibleScalingLowerPolicy332E2644": { + "Type": "AWS::ApplicationAutoScaling::ScalingPolicy", + "Properties": { + "PolicyName": "awsecspatternsqueueQueueProcessingServiceQueueProcessingFargateServiceTaskCountTargetQueueMessagesVisibleScalingLowerPolicy74582401", + "PolicyType": "StepScaling", + "ScalingTargetId": { + "Ref": "QueueProcessingServiceQueueProcessingFargateServiceTaskCountTargetA9D54444" + }, + "StepScalingPolicyConfiguration": { + "AdjustmentType": "ChangeInCapacity", + "MetricAggregationType": "Maximum", + "StepAdjustments": [ + { + "MetricIntervalUpperBound": 0, + "ScalingAdjustment": -1 + } + ] + } + } + }, + "QueueProcessingServiceQueueProcessingFargateServiceTaskCountTargetQueueMessagesVisibleScalingLowerAlarm20C30A06": { + "Type": "AWS::CloudWatch::Alarm", + "Properties": { + "ComparisonOperator": "LessThanOrEqualToThreshold", + "EvaluationPeriods": 1, + "AlarmActions": [ + { + "Ref": "QueueProcessingServiceQueueProcessingFargateServiceTaskCountTargetQueueMessagesVisibleScalingLowerPolicy332E2644" + } + ], + "AlarmDescription": "Lower threshold scaling alarm", + "Dimensions": [ + { + "Name": "QueueName", + "Value": { + "Fn::GetAtt": [ + "QueueProcessingServiceEcsProcessingQueue552F0B37", + "QueueName" + ] + } + } + ], + "MetricName": "ApproximateNumberOfMessagesVisible", + "Namespace": "AWS/SQS", + "Period": 300, + "Statistic": "Maximum", + "Threshold": 0 + } + }, + "QueueProcessingServiceQueueProcessingFargateServiceTaskCountTargetQueueMessagesVisibleScalingUpperPolicy84DD739A": { + "Type": "AWS::ApplicationAutoScaling::ScalingPolicy", + "Properties": { + "PolicyName": "awsecspatternsqueueQueueProcessingServiceQueueProcessingFargateServiceTaskCountTargetQueueMessagesVisibleScalingUpperPolicy23C5F983", + "PolicyType": "StepScaling", + "ScalingTargetId": { + "Ref": "QueueProcessingServiceQueueProcessingFargateServiceTaskCountTargetA9D54444" + }, + "StepScalingPolicyConfiguration": { + "AdjustmentType": "ChangeInCapacity", + "MetricAggregationType": "Maximum", + "StepAdjustments": [ + { + "MetricIntervalLowerBound": 0, + "MetricIntervalUpperBound": 400, + "ScalingAdjustment": 1 + }, + { + "MetricIntervalLowerBound": 400, + "ScalingAdjustment": 5 + } + ] + } + } + }, + "QueueProcessingServiceQueueProcessingFargateServiceTaskCountTargetQueueMessagesVisibleScalingUpperAlarm2660BEDF": { + "Type": "AWS::CloudWatch::Alarm", + "Properties": { + "ComparisonOperator": "GreaterThanOrEqualToThreshold", + "EvaluationPeriods": 1, + "AlarmActions": [ + { + "Ref": "QueueProcessingServiceQueueProcessingFargateServiceTaskCountTargetQueueMessagesVisibleScalingUpperPolicy84DD739A" + } + ], + "AlarmDescription": "Upper threshold scaling alarm", + "Dimensions": [ + { + "Name": "QueueName", + "Value": { + "Fn::GetAtt": [ + "QueueProcessingServiceEcsProcessingQueue552F0B37", + "QueueName" + ] + } + } + ], + "MetricName": "ApproximateNumberOfMessagesVisible", + "Namespace": "AWS/SQS", + "Period": 300, + "Statistic": "Maximum", + "Threshold": 100 + } + }, + "EcsDefaultClusterMnL3mNNYNVPC9C1EC7A3": { + "Type": "AWS::ECS::Cluster" + } + }, + "Outputs": { + "QueueProcessingServiceSQSDeadLetterQueueE9058015": { + "Value": { + "Fn::GetAtt": [ + "QueueProcessingServiceEcsProcessingDeadLetterQueueD47A7C6B", + "QueueName" + ] + } + }, + "QueueProcessingServiceSQSDeadLetterQueueArnF7C6D3A8": { + "Value": { + "Fn::GetAtt": [ + "QueueProcessingServiceEcsProcessingDeadLetterQueueD47A7C6B", + "Arn" + ] + } + }, + "QueueProcessingServiceSQSQueue1AD9CD9C": { + "Value": { + "Fn::GetAtt": [ + "QueueProcessingServiceEcsProcessingQueue552F0B37", + "QueueName" + ] + } + }, + "QueueProcessingServiceSQSQueueArn8C4AE4AE": { + "Value": { + "Fn::GetAtt": [ + "QueueProcessingServiceEcsProcessingQueue552F0B37", + "Arn" + ] + } + } + } +} diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.circuit-breaker-queue-processing-fargate-service.ts b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.circuit-breaker-queue-processing-fargate-service.ts new file mode 100644 index 0000000000000..6ba895ec2f1c9 --- /dev/null +++ b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.circuit-breaker-queue-processing-fargate-service.ts @@ -0,0 +1,21 @@ +import * as path from 'path'; +import * as ec2 from '@aws-cdk/aws-ec2'; +import * as ecs from '@aws-cdk/aws-ecs'; +import { App, Stack } from '@aws-cdk/core'; + +import { QueueProcessingFargateService } from '../../lib'; + +const app = new App(); +const stack = new Stack(app, 'aws-ecs-patterns-queue'); +const vpc = new ec2.Vpc(stack, 'VPC', { + maxAzs: 2, +}); + +new QueueProcessingFargateService(stack, 'QueueProcessingService', { + vpc, + memoryLimitMiB: 512, + circuitBreaker: { rollback: true }, + image: new ecs.AssetImage(path.join(__dirname, '..', 'sqs-reader')), +}); + +app.synth(); diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/test.load-balanced-fargate-service.ts b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/test.load-balanced-fargate-service.ts index 1feffcb2e70fd..3a17962c8b230 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/test.load-balanced-fargate-service.ts +++ b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/test.load-balanced-fargate-service.ts @@ -427,6 +427,58 @@ export = { test.done(); }, + 'setting ALB circuitBreaker works'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + + // WHEN + new ecsPatterns.ApplicationLoadBalancedFargateService(stack, 'Service', { + taskImageOptions: { + image: ecs.ContainerImage.fromRegistry('/aws/aws-example-app'), + }, + circuitBreaker: { rollback: true }, + }); + // THEN + expect(stack).to(haveResourceLike('AWS::ECS::Service', { + DeploymentConfiguration: { + DeploymentCircuitBreaker: { + Enable: true, + Rollback: true, + }, + }, + DeploymentController: { + Type: 'ECS', + }, + })); + test.done(); + }, + + 'setting NLB circuitBreaker works'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + + // WHEN + new ecsPatterns.NetworkLoadBalancedFargateService(stack, 'Service', { + taskImageOptions: { + image: ecs.ContainerImage.fromRegistry('/aws/aws-example-app'), + }, + circuitBreaker: { rollback: true }, + }); + // THEN + expect(stack).to(haveResourceLike('AWS::ECS::Service', { + DeploymentConfiguration: { + DeploymentCircuitBreaker: { + Enable: true, + Rollback: true, + }, + }, + DeploymentController: { + Type: 'ECS', + }, + })); + test.done(); + }, + 'setting NLB special listener port to create the listener'(test: Test) { // GIVEN const stack = new cdk.Stack(); diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/test.queue-processing-fargate-service.ts b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/test.queue-processing-fargate-service.ts index 27671ae22e70d..5207f92629c10 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/test.queue-processing-fargate-service.ts +++ b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/test.queue-processing-fargate-service.ts @@ -344,9 +344,7 @@ export = { serviceName: 'fargate-test-service', family: 'fargate-task-family', platformVersion: ecs.FargatePlatformVersion.VERSION1_4, - deploymentController: { - type: ecs.DeploymentControllerType.CODE_DEPLOY, - }, + circuitBreaker: { rollback: true }, }); // THEN - QueueWorker is of FARGATE launch type, an SQS queue is created and all optional properties are set. @@ -355,12 +353,16 @@ export = { DeploymentConfiguration: { MinimumHealthyPercent: 60, MaximumPercent: 150, + DeploymentCircuitBreaker: { + Enable: true, + Rollback: true, + }, }, LaunchType: 'FARGATE', ServiceName: 'fargate-test-service', PlatformVersion: ecs.FargatePlatformVersion.VERSION1_4, DeploymentController: { - Type: 'CODE_DEPLOY', + Type: 'ECS', }, })); diff --git a/packages/@aws-cdk/aws-ecs/README.md b/packages/@aws-cdk/aws-ecs/README.md index cc4bd432e7dba..5ad2855c8f642 100644 --- a/packages/@aws-cdk/aws-ecs/README.md +++ b/packages/@aws-cdk/aws-ecs/README.md @@ -449,10 +449,10 @@ const service = new ecs.Ec2Service(this, 'Service', { /* ... */ }); const lb = new elb.LoadBalancer(stack, 'LB', { vpc }); lb.addListener({ externalPort: 80 }); -lb.addTarget(service.loadBalancerTarget{ +lb.addTarget(service.loadBalancerTarget({ containerName: 'MyContainer', containerPort: 80 -}); +})); ``` There are two higher-level constructs available which include a load balancer for you that can be found in the aws-ecs-patterns module: diff --git a/packages/@aws-cdk/aws-ecs/lib/base/base-service.ts b/packages/@aws-cdk/aws-ecs/lib/base/base-service.ts index 3ff3f20fd8acd..306b2bced3477 100644 --- a/packages/@aws-cdk/aws-ecs/lib/base/base-service.ts +++ b/packages/@aws-cdk/aws-ecs/lib/base/base-service.ts @@ -387,7 +387,9 @@ export abstract class BaseService extends Resource }, propagateTags: props.propagateTags === PropagatedTagSource.NONE ? undefined : props.propagateTags, enableEcsManagedTags: props.enableECSManagedTags ?? false, - deploymentController: props.deploymentController, + deploymentController: props.circuitBreaker ? { + type: DeploymentControllerType.ECS, + } : props.deploymentController, launchType: launchType, capacityProviderStrategy: props.capacityProviderStrategies, healthCheckGracePeriodSeconds: this.evaluateHealthGracePeriod(props.healthCheckGracePeriod), @@ -984,4 +986,4 @@ function determineContainerNameAndPort(options: DetermineContainerNameAndPortOpt } return {}; -} \ No newline at end of file +} diff --git a/packages/@aws-cdk/aws-ecs/test/fargate/fargate-service.test.ts b/packages/@aws-cdk/aws-ecs/test/fargate/fargate-service.test.ts index 5531b53413f46..cbd43a8d44f67 100644 --- a/packages/@aws-cdk/aws-ecs/test/fargate/fargate-service.test.ts +++ b/packages/@aws-cdk/aws-ecs/test/fargate/fargate-service.test.ts @@ -389,7 +389,7 @@ nodeunitShim({ maxHealthyPercent: 150, minHealthyPercent: 55, deploymentController: { - type: ecs.DeploymentControllerType.CODE_DEPLOY, + type: ecs.DeploymentControllerType.ECS, }, circuitBreaker: { rollback: true }, securityGroup: new ec2.SecurityGroup(stack, 'SecurityGroup1', { @@ -421,7 +421,7 @@ nodeunitShim({ }, }, DeploymentController: { - Type: ecs.DeploymentControllerType.CODE_DEPLOY, + Type: ecs.DeploymentControllerType.ECS, }, DesiredCount: 2, HealthCheckGracePeriodSeconds: 60, @@ -2073,6 +2073,9 @@ nodeunitShim({ Rollback: true, }, }, + DeploymentController: { + Type: ecs.DeploymentControllerType.ECS, + }, })); test.done(); diff --git a/packages/@aws-cdk/aws-efs/README.md b/packages/@aws-cdk/aws-efs/README.md index 002ba355e51eb..444a3a69d7480 100644 --- a/packages/@aws-cdk/aws-efs/README.md +++ b/packages/@aws-cdk/aws-efs/README.md @@ -90,9 +90,9 @@ efs.AccessPoint.fromAccessPointAttributes(this, 'ap', { ⚠️ Notice: When importing an Access Point using `fromAccessPointAttributes()`, you must make sure the mount targets are deployed and their lifecycle state is `available`. Otherwise, you may encounter the following error when deploying: -> EFS file system referenced by access point has +> EFS file system <ARN of efs> referenced by access point <ARN of access point of EFS> has > mount targets created in all availability zones the function will execute in, but not all ->are in the available life cycle state yet. Please wait for them to become available and +> are in the available life cycle state yet. Please wait for them to become available and > try the request again. ### Connecting diff --git a/packages/@aws-cdk/aws-eks/package.json b/packages/@aws-cdk/aws-eks/package.json index 4d27cbfaac281..7e4f0e2ddf090 100644 --- a/packages/@aws-cdk/aws-eks/package.json +++ b/packages/@aws-cdk/aws-eks/package.json @@ -95,7 +95,7 @@ "@aws-cdk/lambda-layer-awscli": "0.0.0", "@aws-cdk/lambda-layer-kubectl": "0.0.0", "constructs": "^3.2.0", - "yaml": "1.10.0" + "yaml": "1.10.2" }, "bundledDependencies": [ "yaml" diff --git a/packages/@aws-cdk/aws-lambda-event-sources/README.md b/packages/@aws-cdk/aws-lambda-event-sources/README.md index 5e1578d9aefd4..eb4f206c8f3c9 100644 --- a/packages/@aws-cdk/aws-lambda-event-sources/README.md +++ b/packages/@aws-cdk/aws-lambda-event-sources/README.md @@ -207,6 +207,67 @@ myFunction.addEventSource(new KinesisEventSource(stream, { })); ``` +## Kafka + +You can write Lambda functions to process data either from [Amazon MSK](https://docs.aws.amazon.com/lambda/latest/dg/with-msk.html) or a [self managed Kafka](https://docs.aws.amazon.com/lambda/latest/dg/kafka-smaa.html) cluster. + +The following code sets up Amazon MSK as an event source for a lambda function. Credentials will need to be configured to access the +MSK cluster, as described in [Username/Password authentication](https://docs.aws.amazon.com/msk/latest/developerguide/msk-password.html). + +```ts +import * as lambda from '@aws-cdk/aws-lambda'; +import * as msk from '@aws-cdk/aws-lambda'; +import { Secret } from '@aws-cdk/aws-secretmanager'; +import { ManagedKafkaEventSource } from '@aws-cdk/aws-lambda-event-sources'; + +// Your MSK cluster +const cluster = msk.Cluster.fromClusterArn(this, 'Cluster', + 'arn:aws:kafka:us-east-1:0123456789019:cluster/SalesCluster/abcd1234-abcd-cafe-abab-9876543210ab-4'); + +// The Kafka topic you want to subscribe to +const topic = 'some-cool-topic' + +// The secret that allows access to your MSK cluster +// You still have to make sure that it is associated with your cluster as described in the documentation +const secret = new Secret(this, 'Secret', { secretName: 'AmazonMSK_KafkaSecret' }); + +myFunction.addEventSource(new ManagedKafkaEventSource({ + cluster: cluster, + topic: topic, + secret: secret, + batchSize: 100, // default + startingPosition: lambda.StartingPosition.TRIM_HORIZON +})); +``` + +The following code sets up a self managed Kafka cluster as an event source. Username and password based authentication +will need to be set up as described in [Managing access and permissions](https://docs.aws.amazon.com/lambda/latest/dg/smaa-permissions.html#smaa-permissions-add-secret). + +```ts +import * as lambda from '@aws-cdk/aws-lambda'; +import { Secret } from '@aws-cdk/aws-secretmanager'; +import { SelfManagedKafkaEventSource } from '@aws-cdk/aws-lambda-event-sources'; + +// The list of Kafka brokers +const bootstrapServers = ['kafka-broker:9092'] + +// The Kafka topic you want to subscribe to +const topic = 'some-cool-topic' + +// The secret that allows access to your self hosted Kafka cluster +const secret = new Secret(this, 'Secret', { ... }); + +myFunction.addEventSource(new SelfManagedKafkaEventSource({ + bootstrapServers: bootstrapServers, + topic: topic, + secret: secret, + batchSize: 100, // default + startingPosition: lambda.StartingPosition.TRIM_HORIZON +})); +``` + +If your self managed Kafka cluster is only reachable via VPC also configure `vpc` `vpcSubnets` and `securityGroup`. + ## Roadmap Eventually, this module will support all the event sources described under diff --git a/packages/@aws-cdk/aws-lambda-event-sources/lib/index.ts b/packages/@aws-cdk/aws-lambda-event-sources/lib/index.ts index 19253a743cae8..555137e51afbf 100644 --- a/packages/@aws-cdk/aws-lambda-event-sources/lib/index.ts +++ b/packages/@aws-cdk/aws-lambda-event-sources/lib/index.ts @@ -1,5 +1,6 @@ export * from './api'; export * from './dynamodb'; +export * from './kafka'; export * from './kinesis'; export * from './s3'; export * from './sns'; diff --git a/packages/@aws-cdk/aws-lambda-event-sources/lib/kafka.ts b/packages/@aws-cdk/aws-lambda-event-sources/lib/kafka.ts new file mode 100644 index 0000000000000..f0782964d93ce --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-event-sources/lib/kafka.ts @@ -0,0 +1,194 @@ +import * as crypto from 'crypto'; +import { ISecurityGroup, IVpc, SubnetSelection } from '@aws-cdk/aws-ec2'; +import * as iam from '@aws-cdk/aws-iam'; +import * as lambda from '@aws-cdk/aws-lambda'; +import * as msk from '@aws-cdk/aws-msk'; +import * as secretsmanager from '@aws-cdk/aws-secretsmanager'; +import { Stack } from '@aws-cdk/core'; +import { StreamEventSource, StreamEventSourceProps } from './stream'; + +// keep this import separate from other imports to reduce chance for merge conflicts with v2-main +// eslint-disable-next-line no-duplicate-imports, import/order +import { Construct } from '@aws-cdk/core'; + +/** + * Properties for a Kafka event source + */ +export interface KafkaEventSourceProps extends StreamEventSourceProps { + /** + * the Kafka topic to subscribe to + */ + readonly topic: string, + /** + * the secret with the Kafka credentials, see https://docs.aws.amazon.com/msk/latest/developerguide/msk-password.html for details + */ + readonly secret: secretsmanager.ISecret +} + +/** + * Properties for a MSK event source + */ +export interface ManagedKafkaEventSourceProps extends KafkaEventSourceProps { + /** + * an MSK cluster construct + */ + readonly cluster: msk.ICluster +} + +/** + * The authentication method to use with SelfManagedKafkaEventSource + */ +export enum AuthenticationMethod { + /** + * SASL_SCRAM_512_AUTH authentication method for your Kafka cluster + */ + SASL_SCRAM_512_AUTH = 'SASL_SCRAM_512_AUTH', + /** + * SASL_SCRAM_256_AUTH authentication method for your Kafka cluster + */ + SASL_SCRAM_256_AUTH = 'SASL_SCRAM_256_AUTH', +} + +/** + * Properties for a self managed Kafka cluster event source. + * If your Kafka cluster is only reachable via VPC make sure to configure it. + */ +export interface SelfManagedKafkaEventSourceProps extends KafkaEventSourceProps { + /** + * The list of host and port pairs that are the addresses of the Kafka brokers in a "bootstrap" Kafka cluster that + * a Kafka client connects to initially to bootstrap itself. They are in the format `abc.xyz.com:xxxx`. + */ + readonly bootstrapServers: string[] + + /** + * If your Kafka brokers are only reachable via VPC provide the VPC here + * + * @default none + */ + readonly vpc?: IVpc; + + /** + * If your Kafka brokers are only reachable via VPC, provide the subnets selection here + * + * @default - none, required if setting vpc + */ + readonly vpcSubnets?: SubnetSelection, + + /** + * If your Kafka brokers are only reachable via VPC, provide the security group here + * + * @default - none, required if setting vpc + */ + readonly securityGroup?: ISecurityGroup + + /** + * The authentication method for your Kafka cluster + * + * @default AuthenticationMethod.SASL_SCRAM_512_AUTH + */ + readonly authenticationMethod?: AuthenticationMethod +} + +/** + * Use a MSK cluster as a streaming source for AWS Lambda + */ +export class ManagedKafkaEventSource extends StreamEventSource { + // This is to work around JSII inheritance problems + private innerProps: ManagedKafkaEventSourceProps; + + constructor(props: ManagedKafkaEventSourceProps) { + super(props); + this.innerProps = props; + } + + public bind(target: lambda.IFunction) { + target.addEventSourceMapping( + `KafkaEventSource:${this.innerProps.cluster.clusterArn}${this.innerProps.topic}`, + this.enrichMappingOptions({ + eventSourceArn: this.innerProps.cluster.clusterArn, + startingPosition: this.innerProps.startingPosition, + // From https://docs.aws.amazon.com/msk/latest/developerguide/msk-password.html#msk-password-limitations, "Amazon MSK only supports SCRAM-SHA-512 authentication." + sourceAccessConfigurations: [{ type: lambda.SourceAccessConfigurationType.SASL_SCRAM_512_AUTH, uri: this.innerProps.secret.secretArn }], + kafkaTopic: this.innerProps.topic, + }), + ); + + this.innerProps.secret.grantRead(target); + + target.addToRolePolicy(new iam.PolicyStatement( + { + actions: ['kafka:DescribeCluster', 'kafka:GetBootstrapBrokers', 'kafka:ListScramSecrets'], + resources: [this.innerProps.cluster.clusterArn], + }, + )); + + target.role?.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSLambdaMSKExecutionRole')); + } +} + +/** + * Use a self hosted Kafka installation as a streaming source for AWS Lambda. + */ +export class SelfManagedKafkaEventSource extends StreamEventSource { + // This is to work around JSII inheritance problems + private innerProps: SelfManagedKafkaEventSourceProps; + + constructor(props: SelfManagedKafkaEventSourceProps) { + super(props); + if (props.vpc) { + if (!props.securityGroup) { + throw new Error('securityGroup must be set when providing vpc'); + } + if (!props.vpcSubnets) { + throw new Error('vpcSubnets must be set when providing vpc'); + } + } + this.innerProps = props; + } + + public bind(target: lambda.IFunction) { + if (!Construct.isConstruct(target)) { throw new Error('Function is not a construct. Unexpected error.'); } + target.addEventSourceMapping( + this.mappingId(target), + this.enrichMappingOptions({ + kafkaBootstrapServers: this.innerProps.bootstrapServers, + kafkaTopic: this.innerProps.topic, + startingPosition: this.innerProps.startingPosition, + sourceAccessConfigurations: this.sourceAccessConfigurations(), + }), + ); + this.innerProps.secret.grantRead(target); + } + + private mappingId(target: lambda.IFunction) { + let hash = crypto.createHash('md5'); + hash.update(JSON.stringify(Stack.of(target).resolve(this.innerProps.bootstrapServers))); + const idHash = hash.digest('hex'); + return `KafkaEventSource:${idHash}:${this.innerProps.topic}`; + } + + private sourceAccessConfigurations() { + let authType; + switch (this.innerProps.authenticationMethod) { + case AuthenticationMethod.SASL_SCRAM_256_AUTH: + authType = lambda.SourceAccessConfigurationType.SASL_SCRAM_256_AUTH; + break; + case AuthenticationMethod.SASL_SCRAM_512_AUTH: + default: + authType = lambda.SourceAccessConfigurationType.SASL_SCRAM_512_AUTH; + break; + } + let sourceAccessConfigurations = [{ type: authType, uri: this.innerProps.secret.secretArn }]; + if (this.innerProps.vpcSubnets !== undefined && this.innerProps.securityGroup !== undefined) { + sourceAccessConfigurations.push({ + type: lambda.SourceAccessConfigurationType.VPC_SECURITY_GROUP, + uri: this.innerProps.securityGroup.securityGroupId, + }, + ); + this.innerProps.vpc?.selectSubnets(this.innerProps.vpcSubnets).subnetIds.forEach((id) => { + sourceAccessConfigurations.push({ type: lambda.SourceAccessConfigurationType.VPC_SUBNET, uri: id }); + }); + } + return sourceAccessConfigurations; + } +} diff --git a/packages/@aws-cdk/aws-lambda-event-sources/lib/stream.ts b/packages/@aws-cdk/aws-lambda-event-sources/lib/stream.ts index d18eaaf3f947c..96907b97835fc 100644 --- a/packages/@aws-cdk/aws-lambda-event-sources/lib/stream.ts +++ b/packages/@aws-cdk/aws-lambda-event-sources/lib/stream.ts @@ -3,7 +3,7 @@ import { Duration } from '@aws-cdk/core'; /** * The set of properties for event sources that follow the streaming model, - * such as, Dynamo and Kinesis. + * such as, Dynamo, Kinesis and Kafka. */ export interface StreamEventSourceProps { /** diff --git a/packages/@aws-cdk/aws-lambda-event-sources/package.json b/packages/@aws-cdk/aws-lambda-event-sources/package.json index 20112e1029cbf..33906c1f5219e 100644 --- a/packages/@aws-cdk/aws-lambda-event-sources/package.json +++ b/packages/@aws-cdk/aws-lambda-event-sources/package.json @@ -72,12 +72,15 @@ "dependencies": { "@aws-cdk/aws-apigateway": "0.0.0", "@aws-cdk/aws-dynamodb": "0.0.0", + "@aws-cdk/aws-ec2": "0.0.0", "@aws-cdk/aws-events": "0.0.0", "@aws-cdk/aws-iam": "0.0.0", "@aws-cdk/aws-kinesis": "0.0.0", "@aws-cdk/aws-lambda": "0.0.0", + "@aws-cdk/aws-msk": "0.0.0", "@aws-cdk/aws-s3": "0.0.0", "@aws-cdk/aws-s3-notifications": "0.0.0", + "@aws-cdk/aws-secretsmanager": "0.0.0", "@aws-cdk/aws-sns": "0.0.0", "@aws-cdk/aws-sns-subscriptions": "0.0.0", "@aws-cdk/aws-sqs": "0.0.0", @@ -88,12 +91,15 @@ "peerDependencies": { "@aws-cdk/aws-apigateway": "0.0.0", "@aws-cdk/aws-dynamodb": "0.0.0", + "@aws-cdk/aws-ec2": "0.0.0", "@aws-cdk/aws-events": "0.0.0", "@aws-cdk/aws-iam": "0.0.0", "@aws-cdk/aws-kinesis": "0.0.0", "@aws-cdk/aws-lambda": "0.0.0", + "@aws-cdk/aws-msk": "0.0.0", "@aws-cdk/aws-s3": "0.0.0", "@aws-cdk/aws-s3-notifications": "0.0.0", + "@aws-cdk/aws-secretsmanager": "0.0.0", "@aws-cdk/aws-sns": "0.0.0", "@aws-cdk/aws-sns-subscriptions": "0.0.0", "@aws-cdk/aws-sqs": "0.0.0", diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/integ.s3.expected.json b/packages/@aws-cdk/aws-lambda-event-sources/test/integ.s3.expected.json index e4b5d64e2d04e..96f5a3e6a63d7 100644 --- a/packages/@aws-cdk/aws-lambda-event-sources/test/integ.s3.expected.json +++ b/packages/@aws-cdk/aws-lambda-event-sources/test/integ.s3.expected.json @@ -185,7 +185,7 @@ "Arn" ] }, - "Runtime": "nodejs14.x", + "Runtime": "nodejs12.x", "Timeout": 300 }, "DependsOn": [ diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/test.kafka.ts b/packages/@aws-cdk/aws-lambda-event-sources/test/test.kafka.ts new file mode 100644 index 0000000000000..9cf1af9e50507 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-event-sources/test/test.kafka.ts @@ -0,0 +1,334 @@ +import { arrayWith, expect, haveResource } from '@aws-cdk/assert'; +import { SecurityGroup, SubnetType, Vpc } from '@aws-cdk/aws-ec2'; +import * as lambda from '@aws-cdk/aws-lambda'; +import * as msk from '@aws-cdk/aws-msk'; +import { Secret } from '@aws-cdk/aws-secretsmanager'; +import * as cdk from '@aws-cdk/core'; +import { Test } from 'nodeunit'; +import * as sources from '../lib'; +import { TestFunction } from './test-function'; + +export = { + 'msk': { + 'default'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const fn = new TestFunction(stack, 'Fn'); + const cluster = msk.Cluster.fromClusterArn(stack, 'Cluster', 'some-arn'); + const kafkaTopic = 'some-topic'; + const secret = new Secret(stack, 'Secret', { secretName: 'AmazonMSK_KafkaSecret' }); + + // WHEN + fn.addEventSource(new sources.ManagedKafkaEventSource( + { + cluster: cluster, + topic: kafkaTopic, + secret: secret, + startingPosition: lambda.StartingPosition.TRIM_HORIZON, + })); + + // THEN + expect(stack).to(haveResource('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + { + Action: [ + 'secretsmanager:GetSecretValue', + 'secretsmanager:DescribeSecret', + ], + Effect: 'Allow', + Resource: { + Ref: 'SecretA720EF05', + }, + }, + { + Action: [ + 'kafka:DescribeCluster', + 'kafka:GetBootstrapBrokers', + 'kafka:ListScramSecrets', + ], + Effect: 'Allow', + Resource: cluster.clusterArn, + }, + ], + Version: '2012-10-17', + }, + PolicyName: 'FnServiceRoleDefaultPolicyC6A839BF', + Roles: [ + { + Ref: 'FnServiceRoleB9001A96', + }, + ], + })); + + expect(stack).to(haveResource('AWS::Lambda::EventSourceMapping', { + EventSourceArn: cluster.clusterArn, + FunctionName: { + Ref: 'Fn9270CBC0', + }, + BatchSize: 100, + StartingPosition: 'TRIM_HORIZON', + Topics: [ + kafkaTopic, + ], + SourceAccessConfigurations: [ + { + Type: 'SASL_SCRAM_512_AUTH', + URI: { + Ref: 'SecretA720EF05', + }, + }, + ], + })); + + test.done(); + }, + }, + + 'self managed kafka': { + 'default'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const fn = new TestFunction(stack, 'Fn'); + const kafkaTopic = 'some-topic'; + const secret = new Secret(stack, 'Secret', { secretName: 'AmazonMSK_KafkaSecret' }); + const bootstrapServers = ['kafka-broker:9092']; + + // WHEN + fn.addEventSource(new sources.SelfManagedKafkaEventSource( + { + bootstrapServers: bootstrapServers, + topic: kafkaTopic, + secret: secret, + startingPosition: lambda.StartingPosition.TRIM_HORIZON, + })); + + // THEN + expect(stack).to(haveResource('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + { + Action: [ + 'secretsmanager:GetSecretValue', + 'secretsmanager:DescribeSecret', + ], + Effect: 'Allow', + Resource: { + Ref: 'SecretA720EF05', + }, + }, + ], + Version: '2012-10-17', + }, + PolicyName: 'FnServiceRoleDefaultPolicyC6A839BF', + Roles: [ + { + Ref: 'FnServiceRoleB9001A96', + }, + ], + })); + + expect(stack).to(haveResource('AWS::Lambda::EventSourceMapping', { + FunctionName: { + Ref: 'Fn9270CBC0', + }, + BatchSize: 100, + SelfManagedEventSource: { + Endpoints: { + KafkaBootstrapServers: bootstrapServers, + }, + }, + StartingPosition: 'TRIM_HORIZON', + Topics: [ + kafkaTopic, + ], + SourceAccessConfigurations: [ + { + Type: 'SASL_SCRAM_512_AUTH', + URI: { + Ref: 'SecretA720EF05', + }, + }, + ], + })); + + test.done(); + }, + + VPC: { + 'correctly rendered in the stack'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const fn = new TestFunction(stack, 'Fn'); + const kafkaTopic = 'some-topic'; + const secret = new Secret(stack, 'Secret', { secretName: 'AmazonMSK_KafkaSecret' }); + const bootstrapServers = ['kafka-broker:9092']; + const sg = SecurityGroup.fromSecurityGroupId(stack, 'SecurityGroup', 'sg-0123456789'); + const vpc = new Vpc(stack, 'Vpc'); + + // WHEN + fn.addEventSource(new sources.SelfManagedKafkaEventSource( + { + bootstrapServers: bootstrapServers, + topic: kafkaTopic, + secret: secret, + startingPosition: lambda.StartingPosition.TRIM_HORIZON, + vpc: vpc, + vpcSubnets: { subnetType: SubnetType.PRIVATE }, + securityGroup: sg, + })); + + // THEN + expect(stack).to(haveResource('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + { + Action: [ + 'secretsmanager:GetSecretValue', + 'secretsmanager:DescribeSecret', + ], + Effect: 'Allow', + Resource: { + Ref: 'SecretA720EF05', + }, + }, + ], + Version: '2012-10-17', + }, + PolicyName: 'FnServiceRoleDefaultPolicyC6A839BF', + Roles: [ + { + Ref: 'FnServiceRoleB9001A96', + }, + ], + })); + + expect(stack).to(haveResource('AWS::Lambda::EventSourceMapping', { + FunctionName: { + Ref: 'Fn9270CBC0', + }, + BatchSize: 100, + SelfManagedEventSource: { + Endpoints: { + KafkaBootstrapServers: bootstrapServers, + }, + }, + StartingPosition: 'TRIM_HORIZON', + Topics: [ + kafkaTopic, + ], + SourceAccessConfigurations: [ + { + Type: 'SASL_SCRAM_512_AUTH', + URI: { + Ref: 'SecretA720EF05', + }, + }, + { + Type: 'VPC_SECURITY_GROUP', + URI: 'sg-0123456789', + }, + { + Type: 'VPC_SUBNET', + URI: { + Ref: 'VpcPrivateSubnet1Subnet536B997A', + }, + }, + { + Type: 'VPC_SUBNET', + URI: { + Ref: 'VpcPrivateSubnet2Subnet3788AAA1', + }, + }, + ], + })); + + test.done(); + }, + 'setting vpc requires vpcSubnets to be set'(test: Test) { + const stack = new cdk.Stack(); + const fn = new TestFunction(stack, 'Fn'); + const kafkaTopic = 'some-topic'; + const secret = new Secret(stack, 'Secret', { secretName: 'AmazonMSK_KafkaSecret' }); + const bootstrapServers = ['kafka-broker:9092']; + const vpc = new Vpc(stack, 'Vpc'); + + test.throws(() => { + fn.addEventSource(new sources.SelfManagedKafkaEventSource( + { + bootstrapServers: bootstrapServers, + topic: kafkaTopic, + secret: secret, + startingPosition: lambda.StartingPosition.TRIM_HORIZON, + vpc: vpc, + securityGroup: SecurityGroup.fromSecurityGroupId(stack, 'SecurityGroup', 'sg-0123456789'), + + })); + }, /vpcSubnets must be set/); + + test.done(); + }, + + 'setting vpc requires securityGroup to be set'(test: Test) { + const stack = new cdk.Stack(); + const fn = new TestFunction(stack, 'Fn'); + const kafkaTopic = 'some-topic'; + const secret = new Secret(stack, 'Secret', { secretName: 'AmazonMSK_KafkaSecret' }); + const bootstrapServers = ['kafka-broker:9092']; + const vpc = new Vpc(stack, 'Vpc'); + + test.throws(() => { + fn.addEventSource(new sources.SelfManagedKafkaEventSource( + { + bootstrapServers: bootstrapServers, + topic: kafkaTopic, + secret: secret, + startingPosition: lambda.StartingPosition.TRIM_HORIZON, + vpc: vpc, + vpcSubnets: { subnetType: SubnetType.PRIVATE }, + })); + }, /securityGroup must be set/); + + test.done(); + }, + }, + + 'using SCRAM-SHA-256'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const fn = new TestFunction(stack, 'Fn'); + const kafkaTopic = 'some-topic'; + const secret = new Secret(stack, 'Secret', { secretName: 'AmazonMSK_KafkaSecret' }); + const bootstrapServers = ['kafka-broker:9092']; + const sg = SecurityGroup.fromSecurityGroupId(stack, 'SecurityGroup', 'sg-0123456789'); + const vpc = new Vpc(stack, 'Vpc'); + + // WHEN + fn.addEventSource(new sources.SelfManagedKafkaEventSource( + { + bootstrapServers: bootstrapServers, + topic: kafkaTopic, + secret: secret, + startingPosition: lambda.StartingPosition.TRIM_HORIZON, + vpc: vpc, + vpcSubnets: { subnetType: SubnetType.PRIVATE }, + securityGroup: sg, + authenticationMethod: sources.AuthenticationMethod.SASL_SCRAM_256_AUTH, + })); + + expect(stack).to(haveResource('AWS::Lambda::EventSourceMapping', { + SourceAccessConfigurations: arrayWith( + { + Type: 'SASL_SCRAM_256_AUTH', + URI: { + Ref: 'SecretA720EF05', + }, + }, + ), + })); + + test.done(); + }, + }, + +} diff --git a/packages/@aws-cdk/aws-lambda-nodejs/package.json b/packages/@aws-cdk/aws-lambda-nodejs/package.json index 03e6cb806817e..c411d343615fe 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/package.json +++ b/packages/@aws-cdk/aws-lambda-nodejs/package.json @@ -67,7 +67,7 @@ "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", "delay": "5.0.0", - "esbuild": "^0.8.55", + "esbuild": "^0.9.3", "pkglint": "0.0.0" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-lambda/lib/event-source-mapping.ts b/packages/@aws-cdk/aws-lambda/lib/event-source-mapping.ts index d44ce1cbea1b4..239bf58671b7e 100644 --- a/packages/@aws-cdk/aws-lambda/lib/event-source-mapping.ts +++ b/packages/@aws-cdk/aws-lambda/lib/event-source-mapping.ts @@ -4,12 +4,78 @@ import { IEventSourceDlq } from './dlq'; import { IFunction } from './function-base'; import { CfnEventSourceMapping } from './lambda.generated'; +/** + * The type of authentication protocol or the VPC components for your event source's SourceAccessConfiguration + * @see https://docs.aws.amazon.com/lambda/latest/dg/API_SourceAccessConfiguration.html#SSS-Type-SourceAccessConfiguration-Type + */ +export class SourceAccessConfigurationType { + + /** + * (MQ) The Secrets Manager secret that stores your broker credentials. + */ + public static readonly BASIC_AUTH = new SourceAccessConfigurationType('BASIC_AUTH'); + + /** + * The subnets associated with your VPC. Lambda connects to these subnets to fetch data from your Self-Managed Apache Kafka cluster. + */ + public static readonly VPC_SUBNET = new SourceAccessConfigurationType('VPC_SUBNET'); + + /** + * The VPC security group used to manage access to your Self-Managed Apache Kafka brokers. + */ + public static readonly VPC_SECURITY_GROUP = new SourceAccessConfigurationType('VPC_SECURITY_GROUP'); + + /** + * The Secrets Manager ARN of your secret key used for SASL SCRAM-256 authentication of your Self-Managed Apache Kafka brokers. + */ + public static readonly SASL_SCRAM_256_AUTH = new SourceAccessConfigurationType('SASL_SCRAM_256_AUTH'); + + /** + * The Secrets Manager ARN of your secret key used for SASL SCRAM-512 authentication of your Self-Managed Apache Kafka brokers. + */ + public static readonly SASL_SCRAM_512_AUTH = new SourceAccessConfigurationType('SASL_SCRAM_512_AUTH'); + + /** A custom source access configuration property */ + public static of(name: string): SourceAccessConfigurationType { + return new SourceAccessConfigurationType(name); + } + + /** + * The key to use in `SourceAccessConfigurationProperty.Type` property in CloudFormation + * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-eventsourcemapping-sourceaccessconfiguration.html#cfn-lambda-eventsourcemapping-sourceaccessconfiguration-type + */ + public readonly type: string; + + private constructor(type: string) { + this.type = type; + } +} + +/** + * Specific settings like the authentication protocol or the VPC components to secure access to your event source. + */ +export interface SourceAccessConfiguration { + /** + * The type of authentication protocol or the VPC components for your event source. For example: "SASL_SCRAM_512_AUTH". + */ + readonly type: SourceAccessConfigurationType, + /** + * The value for your chosen configuration in type. + * For example: "URI": "arn:aws:secretsmanager:us-east-1:01234567890:secret:MyBrokerSecretName". + * The exact string depends on the type. + * @see SourceAccessConfigurationType + */ + readonly uri: string +} + export interface EventSourceMappingOptions { /** * The Amazon Resource Name (ARN) of the event source. Any record added to * this stream can invoke the Lambda function. + * + * @default - not set if using a self managed Kafka cluster, throws an error otherwise */ - readonly eventSourceArn: string; + readonly eventSourceArn?: string; /** * The largest number of records that AWS Lambda will retrieve from your event @@ -101,6 +167,23 @@ export interface EventSourceMappingOptions { * @default - no topic */ readonly kafkaTopic?: string; + + /** + * A list of host and port pairs that are the addresses of the Kafka brokers in a self managed "bootstrap" Kafka cluster + * that a Kafka client connects to initially to bootstrap itself. + * They are in the format `abc.example.com:9096`. + * + * @default - none + */ + readonly kafkaBootstrapServers?: string[] + + /** + * Specific settings like the authentication protocol or the VPC components to secure access to your event source. + * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-eventsourcemapping-sourceaccessconfiguration.html + * + * @default - none + */ + readonly sourceAccessConfigurations?: SourceAccessConfiguration[] } /** @@ -154,6 +237,18 @@ export class EventSourceMapping extends cdk.Resource implements IEventSourceMapp constructor(scope: Construct, id: string, props: EventSourceMappingProps) { super(scope, id); + if (props.eventSourceArn == undefined && props.kafkaBootstrapServers == undefined) { + throw new Error('Either eventSourceArn or kafkaBootstrapServers must be set'); + } + + if (props.eventSourceArn !== undefined && props.kafkaBootstrapServers !== undefined) { + throw new Error('eventSourceArn and kafkaBootstrapServers are mutually exclusive'); + } + + if (props.kafkaBootstrapServers && (props.kafkaBootstrapServers?.length < 1)) { + throw new Error('kafkaBootStrapServers must not be empty if set'); + } + if (props.maxBatchingWindow && props.maxBatchingWindow.toSeconds() > 300) { throw new Error(`maxBatchingWindow cannot be over 300 seconds, got ${props.maxBatchingWindow.toSeconds()}`); } @@ -183,6 +278,11 @@ export class EventSourceMapping extends cdk.Resource implements IEventSourceMapp }; } + let selfManagedEventSource; + if (props.kafkaBootstrapServers) { + selfManagedEventSource = { endpoints: { kafkaBootstrapServers: props.kafkaBootstrapServers } }; + } + const cfnEventSourceMapping = new CfnEventSourceMapping(this, 'Resource', { batchSize: props.batchSize, bisectBatchOnFunctionError: props.bisectBatchOnError, @@ -196,6 +296,8 @@ export class EventSourceMapping extends cdk.Resource implements IEventSourceMapp maximumRetryAttempts: props.retryAttempts, parallelizationFactor: props.parallelizationFactor, topics: props.kafkaTopic !== undefined ? [props.kafkaTopic] : undefined, + sourceAccessConfigurations: props.sourceAccessConfigurations?.map((o) => {return { type: o.type.type, uri: o.uri };}), + selfManagedEventSource, }); this.eventSourceMappingId = cfnEventSourceMapping.ref; } diff --git a/packages/@aws-cdk/aws-lambda/test/event-source-mapping.test.ts b/packages/@aws-cdk/aws-lambda/test/event-source-mapping.test.ts index be42067f263f1..5d833a2d865c6 100644 --- a/packages/@aws-cdk/aws-lambda/test/event-source-mapping.test.ts +++ b/packages/@aws-cdk/aws-lambda/test/event-source-mapping.test.ts @@ -170,4 +170,95 @@ describe('event source mapping', () => { }], }); }); + + test('throws if neither eventSourceArn nor kafkaBootstrapServers are set', () => { + const stack = new cdk.Stack(); + const fn = new Function(stack, 'fn', { + handler: 'index.handler', + code: Code.fromInline('exports.handler = ${handler.toString()}'), + runtime: Runtime.NODEJS_10_X, + }); + + expect(() => new EventSourceMapping(stack, 'test', { + target: fn, + })).toThrow(/Either eventSourceArn or kafkaBootstrapServers must be set/); + }); + + test('throws if both eventSourceArn and kafkaBootstrapServers are set', () => { + const stack = new cdk.Stack(); + const fn = new Function(stack, 'fn', { + handler: 'index.handler', + code: Code.fromInline('exports.handler = ${handler.toString()}'), + runtime: Runtime.NODEJS_10_X, + }); + + expect(() => new EventSourceMapping(stack, 'test', { + eventSourceArn: '', + kafkaBootstrapServers: [], + target: fn, + })).toThrow(/eventSourceArn and kafkaBootstrapServers are mutually exclusive/); + }); + + test('throws if both kafkaBootstrapServers is set but empty', () => { + const stack = new cdk.Stack(); + const fn = new Function(stack, 'fn', { + handler: 'index.handler', + code: Code.fromInline('exports.handler = ${handler.toString()}'), + runtime: Runtime.NODEJS_10_X, + }); + + expect(() => new EventSourceMapping(stack, 'test', { + kafkaBootstrapServers: [], + target: fn, + })).toThrow(/kafkaBootStrapServers must not be empty if set/); + }); + + test('eventSourceArn appears in stack', () => { + const stack = new cdk.Stack(); + const topicNameParam = new cdk.CfnParameter(stack, 'TopicNameParam', { + type: 'String', + }); + + const fn = new Function(stack, 'fn', { + handler: 'index.handler', + code: Code.fromInline('exports.handler = ${handler.toString()}'), + runtime: Runtime.NODEJS_10_X, + }); + + let eventSourceArn = 'some-arn'; + + new EventSourceMapping(stack, 'test', { + target: fn, + eventSourceArn: eventSourceArn, + kafkaTopic: topicNameParam.valueAsString, + }); + + expect(stack).toHaveResourceLike('AWS::Lambda::EventSourceMapping', { + EventSourceArn: eventSourceArn, + }); + }); + + test('kafkaBootstrapServers appears in stack', () => { + const stack = new cdk.Stack(); + const topicNameParam = new cdk.CfnParameter(stack, 'TopicNameParam', { + type: 'String', + }); + + const fn = new Function(stack, 'fn', { + handler: 'index.handler', + code: Code.fromInline('exports.handler = ${handler.toString()}'), + runtime: Runtime.NODEJS_10_X, + }); + + let kafkaBootstrapServers = ['kafka-broker.example.com:9092']; + new EventSourceMapping(stack, 'test', { + target: fn, + kafkaBootstrapServers: kafkaBootstrapServers, + kafkaTopic: topicNameParam.valueAsString, + }); + + expect(stack).toHaveResourceLike('AWS::Lambda::EventSourceMapping', { + SelfManagedEventSource: { Endpoints: { KafkaBootstrapServers: kafkaBootstrapServers } }, + }); + }); }); diff --git a/packages/@aws-cdk/aws-logs/package.json b/packages/@aws-cdk/aws-logs/package.json index f778b855211eb..b5bded382ba10 100644 --- a/packages/@aws-cdk/aws-logs/package.json +++ b/packages/@aws-cdk/aws-logs/package.json @@ -77,7 +77,7 @@ "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", "cfn2ts": "0.0.0", - "nock": "^13.0.10", + "nock": "^13.0.11", "nodeunit": "^0.11.3", "pkglint": "0.0.0", "sinon": "^9.2.4" diff --git a/packages/@aws-cdk/aws-msk/README.md b/packages/@aws-cdk/aws-msk/README.md index 1de05861fc74f..51d93453f1eef 100644 --- a/packages/@aws-cdk/aws-msk/README.md +++ b/packages/@aws-cdk/aws-msk/README.md @@ -9,6 +9,14 @@ > > [CFN Resources]: https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_lib +![cdk-constructs: Experimental](https://img.shields.io/badge/cdk--constructs-experimental-important.svg?style=for-the-badge) + +> The APIs of higher level constructs in this module are experimental and under active development. +> They are subject to non-backward compatible changes or removal in any future version. These are +> not subject to the [Semantic Versioning](https://semver.org/) model and breaking changes will be +> announced in the release notes. This means that while you may use them, you may need to update +> your source code when upgrading to a newer version of this package. + --- diff --git a/packages/@aws-cdk/aws-msk/lib/cluster.ts b/packages/@aws-cdk/aws-msk/lib/cluster.ts new file mode 100644 index 0000000000000..313bd3de5b107 --- /dev/null +++ b/packages/@aws-cdk/aws-msk/lib/cluster.ts @@ -0,0 +1,34 @@ +import { IResource, Resource } from '@aws-cdk/core'; +import { Construct } from 'constructs'; + +/** + * Represents an MSK cluster + */ +export interface ICluster extends IResource { + /** + * the ARN of the MSK cluster + */ + readonly clusterArn: string; +} + +/** + * An MSK cluster + */ +export class Cluster { + /** + * Creates a Cluster construct that represents an existing MSK cluster. + * @param scope + * @param id + * @param clusterArn + */ + public static fromClusterArn(scope: Construct, id: string, clusterArn: string): ICluster { + class Imported extends Resource implements ICluster { + public readonly clusterArn: string; + constructor() { + super(scope, id); + this.clusterArn = clusterArn; + } + } + return new Imported(); + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-msk/lib/index.ts b/packages/@aws-cdk/aws-msk/lib/index.ts index 3cf150cbd7076..9cc4acdc7d61f 100644 --- a/packages/@aws-cdk/aws-msk/lib/index.ts +++ b/packages/@aws-cdk/aws-msk/lib/index.ts @@ -1,2 +1,3 @@ +export * from './cluster'; // AWS::MSK CloudFormation Resources: export * from './msk.generated'; diff --git a/packages/@aws-cdk/aws-msk/package.json b/packages/@aws-cdk/aws-msk/package.json index 939b66619cda7..efa91da07d39f 100644 --- a/packages/@aws-cdk/aws-msk/package.json +++ b/packages/@aws-cdk/aws-msk/package.json @@ -90,7 +90,7 @@ "node": ">= 10.13.0 <13 || >=13.7.0" }, "stability": "experimental", - "maturity": "cfn-only", + "maturity": "experimental", "awscdkio": { "announce": false }, diff --git a/packages/@aws-cdk/aws-rds/lib/instance-engine.ts b/packages/@aws-cdk/aws-rds/lib/instance-engine.ts index 95d462c23f5fc..3b35ad1c87ce1 100644 --- a/packages/@aws-cdk/aws-rds/lib/instance-engine.ts +++ b/packages/@aws-cdk/aws-rds/lib/instance-engine.ts @@ -217,6 +217,11 @@ export class MariaDbEngineVersion { /** Version "10.4.13". */ public static readonly VER_10_4_13 = MariaDbEngineVersion.of('10.4.13', '10.4'); + /** Version "10.5" (only a major version, without a specific minor version). */ + public static readonly VER_10_5 = MariaDbEngineVersion.of('10.5', '10.5'); + /** Version "10.5.8". */ + public static readonly VER_10_5_8 = MariaDbEngineVersion.of('10.5.8', '10.5'); + /** * Create a new MariaDbEngineVersion with an arbitrary version. * diff --git a/packages/@aws-cdk/aws-s3-notifications/test/integ.notifications.expected.json b/packages/@aws-cdk/aws-s3-notifications/test/integ.notifications.expected.json index f0babb81fc0a6..f8b1a350486f9 100644 --- a/packages/@aws-cdk/aws-s3-notifications/test/integ.notifications.expected.json +++ b/packages/@aws-cdk/aws-s3-notifications/test/integ.notifications.expected.json @@ -220,7 +220,7 @@ "Arn" ] }, - "Runtime": "nodejs14.x", + "Runtime": "nodejs12.x", "Timeout": 300 }, "DependsOn": [ diff --git a/packages/@aws-cdk/aws-s3-notifications/test/lambda/integ.bucket-notifications.expected.json b/packages/@aws-cdk/aws-s3-notifications/test/lambda/integ.bucket-notifications.expected.json index 918c4a9d09334..8eb330f53a91e 100644 --- a/packages/@aws-cdk/aws-s3-notifications/test/lambda/integ.bucket-notifications.expected.json +++ b/packages/@aws-cdk/aws-s3-notifications/test/lambda/integ.bucket-notifications.expected.json @@ -244,7 +244,7 @@ "Arn" ] }, - "Runtime": "nodejs14.x", + "Runtime": "nodejs12.x", "Timeout": 300 }, "DependsOn": [ diff --git a/packages/@aws-cdk/aws-s3-notifications/test/sns/integ.sns-bucket-notifications.expected.json b/packages/@aws-cdk/aws-s3-notifications/test/sns/integ.sns-bucket-notifications.expected.json index ecdd9d831e74f..2cd8f17706a09 100644 --- a/packages/@aws-cdk/aws-s3-notifications/test/sns/integ.sns-bucket-notifications.expected.json +++ b/packages/@aws-cdk/aws-s3-notifications/test/sns/integ.sns-bucket-notifications.expected.json @@ -203,7 +203,7 @@ "Arn" ] }, - "Runtime": "nodejs14.x", + "Runtime": "nodejs12.x", "Timeout": 300 }, "DependsOn": [ diff --git a/packages/@aws-cdk/aws-s3-notifications/test/sqs/integ.bucket-notifications.expected.json b/packages/@aws-cdk/aws-s3-notifications/test/sqs/integ.bucket-notifications.expected.json index ea40221e82f15..0e8a6a56cfb6e 100644 --- a/packages/@aws-cdk/aws-s3-notifications/test/sqs/integ.bucket-notifications.expected.json +++ b/packages/@aws-cdk/aws-s3-notifications/test/sqs/integ.bucket-notifications.expected.json @@ -192,7 +192,7 @@ "Arn" ] }, - "Runtime": "nodejs14.x", + "Runtime": "nodejs12.x", "Timeout": 300 }, "DependsOn": [ diff --git a/packages/@aws-cdk/aws-s3/lib/notifications-resource/notifications-resource-handler.ts b/packages/@aws-cdk/aws-s3/lib/notifications-resource/notifications-resource-handler.ts index 8a47247be1b1e..b013bc0ebd5b8 100644 --- a/packages/@aws-cdk/aws-s3/lib/notifications-resource/notifications-resource-handler.ts +++ b/packages/@aws-cdk/aws-s3/lib/notifications-resource/notifications-resource-handler.ts @@ -82,7 +82,7 @@ export class NotificationsResourceHandler extends Construct { Code: { ZipFile: `exports.handler = ${handler.toString()};` }, Handler: 'index.handler', Role: role.roleArn, - Runtime: 'nodejs14.x', + Runtime: 'nodejs12.x', Timeout: 300, }, }); diff --git a/packages/@aws-cdk/aws-sam/package.json b/packages/@aws-cdk/aws-sam/package.json index 686ceb3b92b41..4aa84ecd73fe3 100644 --- a/packages/@aws-cdk/aws-sam/package.json +++ b/packages/@aws-cdk/aws-sam/package.json @@ -78,7 +78,7 @@ "cfn2ts": "0.0.0", "jest": "^26.6.3", "pkglint": "0.0.0", - "ts-jest": "^26.5.3" + "ts-jest": "^26.5.4" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-sns/README.md b/packages/@aws-cdk/aws-sns/README.md index b5d9f52c3d9b9..ca80f72f9aad3 100644 --- a/packages/@aws-cdk/aws-sns/README.md +++ b/packages/@aws-cdk/aws-sns/README.md @@ -131,3 +131,43 @@ codeCommitRepository.onCommit(new targets.SnsTopic(myTopic)); This will result in adding a target to the event rule and will also modify the topic resource policy to allow CloudWatch events to publish to the topic. + +## Topic Policy + +A topic policy is automatically created when `addToResourcePolicy` is called, if +one doesn't already exist. Using `addToResourcePolicy` is the simplest way to +add policies, but a `TopicPolicy` can also be created manually. + +```ts +const topic = new sns.Topic(stack, 'Topic'); +const topicPolicy = new sns.TopicPolicy(stack, 'TopicPolicy', { + topics: [topic], +}); + +topicPolicy.document.addStatements(new iam.PolicyStatement({ + actions: ["sns:Subscribe"], + principals: [new iam.AnyPrincipal()], + resources: [topic.topicArn], +})); +``` + +A policy document can also be passed on `TopicPolicy` construction + +```ts +const topic = new sns.Topic(stack, 'Topic'); +const policyDocument = new iam.PolicyDocument({ + assignSids: true, + statements: [ + new iam.PolicyStatement({ + actions: ["sns:Subscribe"], + principals: [new iam.AnyPrincipal()], + resources: [topic.topicArn] + }), + ], +}); + +const topicPolicy = new sns.TopicPolicy(this, 'Policy', { + topics: [topic], + policyDocument, +}); +``` diff --git a/packages/@aws-cdk/aws-sns/lib/policy.ts b/packages/@aws-cdk/aws-sns/lib/policy.ts index 7d93d863a75f0..03a791bd57814 100644 --- a/packages/@aws-cdk/aws-sns/lib/policy.ts +++ b/packages/@aws-cdk/aws-sns/lib/policy.ts @@ -12,6 +12,12 @@ export interface TopicPolicyProps { * The set of topics this policy applies to. */ readonly topics: ITopic[]; + /** + * IAM policy document to apply to topic(s). + * @default empty policy document + */ + readonly policyDocument?: PolicyDocument; + } /** @@ -32,6 +38,8 @@ export class TopicPolicy extends Resource { constructor(scope: Construct, id: string, props: TopicPolicyProps) { super(scope, id); + this.document = props.policyDocument ?? this.document; + new CfnTopicPolicy(this, 'Resource', { policyDocument: this.document, topics: props.topics.map(t => t.topicArn), diff --git a/packages/@aws-cdk/aws-sns/test/test.sns.ts b/packages/@aws-cdk/aws-sns/test/test.sns.ts index cc4b50aed717c..5261900f9059b 100644 --- a/packages/@aws-cdk/aws-sns/test/test.sns.ts +++ b/packages/@aws-cdk/aws-sns/test/test.sns.ts @@ -276,6 +276,97 @@ export = { test.done(); }, + 'TopicPolicy passed document'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const topic = new sns.Topic(stack, 'MyTopic'); + const ps = new iam.PolicyStatement({ + actions: ['service:statement0'], + principals: [new iam.ArnPrincipal('arn')], + }); + + // WHEN + new sns.TopicPolicy(stack, 'topicpolicy', { topics: [topic], policyDocument: new iam.PolicyDocument({ assignSids: true, statements: [ps] }) }); + + // THEN + expect(stack).toMatch({ + 'Resources': { + 'MyTopic86869434': { + 'Type': 'AWS::SNS::Topic', + }, + 'topicpolicyF8CF12FD': { + 'Type': 'AWS::SNS::TopicPolicy', + 'Properties': { + 'PolicyDocument': { + 'Statement': [ + { + 'Action': 'service:statement0', + 'Effect': 'Allow', + 'Principal': { 'AWS': 'arn' }, + 'Sid': '0', + }, + ], + 'Version': '2012-10-17', + }, + 'Topics': [ + { + 'Ref': 'MyTopic86869434', + }, + ], + }, + }, + }, + }); + + test.done(); + }, + + 'Add statements to policy'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const topic = new sns.Topic(stack, 'MyTopic'); + + // WHEN + const topicPolicy = new sns.TopicPolicy(stack, 'TopicPolicy', { + topics: [topic], + }); + topicPolicy.document.addStatements(new iam.PolicyStatement({ + actions: ['service:statement0'], + principals: [new iam.ArnPrincipal('arn')], + })); + + // THEN + expect(stack).toMatch({ + 'Resources': { + 'MyTopic86869434': { + 'Type': 'AWS::SNS::Topic', + }, + 'TopicPolicyA24B096F': { + 'Type': 'AWS::SNS::TopicPolicy', + 'Properties': { + 'PolicyDocument': { + 'Statement': [ + { + 'Action': 'service:statement0', + 'Effect': 'Allow', + 'Principal': { 'AWS': 'arn' }, + 'Sid': '0', + }, + ], + 'Version': '2012-10-17', + }, + 'Topics': [ + { + 'Ref': 'MyTopic86869434', + }, + ], + }, + }, + }, + }); + test.done(); + }, + 'topic resource policy includes unique SIDs'(test: Test) { const stack = new cdk.Stack(); diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/apigateway/integ.call-http-api.expected.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/apigateway/integ.call-http-api.expected.json index 6afe44cfecda5..56d4889af3d55 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/apigateway/integ.call-http-api.expected.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/apigateway/integ.call-http-api.expected.json @@ -77,7 +77,6 @@ "Ref": "MyHttpApi8AEAAC21" }, "RouteKey": "ANY /", - "AuthorizationScopes": [], "Target": { "Fn::Join": [ "", diff --git a/packages/@aws-cdk/cfnspec/CHANGELOG.md b/packages/@aws-cdk/cfnspec/CHANGELOG.md index 1affea5b1d444..861146ecf1337 100644 --- a/packages/@aws-cdk/cfnspec/CHANGELOG.md +++ b/packages/@aws-cdk/cfnspec/CHANGELOG.md @@ -1,3 +1,86 @@ +# CloudFormation Resource Specification v31.0.0 + +## New Resource Types + +* AWS::CE::AnomalyMonitor +* AWS::CE::AnomalySubscription +* AWS::CertificateManager::Account +* AWS::ECS::ClusterCapacityProviderAssociations +* AWS::RDS::DBProxyEndpoint + +## Attribute Changes + +* AWS::SSM::ResourceDataSync SyncName (__added__) + +## Property Changes + +* AWS::AppSync::GraphQLApi LambdaAuthorizerConfig (__added__) +* AWS::Backup::BackupPlan BackupPlanTags.PrimitiveType (__deleted__) +* AWS::Backup::BackupPlan BackupPlanTags.PrimitiveItemType (__added__) +* AWS::Backup::BackupPlan BackupPlanTags.Type (__added__) +* AWS::DynamoDB::Table KinesisStreamSpecification (__deleted__) +* AWS::DynamoDB::Table ContributorInsightsSpecification (__added__) +* AWS::EC2::LaunchTemplate TagSpecifications (__added__) +* AWS::ECS::CapacityProvider AutoScalingGroupProvider.UpdateType (__changed__) + * Old: Immutable + * New: Mutable +* AWS::ECS::Cluster Configuration (__added__) +* AWS::ECS::Service EnableExecuteCommand (__added__) +* AWS::EFS::FileSystem AvailabilityZoneName (__added__) + +## Property Type Changes + +* AWS::DynamoDB::Table.KinesisStreamSpecification (__removed__) +* AWS::AppSync::GraphQLApi.LambdaAuthorizerConfig (__added__) +* AWS::DynamoDB::Table.ContributorInsightsSpecification (__added__) +* AWS::EC2::LaunchTemplate.TagSpecifications (__added__) +* AWS::ECS::Cluster.ClusterConfiguration (__added__) +* AWS::ECS::Cluster.ExecuteCommandConfiguration (__added__) +* AWS::ECS::Cluster.ExecuteCommandLogConfiguration (__added__) +* AWS::AppSync::GraphQLApi.AdditionalAuthenticationProvider LambdaAuthorizerConfig (__added__) +* AWS::Backup::BackupPlan.BackupPlanResourceType AdvancedBackupSettings.DuplicatesAllowed (__added__) +* AWS::Backup::BackupPlan.BackupPlanResourceType BackupPlanRule.DuplicatesAllowed (__added__) +* AWS::Backup::BackupPlan.BackupRuleResourceType CopyActions.DuplicatesAllowed (__added__) +* AWS::Backup::BackupPlan.BackupRuleResourceType RecoveryPointTags.PrimitiveType (__deleted__) +* AWS::Backup::BackupPlan.BackupRuleResourceType RecoveryPointTags.PrimitiveItemType (__added__) +* AWS::Backup::BackupPlan.BackupRuleResourceType RecoveryPointTags.Type (__added__) +* AWS::DynamoDB::Table.GlobalSecondaryIndex ContributorInsightsSpecification (__added__) +* AWS::ECS::CapacityProvider.AutoScalingGroupProvider ManagedScaling.UpdateType (__changed__) + * Old: Immutable + * New: Mutable +* AWS::ECS::CapacityProvider.AutoScalingGroupProvider ManagedTerminationProtection.UpdateType (__changed__) + * Old: Immutable + * New: Mutable +* AWS::ECS::CapacityProvider.ManagedScaling MaximumScalingStepSize.UpdateType (__changed__) + * Old: Immutable + * New: Mutable +* AWS::ECS::CapacityProvider.ManagedScaling MinimumScalingStepSize.UpdateType (__changed__) + * Old: Immutable + * New: Mutable +* AWS::ECS::CapacityProvider.ManagedScaling Status.UpdateType (__changed__) + * Old: Immutable + * New: Mutable +* AWS::ECS::CapacityProvider.ManagedScaling TargetCapacity.UpdateType (__changed__) + * Old: Immutable + * New: Mutable +* AWS::GameLift::Alias.RoutingStrategy Type.Required (__changed__) + * Old: false + * New: true +* AWS::IoT::TopicRule.S3Action CannedAcl (__added__) +* AWS::IoT::TopicRule.TopicRulePayload Actions.DuplicatesAllowed (__deleted__) +* AWS::IoT::TopicRule.TopicRulePayload RuleDisabled.Required (__changed__) + * Old: true + * New: false +* AWS::SSM::ResourceDataSync.AwsOrganizationsSource OrganizationSourceType.UpdateType (__changed__) + * Old: Immutable + * New: Mutable +* AWS::SSM::ResourceDataSync.AwsOrganizationsSource OrganizationalUnits.DuplicatesAllowed (__added__) +* AWS::SSM::ResourceDataSync.SyncSource SourceRegions.DuplicatesAllowed (__added__) +* AWS::SSM::ResourceDataSync.SyncSource SourceType.UpdateType (__changed__) + * Old: Immutable + * New: Mutable + + # CloudFormation Resource Specification v30.1.0 ## New Resource Types diff --git a/packages/@aws-cdk/cfnspec/cfn.version b/packages/@aws-cdk/cfnspec/cfn.version index a75ef34cbaa5c..221a8da0b5798 100644 --- a/packages/@aws-cdk/cfnspec/cfn.version +++ b/packages/@aws-cdk/cfnspec/cfn.version @@ -1 +1 @@ -30.1.0 +31.0.0 diff --git a/packages/@aws-cdk/cfnspec/spec-source/000_CloudFormationResourceSpecification.json b/packages/@aws-cdk/cfnspec/spec-source/000_CloudFormationResourceSpecification.json index 05d46dca703b8..c3d61d168d11e 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/000_CloudFormationResourceSpecification.json +++ b/packages/@aws-cdk/cfnspec/spec-source/000_CloudFormationResourceSpecification.json @@ -6388,6 +6388,12 @@ "Required": true, "UpdateType": "Mutable" }, + "LambdaAuthorizerConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appsync-graphqlapi-additionalauthenticationprovider.html#cfn-appsync-graphqlapi-additionalauthenticationprovider-lambdaauthorizerconfig", + "Required": false, + "Type": "LambdaAuthorizerConfig", + "UpdateType": "Mutable" + }, "OpenIDConnectConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appsync-graphqlapi-additionalauthenticationprovider.html#cfn-appsync-graphqlapi-additionalauthenticationprovider-openidconnectconfig", "Required": false, @@ -6432,6 +6438,29 @@ } } }, + "AWS::AppSync::GraphQLApi.LambdaAuthorizerConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appsync-graphqlapi-lambdaauthorizerconfig.html", + "Properties": { + "AuthorizerResultTtlInSeconds": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appsync-graphqlapi-lambdaauthorizerconfig.html#cfn-appsync-graphqlapi-lambdaauthorizerconfig-authorizerresultttlinseconds", + "PrimitiveType": "Double", + "Required": false, + "UpdateType": "Mutable" + }, + "AuthorizerUri": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appsync-graphqlapi-lambdaauthorizerconfig.html#cfn-appsync-graphqlapi-lambdaauthorizerconfig-authorizeruri", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "IdentityValidationExpression": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appsync-graphqlapi-lambdaauthorizerconfig.html#cfn-appsync-graphqlapi-lambdaauthorizerconfig-identityvalidationexpression", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + }, "AWS::AppSync::GraphQLApi.LogConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appsync-graphqlapi-logconfig.html", "Properties": { @@ -8238,6 +8267,7 @@ "Properties": { "AdvancedBackupSettings": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-backup-backupplan-backupplanresourcetype.html#cfn-backup-backupplan-backupplanresourcetype-advancedbackupsettings", + "DuplicatesAllowed": true, "ItemType": "AdvancedBackupSettingResourceType", "Required": false, "Type": "List", @@ -8251,6 +8281,7 @@ }, "BackupPlanRule": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-backup-backupplan-backupplanresourcetype.html#cfn-backup-backupplan-backupplanresourcetype-backupplanrule", + "DuplicatesAllowed": true, "ItemType": "BackupRuleResourceType", "Required": true, "Type": "List", @@ -8269,6 +8300,7 @@ }, "CopyActions": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-backup-backupplan-backupruleresourcetype.html#cfn-backup-backupplan-backupruleresourcetype-copyactions", + "DuplicatesAllowed": true, "ItemType": "CopyActionResourceType", "Required": false, "Type": "List", @@ -8282,8 +8314,9 @@ }, "RecoveryPointTags": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-backup-backupplan-backupruleresourcetype.html#cfn-backup-backupplan-backupruleresourcetype-recoverypointtags", - "PrimitiveType": "Json", + "PrimitiveItemType": "String", "Required": false, + "Type": "Map", "UpdateType": "Mutable" }, "RuleName": { @@ -9302,6 +9335,29 @@ } } }, + "AWS::CE::AnomalySubscription.Subscriber": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ce-anomalysubscription-subscriber.html", + "Properties": { + "Address": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ce-anomalysubscription-subscriber.html#cfn-ce-anomalysubscription-subscriber-address", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "Status": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ce-anomalysubscription-subscriber.html#cfn-ce-anomalysubscription-subscriber-status", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "Type": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ce-anomalysubscription-subscriber.html#cfn-ce-anomalysubscription-subscriber-type", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + } + } + }, "AWS::Cassandra::Table.BillingMode": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cassandra-table-billingmode.html", "Properties": { @@ -9370,6 +9426,17 @@ } } }, + "AWS::CertificateManager::Account.ExpiryEventsConfiguration": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-certificatemanager-account-expiryeventsconfiguration.html", + "Properties": { + "DaysBeforeExpiry": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-certificatemanager-account-expiryeventsconfiguration.html#cfn-certificatemanager-account-expiryeventsconfiguration-daysbeforeexpiry", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Mutable" + } + } + }, "AWS::CertificateManager::Certificate.DomainValidationOption": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-certificatemanager-certificate-domainvalidationoption.html", "Properties": { @@ -15690,9 +15757,26 @@ } } }, + "AWS::DynamoDB::Table.ContributorInsightsSpecification": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-contributorinsightsspecification.html", + "Properties": { + "Enabled": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-contributorinsightsspecification.html#cfn-dynamodb-contributorinsightsspecification-enabled", + "PrimitiveType": "Boolean", + "Required": true, + "UpdateType": "Mutable" + } + } + }, "AWS::DynamoDB::Table.GlobalSecondaryIndex": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-gsi.html", "Properties": { + "ContributorInsightsSpecification": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-gsi.html#cfn-dynamodb-contributorinsightsspecification-enabled", + "Required": false, + "Type": "ContributorInsightsSpecification", + "UpdateType": "Mutable" + }, "IndexName": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-gsi.html#cfn-dynamodb-gsi-indexname", "PrimitiveType": "String", @@ -15738,17 +15822,6 @@ } } }, - "AWS::DynamoDB::Table.KinesisStreamSpecification": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-kinesisstreamspecification.html", - "Properties": { - "StreamArn": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-kinesisstreamspecification.html#cfn-dynamodb-kinesisstreamspecification-streamarn", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Mutable" - } - } - }, "AWS::DynamoDB::Table.LocalSecondaryIndex": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-lsi.html", "Properties": { @@ -17341,6 +17414,13 @@ } } }, + "AWS::EC2::LaunchTemplate.TagSpecifications": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-launchtemplate-tagspecifications.html", + "ItemType": "TagSpecification", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, "AWS::EC2::NetworkAclEntry.Icmp": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-networkaclentry-icmp.html", "Properties": { @@ -18954,13 +19034,13 @@ "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-capacityprovider-autoscalinggroupprovider.html#cfn-ecs-capacityprovider-autoscalinggroupprovider-managedscaling", "Required": false, "Type": "ManagedScaling", - "UpdateType": "Immutable" + "UpdateType": "Mutable" }, "ManagedTerminationProtection": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-capacityprovider-autoscalinggroupprovider.html#cfn-ecs-capacityprovider-autoscalinggroupprovider-managedterminationprotection", "PrimitiveType": "String", "Required": false, - "UpdateType": "Immutable" + "UpdateType": "Mutable" } } }, @@ -18971,25 +19051,25 @@ "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-capacityprovider-managedscaling.html#cfn-ecs-capacityprovider-managedscaling-maximumscalingstepsize", "PrimitiveType": "Integer", "Required": false, - "UpdateType": "Immutable" + "UpdateType": "Mutable" }, "MinimumScalingStepSize": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-capacityprovider-managedscaling.html#cfn-ecs-capacityprovider-managedscaling-minimumscalingstepsize", "PrimitiveType": "Integer", "Required": false, - "UpdateType": "Immutable" + "UpdateType": "Mutable" }, "Status": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-capacityprovider-managedscaling.html#cfn-ecs-capacityprovider-managedscaling-status", "PrimitiveType": "String", "Required": false, - "UpdateType": "Immutable" + "UpdateType": "Mutable" }, "TargetCapacity": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-capacityprovider-managedscaling.html#cfn-ecs-capacityprovider-managedscaling-targetcapacity", "PrimitiveType": "Integer", "Required": false, - "UpdateType": "Immutable" + "UpdateType": "Mutable" } } }, @@ -19016,6 +19096,17 @@ } } }, + "AWS::ECS::Cluster.ClusterConfiguration": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-cluster-clusterconfiguration.html", + "Properties": { + "ExecuteCommandConfiguration": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-cluster-clusterconfiguration.html#cfn-ecs-cluster-clusterconfiguration-executecommandconfiguration", + "Required": false, + "Type": "ExecuteCommandConfiguration", + "UpdateType": "Mutable" + } + } + }, "AWS::ECS::Cluster.ClusterSettings": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-cluster-clustersettings.html", "Properties": { @@ -19033,6 +19124,87 @@ } } }, + "AWS::ECS::Cluster.ExecuteCommandConfiguration": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-cluster-executecommandconfiguration.html", + "Properties": { + "KmsKeyId": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-cluster-executecommandconfiguration.html#cfn-ecs-cluster-executecommandconfiguration-kmskeyid", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "LogConfiguration": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-cluster-executecommandconfiguration.html#cfn-ecs-cluster-executecommandconfiguration-logconfiguration", + "Required": false, + "Type": "ExecuteCommandLogConfiguration", + "UpdateType": "Mutable" + }, + "Logging": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-cluster-executecommandconfiguration.html#cfn-ecs-cluster-executecommandconfiguration-logging", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + }, + "AWS::ECS::Cluster.ExecuteCommandLogConfiguration": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-cluster-executecommandlogconfiguration.html", + "Properties": { + "CloudWatchEncryptionEnabled": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-cluster-executecommandlogconfiguration.html#cfn-ecs-cluster-executecommandlogconfiguration-cloudwatchencryptionenabled", + "PrimitiveType": "Boolean", + "Required": false, + "UpdateType": "Mutable" + }, + "CloudWatchLogGroupName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-cluster-executecommandlogconfiguration.html#cfn-ecs-cluster-executecommandlogconfiguration-cloudwatchloggroupname", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "S3BucketName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-cluster-executecommandlogconfiguration.html#cfn-ecs-cluster-executecommandlogconfiguration-s3bucketname", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "S3EncryptionEnabled": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-cluster-executecommandlogconfiguration.html#cfn-ecs-cluster-executecommandlogconfiguration-s3encryptionenabled", + "PrimitiveType": "Boolean", + "Required": false, + "UpdateType": "Mutable" + }, + "S3KeyPrefix": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-cluster-executecommandlogconfiguration.html#cfn-ecs-cluster-executecommandlogconfiguration-s3keyprefix", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + }, + "AWS::ECS::ClusterCapacityProviderAssociations.CapacityProviderStrategy": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-clustercapacityproviderassociations-capacityproviderstrategy.html", + "Properties": { + "Base": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-clustercapacityproviderassociations-capacityproviderstrategy.html#cfn-ecs-clustercapacityproviderassociations-capacityproviderstrategy-base", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Mutable" + }, + "CapacityProvider": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-clustercapacityproviderassociations-capacityproviderstrategy.html#cfn-ecs-clustercapacityproviderassociations-capacityproviderstrategy-capacityprovider", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "Weight": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-clustercapacityproviderassociations-capacityproviderstrategy.html#cfn-ecs-clustercapacityproviderassociations-capacityproviderstrategy-weight", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Mutable" + } + } + }, "AWS::ECS::Service.AwsVpcConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-service-awsvpcconfiguration.html", "Properties": { @@ -24261,7 +24433,7 @@ "Type": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-gamelift-alias-routingstrategy.html#cfn-gamelift-alias-routingstrategy-type", "PrimitiveType": "String", - "Required": false, + "Required": true, "UpdateType": "Mutable" } } @@ -28958,6 +29130,12 @@ "Required": true, "UpdateType": "Mutable" }, + "CannedAcl": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iot-topicrule-s3action.html#cfn-iot-topicrule-s3action-cannedacl", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, "Key": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iot-topicrule-s3action.html#cfn-iot-topicrule-s3action-key", "PrimitiveType": "String", @@ -29069,7 +29247,6 @@ "Properties": { "Actions": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iot-topicrule-topicrulepayload.html#cfn-iot-topicrule-topicrulepayload-actions", - "DuplicatesAllowed": false, "ItemType": "Action", "Required": true, "Type": "List", @@ -29096,7 +29273,7 @@ "RuleDisabled": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iot-topicrule-topicrulepayload.html#cfn-iot-topicrule-topicrulepayload-ruledisabled", "PrimitiveType": "Boolean", - "Required": true, + "Required": false, "UpdateType": "Mutable" }, "Sql": { @@ -45366,6 +45543,23 @@ } } }, + "AWS::RDS::DBProxyEndpoint.TagFormat": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-dbproxyendpoint-tagformat.html", + "Properties": { + "Key": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-dbproxyendpoint-tagformat.html#cfn-rds-dbproxyendpoint-tagformat-key", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "Value": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-dbproxyendpoint-tagformat.html#cfn-rds-dbproxyendpoint-tagformat-value", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + }, "AWS::RDS::DBProxyTargetGroup.ConnectionPoolConfigurationInfoFormat": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-dbproxytargetgroup-connectionpoolconfigurationinfoformat.html", "Properties": { @@ -48346,10 +48540,11 @@ "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ssm-resourcedatasync-awsorganizationssource.html#cfn-ssm-resourcedatasync-awsorganizationssource-organizationsourcetype", "PrimitiveType": "String", "Required": true, - "UpdateType": "Immutable" + "UpdateType": "Mutable" }, "OrganizationalUnits": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ssm-resourcedatasync-awsorganizationssource.html#cfn-ssm-resourcedatasync-awsorganizationssource-organizationalunits", + "DuplicatesAllowed": true, "PrimitiveItemType": "String", "Required": false, "Type": "List", @@ -48409,6 +48604,7 @@ }, "SourceRegions": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ssm-resourcedatasync-syncsource.html#cfn-ssm-resourcedatasync-syncsource-sourceregions", + "DuplicatesAllowed": true, "PrimitiveItemType": "String", "Required": true, "Type": "List", @@ -48418,7 +48614,7 @@ "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ssm-resourcedatasync-syncsource.html#cfn-ssm-resourcedatasync-syncsource-sourcetype", "PrimitiveType": "String", "Required": true, - "UpdateType": "Immutable" + "UpdateType": "Mutable" } } }, @@ -53649,7 +53845,7 @@ } } }, - "ResourceSpecificationVersion": "30.1.0", + "ResourceSpecificationVersion": "31.0.0", "ResourceTypes": { "AWS::ACMPCA::Certificate": { "Attributes": { @@ -57283,6 +57479,12 @@ "Required": true, "UpdateType": "Mutable" }, + "LambdaAuthorizerConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-appsync-graphqlapi.html#cfn-appsync-graphqlapi-lambdaauthorizerconfig", + "Required": false, + "Type": "LambdaAuthorizerConfig", + "UpdateType": "Mutable" + }, "LogConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-appsync-graphqlapi.html#cfn-appsync-graphqlapi-logconfig", "Required": false, @@ -58350,8 +58552,9 @@ }, "BackupPlanTags": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-backup-backupplan.html#cfn-backup-backupplan-backupplantags", - "PrimitiveType": "Json", + "PrimitiveItemType": "String", "Required": false, + "Type": "Map", "UpdateType": "Mutable" } } @@ -58586,6 +58789,97 @@ } } }, + "AWS::CE::AnomalyMonitor": { + "Attributes": { + "CreationDate": { + "PrimitiveType": "String" + }, + "DimensionalValueCount": { + "PrimitiveType": "Integer" + }, + "LastEvaluatedDate": { + "PrimitiveType": "String" + }, + "LastUpdatedDate": { + "PrimitiveType": "String" + }, + "MonitorArn": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ce-anomalymonitor.html", + "Properties": { + "MonitorDimension": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ce-anomalymonitor.html#cfn-ce-anomalymonitor-monitordimension", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "MonitorName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ce-anomalymonitor.html#cfn-ce-anomalymonitor-monitorname", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "MonitorSpecification": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ce-anomalymonitor.html#cfn-ce-anomalymonitor-monitorspecification", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "MonitorType": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ce-anomalymonitor.html#cfn-ce-anomalymonitor-monitortype", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + } + } + }, + "AWS::CE::AnomalySubscription": { + "Attributes": { + "AccountId": { + "PrimitiveType": "String" + }, + "SubscriptionArn": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ce-anomalysubscription.html", + "Properties": { + "Frequency": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ce-anomalysubscription.html#cfn-ce-anomalysubscription-frequency", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "MonitorArnList": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ce-anomalysubscription.html#cfn-ce-anomalysubscription-monitorarnlist", + "PrimitiveItemType": "String", + "Required": true, + "Type": "List", + "UpdateType": "Mutable" + }, + "Subscribers": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ce-anomalysubscription.html#cfn-ce-anomalysubscription-subscribers", + "ItemType": "Subscriber", + "Required": true, + "Type": "List", + "UpdateType": "Mutable" + }, + "SubscriptionName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ce-anomalysubscription.html#cfn-ce-anomalysubscription-subscriptionname", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "Threshold": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ce-anomalysubscription.html#cfn-ce-anomalysubscription-threshold", + "PrimitiveType": "Double", + "Required": true, + "UpdateType": "Mutable" + } + } + }, "AWS::CE::CostCategory": { "Attributes": { "Arn": { @@ -58697,6 +58991,22 @@ } } }, + "AWS::CertificateManager::Account": { + "Attributes": { + "AccountId": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-certificatemanager-account.html", + "Properties": { + "ExpiryEventsConfiguration": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-certificatemanager-account.html#cfn-certificatemanager-account-expiryeventsconfiguration", + "Required": true, + "Type": "ExpiryEventsConfiguration", + "UpdateType": "Mutable" + } + } + }, "AWS::CertificateManager::Certificate": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-certificatemanager-certificate.html", "Properties": { @@ -63708,6 +64018,12 @@ "Required": false, "UpdateType": "Mutable" }, + "ContributorInsightsSpecification": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-contributorinsightsspecification-enabled", + "Required": false, + "Type": "ContributorInsightsSpecification", + "UpdateType": "Mutable" + }, "GlobalSecondaryIndexes": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-gsi", "DuplicatesAllowed": true, @@ -63724,12 +64040,6 @@ "Type": "List", "UpdateType": "Immutable" }, - "KinesisStreamSpecification": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-kinesisstreamspecification", - "Required": false, - "Type": "KinesisStreamSpecification", - "UpdateType": "Mutable" - }, "LocalSecondaryIndexes": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-lsi", "DuplicatesAllowed": true, @@ -64742,6 +65052,12 @@ "PrimitiveType": "String", "Required": false, "UpdateType": "Immutable" + }, + "TagSpecifications": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-launchtemplate.html#cfn-ec2-launchtemplate-tagspecifications", + "Required": false, + "Type": "TagSpecifications", + "UpdateType": "Mutable" } } }, @@ -66868,7 +67184,7 @@ "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ecs-capacityprovider.html#cfn-ecs-capacityprovider-autoscalinggroupprovider", "Required": true, "Type": "AutoScalingGroupProvider", - "UpdateType": "Immutable" + "UpdateType": "Mutable" }, "Name": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ecs-capacityprovider.html#cfn-ecs-capacityprovider-name", @@ -66913,6 +67229,12 @@ "Type": "List", "UpdateType": "Mutable" }, + "Configuration": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ecs-cluster.html#cfn-ecs-cluster-configuration", + "Required": false, + "Type": "ClusterConfiguration", + "UpdateType": "Mutable" + }, "DefaultCapacityProviderStrategy": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ecs-cluster.html#cfn-ecs-cluster-defaultcapacityproviderstrategy", "ItemType": "CapacityProviderStrategyItem", @@ -66929,6 +67251,32 @@ } } }, + "AWS::ECS::ClusterCapacityProviderAssociations": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ecs-clustercapacityproviderassociations.html", + "Properties": { + "CapacityProviders": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ecs-clustercapacityproviderassociations.html#cfn-ecs-clustercapacityproviderassociations-capacityproviders", + "DuplicatesAllowed": false, + "PrimitiveItemType": "String", + "Required": true, + "Type": "List", + "UpdateType": "Mutable" + }, + "Cluster": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ecs-clustercapacityproviderassociations.html#cfn-ecs-clustercapacityproviderassociations-cluster", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "DefaultCapacityProviderStrategy": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ecs-clustercapacityproviderassociations.html#cfn-ecs-clustercapacityproviderassociations-defaultcapacityproviderstrategy", + "ItemType": "CapacityProviderStrategy", + "Required": true, + "Type": "List", + "UpdateType": "Mutable" + } + } + }, "AWS::ECS::PrimaryTaskSet": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ecs-primarytaskset.html", "Properties": { @@ -66997,6 +67345,12 @@ "Required": false, "UpdateType": "Immutable" }, + "EnableExecuteCommand": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ecs-service.html#cfn-ecs-service-enableexecutecommand", + "PrimitiveType": "Boolean", + "Required": false, + "UpdateType": "Mutable" + }, "HealthCheckGracePeriodSeconds": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ecs-service.html#cfn-ecs-service-healthcheckgraceperiodseconds", "PrimitiveType": "Integer", @@ -67333,6 +67687,12 @@ }, "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-efs-filesystem.html", "Properties": { + "AvailabilityZoneName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-efs-filesystem.html#cfn-efs-filesystem-availabilityzonename", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, "BackupPolicy": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-efs-filesystem.html#cfn-efs-filesystem-backuppolicy", "Required": false, @@ -81406,6 +81766,64 @@ } } }, + "AWS::RDS::DBProxyEndpoint": { + "Attributes": { + "DBProxyEndpointArn": { + "PrimitiveType": "String" + }, + "Endpoint": { + "PrimitiveType": "String" + }, + "IsDefault": { + "PrimitiveType": "Boolean" + }, + "VpcId": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbproxyendpoint.html", + "Properties": { + "DBProxyEndpointName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbproxyendpoint.html#cfn-rds-dbproxyendpoint-dbproxyendpointname", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "DBProxyName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbproxyendpoint.html#cfn-rds-dbproxyendpoint-dbproxyname", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "Tags": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbproxyendpoint.html#cfn-rds-dbproxyendpoint-tags", + "ItemType": "TagFormat", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "TargetRole": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbproxyendpoint.html#cfn-rds-dbproxyendpoint-targetrole", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "VpcSecurityGroupIds": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbproxyendpoint.html#cfn-rds-dbproxyendpoint-vpcsecuritygroupids", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "VpcSubnetIds": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbproxyendpoint.html#cfn-rds-dbproxyendpoint-vpcsubnetids", + "PrimitiveItemType": "String", + "Required": true, + "Type": "List", + "UpdateType": "Immutable" + } + } + }, "AWS::RDS::DBProxyTargetGroup": { "Attributes": { "TargetGroupArn": { @@ -83882,6 +84300,11 @@ } }, "AWS::SSM::ResourceDataSync": { + "Attributes": { + "SyncName": { + "PrimitiveType": "String" + } + }, "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ssm-resourcedatasync.html", "Properties": { "BucketName": { diff --git a/packages/@aws-cdk/cloud-assembly-schema/package.json b/packages/@aws-cdk/cloud-assembly-schema/package.json index 724512a094826..86e3a149a0aeb 100644 --- a/packages/@aws-cdk/cloud-assembly-schema/package.json +++ b/packages/@aws-cdk/cloud-assembly-schema/package.json @@ -64,7 +64,7 @@ "jest": "^26.6.3", "mock-fs": "^4.13.0", "pkglint": "0.0.0", - "typescript-json-schema": "^0.49.0" + "typescript-json-schema": "^0.50.0" }, "repository": { "url": "https://github.com/aws/aws-cdk.git", diff --git a/packages/@aws-cdk/cloudformation-diff/package.json b/packages/@aws-cdk/cloudformation-diff/package.json index bcbb1c7193e68..7babcf6ec87c3 100644 --- a/packages/@aws-cdk/cloudformation-diff/package.json +++ b/packages/@aws-cdk/cloudformation-diff/package.json @@ -33,10 +33,10 @@ "@types/string-width": "^4.0.1", "@types/table": "^6.0.0", "cdk-build-tools": "0.0.0", - "fast-check": "^2.13.0", + "fast-check": "^2.14.0", "jest": "^26.6.3", "pkglint": "0.0.0", - "ts-jest": "^26.5.3" + "ts-jest": "^26.5.4" }, "repository": { "url": "https://github.com/aws/aws-cdk.git", diff --git a/packages/@aws-cdk/cloudformation-include/build.js b/packages/@aws-cdk/cloudformation-include/build.js index ab36ffd345d7f..454a10a5014d5 100644 --- a/packages/@aws-cdk/cloudformation-include/build.js +++ b/packages/@aws-cdk/cloudformation-include/build.js @@ -29,6 +29,8 @@ async function main() { for (const constructLibraryDir of constructLibrariesDirs) { const absConstructLibraryDir = path.resolve(constructLibrariesRoot, constructLibraryDir); + if (!fs.statSync(absConstructLibraryDir).isDirectory()) { continue; } // .DS_Store + const libraryPackageJson = require(path.join(absConstructLibraryDir, 'package.json')); const libraryDependencyVersion = dependencies[libraryPackageJson.name]; diff --git a/packages/@aws-cdk/cloudformation-include/package.json b/packages/@aws-cdk/cloudformation-include/package.json index a177759248e07..21af2739ac8b3 100644 --- a/packages/@aws-cdk/cloudformation-include/package.json +++ b/packages/@aws-cdk/cloudformation-include/package.json @@ -369,7 +369,7 @@ "cdk-integ-tools": "0.0.0", "jest": "^26.6.3", "pkglint": "0.0.0", - "ts-jest": "^26.5.3" + "ts-jest": "^26.5.4" }, "keywords": [ "aws", diff --git a/packages/@aws-cdk/core/lib/private/cfn-utils-provider.ts b/packages/@aws-cdk/core/lib/private/cfn-utils-provider.ts index 8200165fbfe34..04a68394fe2f3 100644 --- a/packages/@aws-cdk/core/lib/private/cfn-utils-provider.ts +++ b/packages/@aws-cdk/core/lib/private/cfn-utils-provider.ts @@ -1,5 +1,7 @@ import { Construct } from '../construct-compat'; +import { CustomResource } from '../custom-resource'; import { CustomResourceProvider, CustomResourceProviderRuntime } from '../custom-resource-provider'; +import { CfnUtilsResourceType } from './cfn-utils-provider/consts'; /** * A custom resource provider for CFN utilities such as `CfnJson`. @@ -11,4 +13,35 @@ export class CfnUtilsProvider extends Construct { codeDirectory: `${__dirname}/cfn-utils-provider`, }); } +} + +/** + * Utility functions provided by the CfnUtilsProvider + */ +export abstract class CfnUtils { + /** + * Encode a structure to JSON at CloudFormation deployment time + * + * This would have been suitable for the JSON-encoding of abitrary structures, however: + * + * - It uses a custom resource to do the encoding, and we'd rather not use a custom + * resource if we can avoid it. + * - It cannot be used to encode objects where the keys of the objects can contain + * tokens--because those cannot be represented in the JSON encoding that CloudFormation + * templates use. + * + * This helper is used by `CloudFormationLang.toJSON()` if and only if it encounters + * objects that cannot be stringified any other way. + */ + public static stringify(scope: Construct, id: string, value: any): string { + const resource = new CustomResource(scope, id, { + serviceToken: CfnUtilsProvider.getOrCreate(scope), + resourceType: CfnUtilsResourceType.CFN_JSON_STRINGIFY, + properties: { + Value: value, + }, + }); + + return resource.getAttString('Value'); + } } \ No newline at end of file diff --git a/packages/@aws-cdk/core/lib/private/cfn-utils-provider/consts.ts b/packages/@aws-cdk/core/lib/private/cfn-utils-provider/consts.ts index b1571cabd5b42..9718dcef40645 100644 --- a/packages/@aws-cdk/core/lib/private/cfn-utils-provider/consts.ts +++ b/packages/@aws-cdk/core/lib/private/cfn-utils-provider/consts.ts @@ -5,5 +5,10 @@ export const enum CfnUtilsResourceType { /** * CfnJson */ - CFN_JSON = 'Custom::AWSCDKCfnJson' + CFN_JSON = 'Custom::AWSCDKCfnJson', + + /** + * CfnJsonStringify + */ + CFN_JSON_STRINGIFY = 'Custom::AWSCDKCfnJsonStringify', } diff --git a/packages/@aws-cdk/core/lib/private/cfn-utils-provider/index.ts b/packages/@aws-cdk/core/lib/private/cfn-utils-provider/index.ts index 87bd6bb070e16..f082001f80159 100644 --- a/packages/@aws-cdk/core/lib/private/cfn-utils-provider/index.ts +++ b/packages/@aws-cdk/core/lib/private/cfn-utils-provider/index.ts @@ -9,6 +9,9 @@ export async function handler(event: AWSLambda.CloudFormationCustomResourceEvent if (event.ResourceType === CfnUtilsResourceType.CFN_JSON) { return cfnJsonHandler(event); } + if (event.ResourceType === CfnUtilsResourceType.CFN_JSON_STRINGIFY) { + return cfnJsonStringifyHandler(event); + } throw new Error(`unexpected resource type "${event.ResourceType}`); } @@ -20,3 +23,11 @@ function cfnJsonHandler(event: AWSLambda.CloudFormationCustomResourceEvent) { }, }; } + +function cfnJsonStringifyHandler(event: AWSLambda.CloudFormationCustomResourceEvent) { + return { + Data: { + Value: JSON.stringify(event.ResourceProperties.Value), + }, + }; +} diff --git a/packages/@aws-cdk/core/lib/private/cloudformation-lang.ts b/packages/@aws-cdk/core/lib/private/cloudformation-lang.ts index 310a4632f4e8f..c2be580474426 100644 --- a/packages/@aws-cdk/core/lib/private/cloudformation-lang.ts +++ b/packages/@aws-cdk/core/lib/private/cloudformation-lang.ts @@ -1,6 +1,8 @@ import { Lazy } from '../lazy'; import { DefaultTokenResolver, IFragmentConcatenator, IResolveContext } from '../resolvable'; +import { Stack } from '../stack'; import { Token } from '../token'; +import { CfnUtils } from './cfn-utils-provider'; import { INTRINSIC_KEY_PREFIX, ResolutionTypeHint, resolvedTypeHint } from './resolve'; /** @@ -170,7 +172,8 @@ function tokenAwareStringify(root: any, space: number, ctx: IResolveContext) { // AND it's the result of a token resolution. Otherwise, we just treat this // value as a regular old JSON object (that happens to look a lot like an intrinsic). if (isIntrinsic(obj) && resolvedTypeHint(obj)) { - return renderIntrinsic(obj); + renderIntrinsic(obj); + return; } return renderCollection('{', '}', definedEntries(obj), ([key, value]) => { @@ -211,12 +214,34 @@ function tokenAwareStringify(root: any, space: number, ctx: IResolveContext) { pushLiteral('"'); pushIntrinsic(deepQuoteStringLiterals(intrinsic)); pushLiteral('"'); - break; - - default: + return; + + case ResolutionTypeHint.LIST: + // We need this to look like: + // + // '{"listValue":' ++ STRINGIFY(CFN_EVAL({ Ref: MyList })) ++ '}' + // + // However, STRINGIFY would need to execute at CloudFormation deployment time, and that doesn't exist. + // + // We could *ALMOST* use: + // + // '{"listValue":["' ++ JOIN('","', { Ref: MyList }) ++ '"]}' + // + // But that has the unfortunate side effect that if `CFN_EVAL({ Ref: MyList }) == []`, then it would + // evaluate to `[""]`, which is a different value. Since CloudFormation does not have arbitrary + // conditionals there's no way to deal with this case properly. + // + // Therefore, if we encounter lists we need to defer to a custom resource to handle + // them properly at deploy time. + pushIntrinsic(CfnUtils.stringify(Stack.of(ctx.scope), `CdkJsonStringify${stringifyCounter++}`, intrinsic)); + return; + + case ResolutionTypeHint.NUMBER: pushIntrinsic(intrinsic); - break; + return; } + + throw new Error(`Unexpected type hint: ${resolvedTypeHint(intrinsic)}`); } /** @@ -391,4 +416,6 @@ function deepQuoteStringLiterals(x: any): any { function quoteString(s: string) { s = JSON.stringify(s); return s.substring(1, s.length - 1); -} \ No newline at end of file +} + +let stringifyCounter = 1; \ No newline at end of file diff --git a/packages/@aws-cdk/core/package.json b/packages/@aws-cdk/core/package.json index 643f809bca142..d1a10d8ac8fd2 100644 --- a/packages/@aws-cdk/core/package.json +++ b/packages/@aws-cdk/core/package.json @@ -176,11 +176,11 @@ "devDependencies": { "@types/lodash": "^4.14.168", "@types/minimatch": "^3.0.3", - "@types/node": "^10.17.54", - "@types/sinon": "^9.0.10", + "@types/node": "^10.17.55", + "@types/sinon": "^9.0.11", "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", - "fast-check": "^2.13.0", + "fast-check": "^2.14.0", "lodash": "^4.17.21", "nodeunit-shim": "0.0.0", "pkglint": "0.0.0", diff --git a/packages/@aws-cdk/core/test/cloudformation-json.test.ts b/packages/@aws-cdk/core/test/cloudformation-json.test.ts index cb96020e04904..e9a0957a86269 100644 --- a/packages/@aws-cdk/core/test/cloudformation-json.test.ts +++ b/packages/@aws-cdk/core/test/cloudformation-json.test.ts @@ -103,7 +103,11 @@ describe('tokens that return literals', () => { // WHEN expect(stack.resolve(stack.toJsonString({ someList }))).toEqual({ - 'Fn::Join': ['', ['{"someList":', { Ref: 'Thing' }, '}']], + 'Fn::Join': ['', [ + '{"someList":', + { 'Fn::GetAtt': [expect.stringContaining('CdkJsonStringify'), 'Value'] }, + '}', + ]], }); }); diff --git a/packages/@aws-cdk/custom-resources/package.json b/packages/@aws-cdk/custom-resources/package.json index 97363c57b7918..6c3c3d4f2d0b5 100644 --- a/packages/@aws-cdk/custom-resources/package.json +++ b/packages/@aws-cdk/custom-resources/package.json @@ -77,14 +77,14 @@ "@aws-cdk/aws-ssm": "0.0.0", "@types/aws-lambda": "^8.10.72", "@types/fs-extra": "^8.1.1", - "@types/sinon": "^9.0.10", + "@types/sinon": "^9.0.11", "aws-sdk": "^2.848.0", "aws-sdk-mock": "^5.1.0", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", "cfn2ts": "0.0.0", "fs-extra": "^9.1.0", - "nock": "^13.0.10", + "nock": "^13.0.11", "pkglint": "0.0.0", "sinon": "^9.2.4" }, diff --git a/packages/@aws-cdk/region-info/build-tools/fact-tables.ts b/packages/@aws-cdk/region-info/build-tools/fact-tables.ts index 2f47e02f64da4..c2ce689f3aaf3 100644 --- a/packages/@aws-cdk/region-info/build-tools/fact-tables.ts +++ b/packages/@aws-cdk/region-info/build-tools/fact-tables.ts @@ -19,7 +19,7 @@ export const AWS_CDK_METADATA = new Set([ // 'us-gov-west-1', // 'us-iso-east-1', // 'us-isob-east-1', - // 'af-south-1', + 'af-south-1', 'ap-south-1', 'ap-east-1', // 'ap-northeast-3', @@ -35,7 +35,7 @@ export const AWS_CDK_METADATA = new Set([ 'eu-west-2', 'eu-west-3', 'eu-north-1', - // 'eu-south-1', + 'eu-south-1', 'me-south-1', 'sa-east-1', ]); diff --git a/packages/@aws-cdk/region-info/test/__snapshots__/region-info.test.js.snap b/packages/@aws-cdk/region-info/test/__snapshots__/region-info.test.js.snap index ab12430e57c84..eb7c82b6eb28d 100644 --- a/packages/@aws-cdk/region-info/test/__snapshots__/region-info.test.js.snap +++ b/packages/@aws-cdk/region-info/test/__snapshots__/region-info.test.js.snap @@ -3,7 +3,7 @@ exports[`built-in data is correct 1`] = ` Object { "af-south-1": Object { - "cdkMetadataResourceAvailable": false, + "cdkMetadataResourceAvailable": true, "domainSuffix": "amazonaws.com", "partition": "aws", "s3StaticWebsiteEndpoint": "s3-website.af-south-1.amazonaws.com", @@ -263,7 +263,7 @@ Object { "vpcEndPointServiceNamePrefix": "com.amazonaws.vpce", }, "eu-south-1": Object { - "cdkMetadataResourceAvailable": false, + "cdkMetadataResourceAvailable": true, "domainSuffix": "amazonaws.com", "partition": "aws", "s3StaticWebsiteEndpoint": "s3-website.eu-south-1.amazonaws.com", diff --git a/packages/@aws-cdk/yaml-cfn/package.json b/packages/@aws-cdk/yaml-cfn/package.json index 45e121a4cb7f5..c12e8f6ea4a47 100644 --- a/packages/@aws-cdk/yaml-cfn/package.json +++ b/packages/@aws-cdk/yaml-cfn/package.json @@ -63,7 +63,7 @@ "rosetta:extract": "yarn --silent jsii-rosetta extract" }, "dependencies": { - "yaml": "1.10.0" + "yaml": "1.10.2" }, "devDependencies": { "@aws-cdk/assert": "0.0.0", diff --git a/packages/@monocdk-experiment/assert/package.json b/packages/@monocdk-experiment/assert/package.json index f70aec783eff1..24e740abdfcf4 100644 --- a/packages/@monocdk-experiment/assert/package.json +++ b/packages/@monocdk-experiment/assert/package.json @@ -35,13 +35,13 @@ "devDependencies": { "@monocdk-experiment/rewrite-imports": "0.0.0", "@types/jest": "^26.0.20", - "@types/node": "^10.17.54", + "@types/node": "^10.17.55", "cdk-build-tools": "0.0.0", "constructs": "^3.2.0", "jest": "^26.6.3", "monocdk": "0.0.0", "pkglint": "0.0.0", - "ts-jest": "^26.5.3" + "ts-jest": "^26.5.4" }, "dependencies": { "@aws-cdk/cloudformation-diff": "0.0.0" diff --git a/packages/@monocdk-experiment/rewrite-imports/package.json b/packages/@monocdk-experiment/rewrite-imports/package.json index b824068d0354f..79a36d042e473 100644 --- a/packages/@monocdk-experiment/rewrite-imports/package.json +++ b/packages/@monocdk-experiment/rewrite-imports/package.json @@ -38,7 +38,7 @@ "devDependencies": { "@types/glob": "^7.1.3", "@types/jest": "^26.0.20", - "@types/node": "^10.17.54", + "@types/node": "^10.17.55", "cdk-build-tools": "0.0.0", "pkglint": "0.0.0" }, diff --git a/packages/aws-cdk-lib/package.json b/packages/aws-cdk-lib/package.json index 5380837857d8f..3f4b9857b9231 100644 --- a/packages/aws-cdk-lib/package.json +++ b/packages/aws-cdk-lib/package.json @@ -96,7 +96,7 @@ "minimatch": "^3.0.4", "punycode": "^2.1.1", "semver": "^7.3.4", - "yaml": "1.10.0" + "yaml": "1.10.2" }, "devDependencies": { "@aws-cdk/alexa-ask": "0.0.0", @@ -284,7 +284,7 @@ "@aws-cdk/region-info": "0.0.0", "@aws-cdk/yaml-cfn": "0.0.0", "@types/fs-extra": "^8.1.1", - "@types/node": "^10.17.54", + "@types/node": "^10.17.55", "cdk-build-tools": "0.0.0", "constructs": "^3.2.0", "fs-extra": "^9.1.0", diff --git a/packages/aws-cdk/package.json b/packages/aws-cdk/package.json index 71a094e6e72ca..8cb425eb5159f 100644 --- a/packages/aws-cdk/package.json +++ b/packages/aws-cdk/package.json @@ -39,17 +39,17 @@ "license": "Apache-2.0", "devDependencies": { "@aws-cdk/core": "0.0.0", - "@octokit/rest": "^18.3.2", + "@octokit/rest": "^18.3.5", "@types/archiver": "^5.1.0", "@types/fs-extra": "^8.1.1", "@types/glob": "^7.1.3", "@types/jest": "^26.0.20", "@types/minimatch": "^3.0.3", "@types/mockery": "^1.4.29", - "@types/node": "^10.17.54", + "@types/node": "^10.17.55", "@types/promptly": "^3.0.1", "@types/semver": "^7.3.4", - "@types/sinon": "^9.0.10", + "@types/sinon": "^9.0.11", "@types/table": "^6.0.0", "@types/uuid": "^8.3.0", "@types/wrap-ansi": "^3.0.0", @@ -59,10 +59,10 @@ "jest": "^26.6.3", "make-runnable": "^1.3.8", "mockery": "^2.1.0", - "nock": "^13.0.10", + "nock": "^13.0.11", "pkglint": "0.0.0", "sinon": "^9.2.4", - "ts-jest": "^26.5.3", + "ts-jest": "^26.5.4", "ts-mock-imports": "^1.3.3", "xml-js": "^1.6.11" }, @@ -72,7 +72,7 @@ "@aws-cdk/cx-api": "0.0.0", "@aws-cdk/region-info": "0.0.0", "@aws-cdk/yaml-cfn": "0.0.0", - "archiver": "^5.2.0", + "archiver": "^5.3.0", "aws-sdk": "^2.848.0", "camelcase": "^6.2.0", "cdk-assets": "0.0.0", diff --git a/packages/awslint/package.json b/packages/awslint/package.json index 3be540173745f..892c71823bed0 100644 --- a/packages/awslint/package.json +++ b/packages/awslint/package.json @@ -16,11 +16,11 @@ "awslint": "bin/awslint" }, "dependencies": { - "@jsii/spec": "^1.24.0", + "@jsii/spec": "^1.25.0", "camelcase": "^6.2.0", "colors": "^1.4.0", "fs-extra": "^9.1.0", - "jsii-reflect": "^1.24.0", + "jsii-reflect": "^1.25.0", "yargs": "^16.2.0" }, "devDependencies": { diff --git a/packages/cdk-assets/package.json b/packages/cdk-assets/package.json index 16f767306dbdc..17661e947bbcb 100644 --- a/packages/cdk-assets/package.json +++ b/packages/cdk-assets/package.json @@ -35,7 +35,7 @@ "@types/jest": "^26.0.20", "@types/jszip": "^3.4.1", "@types/mock-fs": "^4.13.0", - "@types/node": "^10.17.54", + "@types/node": "^10.17.55", "@types/yargs": "^15.0.13", "cdk-build-tools": "0.0.0", "jest": "^26.6.3", @@ -46,7 +46,7 @@ "dependencies": { "@aws-cdk/cloud-assembly-schema": "0.0.0", "@aws-cdk/cx-api": "0.0.0", - "archiver": "^5.2.0", + "archiver": "^5.3.0", "aws-sdk": "^2.848.0", "glob": "^7.1.6", "yargs": "^16.2.0" diff --git a/packages/cdk-dasm/package.json b/packages/cdk-dasm/package.json index 067cf1694ff98..ec37b0ca74fac 100644 --- a/packages/cdk-dasm/package.json +++ b/packages/cdk-dasm/package.json @@ -26,8 +26,8 @@ }, "license": "Apache-2.0", "dependencies": { - "codemaker": "^1.24.0", - "yaml": "1.10.0" + "codemaker": "^1.25.0", + "yaml": "1.10.2" }, "devDependencies": { "@types/jest": "^26.0.20", diff --git a/packages/decdk/package.json b/packages/decdk/package.json index 4b2ec6dc2fdc0..c7ef09f0e0036 100644 --- a/packages/decdk/package.json +++ b/packages/decdk/package.json @@ -211,9 +211,9 @@ "@aws-cdk/yaml-cfn": "0.0.0", "constructs": "^3.2.0", "fs-extra": "^9.1.0", - "jsii-reflect": "^1.24.0", + "jsii-reflect": "^1.25.0", "jsonschema": "^1.4.0", - "yaml": "1.10.0", + "yaml": "1.10.2", "yargs": "^16.2.0" }, "devDependencies": { @@ -222,7 +222,7 @@ "@types/yaml": "1.9.7", "@types/yargs": "^15.0.13", "jest": "^26.6.3", - "jsii": "^1.24.0" + "jsii": "^1.25.0" }, "keywords": [ "aws", diff --git a/packages/monocdk/package.json b/packages/monocdk/package.json index 382f47c2be9d0..2978fe7a2e8d0 100644 --- a/packages/monocdk/package.json +++ b/packages/monocdk/package.json @@ -101,7 +101,7 @@ "minimatch": "^3.0.4", "punycode": "^2.1.1", "semver": "^7.3.4", - "yaml": "1.10.0" + "yaml": "1.10.2" }, "devDependencies": { "@aws-cdk/alexa-ask": "0.0.0", @@ -289,7 +289,7 @@ "@aws-cdk/region-info": "0.0.0", "@aws-cdk/yaml-cfn": "0.0.0", "@types/fs-extra": "^8.1.1", - "@types/node": "^10.17.54", + "@types/node": "^10.17.55", "cdk-build-tools": "0.0.0", "constructs": "^3.2.0", "fs-extra": "^9.1.0", diff --git a/scripts/bump.js b/scripts/bump.js index 5d8b4d63a62d0..bcbe8785c436b 100755 --- a/scripts/bump.js +++ b/scripts/bump.js @@ -11,7 +11,7 @@ const forTesting = process.env.BUMP_CANDIDATE || false; async function main() { if (releaseAs !== 'minor' && releaseAs !== 'patch') { - throw new error(`invalid bump type "${releaseAs}". only "minor" (the default) and "patch" are allowed. major version bumps require *slightly* more intention`); + throw new Error(`invalid bump type "${releaseAs}". only "minor" (the default) and "patch" are allowed. major version bumps require *slightly* more intention`); } console.error(`Starting ${releaseAs} version bump`); diff --git a/tools/cdk-build-tools/package.json b/tools/cdk-build-tools/package.json index 645d6eb54b454..ea9b6c6f807da 100644 --- a/tools/cdk-build-tools/package.json +++ b/tools/cdk-build-tools/package.json @@ -39,25 +39,25 @@ "pkglint": "0.0.0" }, "dependencies": { - "@typescript-eslint/eslint-plugin": "^4.16.1", - "@typescript-eslint/parser": "^4.16.1", + "@typescript-eslint/eslint-plugin": "^4.18.0", + "@typescript-eslint/parser": "^4.18.0", "awslint": "0.0.0", "colors": "^1.4.0", - "eslint": "^7.21.0", + "eslint": "^7.22.0", "eslint-import-resolver-node": "^0.3.4", "eslint-import-resolver-typescript": "^2.4.0", "eslint-plugin-cdk": "0.0.0", "eslint-plugin-import": "^2.22.1", - "eslint-plugin-jest": "^24.1.5", + "eslint-plugin-jest": "^24.3.2", "fs-extra": "^9.1.0", "jest": "^26.6.3", - "jsii": "^1.24.0", - "jsii-pacmak": "^1.24.0", + "jsii": "^1.25.0", + "jsii-pacmak": "^1.25.0", "markdownlint-cli": "^0.27.1", "nodeunit": "^0.11.3", "nyc": "^15.1.0", "semver": "^7.3.4", - "ts-jest": "^26.5.3", + "ts-jest": "^26.5.4", "typescript": "~3.9.9", "yargs": "^16.2.0", "yarn-cling": "0.0.0" diff --git a/tools/cfn2ts/package.json b/tools/cfn2ts/package.json index 6bc7f4ebb4d58..98e00832ecd6a 100644 --- a/tools/cfn2ts/package.json +++ b/tools/cfn2ts/package.json @@ -30,7 +30,7 @@ "license": "Apache-2.0", "dependencies": { "@aws-cdk/cfnspec": "0.0.0", - "codemaker": "^1.24.0", + "codemaker": "^1.25.0", "fast-json-patch": "^3.0.0-1", "fs-extra": "^9.1.0", "yargs": "^16.2.0" diff --git a/tools/eslint-plugin-cdk/package.json b/tools/eslint-plugin-cdk/package.json index f21cb470ca5f5..9a5c7fbd5c36b 100644 --- a/tools/eslint-plugin-cdk/package.json +++ b/tools/eslint-plugin-cdk/package.json @@ -12,17 +12,17 @@ "build+test": "npm run build && npm test" }, "devDependencies": { - "@types/eslint": "^7.2.6", + "@types/eslint": "^7.2.7", "@types/fs-extra": "^8.1.1", "@types/jest": "^26.0.20", - "@types/node": "^10.17.54", - "eslint-plugin-rulesdir": "^0.1.0", + "@types/node": "^10.17.55", + "eslint-plugin-rulesdir": "^0.2.0", "jest": "^26.6.3", "typescript": "~3.9.9" }, "dependencies": { - "@typescript-eslint/parser": "^4.16.1", - "eslint": "^7.21.0", + "@typescript-eslint/parser": "^4.18.0", + "eslint": "^7.22.0", "fs-extra": "^9.1.0" }, "jest": { diff --git a/tools/nodeunit-shim/package.json b/tools/nodeunit-shim/package.json index bc18b8dafe37c..d94545d9429ae 100644 --- a/tools/nodeunit-shim/package.json +++ b/tools/nodeunit-shim/package.json @@ -13,7 +13,7 @@ }, "devDependencies": { "@types/jest": "^26.0.20", - "@types/node": "^10.17.54", + "@types/node": "^10.17.55", "typescript": "~3.9.9" }, "dependencies": { diff --git a/tools/yarn-cling/package.json b/tools/yarn-cling/package.json index 7a5f00b076fb3..0a71db1feaf8a 100644 --- a/tools/yarn-cling/package.json +++ b/tools/yarn-cling/package.json @@ -39,7 +39,7 @@ }, "devDependencies": { "@types/jest": "^26.0.20", - "@types/node": "^10.17.54", + "@types/node": "^10.17.55", "@types/yarnpkg__lockfile": "^1.1.4", "jest": "^26.6.3", "pkglint": "0.0.0", diff --git a/version.v1.json b/version.v1.json index 097cc55f8cc18..0a93d433950d0 100644 --- a/version.v1.json +++ b/version.v1.json @@ -1,3 +1,3 @@ { - "version": "1.93.0" + "version": "1.94.1" } diff --git a/yarn.lock b/yarn.lock index 9e33a1efe99be..f534011e483c3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17,21 +17,21 @@ "@babel/highlight" "^7.12.13" "@babel/compat-data@^7.13.8": - version "7.13.8" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.13.8.tgz#5b783b9808f15cef71547f1b691f34f8ff6003a6" - integrity sha512-EaI33z19T4qN3xLXsGf48M2cDqa6ei9tPZlfLdb2HC+e/cFtREiRd8hdSqDbwdLB0/+gLwqJmCYASH0z2bUdog== + version "7.13.11" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.13.11.tgz#9c8fe523c206979c9a81b1e12fe50c1254f1aa35" + integrity sha512-BwKEkO+2a67DcFeS3RLl0Z3Gs2OvdXewuWjc1Hfokhb5eQWP9YRYH1/+VrVZvql2CfjOiNGqSAFOYt4lsqTHzg== "@babel/core@^7.1.0", "@babel/core@^7.7.5": - version "7.13.8" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.13.8.tgz#c191d9c5871788a591d69ea1dc03e5843a3680fb" - integrity sha512-oYapIySGw1zGhEFRd6lzWNLWFX2s5dA/jm+Pw/+59ZdXtjyIuwlXbrId22Md0rgZVop+aVoqow2riXhBLNyuQg== + version "7.13.10" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.13.10.tgz#07de050bbd8193fcd8a3c27918c0890613a94559" + integrity sha512-bfIYcT0BdKeAZrovpMqX2Mx5NrgAckGbwT982AkdS5GNfn3KMGiprlBAtmBcFZRUmpaufS6WZFP8trvx8ptFDw== dependencies: "@babel/code-frame" "^7.12.13" - "@babel/generator" "^7.13.0" - "@babel/helper-compilation-targets" "^7.13.8" + "@babel/generator" "^7.13.9" + "@babel/helper-compilation-targets" "^7.13.10" "@babel/helper-module-transforms" "^7.13.0" - "@babel/helpers" "^7.13.0" - "@babel/parser" "^7.13.4" + "@babel/helpers" "^7.13.10" + "@babel/parser" "^7.13.10" "@babel/template" "^7.12.13" "@babel/traverse" "^7.13.0" "@babel/types" "^7.13.0" @@ -43,7 +43,7 @@ semver "^6.3.0" source-map "^0.5.0" -"@babel/generator@^7.13.0", "@babel/generator@^7.4.0": +"@babel/generator@^7.13.0", "@babel/generator@^7.13.9", "@babel/generator@^7.4.0": version "7.13.9" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.13.9.tgz#3a7aa96f9efb8e2be42d38d80e2ceb4c64d8de39" integrity sha512-mHOOmY0Axl/JCTkxTU6Lf5sWOg/v8nUa+Xkt4zMTftX0wqmb6Sh7J8gvcehBw7q0AhrhAR+FDacKjCZ2X8K+Sw== @@ -52,10 +52,10 @@ jsesc "^2.5.1" source-map "^0.5.0" -"@babel/helper-compilation-targets@^7.13.8": - version "7.13.8" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.13.8.tgz#02bdb22783439afb11b2f009814bdd88384bd468" - integrity sha512-pBljUGC1y3xKLn1nrx2eAhurLMA8OqBtBP/JwG4U8skN7kf8/aqwwxpV1N6T0e7r6+7uNitIa/fUxPFagSXp3A== +"@babel/helper-compilation-targets@^7.13.10": + version "7.13.10" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.13.10.tgz#1310a1678cb8427c07a753750da4f8ce442bdd0c" + integrity sha512-/Xju7Qg1GQO4mHZ/Kcs6Au7gfafgZnwm+a7sy/ow/tV1sHeraRUHbjdat8/UvDor4Tez+siGKDk6zIKtCPKVJA== dependencies: "@babel/compat-data" "^7.13.8" "@babel/helper-validator-option" "^7.12.17" @@ -153,28 +153,28 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.12.17.tgz#d1fbf012e1a79b7eebbfdc6d270baaf8d9eb9831" integrity sha512-TopkMDmLzq8ngChwRlyjR6raKD6gMSae4JdYDB8bByKreQgG0RBTuKe9LRxW3wFtUnjxOPRKBDwEH6Mg5KeDfw== -"@babel/helpers@^7.13.0": - version "7.13.0" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.13.0.tgz#7647ae57377b4f0408bf4f8a7af01c42e41badc0" - integrity sha512-aan1MeFPxFacZeSz6Ld7YZo5aPuqnKlD7+HZY75xQsueczFccP9A7V05+oe0XpLwHK3oLorPe9eaAUljL7WEaQ== +"@babel/helpers@^7.13.10": + version "7.13.10" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.13.10.tgz#fd8e2ba7488533cdeac45cc158e9ebca5e3c7df8" + integrity sha512-4VO883+MWPDUVRF3PhiLBUFHoX/bsLTGFpFK/HqvvfBZz2D57u9XzPVNFVBTc0PW/CWR9BXTOKt8NF4DInUHcQ== dependencies: "@babel/template" "^7.12.13" "@babel/traverse" "^7.13.0" "@babel/types" "^7.13.0" "@babel/highlight@^7.10.4", "@babel/highlight@^7.12.13": - version "7.13.8" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.13.8.tgz#10b2dac78526424dfc1f47650d0e415dfd9dc481" - integrity sha512-4vrIhfJyfNf+lCtXC2ck1rKSzDwciqF7IWFhXXrSOUC2O5DrVp+w4c6ed4AllTxhTkUP5x2tYj41VaxdVMMRDw== + version "7.13.10" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.13.10.tgz#a8b2a66148f5b27d666b15d81774347a731d52d1" + integrity sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg== dependencies: "@babel/helper-validator-identifier" "^7.12.11" chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.12.13", "@babel/parser@^7.13.0", "@babel/parser@^7.13.4", "@babel/parser@^7.4.3": - version "7.13.9" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.13.9.tgz#ca34cb95e1c2dd126863a84465ae8ef66114be99" - integrity sha512-nEUfRiARCcaVo3ny3ZQjURjHQZUo/JkEw7rLlSZy/psWGnvwXFtPcr6jb7Yb41DVW5LTe6KRq9LGleRNsg1Frw== +"@babel/parser@^7.1.0", "@babel/parser@^7.12.13", "@babel/parser@^7.13.0", "@babel/parser@^7.13.10", "@babel/parser@^7.4.3": + version "7.13.11" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.13.11.tgz#f93ebfc99d21c1772afbbaa153f47e7ce2f50b88" + integrity sha512-PhuoqeHoO9fc4ffMEVk4qb/w/s2iOSWohvbHxLtxui0eBg3Lg5gN1U8wp1V1u61hOWkPQJJyJzGH6Y+grwkq8Q== "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" @@ -587,10 +587,10 @@ "@types/yargs" "^15.0.0" chalk "^4.0.0" -"@jsii/spec@^1.24.0": - version "1.24.0" - resolved "https://registry.yarnpkg.com/@jsii/spec/-/spec-1.24.0.tgz#59dd43af7bb65074b39bd457a98f4ab3cb385bd3" - integrity sha512-Km0va0ZBlzWPOijsNlo7SwozYT6Ej9h01xXYtBmoHw2CLccofOEQLV2Ig3+ydhU+aTW5yLKJrVPsAjJoaaBAgA== +"@jsii/spec@^1.25.0": + version "1.25.0" + resolved "https://registry.yarnpkg.com/@jsii/spec/-/spec-1.25.0.tgz#535b85aa26d3db1d188c04300a2e20529eeee7fd" + integrity sha512-Zr56+uqZLoxI8qxIZZEweZdYBo0KqWf+q25m/okgwcKV4njCZuh0APXzeT/ebSkSOHQ3tneEE+g2EP/8IPP2og== dependencies: jsonschema "^1.4.0" @@ -1321,15 +1321,16 @@ "@octokit/types" "^6.0.3" "@octokit/core@^3.2.3": - version "3.2.5" - resolved "https://registry.yarnpkg.com/@octokit/core/-/core-3.2.5.tgz#57becbd5fd789b0592b915840855f3a5f233d554" - integrity sha512-+DCtPykGnvXKWWQI0E1XD+CCeWSBhB6kwItXqfFmNBlIlhczuDPbg+P6BtLnVBaRJDAjv+1mrUJuRsFSjktopg== + version "3.3.1" + resolved "https://registry.yarnpkg.com/@octokit/core/-/core-3.3.1.tgz#c6bb6ba171ad84a5f430853a98892cfe8f93d8cd" + integrity sha512-Dc5NNQOYjgZU5S1goN6A/E500yXOfDUFRGQB8/2Tl16AcfvS3H9PudyOe3ZNE/MaVyHPIfC0htReHMJb1tMrvw== dependencies: "@octokit/auth-token" "^2.4.4" "@octokit/graphql" "^4.5.8" "@octokit/request" "^5.4.12" + "@octokit/request-error" "^2.0.5" "@octokit/types" "^6.0.3" - before-after-hook "^2.1.0" + before-after-hook "^2.2.0" universal-user-agent "^6.0.0" "@octokit/endpoint@^6.0.1": @@ -1342,18 +1343,18 @@ universal-user-agent "^6.0.0" "@octokit/graphql@^4.5.8": - version "4.6.0" - resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-4.6.0.tgz#f9abca55f82183964a33439d5264674c701c3327" - integrity sha512-CJ6n7izLFXLvPZaWzCQDjU/RP+vHiZmWdOunaCS87v+2jxMsW9FB5ktfIxybRBxZjxuJGRnxk7xJecWTVxFUYQ== + version "4.6.1" + resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-4.6.1.tgz#f975486a46c94b7dbe58a0ca751935edc7e32cc9" + integrity sha512-2lYlvf4YTDgZCTXTW4+OX+9WTLFtEUc6hGm4qM1nlZjzxj+arizM4aHWzBVBCxY9glh7GIs0WEuiSgbVzv8cmA== dependencies: "@octokit/request" "^5.3.0" "@octokit/types" "^6.0.3" universal-user-agent "^6.0.0" -"@octokit/openapi-types@^5.2.2": - version "5.2.2" - resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-5.2.2.tgz#1590c118a131031610faffd4222ae54915e2b82d" - integrity sha512-b3nHy/0uufJJsaZERwZM0syLRO6gfr6vvBPLewQxBKzzbhGDx1ygTyoELMNADD7mIPPzGMqbfdCeJTSeZueZwA== +"@octokit/openapi-types@^5.3.2": + version "5.3.2" + resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-5.3.2.tgz#b8ac43c5c3d00aef61a34cf744e315110c78deb4" + integrity sha512-NxF1yfYOUO92rCx3dwvA2onF30Vdlg7YUkMVXkeptqpzA3tRLplThhFleV/UKWFgh7rpKu1yYRbvNDUtzSopKA== "@octokit/plugin-enterprise-rest@^6.0.1": version "6.0.1" @@ -1368,9 +1369,9 @@ "@octokit/types" "^2.0.1" "@octokit/plugin-paginate-rest@^2.6.2": - version "2.11.0" - resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.11.0.tgz#3568c43896a3355f4a0bbb3a64f443b2abdc760d" - integrity sha512-7L9xQank2G3r1dGqrVPo1z62V5utbykOUzlmNHPz87Pww/JpZQ9KyG5CHtUzgmB4n5iDRKYNK/86A8D98HP0yA== + version "2.13.2" + resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.13.2.tgz#7b8244a0dd7a31135ba2adc58a533213837bfe87" + integrity sha512-mjfBcla00UNS4EI/NN7toEbUM45ow3kk4go+LxsXAFLQodsrXcIZbftUhXTqi6ZKd+r6bcqMI+Lv4dshLtFjww== dependencies: "@octokit/types" "^6.11.0" @@ -1387,12 +1388,12 @@ "@octokit/types" "^2.0.1" deprecation "^2.3.1" -"@octokit/plugin-rest-endpoint-methods@4.13.2": - version "4.13.2" - resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-4.13.2.tgz#4e1fa30742a7bb1f0fe99e2f8e2b21f7aa8b7eb5" - integrity sha512-pnn0lGE05nqZ+EZuZgJBffJ4QRAlrlvg3LBFjCKHqUUWCI3PMqZ8kPJOxFj0R3B3D5hoGambtEIpCnaRD6nRJw== +"@octokit/plugin-rest-endpoint-methods@4.13.5": + version "4.13.5" + resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-4.13.5.tgz#ad76285b82fe05fbb4adf2774a9c887f3534a880" + integrity sha512-kYKcWkFm4Ldk8bZai2RVEP1z97k1C/Ay2FN9FNTBg7JIyKoiiJjks4OtT6cuKeZX39tqa+C3J9xeYc6G+6g8uQ== dependencies: - "@octokit/types" "^6.11.2" + "@octokit/types" "^6.12.2" deprecation "^2.3.1" "@octokit/request-error@^1.0.2": @@ -1404,7 +1405,7 @@ deprecation "^2.0.0" once "^1.4.0" -"@octokit/request-error@^2.0.0": +"@octokit/request-error@^2.0.0", "@octokit/request-error@^2.0.5": version "2.0.5" resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-2.0.5.tgz#72cc91edc870281ad583a42619256b380c600143" integrity sha512-T/2wcCFyM7SkXzNoyVNWjyVlUwBvW3igM3Btr/eKYiPmucXTtkxt2RBsf6gn3LTzaLSLTQtNmvg+dGsOxQrjZg== @@ -1449,15 +1450,15 @@ once "^1.4.0" universal-user-agent "^4.0.0" -"@octokit/rest@^18.3.2": - version "18.3.2" - resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-18.3.2.tgz#dae61ff8c70e3f968e182919f36f1338163c8ea8" - integrity sha512-TSTI47/jLqdq8qvc/a/P/VApBal7QHeISPZ8a1v7ma8NN/YdU5HRTSCb15+IvzUeuM7Iagp0aG+ypvQXJgmgQw== +"@octokit/rest@^18.3.5": + version "18.3.5" + resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-18.3.5.tgz#a89903d46e0b4273bd3234674ec2777a651d68ab" + integrity sha512-ZPeRms3WhWxQBEvoIh0zzf8xdU2FX0Capa7+lTca8YHmRsO3QNJzf1H3PcuKKsfgp91/xVDRtX91sTe1kexlbw== dependencies: "@octokit/core" "^3.2.3" "@octokit/plugin-paginate-rest" "^2.6.2" "@octokit/plugin-request-log" "^1.0.2" - "@octokit/plugin-rest-endpoint-methods" "4.13.2" + "@octokit/plugin-rest-endpoint-methods" "4.13.5" "@octokit/types@^2.0.0", "@octokit/types@^2.0.1": version "2.16.2" @@ -1466,12 +1467,12 @@ dependencies: "@types/node" ">= 8" -"@octokit/types@^6.0.3", "@octokit/types@^6.11.0", "@octokit/types@^6.11.2", "@octokit/types@^6.7.1": - version "6.11.2" - resolved "https://registry.yarnpkg.com/@octokit/types/-/types-6.11.2.tgz#43973dc29cdf59bf9d5f3ab0d16275c4b4a6eb8d" - integrity sha512-EKQRFZU/oOfUlqk9ntLIE5UO/bcOx8exFpdXGBciJP90f05me3mza0sacIpqVqmiIQP3nJsBjnZHMmtijE5XwQ== +"@octokit/types@^6.0.3", "@octokit/types@^6.11.0", "@octokit/types@^6.12.2", "@octokit/types@^6.7.1": + version "6.12.2" + resolved "https://registry.yarnpkg.com/@octokit/types/-/types-6.12.2.tgz#5b44add079a478b8eb27d78cf384cc47e4411362" + integrity sha512-kCkiN8scbCmSq+gwdJV0iLgHc0O/GTPY1/cffo9kECu1MvatLPh9E+qFhfRIktKfHEA6ZYvv6S1B4Wnv3bi3pA== dependencies: - "@octokit/openapi-types" "^5.2.2" + "@octokit/openapi-types" "^5.3.2" "@sinonjs/commons@^1.6.0", "@sinonjs/commons@^1.7.0", "@sinonjs/commons@^1.8.1": version "1.8.2" @@ -1519,9 +1520,9 @@ integrity sha512-jOrTwAhSiUtBIN/QsWNKlI4+4aDtpZ0sr2BRvKW6XQZdspgHUSHPcuzxbzCRiHUiDQ+0026u5TSE38VyIhNnfA== "@types/babel__core@^7.0.0", "@types/babel__core@^7.1.7": - version "7.1.12" - resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.12.tgz#4d8e9e51eb265552a7e4f1ff2219ab6133bdfb2d" - integrity sha512-wMTHiiTiBAAPebqaPiPDLFA4LYPKr6Ph0Xq/6rq1Ur3v66HXyG+clfR9CNETkD7MQS8ZHvpQOtA53DLws5WAEQ== + version "7.1.13" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.13.tgz#bc6eea53975fdf163aff66c086522c6f293ae4cf" + integrity sha512-CC6amBNND16pTk4K3ZqKIaba6VGKAQs3gMjEY17FVd56oI/ZWt9OhS6riYiWv9s8ENbYUi7p8lgqb0QHQvUKQQ== dependencies: "@babel/parser" "^7.1.0" "@babel/types" "^7.0.0" @@ -1545,16 +1546,16 @@ "@babel/types" "^7.0.0" "@types/babel__traverse@*", "@types/babel__traverse@^7.0.4", "@types/babel__traverse@^7.0.6": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.11.0.tgz#b9a1efa635201ba9bc850323a8793ee2d36c04a0" - integrity sha512-kSjgDMZONiIfSH1Nxcr5JIRMwUetDki63FSQfpTCz8ogF3Ulqm8+mr5f78dUYs6vMiB6gBusQqfQmBvHZj/lwg== + version "7.11.1" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.11.1.tgz#654f6c4f67568e24c23b367e947098c6206fa639" + integrity sha512-Vs0hm0vPahPMYi9tDjtP66llufgO3ST16WXaSTtDGEl9cewAl3AibmxWw6TINOqHPT9z0uABKAYjT9jNSg4npw== dependencies: "@babel/types" "^7.3.0" -"@types/eslint@^7.2.6": - version "7.2.6" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-7.2.6.tgz#5e9aff555a975596c03a98b59ecd103decc70c3c" - integrity sha512-I+1sYH+NPQ3/tVqCeUSBwTE/0heyvtXqpIopUUArlBm0Kpocb8FbMa3AZ/ASKIFpN3rnEx932TTXDbt9OXsNDw== +"@types/eslint@^7.2.7": + version "7.2.7" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-7.2.7.tgz#f7ef1cf0dceab0ae6f9a976a0a9af14ab1baca26" + integrity sha512-EHXbc1z2GoQRqHaAT7+grxlTJ3WE2YNeD6jlpPoRc83cCoThRY+NUWjCUZaYmk51OICkPXn2hhphcWcWXgNW0Q== dependencies: "@types/estree" "*" "@types/json-schema" "*" @@ -1613,7 +1614,7 @@ jest-diff "^26.0.0" pretty-format "^26.0.0" -"@types/json-schema@*", "@types/json-schema@^7.0.3", "@types/json-schema@^7.0.6": +"@types/json-schema@*", "@types/json-schema@^7.0.3", "@types/json-schema@^7.0.7": version "7.0.7" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.7.tgz#98a993516c859eb0d5c4c8f098317a9ea68db9ad" integrity sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA== @@ -1664,15 +1665,15 @@ resolved "https://registry.yarnpkg.com/@types/mockery/-/mockery-1.4.29.tgz#9ba22df37f07e3780fff8531d1a38e633f9457a5" integrity sha1-m6It838H43gP/4Ux0aOOYz+UV6U= -"@types/node@*", "@types/node@>= 8": - version "14.14.31" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.31.tgz#72286bd33d137aa0d152d47ec7c1762563d34055" - integrity sha512-vFHy/ezP5qI0rFgJ7aQnjDXwAMrG0KqqIH7tQG5PPv3BWBayOPIQNBjVc/P6hhdZfMx51REc6tfDNXHUio893g== +"@types/node@*", "@types/node@>= 8", "@types/node@^14.14.33": + version "14.14.35" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.35.tgz#42c953a4e2b18ab931f72477e7012172f4ffa313" + integrity sha512-Lt+wj8NVPx0zUmUwumiVXapmaLUcAk3yPuHCFVXras9k5VT9TdhJqKqGVUQCD60OTMCl0qxJ57OiTL0Mic3Iag== -"@types/node@^10.17.54": - version "10.17.54" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.54.tgz#a737488631aca3ec7bd9f6229d77f1079e444793" - integrity sha512-c8Lm7+hXdSPmWH4B9z/P/xIXhFK3mCQin4yCYMd2p1qpMG5AfgyJuYZ+3q2dT7qLiMMMGMd5dnkFpdqJARlvtQ== +"@types/node@^10.17.55": + version "10.17.55" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.55.tgz#a147f282edec679b894d4694edb5abeb595fecbd" + integrity sha512-koZJ89uLZufDvToeWO5BrC4CR4OUfHnUz2qoPs/daQH6qq3IN62QFxCTZ+bKaCE0xaoCAJYE4AXre8AbghCrhg== "@types/nodeunit@^0.0.31": version "0.0.31" @@ -1685,9 +1686,9 @@ integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA== "@types/prettier@^2.0.0": - version "2.2.2" - resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.2.2.tgz#e2280c89ddcbeef340099d6968d8c86ba155fdf6" - integrity sha512-i99hy7Ki19EqVOl77WplDrvgNugHnsSjECVR/wUrzw2TJXz1zlUfT2ngGckR6xN7yFYaijsMAqPkOLx9HgUqHg== + version "2.2.3" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.2.3.tgz#ef65165aea2924c9359205bf748865b8881753c0" + integrity sha512-PijRCG/K3s3w1We6ynUKdxEc5AcuuH3NBmMDP8uvKVp6X43UY7NQlTzczakXP3DJR0F4dfNQIGjU2cUeRYs2AA== "@types/promptly@^3.0.1": version "3.0.1" @@ -1711,10 +1712,10 @@ resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.4.tgz#43d7168fec6fa0988bb1a513a697b29296721afb" integrity sha512-+nVsLKlcUCeMzD2ufHEYuJ9a2ovstb6Dp52A5VsoKxDXgvE051XgHI/33I1EymwkRGQkwnA0LkhnUzituGs4EQ== -"@types/sinon@^9.0.10": - version "9.0.10" - resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-9.0.10.tgz#7fb9bcb6794262482859cab66d59132fca18fcf7" - integrity sha512-/faDC0erR06wMdybwI/uR8wEKV/E83T0k4sepIpB7gXuy2gzx2xiOjmztq6a2Y6rIGJ04D+6UU0VBmWy+4HEMA== +"@types/sinon@^9.0.11": + version "9.0.11" + resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-9.0.11.tgz#7af202dda5253a847b511c929d8b6dda170562eb" + integrity sha512-PwP4UY33SeeVKodNE37ZlOsR9cReypbMJOhZ7BVE0lB+Hix3efCOxiJWiE5Ia+yL9Cn2Ch72EjFTRze8RZsNtg== dependencies: "@types/sinonjs__fake-timers" "*" @@ -1781,13 +1782,13 @@ resolved "https://registry.yarnpkg.com/@types/yarnpkg__lockfile/-/yarnpkg__lockfile-1.1.4.tgz#445251eb00bd9c1e751f82c7c6bf4f714edfd464" integrity sha512-/emrKCfQMQmFCqRqqBJ0JueHBT06jBRM3e8OgnvDUcvuExONujIk2hFA5dNsN9Nt41ljGVDdChvCydATZ+KOZw== -"@typescript-eslint/eslint-plugin@^4.16.1": - version "4.16.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.16.1.tgz#2caf6a79dd19c3853b8d39769a27fccb24e4e651" - integrity sha512-SK777klBdlkUZpZLC1mPvyOWk9yAFCWmug13eAjVQ4/Q1LATE/NbcQL1xDHkptQkZOLnPmLUA1Y54m8dqYwnoQ== +"@typescript-eslint/eslint-plugin@^4.18.0": + version "4.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.18.0.tgz#50fbce93211b5b690895d20ebec6fe8db48af1f6" + integrity sha512-Lzkc/2+7EoH7+NjIWLS2lVuKKqbEmJhtXe3rmfA8cyiKnZm3IfLf51irnBcmow8Q/AptVV0XBZmBJKuUJTe6cQ== dependencies: - "@typescript-eslint/experimental-utils" "4.16.1" - "@typescript-eslint/scope-manager" "4.16.1" + "@typescript-eslint/experimental-utils" "4.18.0" + "@typescript-eslint/scope-manager" "4.18.0" debug "^4.1.1" functional-red-black-tree "^1.0.1" lodash "^4.17.15" @@ -1795,60 +1796,60 @@ semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/experimental-utils@4.16.1", "@typescript-eslint/experimental-utils@^4.0.1": - version "4.16.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.16.1.tgz#da7a396dc7d0e01922acf102b76efff17320b328" - integrity sha512-0Hm3LSlMYFK17jO4iY3un1Ve9x1zLNn4EM50Lia+0EV99NdbK+cn0er7HC7IvBA23mBg3P+8dUkMXy4leL33UQ== +"@typescript-eslint/experimental-utils@4.18.0", "@typescript-eslint/experimental-utils@^4.0.1": + version "4.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.18.0.tgz#ed6c955b940334132b17100d2917449b99a91314" + integrity sha512-92h723Kblt9JcT2RRY3QS2xefFKar4ZQFVs3GityOKWQYgtajxt/tuXIzL7sVCUlM1hgreiV5gkGYyBpdOwO6A== dependencies: "@types/json-schema" "^7.0.3" - "@typescript-eslint/scope-manager" "4.16.1" - "@typescript-eslint/types" "4.16.1" - "@typescript-eslint/typescript-estree" "4.16.1" + "@typescript-eslint/scope-manager" "4.18.0" + "@typescript-eslint/types" "4.18.0" + "@typescript-eslint/typescript-estree" "4.18.0" eslint-scope "^5.0.0" eslint-utils "^2.0.0" -"@typescript-eslint/parser@^4.16.1": - version "4.16.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.16.1.tgz#3bbd3234dd3c5b882b2bcd9899bc30e1e1586d2a" - integrity sha512-/c0LEZcDL5y8RyI1zLcmZMvJrsR6SM1uetskFkoh3dvqDKVXPsXI+wFB/CbVw7WkEyyTKobC1mUNp/5y6gRvXg== +"@typescript-eslint/parser@^4.18.0": + version "4.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.18.0.tgz#a211edb14a69fc5177054bec04c95b185b4dde21" + integrity sha512-W3z5S0ZbecwX3PhJEAnq4mnjK5JJXvXUDBYIYGoweCyWyuvAKfGHvzmpUzgB5L4cRBb+cTu9U/ro66dx7dIimA== dependencies: - "@typescript-eslint/scope-manager" "4.16.1" - "@typescript-eslint/types" "4.16.1" - "@typescript-eslint/typescript-estree" "4.16.1" + "@typescript-eslint/scope-manager" "4.18.0" + "@typescript-eslint/types" "4.18.0" + "@typescript-eslint/typescript-estree" "4.18.0" debug "^4.1.1" -"@typescript-eslint/scope-manager@4.16.1": - version "4.16.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.16.1.tgz#244e2006bc60cfe46987e9987f4ff49c9e3f00d5" - integrity sha512-6IlZv9JaurqV0jkEg923cV49aAn8V6+1H1DRfhRcvZUrptQ+UtSKHb5kwTayzOYTJJ/RsYZdcvhOEKiBLyc0Cw== +"@typescript-eslint/scope-manager@4.18.0": + version "4.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.18.0.tgz#d75b55234c35d2ff6ac945758d6d9e53be84a427" + integrity sha512-olX4yN6rvHR2eyFOcb6E4vmhDPsfdMyfQ3qR+oQNkAv8emKKlfxTWUXU5Mqxs2Fwe3Pf1BoPvrwZtwngxDzYzQ== dependencies: - "@typescript-eslint/types" "4.16.1" - "@typescript-eslint/visitor-keys" "4.16.1" + "@typescript-eslint/types" "4.18.0" + "@typescript-eslint/visitor-keys" "4.18.0" -"@typescript-eslint/types@4.16.1": - version "4.16.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.16.1.tgz#5ba2d3e38b1a67420d2487519e193163054d9c15" - integrity sha512-nnKqBwMgRlhzmJQF8tnFDZWfunXmJyuXj55xc8Kbfup4PbkzdoDXZvzN8//EiKR27J6vUSU8j4t37yUuYPiLqA== +"@typescript-eslint/types@4.18.0": + version "4.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.18.0.tgz#bebe323f81f2a7e2e320fac9415e60856267584a" + integrity sha512-/BRociARpj5E+9yQ7cwCF/SNOWwXJ3qhjurMuK2hIFUbr9vTuDeu476Zpu+ptxY2kSxUHDGLLKy+qGq2sOg37A== -"@typescript-eslint/typescript-estree@4.16.1": - version "4.16.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.16.1.tgz#c2fc46b05a48fbf8bbe8b66a63f0a9ba04b356f1" - integrity sha512-m8I/DKHa8YbeHt31T+UGd/l8Kwr0XCTCZL3H4HMvvLCT7HU9V7yYdinTOv1gf/zfqNeDcCgaFH2BMsS8x6NvJg== +"@typescript-eslint/typescript-estree@4.18.0": + version "4.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.18.0.tgz#756d3e61da8c16ab99185532c44872f4cd5538cb" + integrity sha512-wt4xvF6vvJI7epz+rEqxmoNQ4ZADArGQO9gDU+cM0U5fdVv7N+IAuVoVAoZSOZxzGHBfvE3XQMLdy+scsqFfeg== dependencies: - "@typescript-eslint/types" "4.16.1" - "@typescript-eslint/visitor-keys" "4.16.1" + "@typescript-eslint/types" "4.18.0" + "@typescript-eslint/visitor-keys" "4.18.0" debug "^4.1.1" globby "^11.0.1" is-glob "^4.0.1" semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/visitor-keys@4.16.1": - version "4.16.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.16.1.tgz#d7571fb580749fae621520deeb134370bbfc7293" - integrity sha512-s/aIP1XcMkEqCNcPQtl60ogUYjSM8FU2mq1O7y5cFf3Xcob1z1iXWNB6cC43Op+NGRTFgGolri6s8z/efA9i1w== +"@typescript-eslint/visitor-keys@4.18.0": + version "4.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.18.0.tgz#4e6fe2a175ee33418318a029610845a81e2ff7b6" + integrity sha512-Q9t90JCvfYaN0OfFUgaLqByOfz8yPeTAdotn/XYNm5q9eHax90gzdb+RJ6E9T5s97Kv/UHWKERTmqA0jTKAEHw== dependencies: - "@typescript-eslint/types" "4.16.1" + "@typescript-eslint/types" "4.18.0" eslint-visitor-keys "^2.0.0" "@yarnpkg/lockfile@^1.1.0": @@ -1873,7 +1874,7 @@ JSONStream@^1.0.4, JSONStream@^1.3.4: jsonparse "^1.2.0" through ">=2.2.7 <3" -abab@^2.0.3: +abab@^2.0.3, abab@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a" integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q== @@ -1906,6 +1907,11 @@ acorn@^7.1.1, acorn@^7.4.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== +acorn@^8.0.5: + version "8.1.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.1.0.tgz#52311fd7037ae119cbb134309e901aa46295b3fe" + integrity sha512-LWCF/Wn0nfHOmJ9rzQApGnxnvgfROzGilS8936rqN/lfcYkY9MYZzdMqN+2NJ4SlTc+m5HiSa+kNfDtI64dwUA== + add-stream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/add-stream/-/add-stream-1.0.0.tgz#6a7990437ca736d5e1288db92bd3266d5f5cb2aa" @@ -1958,9 +1964,9 @@ ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4: uri-js "^4.2.2" ajv@^7.0.2: - version "7.1.1" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-7.1.1.tgz#1e6b37a454021fa9941713f38b952fc1c8d32a84" - integrity sha512-ga/aqDYnUy/o7vbsRTFhhTsNeXiYb5JWDIcRIeZfwRNCefwjNTVYCGdGSUrEmiu3yDK3vFvNbgJxvrQW4JXrYQ== + version "7.2.1" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-7.2.1.tgz#a5ac226171912447683524fa2f1248fcf8bac83d" + integrity sha512-+nu0HDv7kNSOua9apAVc979qd932rrZeb3WOvoiD31A/p1mIE5/9bN2027pE2rOPYEdS3UHzsvof4hY+lM9/WQ== dependencies: fast-deep-equal "^3.1.1" json-schema-traverse "^1.0.0" @@ -2084,18 +2090,18 @@ archiver-utils@^2.1.0: normalize-path "^3.0.0" readable-stream "^2.0.0" -archiver@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/archiver/-/archiver-5.2.0.tgz#25aa1b3d9febf7aec5b0f296e77e69960c26db94" - integrity sha512-QEAKlgQuAtUxKeZB9w5/ggKXh21bZS+dzzuQ0RPBC20qtDCbTyzqmisoeJP46MP39fg4B4IcyvR+yeyEBdblsQ== +archiver@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/archiver/-/archiver-5.3.0.tgz#dd3e097624481741df626267564f7dd8640a45ba" + integrity sha512-iUw+oDwK0fgNpvveEsdQ0Ase6IIKztBJU2U0E9MzszMfmVVUyv1QJhS2ITW9ZCqx8dktAxVAjWWkKehuZE8OPg== dependencies: archiver-utils "^2.1.0" async "^3.2.0" buffer-crc32 "^0.2.1" readable-stream "^3.6.0" readdir-glob "^1.0.0" - tar-stream "^2.1.4" - zip-stream "^4.0.4" + tar-stream "^2.2.0" + zip-stream "^4.1.0" archy@^1.0.0: version "1.0.0" @@ -2285,9 +2291,9 @@ aws-sdk-mock@^5.1.0: traverse "^0.6.6" aws-sdk@^2.596.0, aws-sdk@^2.637.0, aws-sdk@^2.848.0: - version "2.856.0" - resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.856.0.tgz#a82719952949bdfda73832b465321a49577cf784" - integrity sha512-B9uRDhIxlmaz5GIDC2Q+OgVMnsPFzuu1HknWedpTre6ARG+Ukm8KQ3VA5MhsBtSm61X5u1Uwk5AlEv+feLaShA== + version "2.865.0" + resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.865.0.tgz#e80cc4a07059068d7354f9043df4ede9fbe11a41" + integrity sha512-JUaUlGjnJY4Nnd/xnWt8rPmTwebVvA26XfnUM3tyAPtSClwniANkaRq4UdHI0uU3R+V4N2Cuohy8XSLOzBG/4A== dependencies: buffer "4.9.2" events "1.1.1" @@ -2407,10 +2413,10 @@ bcrypt-pbkdf@^1.0.0: dependencies: tweetnacl "^0.14.3" -before-after-hook@^2.0.0, before-after-hook@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.1.1.tgz#99ae36992b5cfab4a83f6bee74ab27835f28f405" - integrity sha512-5ekuQOvO04MDj7kYZJaMab2S8SPjGJbotVNyv7QYFCOAwrGZs/YnoDNlh1U+m5hl7H2D/+n0taaAV/tfyd3KMA== +before-after-hook@^2.0.0, before-after-hook@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.2.0.tgz#09c40d92e936c64777aa385c4e9b904f8147eaf0" + integrity sha512-jH6rKQIfroBbhEXVmI7XmXe3ix5S/PgJqpzdDPnR8JGLHWNYLsYZ6tK5iWOF/Ra3oqEX0NobXGlzbiylIzVphQ== bind-obj-methods@^2.0.0: version "2.0.1" @@ -2684,9 +2690,9 @@ camelcase@^6.0.0, camelcase@^6.2.0: integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== caniuse-lite@^1.0.30001181: - version "1.0.30001196" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001196.tgz#00518a2044b1abf3e0df31fadbe5ed90b63f4e64" - integrity sha512-CPvObjD3ovWrNBaXlAIGWmg2gQQuJ5YhuciUOjPRox6hIQttu8O+b51dx6VIpIY9ESd2d0Vac1RKpICdG4rGUg== + version "1.0.30001202" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001202.tgz#4cb3bd5e8a808e8cd89e4e66c549989bc8137201" + integrity sha512-ZcijQNqrcF8JNLjzvEiXqX4JUYxoZa7Pvcsd9UD8Kz4TvhTonOSNRsK+qtvpVL4l6+T1Rh4LFtLfnNWg6BGWCQ== capture-exit@^2.0.0: version "2.0.0" @@ -2868,10 +2874,10 @@ code-point-at@^1.0.0: resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= -codemaker@^1.24.0: - version "1.24.0" - resolved "https://registry.yarnpkg.com/codemaker/-/codemaker-1.24.0.tgz#6b8d4d106fd275713a078bf62fc5c6ebcaa65343" - integrity sha512-oKi5BNSyH0LBtFoxWKRvWnTut8NRdRgOzIF6/YKCaNnVECqq0oMqUpEBKNgcS+sOxfJfI/tkORpSdNGGVE0tmA== +codemaker@^1.25.0: + version "1.25.0" + resolved "https://registry.yarnpkg.com/codemaker/-/codemaker-1.25.0.tgz#987abcdf4f1ea7c3d71083dded4ce72941044710" + integrity sha512-54qCHs6X6llXIAztHCo2IyzzvuH9GrEecwxxTU925M3EJV4z+7PMiI1AollZxSeyY2pGO5TjNlAQAyLXETI3NQ== dependencies: camelcase "^6.2.0" decamelize "^5.0.0" @@ -3026,9 +3032,9 @@ console-control-strings@^1.0.0, console-control-strings@~1.1.0: integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= constructs@^3.2.0: - version "3.3.55" - resolved "https://registry.yarnpkg.com/constructs/-/constructs-3.3.55.tgz#ee54bd2202d8d72d9ce10694f055054d8cffef1f" - integrity sha512-PKlPeHnIN7EAdanoVpwUnj6Zb5Zhgb6lCQ1YTES52puksbw34TG7oqO2kzmTVTK3MVDMUdhCDKyroaVmNOtiiw== + version "3.3.65" + resolved "https://registry.yarnpkg.com/constructs/-/constructs-3.3.65.tgz#e1cef2a91ccbf10a10147e38e238b1a3482ee2a6" + integrity sha512-/tjHzxwK4Nz9SAm40kkC2mij3Y3LngVVj/dvk7Xpex25/PMhVRYy1pmJ0/5I5Y6bAMG1HRjcSAyf4k9YZyxJjw== contains-path@^0.1.0: version "0.1.0" @@ -3370,7 +3376,7 @@ cssom@~0.3.6: resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== -cssstyle@^2.2.0: +cssstyle@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852" integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A== @@ -3488,7 +3494,7 @@ decamelize@^5.0.0: resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-5.0.0.tgz#88358157b010ef133febfd27c18994bd80c6215b" integrity sha512-U75DcT5hrio3KNtvdULAWnLiAPbFUC4191ldxMmj4FA/mRuBnmDwU0boNfPyFRhnan+Jm+haLeSn3P0afcBn4w== -decimal.js@^10.2.0: +decimal.js@^10.2.1: version "10.2.1" resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.2.1.tgz#238ae7b0f0c793d3e3cea410108b35a2c01426a3" integrity sha512-KaL7+6Fw6i5A2XSnsbhm/6B+NuEA7TZ4vqxnd5tXz9sbKtrN9Srj8ab4vKVdK8YAqZO9P1kg45Y6YLoduPf+kw== @@ -3782,9 +3788,9 @@ ejs@^2.5.2: integrity sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA== electron-to-chromium@^1.3.649: - version "1.3.680" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.680.tgz#88cc44bd2a85b46cf7521f714db57dd74d0cd488" - integrity sha512-XBACJT9RdpdWtoMXQPR8Be3ZtmizWWbxfw8cY2b5feUwiDO3FUl8qo4W2jXoq/WnnA3xBRqafu1XbpczqyUvlA== + version "1.3.690" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.690.tgz#54df63ec42fba6b8e9e05fe4be52caeeedb6e634" + integrity sha512-zPbaSv1c8LUKqQ+scNxJKv01RYFkVVF1xli+b+3Ty8ONujHjAMg+t/COmdZqrtnS1gT+g4hbSodHillymt1Lww== emittery@^0.7.1: version "0.7.2" @@ -3833,9 +3839,9 @@ entities@~2.1.0: integrity sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w== env-paths@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.0.tgz#cdca557dc009152917d6166e2febe1f039685e43" - integrity sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA== + version "2.2.1" + resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" + integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== envinfo@^7.3.1: version "7.7.4" @@ -3921,10 +3927,10 @@ es6-promisify@^5.0.0: dependencies: es6-promise "^4.0.3" -esbuild@^0.8.55: - version "0.8.55" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.8.55.tgz#4bf949c44db4ffc2a206ac0c002e8e94eecff7d5" - integrity sha512-mM/s7hjYe5mQR+zAWOM5JVrCtYCke182E9l1Bbs6rG5EDP3b1gZF9sHZka53PD/iNt6OccymVZRWkTtBfcKW4w== +esbuild@^0.9.3: + version "0.9.3" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.9.3.tgz#09293a0b824159c6aa2488d1c6c22f57d8448f74" + integrity sha512-G8k0olucZp3LJ7I/p8y388t+IEyb2Y78nHrLeIxuqZqh6TYqDYP/B/7drAvYKfh83CGwKal9txVP+FTypsPJug== escalade@^3.1.1: version "3.1.1" @@ -3946,7 +3952,7 @@ escape-string-regexp@^4.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== -escodegen@^1.14.1, escodegen@^1.8.1: +escodegen@^1.8.1: version "1.14.3" resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503" integrity sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw== @@ -3958,6 +3964,18 @@ escodegen@^1.14.1, escodegen@^1.8.1: optionalDependencies: source-map "~0.6.1" +escodegen@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.0.0.tgz#5e32b12833e8aa8fa35e1bf0befa89380484c7dd" + integrity sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw== + dependencies: + esprima "^4.0.1" + estraverse "^5.2.0" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.6.1" + eslint-config-standard@^14.1.1: version "14.1.1" resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-14.1.1.tgz#830a8e44e7aef7de67464979ad06b406026c56ea" @@ -4017,10 +4035,10 @@ eslint-plugin-import@^2.22.1: resolve "^1.17.0" tsconfig-paths "^3.9.0" -eslint-plugin-jest@^24.1.5: - version "24.1.5" - resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-24.1.5.tgz#1e866a9f0deac587d0a3d5d7cefe99815a580de2" - integrity sha512-FIP3lwC8EzEG+rOs1y96cOJmMVpdFNreoDJv29B5vIupVssRi8zrSY3QadogT0K3h1Y8TMxJ6ZSAzYUmFCp2hg== +eslint-plugin-jest@^24.3.2: + version "24.3.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-24.3.2.tgz#30a8b2dea6278d0da1d6fb9d6cd530aaf58050a1" + integrity sha512-cicWDr+RvTAOKS3Q/k03+Z3odt3VCiWamNUHWd6QWbVQWcYJyYgUTu8x0mx9GfeDEimawU5kQC+nQ3MFxIM6bw== dependencies: "@typescript-eslint/experimental-utils" "^4.0.1" @@ -4041,10 +4059,10 @@ eslint-plugin-promise@^4.3.1: resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-4.3.1.tgz#61485df2a359e03149fdafc0a68b0e030ad2ac45" integrity sha512-bY2sGqyptzFBDLh/GMbAxfdJC+b0f23ME63FOE4+Jao0oZ3E1LEwFtWJX/1pGMJLiTtrSSern2CRM/g+dfc0eQ== -eslint-plugin-rulesdir@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-rulesdir/-/eslint-plugin-rulesdir-0.1.0.tgz#ad144d7e98464fda82963eff3fab331aecb2bf08" - integrity sha1-rRRNfphGT9qClj7/P6szGuyyvwg= +eslint-plugin-rulesdir@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-rulesdir/-/eslint-plugin-rulesdir-0.2.0.tgz#0d729e3f11bcb1a18d9b724a29a6d1a082ac2d62" + integrity sha512-PPQPCsPkzF3upl1862swPA1bmDAAHKHmJJ4JTHJ11JCVCU4sycB0K5LLA/Rwr6r4VbnpScvUvHV4hqfdjvFmhQ== eslint-plugin-standard@^4.1.0: version "4.1.0" @@ -4076,10 +4094,10 @@ eslint-visitor-keys@^2.0.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8" integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ== -eslint@^7.21.0: - version "7.21.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.21.0.tgz#4ecd5b8c5b44f5dedc9b8a110b01bbfeb15d1c83" - integrity sha512-W2aJbXpMNofUp0ztQaF40fveSsJBjlSCSWpy//gzfTvwC+USs/nceBrKmlJOiM8r1bLwP2EuYkCqArn/6QTIgg== +eslint@^7.22.0: + version "7.22.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.22.0.tgz#07ecc61052fec63661a2cab6bd507127c07adc6f" + integrity sha512-3VawOtjSJUQiiqac8MQc+w457iGLfuNGLFn8JmF051tTKbh5/x/0vlcEj8OgDCaw7Ysa2Jn8paGshV7x2abKXg== dependencies: "@babel/code-frame" "7.12.11" "@eslint/eslintrc" "^0.4.0" @@ -4098,7 +4116,7 @@ eslint@^7.21.0: file-entry-cache "^6.0.1" functional-red-black-tree "^1.0.1" glob-parent "^5.0.0" - globals "^12.1.0" + globals "^13.6.0" ignore "^4.0.6" import-fresh "^3.0.0" imurmurhash "^0.1.4" @@ -4106,7 +4124,7 @@ eslint@^7.21.0: js-yaml "^3.13.1" json-stable-stringify-without-jsonify "^1.0.1" levn "^0.4.1" - lodash "^4.17.20" + lodash "^4.17.21" minimatch "^3.0.4" natural-compare "^1.4.0" optionator "^0.9.1" @@ -4303,10 +4321,10 @@ extsprintf@^1.2.0: resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= -fast-check@^2.13.0: - version "2.13.0" - resolved "https://registry.yarnpkg.com/fast-check/-/fast-check-2.13.0.tgz#92a50a6a39b58760d4b0b52b12f98f28a9f020f6" - integrity sha512-IOfzKm/SCA+jpUEgAfqAuxHYPmgtmpnnwljQmYPRGrqYczcTKApXKHza/SNxFxYkecWfZilYa0DJdBvqz1bcSw== +fast-check@^2.14.0: + version "2.14.0" + resolved "https://registry.yarnpkg.com/fast-check/-/fast-check-2.14.0.tgz#13e891977a7cc1ba87aa3883c75053990c02fb21" + integrity sha512-4hm0ioyEVCwgjBLBqriwAFYu3/yc7pNH9fBfvzi6JRWRs4R3mwZwrr/d4MHbY0fTBJ0Uakg4TaMAAQ8Cnt2+KQ== dependencies: pure-rand "^4.1.1" @@ -4868,9 +4886,9 @@ glob-parent@^3.1.0: path-dirname "^1.0.0" glob-parent@^5.0.0, glob-parent@^5.1.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" - integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== dependencies: is-glob "^4.0.1" @@ -4903,6 +4921,13 @@ globals@^12.1.0: dependencies: type-fest "^0.8.1" +globals@^13.6.0: + version "13.6.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.6.0.tgz#d77138e53738567bb96a3916ff6f6b487af20ef7" + integrity sha512-YFKCX0SiPg7l5oKYCJ2zZGxcXprVXHcSnVuvzrT3oSENQonVLqM5pf9fN5dLGZGyCjhw8TN8Btwe/jKnZ0pjvQ== + dependencies: + type-fest "^0.20.2" + globby@^11.0.1: version "11.0.2" resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.2.tgz#1af538b766a3b540ebfb58a32b2e2d5897321d83" @@ -5057,10 +5082,10 @@ hosted-git-info@^2.1.4, hosted-git-info@^2.7.1: resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg== -hosted-git-info@^3.0.6: - version "3.0.8" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-3.0.8.tgz#6e35d4cc87af2c5f816e4cb9ce350ba87a3f370d" - integrity sha512-aXpmwoOhRBrw6X3j0h5RloK4x1OzsxMPyxqIHyNfSe2pypkVTZFpEiRoSipPEPlMrh0HW/XsjkJ5WgnCirpNUw== +hosted-git-info@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-4.0.0.tgz#9f06639a90beff66cacae6e77f8387b431d61ddc" + integrity sha512-fqhGdjk4av7mT9fU/B01dUtZ+WZSc/XEXMoLXDVZukiQRXxeHSSz3AqbeWRJHtF8EQYHlAgB1NSAHU0Cm7aqZA== dependencies: lru-cache "^6.0.0" @@ -5312,11 +5337,6 @@ interpret@^1.0.0: resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== -ip-regex@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" - integrity sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk= - ip@1.1.5, ip@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" @@ -6250,65 +6270,65 @@ jsesc@^2.5.1: resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== -jsii-diff@^1.24.0: - version "1.24.0" - resolved "https://registry.yarnpkg.com/jsii-diff/-/jsii-diff-1.24.0.tgz#97375083661a9cdd931764b526184bb5eb192497" - integrity sha512-Wkj/fyAmtNsaLSr5r6abgm5nnU7aHnlaqj//gG0azum7+TkbrmNj9LaxwXYJWT2fROCmP/fS8/jJta5U3wAi7Q== +jsii-diff@^1.25.0: + version "1.25.0" + resolved "https://registry.yarnpkg.com/jsii-diff/-/jsii-diff-1.25.0.tgz#410c05422427291c7b19e2d410090b6945eda142" + integrity sha512-rW4mpldvQrUDgDY+9Bvglew6nwXPWyVaePgeYTTB/4+9NEoAE7vecQAYhDokTBRdcOVCaEt5ffucwwawMu2ctQ== dependencies: - "@jsii/spec" "^1.24.0" + "@jsii/spec" "^1.25.0" fs-extra "^9.1.0" - jsii-reflect "^1.24.0" + jsii-reflect "^1.25.0" log4js "^6.3.0" typescript "~3.9.9" yargs "^16.2.0" -jsii-pacmak@^1.24.0: - version "1.24.0" - resolved "https://registry.yarnpkg.com/jsii-pacmak/-/jsii-pacmak-1.24.0.tgz#f16cb329ded0b2ce435846013910c811c6e29c34" - integrity sha512-8L5AOOy2LU3Y8tLy+KBTdmtxfu+Kn6g54htj+d1g3dVCxApC/G83C1DudhkYCxM3gDavsLPHhG6+fyopdTVV5A== +jsii-pacmak@^1.25.0: + version "1.25.0" + resolved "https://registry.yarnpkg.com/jsii-pacmak/-/jsii-pacmak-1.25.0.tgz#389bc16b8c7337769c2ed7a03e04262476b9b69b" + integrity sha512-GEVdCYvnwYVnVNdcLDrvStaHqWIXBiZCpM9i4LS2rpA+qSsyXJUF8FV4cj2YFjdHsolUdY1EKY7njSs8XQ+1gg== dependencies: - "@jsii/spec" "^1.24.0" + "@jsii/spec" "^1.25.0" clone "^2.1.2" - codemaker "^1.24.0" + codemaker "^1.25.0" commonmark "^0.29.3" escape-string-regexp "^4.0.0" fs-extra "^9.1.0" - jsii-reflect "^1.24.0" - jsii-rosetta "^1.24.0" + jsii-reflect "^1.25.0" + jsii-rosetta "^1.25.0" semver "^7.3.4" spdx-license-list "^6.4.0" xmlbuilder "^15.1.1" yargs "^16.2.0" -jsii-reflect@^1.24.0: - version "1.24.0" - resolved "https://registry.yarnpkg.com/jsii-reflect/-/jsii-reflect-1.24.0.tgz#61589ba10bc4bceeaeb68dd9e13acc22ac4b4e73" - integrity sha512-LWWReRtLhmyUMRD5NOFDV+HJHP/ChHRa6alccSPU9vTL5tm9HtMW0oO2XaVj4a2YPujvQ+sH7APzndj60Qgzqw== +jsii-reflect@^1.25.0: + version "1.25.0" + resolved "https://registry.yarnpkg.com/jsii-reflect/-/jsii-reflect-1.25.0.tgz#713727a07b270d61304a122be7cb50e135b8fdf0" + integrity sha512-ufBgOeGe6WVmx0CO7ABraEYOzhzxvmx6gJuUvOz/8XMe1dIIU2USLW3O1ArkEtIWchN4F2gITdd7I7jhdzzN1A== dependencies: - "@jsii/spec" "^1.24.0" + "@jsii/spec" "^1.25.0" colors "^1.4.0" fs-extra "^9.1.0" - oo-ascii-tree "^1.24.0" + oo-ascii-tree "^1.25.0" yargs "^16.2.0" -jsii-rosetta@^1.24.0: - version "1.24.0" - resolved "https://registry.yarnpkg.com/jsii-rosetta/-/jsii-rosetta-1.24.0.tgz#f0c674e6fa88d449360171400a46c556cde184bd" - integrity sha512-BMYxIjYG62wctUZFjYc5xKPNTgzTRRw2Fp8R9p4o0VeFE224ntyHgy9y7oKuCu+K1ev917NRoCLj7f2tyGTMAg== +jsii-rosetta@^1.25.0: + version "1.25.0" + resolved "https://registry.yarnpkg.com/jsii-rosetta/-/jsii-rosetta-1.25.0.tgz#07eb3c26f76f6ce7d56052014d651a8946629a73" + integrity sha512-2g+O5mkXrcsJPrHs71WPvLhcV4JERYUUzfG4rArZQ+YsGYSlpP2K6FdYlAk8haeCeEgyaedNgsbcW9NbxV8p3A== dependencies: - "@jsii/spec" "^1.24.0" + "@jsii/spec" "^1.25.0" commonmark "^0.29.3" fs-extra "^9.1.0" typescript "~3.9.9" - xmldom "^0.4.0" + xmldom "^0.5.0" yargs "^16.2.0" -jsii@^1.24.0: - version "1.24.0" - resolved "https://registry.yarnpkg.com/jsii/-/jsii-1.24.0.tgz#48e156b77f54d067520e0789f75d70c883be058a" - integrity sha512-ROCFFFdbs2o8OgQEWvpMY/UMXshndkGr8TunG0NQx8kQfONYeCjgNFqMcbcyXuhlR+DI1MUGVVOzw6zc9geyGA== +jsii@^1.25.0: + version "1.25.0" + resolved "https://registry.yarnpkg.com/jsii/-/jsii-1.25.0.tgz#ec60566f6c2c7829d25aa8f1fb14d49c700f621e" + integrity sha512-5dchUvG+RTc48v8euUUNvxKxAlPMIaE9rG8BFp4RiXQiB3EFDTJeeM89cXK4w/vAhjgDlAxMDx3EJr7k6e461A== dependencies: - "@jsii/spec" "^1.24.0" + "@jsii/spec" "^1.25.0" case "^1.6.3" colors "^1.4.0" deep-equal "^2.0.5" @@ -6858,9 +6878,9 @@ map-obj@^2.0.0: integrity sha1-plzSkIepJZi4eRJXpSPgISIqwfk= map-obj@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.1.0.tgz#b91221b542734b9f14256c0132c897c5d7256fd5" - integrity sha512-glc9y00wgtwcDmp7GaE/0b0OnxpNJsVf3ael/An6Fe2Q51LLwN1er6sdomLRzz5h0+yMpiYLhWYF5R7HeqVd4g== + version "4.2.0" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.2.0.tgz#0e8bc823e2aaca8a0942567d12ed14f389eec153" + integrity sha512-NAq0fCmZYGz9UFEQyndp7sisrow4GroyGeKluyKC/chuITZsPyOyC1UJZPJlVFImhXdROIP5xqouRLThT3BbpQ== map-visit@^1.0.0: version "1.0.0" @@ -7273,10 +7293,10 @@ nise@^4.0.4: just-extend "^4.0.2" path-to-regexp "^1.7.0" -nock@^13.0.10: - version "13.0.10" - resolved "https://registry.yarnpkg.com/nock/-/nock-13.0.10.tgz#a9a015269408d56ec9ac57fe3ede86b0a83ecc6a" - integrity sha512-AvUO/tbiWVBjlC3WsuIutPXltPbPmHWfcLwDSYzykKBJhOeo9eZPczo8n9aV4AHHCgpeL70zBXLwiSE+mzx89g== +nock@^13.0.11: + version "13.0.11" + resolved "https://registry.yarnpkg.com/nock/-/nock-13.0.11.tgz#ba733252e720897ca50033205c39db0c7470f331" + integrity sha512-sKZltNkkWblkqqPAsjYW0bm3s9DcHRPiMOyKO/PkfJ+ANHZ2+LA2PLe22r4lLrKgXaiSaDQwW3qGsJFtIpQIeQ== dependencies: debug "^4.1.0" json-stringify-safe "^5.0.1" @@ -7325,9 +7345,9 @@ node-modules-regexp@^1.0.0: integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA= node-notifier@^8.0.0: - version "8.0.1" - resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-8.0.1.tgz#f86e89bbc925f2b068784b31f382afdc6ca56be1" - integrity sha512-BvEXF+UmsnAfYfoapKM9nGxnP+Wn7P91YfXmrKnfcYCx6VBeoN5Ez5Ogck6I8Bi5k4RlpqRYaw75pAwzX9OphA== + version "8.0.2" + resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-8.0.2.tgz#f3167a38ef0d2c8a866a83e318c1ba0efeb702c5" + integrity sha512-oJP/9NAdd9+x2Q+rfphB2RJCHjod70RcRLjosiPMMu5gjIfwVnOUGq2nbTjTUbmy0DJ/tFIVT30+Qe3nzl4TJg== dependencies: growly "^1.3.0" is-wsl "^2.2.0" @@ -7375,11 +7395,11 @@ normalize-package-data@^2.0.0, normalize-package-data@^2.3.0, normalize-package- validate-npm-package-license "^3.0.1" normalize-package-data@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-3.0.0.tgz#1f8a7c423b3d2e85eb36985eaf81de381d01301a" - integrity sha512-6lUjEI0d3v6kFrtgA/lOx4zHCWULXsFNIjHolnZCKCTLA6m/G625cdn3O7eNmT0iD3jfo6HZ9cdImGZwf21prw== + version "3.0.1" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-3.0.1.tgz#98dc56dfe6755d99b1c53f046e1e3d2dde55a1c7" + integrity sha512-D/ttLdxo71msR4FF3VgSwK4blHfE3/vGByz1NCeE7/Dh8reQOKNJJjk5L10mLq9jxa+ZHzT1/HLgxljzbXE7Fw== dependencies: - hosted-git-info "^3.0.6" + hosted-git-info "^4.0.0" resolve "^1.17.0" semver "^7.3.2" validate-npm-package-license "^3.0.1" @@ -7664,10 +7684,10 @@ onetime@^5.1.0: dependencies: mimic-fn "^2.1.0" -oo-ascii-tree@^1.24.0: - version "1.24.0" - resolved "https://registry.yarnpkg.com/oo-ascii-tree/-/oo-ascii-tree-1.24.0.tgz#4eae1b2c2c6ba5bd83129c54d4b82443316dd378" - integrity sha512-rJYspYyrr2lDCDnybz4/70eml5cen98r4u2uw8sGodROePXiKKE+2Al8tfiS6uYx7vUEozEHCLoNQ/2jpxa7gw== +oo-ascii-tree@^1.25.0: + version "1.25.0" + resolved "https://registry.yarnpkg.com/oo-ascii-tree/-/oo-ascii-tree-1.25.0.tgz#97ce4d7e61a26d9c44117b041bf313a5329edf85" + integrity sha512-bV3aHhVkSc862VMMj1JV9y8yBqzhXCMNE9UFt8w9NwkM7tvw94O8niGlvmFzNx2Hf4+qhO4gYdtRAYQqUaH+1w== opener@^1.5.1: version "1.5.2" @@ -7963,10 +7983,10 @@ parse-url@^5.0.0: parse-path "^4.0.0" protocols "^1.4.0" -parse5@5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178" - integrity sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug== +parse5@6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" + integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== pascalcase@^0.1.1: version "0.1.1" @@ -8252,7 +8272,7 @@ pseudomap@^1.0.2: resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= -psl@^1.1.28: +psl@^1.1.28, psl@^1.1.33: version "1.8.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== @@ -8615,7 +8635,7 @@ request-promise-core@1.1.4: dependencies: lodash "^4.17.19" -request-promise-native@^1.0.8: +request-promise-native@^1.0.9: version "1.0.9" resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.9.tgz#e407120526a5efdc9a39b28a5679bf47b9d9dc28" integrity sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g== @@ -8731,9 +8751,9 @@ reusify@^1.0.4: integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== rfdc@^1.1.4: - version "1.2.0" - resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.2.0.tgz#9e9894258f48f284b43c3143c68070a4f373b949" - integrity sha512-ijLyszTMmUrXvjSooucVQwimGUk84eRcmCuLV8Xghe3UO85mjUtRAHRyoMM6XtyqbECaXuBWx18La3523sXINA== + version "1.3.0" + resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" + integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== rimraf@^2.5.4, rimraf@^2.6.2, rimraf@^2.6.3: version "2.7.1" @@ -8827,7 +8847,7 @@ sax@>=0.6.0, sax@^1.2.4: resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== -saxes@^5.0.0: +saxes@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d" integrity sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw== @@ -9036,9 +9056,9 @@ socks-proxy-agent@^4.0.0: socks "~2.3.2" socks@^2.3.3: - version "2.5.1" - resolved "https://registry.yarnpkg.com/socks/-/socks-2.5.1.tgz#7720640b6b5ec9a07d556419203baa3f0596df5f" - integrity sha512-oZCsJJxapULAYJaEYBSzMcz8m3jqgGrHaGhkmU/o/PQfFWYWxkAaA0UMGImb6s6tEXfKi959X6VJjMMQ3P6TTQ== + version "2.6.0" + resolved "https://registry.yarnpkg.com/socks/-/socks-2.6.0.tgz#6b984928461d39871b3666754b9000ecf39dfac2" + integrity sha512-mNmr9owlinMplev0Wd7UHFlqI4ofnBnNzFuzrm63PPaHgbkqCFe4T5LzwKmtQ/f2tX0NTpcdVLyD/FHxFBstYw== dependencies: ip "^1.1.5" smart-buffer "^4.1.0" @@ -9302,9 +9322,9 @@ strict-uri-encode@^2.0.0: integrity sha1-ucczDHBChi9rFC3CdLvMWGbONUY= string-length@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.1.tgz#4a973bf31ef77c4edbceadd6af2611996985f8a1" - integrity sha512-PKyXUd0LK0ePjSOnWn34V2uD6acUWev9uy0Ft05k0E8xRW+SKcA0F7eMr7h5xlzfn+4O3N+55rduYyet3Jk+jw== + version "4.0.2" + resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" + integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== dependencies: char-regex "^1.0.2" strip-ansi "^6.0.0" @@ -9605,7 +9625,7 @@ tap@^12.0.1: write-file-atomic "^2.4.2" yapool "^1.0.0" -tar-stream@^2.1.4: +tar-stream@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== @@ -9810,14 +9830,14 @@ tough-cookie@^2.3.3, tough-cookie@~2.5.0: psl "^1.1.28" punycode "^2.1.1" -tough-cookie@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-3.0.1.tgz#9df4f57e739c26930a018184887f4adb7dca73b2" - integrity sha512-yQyJ0u4pZsv9D4clxO69OEjLWYw+jbgspjTue4lTQZLfV0c5l1VmK2y1JK8E9ahdpltPOaAThPcp5nKPUgSnsg== +tough-cookie@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.0.0.tgz#d822234eeca882f991f0f908824ad2622ddbece4" + integrity sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg== dependencies: - ip-regex "^2.1.0" - psl "^1.1.28" + psl "^1.1.33" punycode "^2.1.1" + universalify "^0.1.2" tr46@^1.0.1: version "1.0.1" @@ -9863,10 +9883,10 @@ trivial-deferred@^1.0.1: resolved "https://registry.yarnpkg.com/trivial-deferred/-/trivial-deferred-1.0.1.tgz#376d4d29d951d6368a6f7a0ae85c2f4d5e0658f3" integrity sha1-N21NKdlR1jaKb3oK6FwvTV4GWPM= -ts-jest@^26.5.3: - version "26.5.3" - resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-26.5.3.tgz#a6ee00ba547be3b09877550df40a1465d0295554" - integrity sha512-nBiiFGNvtujdLryU7MiMQh1iPmnZ/QvOskBbD2kURiI1MwqvxlxNnaAB/z9TbslMqCsSbu5BXvSSQPc5tvHGeA== +ts-jest@^26.5.4: + version "26.5.4" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-26.5.4.tgz#207f4c114812a9c6d5746dd4d1cdf899eafc9686" + integrity sha512-I5Qsddo+VTm94SukBJ4cPimOoFZsYTeElR2xy6H2TOVs+NsvgYglW8KuQgKoApOKuaU/Ix/vrF9ebFZlb5D2Pg== dependencies: bs-logger "0.x" buffer-from "1.x" @@ -9933,9 +9953,9 @@ tslib@^2.0.1: integrity sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A== tsutils@^3.17.1: - version "3.20.0" - resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.20.0.tgz#ea03ea45462e146b53d70ce0893de453ff24f698" - integrity sha512-RYbuQuvkhuqVeXweWT3tJLKOEJ/UUw9GjNEZGWdrLLlM+611o1gwLHBpxoFJKKl25fLprp2eVthtKs5JOrNeXg== + version "3.21.0" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" + integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== dependencies: tslib "^1.8.1" @@ -9980,6 +10000,11 @@ type-fest@^0.18.0: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.18.1.tgz#db4bc151a4a2cf4eebf9add5db75508db6cc841f" integrity sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw== +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== + type-fest@^0.3.0: version "0.3.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.3.1.tgz#63d00d204e059474fe5e1b7c011112bbd1dc29e1" @@ -10007,16 +10032,17 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript-json-schema@^0.49.0: - version "0.49.0" - resolved "https://registry.yarnpkg.com/typescript-json-schema/-/typescript-json-schema-0.49.0.tgz#442f6347ca85fb0d9811f217fb0d6537b68734b3" - integrity sha512-PumZkTmEE3T8TVyoJU6ZCp3K6VCmCb3Ei6fUaRIuDsIzYtmdJc6jV1D0RyBe5sd5mJ1iB6Zckm4KAKbqXs9oDw== +typescript-json-schema@^0.50.0: + version "0.50.0" + resolved "https://registry.yarnpkg.com/typescript-json-schema/-/typescript-json-schema-0.50.0.tgz#4a78b6b0eca0cfcd518ccfbacef4575ee50c2e45" + integrity sha512-53X6J+Mgf/4P9qkPnLM0tkfbGMzjL2MDSsMvpO5MKyZOMp//Widup3oJS9Su9GnIme01ki7LARCPh6Y0Ej14iQ== dependencies: - "@types/json-schema" "^7.0.6" + "@types/json-schema" "^7.0.7" + "@types/node" "^14.14.33" glob "^7.1.6" json-stable-stringify "^1.0.1" ts-node "^9.1.1" - typescript "^4.1.3" + typescript "^4.2.3" yargs "^16.2.0" typescript@^3.3.3, typescript@~3.9.9: @@ -10024,10 +10050,10 @@ typescript@^3.3.3, typescript@~3.9.9: resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.9.tgz#e69905c54bc0681d0518bd4d587cc6f2d0b1a674" integrity sha512-kdMjTiekY+z/ubJCATUPlRDl39vXYiMV9iyeMuEuXZh2we6zz80uovNN2WlAxmmdE/Z/YQe+EbOEXB5RHEED3w== -typescript@^4.1.3: - version "4.2.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.2.2.tgz#1450f020618f872db0ea17317d16d8da8ddb8c4c" - integrity sha512-tbb+NVrLfnsJy3M59lsDgrzWIflR4d4TIUjz+heUnHZwdF7YsrMTKoRERiIvI2lvBG95dfpLxB21WZhys1bgaQ== +typescript@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.2.3.tgz#39062d8019912d43726298f09493d598048c1ce3" + integrity sha512-qOcYwxaByStAWrBf4x0fibwZvMRG+r4cQoTjbPtUlrWjBHbmCAww1i448U0GJ+3cNNEtebDteo/cHOR3xJ4wEw== typescript@~3.8.3: version "3.8.3" @@ -10040,9 +10066,9 @@ uc.micro@^1.0.1, uc.micro@^1.0.5: integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA== uglify-js@^3.1.4: - version "3.13.0" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.13.0.tgz#66ed69f7241f33f13531d3d51d5bcebf00df7f69" - integrity sha512-TWYSWa9T2pPN4DIJYbU9oAjQx+5qdV5RUDxwARg8fmJZrD/V27Zj0JngW5xg1DFz42G0uDYl2XhzF6alSzD62w== + version "3.13.1" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.13.1.tgz#2749d4b8b5b7d67460b4a418023ff73c3fefa60a" + integrity sha512-EWhx3fHy3M9JbaeTnO+rEqzCe1wtyQClv6q3YWq0voOj4E+bMZBErVS1GAHPDiRGONYq34M1/d8KuQMgvi6Gjw== uid-number@0.0.6: version "0.0.6" @@ -10108,7 +10134,7 @@ universal-user-agent@^6.0.0: resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.0.tgz#3381f8503b251c0d9cd21bc1de939ec9df5480ee" integrity sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w== -universalify@^0.1.0: +universalify@^0.1.0, universalify@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== @@ -10194,9 +10220,9 @@ uuid@^8.3.0, uuid@^8.3.2: integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== v8-compile-cache@^2.0.3: - version "2.2.0" - resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz#9471efa3ef9128d2f7c6a7ca39c4dd6b5055b132" - integrity sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q== + version "2.3.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" + integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== v8-to-istanbul@^7.0.0: version "7.1.0" @@ -10469,10 +10495,10 @@ write-pkg@^3.1.0: sort-keys "^2.0.0" write-json-file "^2.2.0" -ws@^7.2.3: - version "7.4.3" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.3.tgz#1f9643de34a543b8edb124bdcbc457ae55a6e5cd" - integrity sha512-hr6vCR76GsossIRsr8OLR9acVVm1jyfEWvhbNjtgPOrfvAlKzvyeg/P6r8RuDjRyrcQoPQT7K0DGEPc7Ae6jzA== +ws@^7.4.4: + version "7.4.4" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.4.tgz#383bc9742cb202292c9077ceab6f6047b17f2d59" + integrity sha512-Qm8k8ojNQIMx7S+Zp8u/uHOx7Qazv3Yv4q68MiWWWOJhiwG5W3x7iqmRtJo8xxrciZUY4vRxUTJCKuRnF28ZZw== xml-js@^1.6.11: version "1.6.11" @@ -10514,10 +10540,10 @@ xmlchars@^2.2.0: resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== -xmldom@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.4.0.tgz#8771e482a333af44587e30ce026f0998c23f3830" - integrity sha512-2E93k08T30Ugs+34HBSTQLVtpi6mCddaY8uO+pMNk1pqSjV5vElzn4mmh6KLxN3hki8rNcHSYzILoh3TEWORvA== +xmldom@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.5.0.tgz#193cb96b84aa3486127ea6272c4596354cb4962e" + integrity sha512-Foaj5FXVzgn7xFzsKeNIde9g6aFBxTPi37iwsno8QvApmtg7KYrr+OPyRHcJF7dud2a5nGRBXK3n0dL62Gf7PA== xregexp@2.0.0: version "2.0.0" @@ -10554,10 +10580,10 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yaml@*, yaml@1.10.0, yaml@^1.5.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.0.tgz#3b593add944876077d4d683fee01081bd9fff31e" - integrity sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg== +yaml@*, yaml@1.10.2, yaml@^1.5.0: + version "1.10.2" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" + integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== yaml@2.0.0-1: version "2.0.0-1" @@ -10570,9 +10596,9 @@ yapool@^1.0.0: integrity sha1-9pPymjFbUNmp2iZGp6ZkXJaYW2o= yargs-parser@20.x, yargs-parser@^20.2.2, yargs-parser@^20.2.3: - version "20.2.6" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.6.tgz#69f920addf61aafc0b8b89002f5d66e28f2d8b20" - integrity sha512-AP1+fQIWSM/sMiET8fyayjx/J+JmTPt2Mr0FkrgqB4todtfa53sOsrSAcIrJRD5XS20bKUwaDIuMkWKCEiQLKA== + version "20.2.7" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.7.tgz#61df85c113edfb5a7a4e36eb8aa60ef423cbc90a" + integrity sha512-FiNkvbeHzB/syOjIUxFDCnhSfzAL8R5vs40MgLFBorXACCOAEaWu0gRZl14vG8MR9AOJIZbmkjhusqBYZ3HTHw== yargs-parser@^13.0.0, yargs-parser@^13.1.2: version "13.1.2" @@ -10671,7 +10697,7 @@ yocto-queue@^0.1.0: resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== -zip-stream@^4.0.4: +zip-stream@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-4.1.0.tgz#51dd326571544e36aa3f756430b313576dc8fc79" integrity sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A==