diff --git a/.github/workflows/cr-checklist.yml b/.github/workflows/cr-checklist.yml index cdca37051a4d5..5badcb02eb2ac 100644 --- a/.github/workflows/cr-checklist.yml +++ b/.github/workflows/cr-checklist.yml @@ -9,7 +9,7 @@ jobs: name: Creates a checklist for PRs that contain changes to custom resources steps: - name: Checkout repo - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Dynamic checklist action uses: vishalsinha21/dynamic-checklist@v1 with: diff --git a/.github/workflows/pr-linter.yml b/.github/workflows/pr-linter.yml index 8231b94fa2319..73cc7b595e00d 100644 --- a/.github/workflows/pr-linter.yml +++ b/.github/workflows/pr-linter.yml @@ -21,7 +21,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install & Build prlint run: yarn install --frozen-lockfile && cd tools/@aws-cdk/prlint && yarn build+test diff --git a/.github/workflows/v2-pull-request.yml b/.github/workflows/v2-pull-request.yml index 351ee2c8c427f..8e7e00acdbc25 100644 --- a/.github/workflows/v2-pull-request.yml +++ b/.github/workflows/v2-pull-request.yml @@ -23,7 +23,7 @@ jobs: runs-on: ubuntu-latest steps: - name: checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: branch: ${{ github.event.pull_request.head.ref }} token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/yarn-upgrade.yml b/.github/workflows/yarn-upgrade.yml index f1ac15ec0831b..c9c6edb8d82b5 100644 --- a/.github/workflows/yarn-upgrade.yml +++ b/.github/workflows/yarn-upgrade.yml @@ -15,10 +15,10 @@ jobs: steps: - name: Check Out - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Set up Node - uses: actions/setup-node@v2.5.1 + uses: actions/setup-node@v3 with: node-version: 12 @@ -87,7 +87,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check Out - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Download patch uses: actions/download-artifact@v2 diff --git a/.mergify.yml b/.mergify.yml index 3348c3b934909..c2f007acd3d1d 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -10,7 +10,7 @@ pull_request_rules: label: add: [ contribution/core ] conditions: - - author~=^(eladb|RomainMuller|garnaat|nija-at|skinny85|rix0rrr|NGL321|Jerry-AWS|MrArnoldPalmer|NetaNir|iliapolo|njlynch|ericzbeard|ccfife|fulghum|pkandasamy91|SoManyHs|uttarasridhar|otaviomacedo|BenChaimberg|madeline-k|BryanPan342|kaizen3031593|comcalvi|Chriscbr|corymhall|peterwoodworth|ryparker)$ + - author~=^(eladb|RomainMuller|garnaat|nija-at|skinny85|rix0rrr|NGL321|Jerry-AWS|MrArnoldPalmer|NetaNir|iliapolo|njlynch|ericzbeard|ccfife|fulghum|pkandasamy91|SoManyHs|uttarasridhar|otaviomacedo|BenChaimberg|madeline-k|BryanPan342|kaizen3031593|comcalvi|Chriscbr|corymhall|peterwoodworth|ryparker|TheRealAmazonKendra)$ - -label~="contribution/core" - name: automatic merge actions: diff --git a/CHANGELOG.md b/CHANGELOG.md index 74f2483060f2a..435ac9555c58a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,100 @@ 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.147.0](https://github.com/aws/aws-cdk/compare/v1.146.0...v1.147.0) (2022-03-01) + + +### Features + +* **cfnspec:** cloudformation spec v58.0.0 ([#19153](https://github.com/aws/aws-cdk/issues/19153)) ([a6b0a10](https://github.com/aws/aws-cdk/commit/a6b0a1018694a0696ed27635d4def5d1630b8f9a)) +* **cli:** hotswap support for resources in nested stacks ([#18950](https://github.com/aws/aws-cdk/issues/18950)) ([2ea9da1](https://github.com/aws/aws-cdk/commit/2ea9da118794809265d215e3d2f554bbcb91b271)) +* **ec2:** add c6a instances ([#19113](https://github.com/aws/aws-cdk/issues/19113)) ([427cdfd](https://github.com/aws/aws-cdk/commit/427cdfde5e8c48ed7c1f86b275ccb2516a901239)) + + +### Bug Fixes + +* **apigateway:** fix strange vtl template for cors preflight request ([#19104](https://github.com/aws/aws-cdk/issues/19104)) ([59ef06a](https://github.com/aws/aws-cdk/commit/59ef06ae2a70fcb1800fcc1f40eec671c77440f0)), closes [/datatracker.ietf.org/doc/html/rfc6454#section-7](https://github.com/aws//datatracker.ietf.org/doc/html/rfc6454/issues/section-7) +* **aws-apigateway:** api gateway usage plan ([#19023](https://github.com/aws/aws-cdk/issues/19023)) ([5b764cc](https://github.com/aws/aws-cdk/commit/5b764cc397de4f4b203f5c69fa0128c6dced49f9)), closes [#18994](https://github.com/aws/aws-cdk/issues/18994) +* **aws-lambda-python:** skip default docker build when image passed ([#19143](https://github.com/aws/aws-cdk/issues/19143)) ([7300f2e](https://github.com/aws/aws-cdk/commit/7300f2eee9e1593eef271d7a953edf80a8962e08)), closes [#18082](https://github.com/aws/aws-cdk/issues/18082) +* **cli:** cdk version displays notices ([#19181](https://github.com/aws/aws-cdk/issues/19181)) ([fa16f7a](https://github.com/aws/aws-cdk/commit/fa16f7a9c11981da75e44ffc83adcdc6edad94fc)) +* **cli:** long connection timeout slows the CLI down ([#19187](https://github.com/aws/aws-cdk/issues/19187)) ([6595d04](https://github.com/aws/aws-cdk/commit/6595d044e29fb262fb62430783ad08359e16bc30)) +* **custom-resources:** physical resource id must be determined before isComplete ([#18630](https://github.com/aws/aws-cdk/issues/18630)) ([c190367](https://github.com/aws/aws-cdk/commit/c1903678aba31ca5b23a3bebb84249921e15dd5c)) +* **dynamodb:** `grant*Data()` methods are missing the `dynamodb:DescribeTable` permission ([#19129](https://github.com/aws/aws-cdk/issues/19129)) ([4a44a65](https://github.com/aws/aws-cdk/commit/4a44a65bb4634081e04811966d5f4e2fd49bc7c6)), closes [#18773](https://github.com/aws/aws-cdk/issues/18773) +* **dynamodb:** `Table.grantWriteData()` doesn't include enough KMS permissions ([#19102](https://github.com/aws/aws-cdk/issues/19102)) ([77f1e0b](https://github.com/aws/aws-cdk/commit/77f1e0b57bd4508ade86be7733e71e94a47d7f4c)), closes [#10010](https://github.com/aws/aws-cdk/issues/10010) +* **ec2:** invalid volume type check for iops ([#19073](https://github.com/aws/aws-cdk/issues/19073)) ([3f49f02](https://github.com/aws/aws-cdk/commit/3f49f020090142c77feb892894c54e62dc4de7ae)) +* **eks:** Helm charts fail to install when provided as an asset ([#19180](https://github.com/aws/aws-cdk/issues/19180)) ([9961257](https://github.com/aws/aws-cdk/commit/99612574bbaf97379482e9e424e1d1115809d74b)) +* **lambda-nodejs:** `logLevel` property of `BundlingOptions` is ignored when `nodeModules` are defined ([#18456](https://github.com/aws/aws-cdk/issues/18456)) ([5c40b90](https://github.com/aws/aws-cdk/commit/5c40b90707b869f62e59613d50d5deaafbaa52f1)), closes [#18383](https://github.com/aws/aws-cdk/issues/18383) +* **stepfunctions-tasks:** RUN_JOB integration pattern not supported for CallAwsService ([#19186](https://github.com/aws/aws-cdk/issues/19186)) ([4b134b7](https://github.com/aws/aws-cdk/commit/4b134b785115f026a0eaa37b699cd32c85ff8e73)), closes [#19174](https://github.com/aws/aws-cdk/issues/19174) +* apply tags to nested stack ([#19128](https://github.com/aws/aws-cdk/issues/19128)) ([3af329b](https://github.com/aws/aws-cdk/commit/3af329bcb66b9dffce0c03f0816b33e91e901808)), closes [#17463](https://github.com/aws/aws-cdk/issues/17463) +* **triggers:** not published as part of v2 ([#19168](https://github.com/aws/aws-cdk/issues/19168)) ([8f727d1](https://github.com/aws/aws-cdk/commit/8f727d15f8f87d4ca323fee449826908db7971a4)), closes [#19164](https://github.com/aws/aws-cdk/issues/19164) +* construct paths are not printed for nested stacks in CLI output ([#18725](https://github.com/aws/aws-cdk/issues/18725)) ([b0e0155](https://github.com/aws/aws-cdk/commit/b0e0155f87a65c34a75e11776f98d55b83d2b220)) +* **rds:** MySQL Cluster version 8.0 uses wrong Parameter for S3 import ([#19145](https://github.com/aws/aws-cdk/issues/19145)) ([96b2034](https://github.com/aws/aws-cdk/commit/96b2034c44b441a96cfe19855d343b0f983c8772)), closes [#19126](https://github.com/aws/aws-cdk/issues/19126) + +## [1.146.0](https://github.com/aws/aws-cdk/compare/v1.145.0...v1.146.0) (2022-02-24) + + +### Features + +* **apigatewayv2:** Import existing WebSocketApi from attributes ([#18958](https://github.com/aws/aws-cdk/issues/18958)) ([f203845](https://github.com/aws/aws-cdk/commit/f203845d26ae8333f467f1cb91ad965697087d85)) +* **cli:** bundle dependencies ([#18667](https://github.com/aws/aws-cdk/issues/18667)) ([31d135f](https://github.com/aws/aws-cdk/commit/31d135fb51d3cd4e26fbdc132e03815a1416da75)) +* **cli:** support for matching notices with arbitrary module names ([#19088](https://github.com/aws/aws-cdk/issues/19088)) ([a87dee7](https://github.com/aws/aws-cdk/commit/a87dee756057e554909207237b70f80af185b110)) +* **cli:** support for notices ([#18936](https://github.com/aws/aws-cdk/issues/18936)) ([d37fbbb](https://github.com/aws/aws-cdk/commit/d37fbbbb31003d69da88b9340a6a9c9e1e927ac5)) +* **cloudfront-origins:** extend max keepaliveTimeout of HttpOrigin to 180 ([#18837](https://github.com/aws/aws-cdk/issues/18837)) ([171fdcd](https://github.com/aws/aws-cdk/commit/171fdcdf595fcff5b2567b17e6fa73bf0d42e1bc)), closes [#18697](https://github.com/aws/aws-cdk/issues/18697) +* **eks:** Allow helm pull from OCI repositories ([#18547](https://github.com/aws/aws-cdk/issues/18547)) ([7e624d9](https://github.com/aws/aws-cdk/commit/7e624d994c94dbd584643c4cb6e9f8df53dabc18)) +* **lambda:** add a fromFunctionName() method ([#19076](https://github.com/aws/aws-cdk/issues/19076)) ([5b92cc3](https://github.com/aws/aws-cdk/commit/5b92cc3a31eea29b40814498fca614eb1c7c8724)), closes [#18255](https://github.com/aws/aws-cdk/issues/18255) [#19031](https://github.com/aws/aws-cdk/issues/19031) +* **pipelines:** ECR source action ([#16385](https://github.com/aws/aws-cdk/issues/16385)) ([fc11ae2](https://github.com/aws/aws-cdk/commit/fc11ae2c4ec3bd9dfe3ff813aa831c744d8ac444)), closes [#16378](https://github.com/aws/aws-cdk/issues/16378) +* **pipelines:** step outputs ([#19024](https://github.com/aws/aws-cdk/issues/19024)) ([0dec2ee](https://github.com/aws/aws-cdk/commit/0dec2ee78a70832c3a697be26c67498460a587dd)), closes [#17189](https://github.com/aws/aws-cdk/issues/17189) [#18893](https://github.com/aws/aws-cdk/issues/18893) [#15943](https://github.com/aws/aws-cdk/issues/15943) [#16407](https://github.com/aws/aws-cdk/issues/16407) +* **rds:** make VPC optional for serverless Clusters ([#17413](https://github.com/aws/aws-cdk/issues/17413)) ([4f7818d](https://github.com/aws/aws-cdk/commit/4f7818dd76bd48ed652407f4852cc97ba57d7395)), closes [#17401](https://github.com/aws/aws-cdk/issues/17401) +* triggers ([#19011](https://github.com/aws/aws-cdk/issues/19011)) ([11d6c69](https://github.com/aws/aws-cdk/commit/11d6c69a8b1ee70cbea025d134be7702dd804444)) + + +### Bug Fixes + +* **cli:** hotswapping is slow for many resources deployed at once ([#19081](https://github.com/aws/aws-cdk/issues/19081)) ([040238e](https://github.com/aws/aws-cdk/commit/040238e9285945d1c48ef79474e527b871e7824c)), closes [#19021](https://github.com/aws/aws-cdk/issues/19021) +* **s3-notifications:** notifications allowed with imported kms keys ([#18989](https://github.com/aws/aws-cdk/issues/18989)) ([7441418](https://github.com/aws/aws-cdk/commit/7441418fbf9ffdf8d85a573e3c81c45c5648fe8a)) +* API compatibility check fails in CI pipeline ([#19069](https://github.com/aws/aws-cdk/issues/19069)) ([6ec1005](https://github.com/aws/aws-cdk/commit/6ec1005c9cfa9723520885748d759b00be5cd2fa)), closes [#19070](https://github.com/aws/aws-cdk/issues/19070) +* **cloudfront:** trim autogenerated cache policy name ([#18953](https://github.com/aws/aws-cdk/issues/18953)) ([c7394c9](https://github.com/aws/aws-cdk/commit/c7394c96c42cb6a5af1e309bee2a5f11eb3ad35c)), closes [#18918](https://github.com/aws/aws-cdk/issues/18918) +* **elasticloadbalancingv2:** validate port/protocol are not provided for lambda targets ([#19043](https://github.com/aws/aws-cdk/issues/19043)) ([64d26cc](https://github.com/aws/aws-cdk/commit/64d26cc22b1fe456777c3367769ddbe860f26cf3)), closes [#12514](https://github.com/aws/aws-cdk/issues/12514) +* **route53:** fix cross account delegation deployment dependency ([#19047](https://github.com/aws/aws-cdk/issues/19047)) ([692a0d0](https://github.com/aws/aws-cdk/commit/692a0d06f2865503d1d88b0ba8af38ecceaec871)), closes [#19041](https://github.com/aws/aws-cdk/issues/19041) + +## [1.145.0](https://github.com/aws/aws-cdk/compare/v1.144.0...v1.145.0) (2022-02-18) + + +### Features + +* **aws-stepfunctions-tasks:** add environment property for SageMakerCreateTrainingJob ([#18976](https://github.com/aws/aws-cdk/issues/18976)) ([60d6e66](https://github.com/aws/aws-cdk/commit/60d6e66baef9d30db23e93b16f7c6d159ddf58c4)), closes [#18919](https://github.com/aws/aws-cdk/issues/18919) +* **cfnspec:** cloudformation spec v56.0.0 ([#18930](https://github.com/aws/aws-cdk/issues/18930)) ([24a52ae](https://github.com/aws/aws-cdk/commit/24a52ae1c250ec1875e64d6fc4ef8bec2f47399a)) +* **cfnspec:** cloudformation spec v57.0.0 ([#19030](https://github.com/aws/aws-cdk/issues/19030)) ([f0acbc4](https://github.com/aws/aws-cdk/commit/f0acbc469d835ad8808f4176eed53bf2af7c66e2)) +* **cli:** hotswap for appsync vtl mapping template changes ([#18881](https://github.com/aws/aws-cdk/issues/18881)) ([9858002](https://github.com/aws/aws-cdk/commit/985800228d04b9c2f3ac117e3b41c7f089547d38)) +* **codepipeline:** add support for CloudFormation StackSet actions ([#14225](https://github.com/aws/aws-cdk/issues/14225)) ([d8bc0d0](https://github.com/aws/aws-cdk/commit/d8bc0d08a9796724bb31cc5d7552cf99297678d9)) +* **config:** S3_BUCKET_LEVEL_PUBLIC_ACCESS_PROHIBITED managed rule ([#18890](https://github.com/aws/aws-cdk/issues/18890)) ([1a7e3e2](https://github.com/aws/aws-cdk/commit/1a7e3e20e005b4165a27506615c7245b88ce998b)), closes [#18888](https://github.com/aws/aws-cdk/issues/18888) +* **core:** stack synthesizer that uses CLI credentials ([#18963](https://github.com/aws/aws-cdk/issues/18963)) ([a36b72b](https://github.com/aws/aws-cdk/commit/a36b72b5045fceada7c96d00770d8c48f2ca1415)), closes [#16888](https://github.com/aws/aws-cdk/issues/16888) +* **ec2:** allow imdsv2 usage on bastion host ([#18955](https://github.com/aws/aws-cdk/issues/18955)) ([8c6777c](https://github.com/aws/aws-cdk/commit/8c6777c904588f9b911d8b8a5d63a65ae1c7aad9)) +* **ecs:** support version stages and ids for Secrets ([#18174](https://github.com/aws/aws-cdk/issues/18174)) ([6d091c2](https://github.com/aws/aws-cdk/commit/6d091c2da7749a81c3752953d0bc7db65ab48f45)), closes [#18123](https://github.com/aws/aws-cdk/issues/18123) +* **events:** API Destinations ([#13729](https://github.com/aws/aws-cdk/issues/13729)) ([2adbc14](https://github.com/aws/aws-cdk/commit/2adbc14bae8266a6bd357e752185133a32e4ca87)) +* **iot-actions:** add SNS publish action ([#18839](https://github.com/aws/aws-cdk/issues/18839)) ([3a39f6b](https://github.com/aws/aws-cdk/commit/3a39f6bf34eb428c527db1c614ed682c582821fb)), closes [#17700](https://github.com/aws/aws-cdk/issues/17700) +* **iotevents:** create new module for IoT Events actions ([#18956](https://github.com/aws/aws-cdk/issues/18956)) ([3533ea9](https://github.com/aws/aws-cdk/commit/3533ea9cb7ec7fd9e230abd27556a87d3559bdb8)), closes [/github.com/aws/aws-cdk/pull/18869#discussion_r802719713](https://github.com/aws//github.com/aws/aws-cdk/pull/18869/issues/discussion_r802719713) +* **lambda:** allow Topic to be dlq for Lambda ([#18546](https://github.com/aws/aws-cdk/issues/18546)) ([f8d8fe4](https://github.com/aws/aws-cdk/commit/f8d8fe4e1397e3d8da91a3a44f025475c8b7f592)), closes [#16246](https://github.com/aws/aws-cdk/issues/16246) +* **logs:** custom Role for Kinesis destination ([#13553](https://github.com/aws/aws-cdk/issues/13553)) ([bb96621](https://github.com/aws/aws-cdk/commit/bb96621d642fedcf1e22086a249034ca1ab63f73)), closes [#7661](https://github.com/aws/aws-cdk/issues/7661) +* **rds:** simpler way to configure parameters for instance and cluster ([#18126](https://github.com/aws/aws-cdk/issues/18126)) ([3ba9088](https://github.com/aws/aws-cdk/commit/3ba90881dab49f47220872e6e5afef3a7732ef13)), closes [#18124](https://github.com/aws/aws-cdk/issues/18124) +* **s3-deployment:** add `deployedBucket` attribute for sequencing ([#15384](https://github.com/aws/aws-cdk/issues/15384)) ([edac101](https://github.com/aws/aws-cdk/commit/edac1011574f3cf38bb0ac39400bf41c66337ffd)) + + +### Bug Fixes + +* **assertions:** 'pattern.indexOf' is not a function ([#19009](https://github.com/aws/aws-cdk/issues/19009)) ([6df26e7](https://github.com/aws/aws-cdk/commit/6df26e7ed73455b77b07707debef5bb26ae78909)) +* **assertions:** incorrect assertions when >1 messages on a resource ([#18948](https://github.com/aws/aws-cdk/issues/18948)) ([072e1b9](https://github.com/aws/aws-cdk/commit/072e1b990a43768b88a05dd436dd6d6d9649c13a)), closes [#18840](https://github.com/aws/aws-cdk/issues/18840) +* **aws-cdk:** include nested stacks when building changesets ([#17396](https://github.com/aws/aws-cdk/issues/17396)) ([a7dbeef](https://github.com/aws/aws-cdk/commit/a7dbeef9eae3e00e209d06f5cc5bb3bf3d084d18)), closes [#5722](https://github.com/aws/aws-cdk/issues/5722) +* **cli:** handle attributes of AWS::Events::EventBus when hotswapping ([#18834](https://github.com/aws/aws-cdk/issues/18834)) ([a30a32a](https://github.com/aws/aws-cdk/commit/a30a32aaa5dfb764022370fe7867564d57640bfb)), closes [#18831](https://github.com/aws/aws-cdk/issues/18831) +* **core:** undeployable due to invalid mapping ([#18922](https://github.com/aws/aws-cdk/issues/18922)) ([db28485](https://github.com/aws/aws-cdk/commit/db28485f4d2ea243e4184dd06b52395b4980beba)), closes [#18789](https://github.com/aws/aws-cdk/issues/18789) [#18789](https://github.com/aws/aws-cdk/issues/18789) +* **lambda:** unlock use case for cross-account functions w/ preconfigured permissions ([#18979](https://github.com/aws/aws-cdk/issues/18979)) ([023108a](https://github.com/aws/aws-cdk/commit/023108ac080ba34c82ef0b60fee20014c4a78428)), closes [#18228](https://github.com/aws/aws-cdk/issues/18228) [#18781](https://github.com/aws/aws-cdk/issues/18781) [#18967](https://github.com/aws/aws-cdk/issues/18967) [#18781](https://github.com/aws/aws-cdk/issues/18781) +* **lambda:** Validate Lambda "functionName" parameter ([#17970](https://github.com/aws/aws-cdk/issues/17970)) ([a416a2d](https://github.com/aws/aws-cdk/commit/a416a2d68f14c0711d42b38e81b0091d160dfd6f)), closes [#13264](https://github.com/aws/aws-cdk/issues/13264) +* **pipelines:** self-mutate always adds analytics ([#19010](https://github.com/aws/aws-cdk/issues/19010)) ([bc47b29](https://github.com/aws/aws-cdk/commit/bc47b2937a806d6522a4d9106976200bf6810024)), closes [#18933](https://github.com/aws/aws-cdk/issues/18933) +* **stepfunctions:** imported State Machine sill has region and account from its Stack, instead of its ARN ([#19026](https://github.com/aws/aws-cdk/issues/19026)) ([23329b4](https://github.com/aws/aws-cdk/commit/23329b4ac7c845efe7d0e0d7ce03499e7dd723ac)), closes [#17982](https://github.com/aws/aws-cdk/issues/17982) +* python3 version check with Python 3.10 ([#18754](https://github.com/aws/aws-cdk/issues/18754)) ([0ef6527](https://github.com/aws/aws-cdk/commit/0ef65279cc5f2269046e0bae05d44f5aabc43eb9)) +* **stepfunctions-tasks:** EMR Create Cluster does not support dynamic allocation of step concurrency level ([#18972](https://github.com/aws/aws-cdk/issues/18972)) ([d19e538](https://github.com/aws/aws-cdk/commit/d19e5386f737aa58f27c7ac2082306006dcd6d95)) +* **synthetics:** generated role has incorrect permissions for cloudwatch logs ([#18946](https://github.com/aws/aws-cdk/issues/18946)) ([f8bb85f](https://github.com/aws/aws-cdk/commit/f8bb85fad8f659a2b72d5d05d7a94c97765a76f8)), closes [#18910](https://github.com/aws/aws-cdk/issues/18910) + ## [1.144.0](https://github.com/aws/aws-cdk/compare/v1.143.0...v1.144.0) (2022-02-08) diff --git a/package.json b/package.json index 54c8fd3391498..9c9efa4f00664 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "jsii-rosetta": "^1.54.0", "lerna": "^4.0.0", "patch-package": "^6.4.7", + "semver": "^6.3.0", "standard-version": "^9.3.2", "typescript": "~3.9.10" }, diff --git a/packages/@aws-cdk-containers/ecs-service-extensions/package.json b/packages/@aws-cdk-containers/ecs-service-extensions/package.json index 458d547a21a6f..3587f60c10eda 100644 --- a/packages/@aws-cdk-containers/ecs-service-extensions/package.json +++ b/packages/@aws-cdk-containers/ecs-service-extensions/package.json @@ -37,7 +37,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/aws-autoscaling": "0.0.0", diff --git a/packages/@aws-cdk-containers/ecs-service-extensions/test/integ.assign-public-ip.expected.json b/packages/@aws-cdk-containers/ecs-service-extensions/test/integ.assign-public-ip.expected.json index 556524b695267..e9de0e4c0f997 100644 --- a/packages/@aws-cdk-containers/ecs-service-extensions/test/integ.assign-public-ip.expected.json +++ b/packages/@aws-cdk-containers/ecs-service-extensions/test/integ.assign-public-ip.expected.json @@ -766,7 +766,8 @@ "dynamodb:BatchWriteItem", "dynamodb:PutItem", "dynamodb:UpdateItem", - "dynamodb:DeleteItem" + "dynamodb:DeleteItem", + "dynamodb:DescribeTable" ], "Effect": "Allow", "Resource": [ diff --git a/packages/@aws-cdk/alexa-ask/package.json b/packages/@aws-cdk/alexa-ask/package.json index ece5934f1136a..2d533773cdc92 100644 --- a/packages/@aws-cdk/alexa-ask/package.json +++ b/packages/@aws-cdk/alexa-ask/package.json @@ -84,7 +84,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/app-delivery/package.json b/packages/@aws-cdk/app-delivery/package.json index 4263aaa52bcf0..cb0dc160c9850 100644 --- a/packages/@aws-cdk/app-delivery/package.json +++ b/packages/@aws-cdk/app-delivery/package.json @@ -72,7 +72,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "fast-check": "^2.22.0", "jest": "^27.5.1" }, diff --git a/packages/@aws-cdk/assert-internal/package.json b/packages/@aws-cdk/assert-internal/package.json index 03fb9d4d13706..b1074a77bd1a4 100644 --- a/packages/@aws-cdk/assert-internal/package.json +++ b/packages/@aws-cdk/assert-internal/package.json @@ -26,7 +26,7 @@ "devDependencies": { "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1", "ts-jest": "^27.1.3" }, diff --git a/packages/@aws-cdk/assert/package.json b/packages/@aws-cdk/assert/package.json index b462bcbbab2db..dc22fd90c4d0d 100644 --- a/packages/@aws-cdk/assert/package.json +++ b/packages/@aws-cdk/assert/package.json @@ -37,7 +37,7 @@ "@aws-cdk/assert-internal": "0.0.0", "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "aws-cdk-migration": "0.0.0", "constructs": "^3.3.69", "jest": "^27.3.1", diff --git a/packages/@aws-cdk/assertions/lib/private/cyclic.ts b/packages/@aws-cdk/assertions/lib/private/cyclic.ts index 07451a126ad28..85aa0cbf07147 100644 --- a/packages/@aws-cdk/assertions/lib/private/cyclic.ts +++ b/packages/@aws-cdk/assertions/lib/private/cyclic.ts @@ -70,11 +70,16 @@ function findExpressionDependencies(obj: any): Set { } else if (keys.length === 1 && keys[0] === 'Fn::Sub') { const argument = x[keys[0]]; const pattern = Array.isArray(argument) ? argument[0] : argument; - for (const logId of logicalIdsInSubString(pattern)) { - ret.add(logId); + + // pattern should always be a string, but we've encountered some cases in which + // it isn't. Better safeguard. + if (typeof pattern === 'string') { + for (const logId of logicalIdsInSubString(pattern)) { + ret.add(logId); + } } const contextDict = Array.isArray(argument) ? argument[1] : undefined; - if (contextDict) { + if (contextDict && typeof contextDict === 'object') { Object.values(contextDict).forEach(recurse); } } else { diff --git a/packages/@aws-cdk/assertions/lib/private/messages.ts b/packages/@aws-cdk/assertions/lib/private/messages.ts index 935b4a4b32fad..95e898b687183 100644 --- a/packages/@aws-cdk/assertions/lib/private/messages.ts +++ b/packages/@aws-cdk/assertions/lib/private/messages.ts @@ -10,7 +10,6 @@ export function findMessage(messages: Messages, constructPath: string, props: an return {}; } - Object.values(result.matches).forEach((m) => handleTrace(m)); return result.matches; } diff --git a/packages/@aws-cdk/assertions/package.json b/packages/@aws-cdk/assertions/package.json index 13d718b66e355..3c2533d04ae9d 100644 --- a/packages/@aws-cdk/assertions/package.json +++ b/packages/@aws-cdk/assertions/package.json @@ -65,7 +65,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0", "@types/fs-extra": "^9.0.13", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "constructs": "^3.3.69", "jest": "^27.5.1", "ts-jest": "^27.1.3" diff --git a/packages/@aws-cdk/assertions/test/annotations.test.ts b/packages/@aws-cdk/assertions/test/annotations.test.ts index 615cd069bdaa4..2b1c0c0274ead 100644 --- a/packages/@aws-cdk/assertions/test/annotations.test.ts +++ b/packages/@aws-cdk/assertions/test/annotations.test.ts @@ -7,13 +7,12 @@ describe('Messages', () => { let annotations: _Annotations; beforeAll(() => { stack = new Stack(); - const foo = new CfnResource(stack, 'Foo', { + new CfnResource(stack, 'Foo', { type: 'Foo::Bar', properties: { Fred: 'Thud', }, }); - foo.node.setContext('disable-stack-trace', false); new CfnResource(stack, 'Bar', { type: 'Foo::Bar', @@ -61,11 +60,6 @@ describe('Messages', () => { const result = annotations.findError('*', 'no message looks like this'); expect(result.length).toEqual(0); }); - - test('trace is redacted', () => { - const result = annotations.findError('/Default/Foo', Match.anyValue()); - expect(result[0].entry.trace).toEqual('redacted'); - }); }); describe('hasWarning', () => { @@ -165,15 +159,7 @@ describe('Multiple Messages on the Resource', () => { const result2 = annotations.findError('/Default/Bar', Match.stringLikeRegexp('error:.*')); expect(result2.length).toEqual(2); const result3 = annotations.findWarning('/Default/Bar', 'warning: Foo::Bar is deprecated'); - expect(result3).toEqual([{ - level: 'warning', - entry: { - type: 'aws:cdk:warning', - data: 'warning: Foo::Bar is deprecated', - trace: 'redacted', - }, - id: '/Default/Bar', - }]); + expect(result3[0].entry.data).toEqual('warning: Foo::Bar is deprecated'); }); }); class MyAspect implements IAspect { diff --git a/packages/@aws-cdk/assets/package.json b/packages/@aws-cdk/assets/package.json index 2da7192c43228..30adc5c82cfcb 100644 --- a/packages/@aws-cdk/assets/package.json +++ b/packages/@aws-cdk/assets/package.json @@ -80,7 +80,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "@types/sinon": "^9.0.11", "aws-cdk": "0.0.0", "jest": "^27.5.1", diff --git a/packages/@aws-cdk/aws-accessanalyzer/package.json b/packages/@aws-cdk/aws-accessanalyzer/package.json index faf809becc93b..ed8871901f393 100644 --- a/packages/@aws-cdk/aws-accessanalyzer/package.json +++ b/packages/@aws-cdk/aws-accessanalyzer/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-acmpca/package.json b/packages/@aws-cdk/aws-acmpca/package.json index a4a7a79a1e8e6..8522c051e20b0 100644 --- a/packages/@aws-cdk/aws-acmpca/package.json +++ b/packages/@aws-cdk/aws-acmpca/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-amazonmq/package.json b/packages/@aws-cdk/aws-amazonmq/package.json index c7050a78a44e4..56d6e296c4ed0 100644 --- a/packages/@aws-cdk/aws-amazonmq/package.json +++ b/packages/@aws-cdk/aws-amazonmq/package.json @@ -84,7 +84,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-amplify/package.json b/packages/@aws-cdk/aws-amplify/package.json index e546c68ed28c4..7a221bfd747f5 100644 --- a/packages/@aws-cdk/aws-amplify/package.json +++ b/packages/@aws-cdk/aws-amplify/package.json @@ -86,7 +86,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "@types/yaml": "1.9.6", "aws-sdk": "^2.848.0" }, diff --git a/packages/@aws-cdk/aws-apigateway/README.md b/packages/@aws-cdk/aws-apigateway/README.md index 83e9d04cd31c6..8dae2d1cf9165 100644 --- a/packages/@aws-cdk/aws-apigateway/README.md +++ b/packages/@aws-cdk/aws-apigateway/README.md @@ -126,7 +126,7 @@ Other metadata such as billing details, AWS account ID and resource ARNs are not By default, a `prod` stage is provisioned. -In order to reduce the payload size sent to AWS Step Functions, `headers` are not forwarded to the Step Functions execution input. It is possible to choose whether `headers`, `requestContext`, `path` and `querystring` are included or not. By default, `headers` are excluded in all requests. +In order to reduce the payload size sent to AWS Step Functions, `headers` are not forwarded to the Step Functions execution input. It is possible to choose whether `headers`, `requestContext`, `path`, `querystring`, and `authorizer` are included or not. By default, `headers` are excluded in all requests. More details about AWS Step Functions payload limit can be found at https://docs.aws.amazon.com/step-functions/latest/dg/limits-overview.html#service-limits-task-executions. @@ -184,7 +184,7 @@ AWS Step Functions will receive the following execution input: } ``` -Additional information around the request such as the request context and headers can be included as part of the input +Additional information around the request such as the request context, authorizer context, and headers can be included as part of the input forwarded to the state machine. The following example enables headers to be included in the input but not query string. ```ts fixture=stepfunctions @@ -193,6 +193,7 @@ new apigateway.StepFunctionsRestApi(this, 'StepFunctionsRestApi', { headers: true, path: false, querystring: false, + authorizer: false, requestContext: { caller: true, user: true, diff --git a/packages/@aws-cdk/aws-apigateway/lib/integrations/stepfunctions.ts b/packages/@aws-cdk/aws-apigateway/lib/integrations/stepfunctions.ts index 339e7b2949198..f9461eb0b44e8 100644 --- a/packages/@aws-cdk/aws-apigateway/lib/integrations/stepfunctions.ts +++ b/packages/@aws-cdk/aws-apigateway/lib/integrations/stepfunctions.ts @@ -68,6 +68,20 @@ export interface StepFunctionsExecutionIntegrationOptions extends IntegrationOpt * @default false */ readonly headers?: boolean; + + /** + * If the whole authorizer object, including custom context values should be in the execution input. The execution input will include a new key `authorizer`: + * + * { + * "body": {}, + * "authorizer": { + * "key": "value" + * } + * } + * + * @default false + */ + readonly authorizer?: boolean; } /** @@ -189,7 +203,7 @@ function integrationResponse() { '#if($input.path(\'$.status\').toString().equals("FAILED"))', '#set($context.responseOverride.status = 500)', '{', - '"error": "$input.path(\'$.error\')"', + '"error": "$input.path(\'$.error\')",', '"cause": "$input.path(\'$.cause\')"', '}', '#else', @@ -241,6 +255,7 @@ function templateString( const includeHeader = options.headers?? false; const includeQueryString = options.querystring?? true; const includePath = options.path?? true; + const includeAuthorizer = options.authorizer ?? false; if (options.requestContext && Object.keys(options.requestContext).length > 0) { requestContextStr = requestContext(options.requestContext); @@ -251,6 +266,7 @@ function templateString( templateStr = templateStr.replace('%INCLUDE_HEADERS%', String(includeHeader)); templateStr = templateStr.replace('%INCLUDE_QUERYSTRING%', String(includeQueryString)); templateStr = templateStr.replace('%INCLUDE_PATH%', String(includePath)); + templateStr = templateStr.replace('%INCLUDE_AUTHORIZER%', String(includeAuthorizer)); templateStr = templateStr.replace('%REQUESTCONTEXT%', requestContextStr); return templateStr; diff --git a/packages/@aws-cdk/aws-apigateway/lib/integrations/stepfunctions.vtl b/packages/@aws-cdk/aws-apigateway/lib/integrations/stepfunctions.vtl index df4eda7c279d5..f389662efd6ed 100644 --- a/packages/@aws-cdk/aws-apigateway/lib/integrations/stepfunctions.vtl +++ b/packages/@aws-cdk/aws-apigateway/lib/integrations/stepfunctions.vtl @@ -9,6 +9,7 @@ #set($includeHeaders = %INCLUDE_HEADERS%) #set($includeQueryString = %INCLUDE_QUERYSTRING%) #set($includePath = %INCLUDE_PATH%) +#set($includeAuthorizer = %INCLUDE_AUTHORIZER%) #set($allParams = $input.params()) { "stateMachineArn": "%STATEMACHINE%", @@ -49,6 +50,17 @@ #set($inputString = "$inputString }") #end + #if ($includeAuthorizer) + #set($inputString = "$inputString, @@authorizer@@:{") + #foreach($paramName in $context.authorizer.keySet()) + #set($inputString = "$inputString @@$paramName@@: @@$util.escapeJavaScript($context.authorizer.get($paramName))@@") + #if($foreach.hasNext) + #set($inputString = "$inputString,") + #end + #end + #set($inputString = "$inputString }") + #end + #set($requestContext = "%REQUESTCONTEXT%") ## Check if the request context should be included as part of the execution input #if($requestContext && !$requestContext.empty) diff --git a/packages/@aws-cdk/aws-apigateway/lib/resource.ts b/packages/@aws-cdk/aws-apigateway/lib/resource.ts index 714e99bce7a0b..f843ee1b5e25a 100644 --- a/packages/@aws-cdk/aws-apigateway/lib/resource.ts +++ b/packages/@aws-cdk/aws-apigateway/lib/resource.ts @@ -311,8 +311,8 @@ export abstract class ResourceBase extends ResourceConstruct implements IResourc const template = new Array(); - template.push('#set($origin = $input.params("Origin"))'); - template.push('#if($origin == "") #set($origin = $input.params("origin")) #end'); + template.push('#set($origin = $input.params().header.get("Origin"))'); + template.push('#if($origin == "") #set($origin = $input.params().header.get("origin")) #end'); const condition = origins.map(o => `$origin.matches("${o}")`).join(' || '); diff --git a/packages/@aws-cdk/aws-apigateway/lib/stepfunctions-api.ts b/packages/@aws-cdk/aws-apigateway/lib/stepfunctions-api.ts index 69addc0619383..bbae7158f1ac1 100644 --- a/packages/@aws-cdk/aws-apigateway/lib/stepfunctions-api.ts +++ b/packages/@aws-cdk/aws-apigateway/lib/stepfunctions-api.ts @@ -11,12 +11,12 @@ import { Model } from './model'; * */ export interface StepFunctionsRestApiProps extends RestApiProps { -/** - * The default State Machine that handles all requests from this API. - * - * This stateMachine will be used as a the default integration for all methods in - * this API, unless specified otherwise in `addMethod`. - */ + /** + * The default State Machine that handles all requests from this API. + * + * This stateMachine will be used as a the default integration for all methods in + * this API, unless specified otherwise in `addMethod`. + */ readonly stateMachine: sfn.IStateMachine; /** @@ -75,6 +75,20 @@ export interface StepFunctionsRestApiProps extends RestApiProps { * @default false */ readonly headers?: boolean; + + /** + * If the whole authorizer object, including custom context values should be in the execution input. The execution input will include a new key `authorizer`: + * + * { + * "body": {}, + * "authorizer": { + * "key": "value" + * } + * } + * + * @default false + */ + readonly authorizer?: boolean; } /** @@ -96,6 +110,7 @@ export class StepFunctionsRestApi extends RestApi { path: props.path?? true, querystring: props.querystring?? true, headers: props.headers, + authorizer: props.authorizer, }); super(scope, id, props); diff --git a/packages/@aws-cdk/aws-apigateway/lib/usage-plan.ts b/packages/@aws-cdk/aws-apigateway/lib/usage-plan.ts index 4db28eb936e80..2f10071259517 100644 --- a/packages/@aws-cdk/aws-apigateway/lib/usage-plan.ts +++ b/packages/@aws-cdk/aws-apigateway/lib/usage-plan.ts @@ -6,7 +6,7 @@ import { CfnUsagePlan, CfnUsagePlanKey } from './apigateway.generated'; import { Method } from './method'; import { IRestApi } from './restapi'; import { Stage } from './stage'; -import { validateInteger } from './util'; +import { validateDouble, validateInteger } from './util'; /** * Container for defining throttling parameters to API stages or methods. @@ -316,7 +316,7 @@ export class UsagePlan extends UsagePlanBase { const burstLimit = props.burstLimit; validateInteger(burstLimit, 'Throttle burst limit'); const rateLimit = props.rateLimit; - validateInteger(rateLimit, 'Throttle rate limit'); + validateDouble(rateLimit, 'Throttle rate limit'); ret = { burstLimit: burstLimit, diff --git a/packages/@aws-cdk/aws-apigateway/lib/util.ts b/packages/@aws-cdk/aws-apigateway/lib/util.ts index 7facdc35bc2a0..550250edcd432 100644 --- a/packages/@aws-cdk/aws-apigateway/lib/util.ts +++ b/packages/@aws-cdk/aws-apigateway/lib/util.ts @@ -78,6 +78,12 @@ export function validateInteger(property: number | undefined, messagePrefix: str } } +export function validateDouble(property: number | undefined, messagePrefix: string) { + if (property && isNaN(property) && isNaN(parseFloat(property.toString()))) { + throw new Error(`${messagePrefix} should be an double`); + } +} + export class JsonSchemaMapper { /** * Transforms naming of some properties to prefix with a $, where needed diff --git a/packages/@aws-cdk/aws-apigateway/package.json b/packages/@aws-cdk/aws-apigateway/package.json index cff64a652688b..3243e168f0919 100644 --- a/packages/@aws-cdk/aws-apigateway/package.json +++ b/packages/@aws-cdk/aws-apigateway/package.json @@ -84,7 +84,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/aws-certificatemanager": "0.0.0", diff --git a/packages/@aws-cdk/aws-apigateway/test/cors.test.ts b/packages/@aws-cdk/aws-apigateway/test/cors.test.ts index 581b8af3e6c53..c573e6302589e 100644 --- a/packages/@aws-cdk/aws-apigateway/test/cors.test.ts +++ b/packages/@aws-cdk/aws-apigateway/test/cors.test.ts @@ -290,7 +290,7 @@ describe('cors', () => { 'method.response.header.Access-Control-Allow-Methods': "'OPTIONS,GET,PUT,POST,DELETE,PATCH,HEAD'", }, ResponseTemplates: { - 'application/json': '#set($origin = $input.params("Origin"))\n#if($origin == "") #set($origin = $input.params("origin")) #end\n#if($origin.matches("https://amazon.com") || $origin.matches("https://aws.amazon.com"))\n #set($context.responseOverride.header.Access-Control-Allow-Origin = $origin)\n#end', + 'application/json': '#set($origin = $input.params().header.get("Origin"))\n#if($origin == "") #set($origin = $input.params().header.get("origin")) #end\n#if($origin.matches("https://amazon.com") || $origin.matches("https://aws.amazon.com"))\n #set($context.responseOverride.header.Access-Control-Allow-Origin = $origin)\n#end', }, StatusCode: '204', }, diff --git a/packages/@aws-cdk/aws-apigateway/test/integ.cors.expected.json b/packages/@aws-cdk/aws-apigateway/test/integ.cors.expected.json index 22b5c45a87b53..02d757e898afe 100644 --- a/packages/@aws-cdk/aws-apigateway/test/integ.cors.expected.json +++ b/packages/@aws-cdk/aws-apigateway/test/integ.cors.expected.json @@ -51,7 +51,7 @@ "corsapitest8682546E" ] }, - "corsapitestDeployment2BF1633A228079ea05e5799220dd4ca13512b92d": { + "corsapitestDeployment2BF1633A51392cbce1ac2785bd0e53063423e203": { "Type": "AWS::ApiGateway::Deployment", "Properties": { "RestApiId": { @@ -74,7 +74,7 @@ "Ref": "corsapitest8682546E" }, "DeploymentId": { - "Ref": "corsapitestDeployment2BF1633A228079ea05e5799220dd4ca13512b92d" + "Ref": "corsapitestDeployment2BF1633A51392cbce1ac2785bd0e53063423e203" }, "StageName": "prod" }, @@ -472,7 +472,7 @@ "method.response.header.Access-Control-Allow-Methods": "'OPTIONS,GET,PUT,POST,DELETE,PATCH,HEAD'" }, "ResponseTemplates": { - "application/json": "#set($origin = $input.params(\"Origin\"))\n#if($origin == \"\") #set($origin = $input.params(\"origin\")) #end\n#if($origin.matches(\"https://www.test-cors.org\"))\n #set($context.responseOverride.header.Access-Control-Allow-Origin = $origin)\n#end" + "application/json": "#set($origin = $input.params().header.get(\"Origin\"))\n#if($origin == \"\") #set($origin = $input.params().header.get(\"origin\")) #end\n#if($origin.matches(\"https://www.test-cors.org\"))\n #set($context.responseOverride.header.Access-Control-Allow-Origin = $origin)\n#end" }, "StatusCode": "204" } diff --git a/packages/@aws-cdk/aws-apigateway/test/integ.stepfunctions-api.expected.json b/packages/@aws-cdk/aws-apigateway/test/integ.stepfunctions-api.expected.json index 33976c0937cf5..afbccd88a73ae 100644 --- a/packages/@aws-cdk/aws-apigateway/test/integ.stepfunctions-api.expected.json +++ b/packages/@aws-cdk/aws-apigateway/test/integ.stepfunctions-api.expected.json @@ -160,7 +160,7 @@ "IntegrationResponses": [ { "ResponseTemplates": { - "application/json": "#set($inputRoot = $input.path('$'))\n#if($input.path('$.status').toString().equals(\"FAILED\"))\n#set($context.responseOverride.status = 500)\n{\n\"error\": \"$input.path('$.error')\"\n\"cause\": \"$input.path('$.cause')\"\n}\n#else\n$input.path('$.output')\n#end" + "application/json": "#set($inputRoot = $input.path('$'))\n#if($input.path('$.status').toString().equals(\"FAILED\"))\n#set($context.responseOverride.status = 500)\n{\n\"error\": \"$input.path('$.error')\",\n\"cause\": \"$input.path('$.cause')\"\n}\n#else\n$input.path('$.output')\n#end" }, "StatusCode": "200" }, @@ -185,11 +185,11 @@ "Fn::Join": [ "", [ - "## Velocity Template used for API Gateway request mapping template\n##\n## This template forwards the request body, header, path, and querystring\n## to the execution input of the state machine.\n##\n## \"@@\" is used here as a placeholder for '\"' to avoid using escape characters.\n\n#set($inputString = '')\n#set($includeHeaders = true)\n#set($includeQueryString = false)\n#set($includePath = false)\n#set($allParams = $input.params())\n{\n \"stateMachineArn\": \"", + "## Velocity Template used for API Gateway request mapping template\n##\n## This template forwards the request body, header, path, and querystring\n## to the execution input of the state machine.\n##\n## \"@@\" is used here as a placeholder for '\"' to avoid using escape characters.\n\n#set($inputString = '')\n#set($includeHeaders = true)\n#set($includeQueryString = false)\n#set($includePath = false)\n#set($includeAuthorizer = false)\n#set($allParams = $input.params())\n{\n \"stateMachineArn\": \"", { "Ref": "StateMachine2E01A3A5" }, - "\",\n\n #set($inputString = \"$inputString,@@body@@: $input.body\")\n\n #if ($includeHeaders)\n #set($inputString = \"$inputString, @@header@@:{\")\n #foreach($paramName in $allParams.header.keySet())\n #set($inputString = \"$inputString @@$paramName@@: @@$util.escapeJavaScript($allParams.header.get($paramName))@@\")\n #if($foreach.hasNext)\n #set($inputString = \"$inputString,\")\n #end\n #end\n #set($inputString = \"$inputString }\")\n \n #end\n\n #if ($includeQueryString)\n #set($inputString = \"$inputString, @@querystring@@:{\")\n #foreach($paramName in $allParams.querystring.keySet())\n #set($inputString = \"$inputString @@$paramName@@: @@$util.escapeJavaScript($allParams.querystring.get($paramName))@@\")\n #if($foreach.hasNext)\n #set($inputString = \"$inputString,\")\n #end\n #end\n #set($inputString = \"$inputString }\")\n #end\n\n #if ($includePath)\n #set($inputString = \"$inputString, @@path@@:{\")\n #foreach($paramName in $allParams.path.keySet())\n #set($inputString = \"$inputString @@$paramName@@: @@$util.escapeJavaScript($allParams.path.get($paramName))@@\")\n #if($foreach.hasNext)\n #set($inputString = \"$inputString,\")\n #end\n #end\n #set($inputString = \"$inputString }\")\n #end\n \n #set($requestContext = \"{@@accountId@@:@@$context.identity.accountId@@,@@userArn@@:@@$context.identity.userArn@@}\")\n ## Check if the request context should be included as part of the execution input\n #if($requestContext && !$requestContext.empty)\n #set($inputString = \"$inputString,\")\n #set($inputString = \"$inputString @@requestContext@@: $requestContext\")\n #end\n\n #set($inputString = \"$inputString}\")\n #set($inputString = $inputString.replaceAll(\"@@\",'\"'))\n #set($len = $inputString.length() - 1)\n \"input\": \"{$util.escapeJavaScript($inputString.substring(1,$len))}\"\n}\n" + "\",\n\n #set($inputString = \"$inputString,@@body@@: $input.body\")\n\n #if ($includeHeaders)\n #set($inputString = \"$inputString, @@header@@:{\")\n #foreach($paramName in $allParams.header.keySet())\n #set($inputString = \"$inputString @@$paramName@@: @@$util.escapeJavaScript($allParams.header.get($paramName))@@\")\n #if($foreach.hasNext)\n #set($inputString = \"$inputString,\")\n #end\n #end\n #set($inputString = \"$inputString }\")\n \n #end\n\n #if ($includeQueryString)\n #set($inputString = \"$inputString, @@querystring@@:{\")\n #foreach($paramName in $allParams.querystring.keySet())\n #set($inputString = \"$inputString @@$paramName@@: @@$util.escapeJavaScript($allParams.querystring.get($paramName))@@\")\n #if($foreach.hasNext)\n #set($inputString = \"$inputString,\")\n #end\n #end\n #set($inputString = \"$inputString }\")\n #end\n\n #if ($includePath)\n #set($inputString = \"$inputString, @@path@@:{\")\n #foreach($paramName in $allParams.path.keySet())\n #set($inputString = \"$inputString @@$paramName@@: @@$util.escapeJavaScript($allParams.path.get($paramName))@@\")\n #if($foreach.hasNext)\n #set($inputString = \"$inputString,\")\n #end\n #end\n #set($inputString = \"$inputString }\")\n #end\n \n #if ($includeAuthorizer)\n #set($inputString = \"$inputString, @@authorizer@@:{\")\n #foreach($paramName in $context.authorizer.keySet())\n #set($inputString = \"$inputString @@$paramName@@: @@$util.escapeJavaScript($context.authorizer.get($paramName))@@\")\n #if($foreach.hasNext)\n #set($inputString = \"$inputString,\")\n #end\n #end\n #set($inputString = \"$inputString }\")\n #end\n\n #set($requestContext = \"{@@accountId@@:@@$context.identity.accountId@@,@@userArn@@:@@$context.identity.userArn@@}\")\n ## Check if the request context should be included as part of the execution input\n #if($requestContext && !$requestContext.empty)\n #set($inputString = \"$inputString,\")\n #set($inputString = \"$inputString @@requestContext@@: $requestContext\")\n #end\n\n #set($inputString = \"$inputString}\")\n #set($inputString = $inputString.replaceAll(\"@@\",'\"'))\n #set($len = $inputString.length() - 1)\n \"input\": \"{$util.escapeJavaScript($inputString.substring(1,$len))}\"\n}\n" ] ] } diff --git a/packages/@aws-cdk/aws-apigateway/test/integrations/stepfunctions.test.ts b/packages/@aws-cdk/aws-apigateway/test/integrations/stepfunctions.test.ts index 830ca2a8e2000..32fd13c5741c0 100644 --- a/packages/@aws-cdk/aws-apigateway/test/integrations/stepfunctions.test.ts +++ b/packages/@aws-cdk/aws-apigateway/test/integrations/stepfunctions.test.ts @@ -52,11 +52,11 @@ describe('StepFunctionsIntegration', () => { 'Fn::Join': [ '', [ - "## Velocity Template used for API Gateway request mapping template\n##\n## This template forwards the request body, header, path, and querystring\n## to the execution input of the state machine.\n##\n## \"@@\" is used here as a placeholder for '\"' to avoid using escape characters.\n\n#set($inputString = '')\n#set($includeHeaders = false)\n#set($includeQueryString = true)\n#set($includePath = true)\n#set($allParams = $input.params())\n{\n \"stateMachineArn\": \"", + "## Velocity Template used for API Gateway request mapping template\n##\n## This template forwards the request body, header, path, and querystring\n## to the execution input of the state machine.\n##\n## \"@@\" is used here as a placeholder for '\"' to avoid using escape characters.\n\n#set($inputString = '')\n#set($includeHeaders = false)\n#set($includeQueryString = true)\n#set($includePath = true)\n#set($includeAuthorizer = false)\n#set($allParams = $input.params())\n{\n \"stateMachineArn\": \"", { Ref: 'StateMachine2E01A3A5', }, - "\",\n\n #set($inputString = \"$inputString,@@body@@: $input.body\")\n\n #if ($includeHeaders)\n #set($inputString = \"$inputString, @@header@@:{\")\n #foreach($paramName in $allParams.header.keySet())\n #set($inputString = \"$inputString @@$paramName@@: @@$util.escapeJavaScript($allParams.header.get($paramName))@@\")\n #if($foreach.hasNext)\n #set($inputString = \"$inputString,\")\n #end\n #end\n #set($inputString = \"$inputString }\")\n \n #end\n\n #if ($includeQueryString)\n #set($inputString = \"$inputString, @@querystring@@:{\")\n #foreach($paramName in $allParams.querystring.keySet())\n #set($inputString = \"$inputString @@$paramName@@: @@$util.escapeJavaScript($allParams.querystring.get($paramName))@@\")\n #if($foreach.hasNext)\n #set($inputString = \"$inputString,\")\n #end\n #end\n #set($inputString = \"$inputString }\")\n #end\n\n #if ($includePath)\n #set($inputString = \"$inputString, @@path@@:{\")\n #foreach($paramName in $allParams.path.keySet())\n #set($inputString = \"$inputString @@$paramName@@: @@$util.escapeJavaScript($allParams.path.get($paramName))@@\")\n #if($foreach.hasNext)\n #set($inputString = \"$inputString,\")\n #end\n #end\n #set($inputString = \"$inputString }\")\n #end\n \n #set($requestContext = \"\")\n ## Check if the request context should be included as part of the execution input\n #if($requestContext && !$requestContext.empty)\n #set($inputString = \"$inputString,\")\n #set($inputString = \"$inputString @@requestContext@@: $requestContext\")\n #end\n\n #set($inputString = \"$inputString}\")\n #set($inputString = $inputString.replaceAll(\"@@\",'\"'))\n #set($len = $inputString.length() - 1)\n \"input\": \"{$util.escapeJavaScript($inputString.substring(1,$len))}\"\n}\n", + "\",\n\n #set($inputString = \"$inputString,@@body@@: $input.body\")\n\n #if ($includeHeaders)\n #set($inputString = \"$inputString, @@header@@:{\")\n #foreach($paramName in $allParams.header.keySet())\n #set($inputString = \"$inputString @@$paramName@@: @@$util.escapeJavaScript($allParams.header.get($paramName))@@\")\n #if($foreach.hasNext)\n #set($inputString = \"$inputString,\")\n #end\n #end\n #set($inputString = \"$inputString }\")\n \n #end\n\n #if ($includeQueryString)\n #set($inputString = \"$inputString, @@querystring@@:{\")\n #foreach($paramName in $allParams.querystring.keySet())\n #set($inputString = \"$inputString @@$paramName@@: @@$util.escapeJavaScript($allParams.querystring.get($paramName))@@\")\n #if($foreach.hasNext)\n #set($inputString = \"$inputString,\")\n #end\n #end\n #set($inputString = \"$inputString }\")\n #end\n\n #if ($includePath)\n #set($inputString = \"$inputString, @@path@@:{\")\n #foreach($paramName in $allParams.path.keySet())\n #set($inputString = \"$inputString @@$paramName@@: @@$util.escapeJavaScript($allParams.path.get($paramName))@@\")\n #if($foreach.hasNext)\n #set($inputString = \"$inputString,\")\n #end\n #end\n #set($inputString = \"$inputString }\")\n #end\n \n #if ($includeAuthorizer)\n #set($inputString = \"$inputString, @@authorizer@@:{\")\n #foreach($paramName in $context.authorizer.keySet())\n #set($inputString = \"$inputString @@$paramName@@: @@$util.escapeJavaScript($context.authorizer.get($paramName))@@\")\n #if($foreach.hasNext)\n #set($inputString = \"$inputString,\")\n #end\n #end\n #set($inputString = \"$inputString }\")\n #end\n\n #set($requestContext = \"\")\n ## Check if the request context should be included as part of the execution input\n #if($requestContext && !$requestContext.empty)\n #set($inputString = \"$inputString,\")\n #set($inputString = \"$inputString @@requestContext@@: $requestContext\")\n #end\n\n #set($inputString = \"$inputString}\")\n #set($inputString = $inputString.replaceAll(\"@@\",'\"'))\n #set($len = $inputString.length() - 1)\n \"input\": \"{$util.escapeJavaScript($inputString.substring(1,$len))}\"\n}\n", ], ], }, @@ -264,6 +264,34 @@ describe('StepFunctionsIntegration', () => { }); }); + test('authorizer context is included when specified by the integration', () => { + //GIVEN + const { stack, api, stateMachine } = givenSetup(); + + //WHEN + const integ = apigw.StepFunctionsIntegration.startExecution(stateMachine, { + authorizer: true, + }); + api.root.addMethod('GET', integ); + + Template.fromStack(stack).hasResourceProperties('AWS::ApiGateway::Method', { + Integration: { + RequestTemplates: { + 'application/json': { + 'Fn::Join': [ + '', + [ + Match.stringLikeRegexp('#set\\(\\$includeAuthorizer = true\\)'), + { Ref: 'StateMachine2E01A3A5' }, + Match.anyValue(), + ], + ], + }, + }, + }, + }); + }); + test('works for imported RestApi', () => { const stack = new cdk.Stack(); const api = apigw.RestApi.fromRestApiAttributes(stack, 'RestApi', { @@ -390,7 +418,7 @@ function getIntegrationResponse() { '#if($input.path(\'$.status\').toString().equals("FAILED"))', '#set($context.responseOverride.status = 500)', '{', - '"error": "$input.path(\'$.error\')"', + '"error": "$input.path(\'$.error\')",', '"cause": "$input.path(\'$.cause\')"', '}', '#else', diff --git a/packages/@aws-cdk/aws-apigateway/test/stepfunctions-api.test.ts b/packages/@aws-cdk/aws-apigateway/test/stepfunctions-api.test.ts index 51426a4ffe6c3..5922d61025965 100644 --- a/packages/@aws-cdk/aws-apigateway/test/stepfunctions-api.test.ts +++ b/packages/@aws-cdk/aws-apigateway/test/stepfunctions-api.test.ts @@ -44,11 +44,11 @@ describe('Step Functions api', () => { 'Fn::Join': [ '', [ - "## Velocity Template used for API Gateway request mapping template\n##\n## This template forwards the request body, header, path, and querystring\n## to the execution input of the state machine.\n##\n## \"@@\" is used here as a placeholder for '\"' to avoid using escape characters.\n\n#set($inputString = '')\n#set($includeHeaders = false)\n#set($includeQueryString = true)\n#set($includePath = true)\n#set($allParams = $input.params())\n{\n \"stateMachineArn\": \"", + "## Velocity Template used for API Gateway request mapping template\n##\n## This template forwards the request body, header, path, and querystring\n## to the execution input of the state machine.\n##\n## \"@@\" is used here as a placeholder for '\"' to avoid using escape characters.\n\n#set($inputString = '')\n#set($includeHeaders = false)\n#set($includeQueryString = true)\n#set($includePath = true)\n#set($includeAuthorizer = false)\n#set($allParams = $input.params())\n{\n \"stateMachineArn\": \"", { Ref: 'StateMachine2E01A3A5', }, - "\",\n\n #set($inputString = \"$inputString,@@body@@: $input.body\")\n\n #if ($includeHeaders)\n #set($inputString = \"$inputString, @@header@@:{\")\n #foreach($paramName in $allParams.header.keySet())\n #set($inputString = \"$inputString @@$paramName@@: @@$util.escapeJavaScript($allParams.header.get($paramName))@@\")\n #if($foreach.hasNext)\n #set($inputString = \"$inputString,\")\n #end\n #end\n #set($inputString = \"$inputString }\")\n \n #end\n\n #if ($includeQueryString)\n #set($inputString = \"$inputString, @@querystring@@:{\")\n #foreach($paramName in $allParams.querystring.keySet())\n #set($inputString = \"$inputString @@$paramName@@: @@$util.escapeJavaScript($allParams.querystring.get($paramName))@@\")\n #if($foreach.hasNext)\n #set($inputString = \"$inputString,\")\n #end\n #end\n #set($inputString = \"$inputString }\")\n #end\n\n #if ($includePath)\n #set($inputString = \"$inputString, @@path@@:{\")\n #foreach($paramName in $allParams.path.keySet())\n #set($inputString = \"$inputString @@$paramName@@: @@$util.escapeJavaScript($allParams.path.get($paramName))@@\")\n #if($foreach.hasNext)\n #set($inputString = \"$inputString,\")\n #end\n #end\n #set($inputString = \"$inputString }\")\n #end\n \n #set($requestContext = \"\")\n ## Check if the request context should be included as part of the execution input\n #if($requestContext && !$requestContext.empty)\n #set($inputString = \"$inputString,\")\n #set($inputString = \"$inputString @@requestContext@@: $requestContext\")\n #end\n\n #set($inputString = \"$inputString}\")\n #set($inputString = $inputString.replaceAll(\"@@\",'\"'))\n #set($len = $inputString.length() - 1)\n \"input\": \"{$util.escapeJavaScript($inputString.substring(1,$len))}\"\n}\n", + "\",\n\n #set($inputString = \"$inputString,@@body@@: $input.body\")\n\n #if ($includeHeaders)\n #set($inputString = \"$inputString, @@header@@:{\")\n #foreach($paramName in $allParams.header.keySet())\n #set($inputString = \"$inputString @@$paramName@@: @@$util.escapeJavaScript($allParams.header.get($paramName))@@\")\n #if($foreach.hasNext)\n #set($inputString = \"$inputString,\")\n #end\n #end\n #set($inputString = \"$inputString }\")\n \n #end\n\n #if ($includeQueryString)\n #set($inputString = \"$inputString, @@querystring@@:{\")\n #foreach($paramName in $allParams.querystring.keySet())\n #set($inputString = \"$inputString @@$paramName@@: @@$util.escapeJavaScript($allParams.querystring.get($paramName))@@\")\n #if($foreach.hasNext)\n #set($inputString = \"$inputString,\")\n #end\n #end\n #set($inputString = \"$inputString }\")\n #end\n\n #if ($includePath)\n #set($inputString = \"$inputString, @@path@@:{\")\n #foreach($paramName in $allParams.path.keySet())\n #set($inputString = \"$inputString @@$paramName@@: @@$util.escapeJavaScript($allParams.path.get($paramName))@@\")\n #if($foreach.hasNext)\n #set($inputString = \"$inputString,\")\n #end\n #end\n #set($inputString = \"$inputString }\")\n #end\n \n #if ($includeAuthorizer)\n #set($inputString = \"$inputString, @@authorizer@@:{\")\n #foreach($paramName in $context.authorizer.keySet())\n #set($inputString = \"$inputString @@$paramName@@: @@$util.escapeJavaScript($context.authorizer.get($paramName))@@\")\n #if($foreach.hasNext)\n #set($inputString = \"$inputString,\")\n #end\n #end\n #set($inputString = \"$inputString }\")\n #end\n\n #set($requestContext = \"\")\n ## Check if the request context should be included as part of the execution input\n #if($requestContext && !$requestContext.empty)\n #set($inputString = \"$inputString,\")\n #set($inputString = \"$inputString @@requestContext@@: $requestContext\")\n #end\n\n #set($inputString = \"$inputString}\")\n #set($inputString = $inputString.replaceAll(\"@@\",'\"'))\n #set($len = $inputString.length() - 1)\n \"input\": \"{$util.escapeJavaScript($inputString.substring(1,$len))}\"\n}\n", ], ], }, @@ -181,7 +181,7 @@ function getIntegrationResponse() { '#if($input.path(\'$.status\').toString().equals("FAILED"))', '#set($context.responseOverride.status = 500)', '{', - '"error": "$input.path(\'$.error\')"', + '"error": "$input.path(\'$.error\')",', '"cause": "$input.path(\'$.cause\')"', '}', '#else', diff --git a/packages/@aws-cdk/aws-apigateway/test/usage-plan.test.ts b/packages/@aws-cdk/aws-apigateway/test/usage-plan.test.ts index b31e3c90b256b..26a63641abc4e 100644 --- a/packages/@aws-cdk/aws-apigateway/test/usage-plan.test.ts +++ b/packages/@aws-cdk/aws-apigateway/test/usage-plan.test.ts @@ -27,13 +27,13 @@ describe('usage plan', () => { }); }); - test('usage plan with throttling limits', () => { + test('usage plan with integer throttling limits', () => { // GIVEN const stack = new cdk.Stack(); const api = new apigateway.RestApi(stack, 'my-api', { cloudWatchRole: false, deploy: true, deployOptions: { stageName: 'test' } }); const method: apigateway.Method = api.root.addMethod('GET'); // Need at least one method on the api const usagePlanName = 'Basic'; - const usagePlanDescription = 'Basic Usage Plan with throttling limits'; + const usagePlanDescription = 'Basic Usage Plan with integer throttling limits'; // WHEN new apigateway.UsagePlan(stack, 'my-usage-plan', { @@ -78,6 +78,57 @@ describe('usage plan', () => { }); }); + test('usage plan with integer and float throttling limits', () => { + // GIVEN + const stack = new cdk.Stack(); + const api = new apigateway.RestApi(stack, 'my-api', { cloudWatchRole: false, deploy: true, deployOptions: { stageName: 'test' } }); + const method: apigateway.Method = api.root.addMethod('GET'); // Need at least one method on the api + const usagePlanName = 'Basic'; + const usagePlanDescription = 'Basic Usage Plan with integer and float throttling limits'; + + // WHEN + new apigateway.UsagePlan(stack, 'my-usage-plan', { + name: usagePlanName, + description: usagePlanDescription, + apiStages: [ + { + stage: api.deploymentStage, + throttle: [ + { + method, + throttle: { + burstLimit: 20, + rateLimit: 10.5, + }, + }, + ], + }, + ], + }); + + // THEN + Template.fromStack(stack).hasResourceProperties(RESOURCE_TYPE, { + UsagePlanName: usagePlanName, + Description: usagePlanDescription, + ApiStages: [ + { + ApiId: { + Ref: 'myapi4C7BF186', + }, + Stage: { + Ref: 'myapiDeploymentStagetest4A4AB65E', + }, + Throttle: { + '//GET': { + BurstLimit: 20, + RateLimit: 10.5, + }, + }, + }, + ], + }); + }); + test('usage plan with blocked methods', () => { // GIVEN const stack = new cdk.Stack(); diff --git a/packages/@aws-cdk/aws-apigatewayv2-authorizers/package.json b/packages/@aws-cdk/aws-apigatewayv2-authorizers/package.json index 084eb7c3dd027..dd8a9418e6e2c 100644 --- a/packages/@aws-cdk/aws-apigatewayv2-authorizers/package.json +++ b/packages/@aws-cdk/aws-apigatewayv2-authorizers/package.json @@ -86,7 +86,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0", "@types/aws-lambda": "^8.10.92", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/aws-apigatewayv2": "0.0.0", diff --git a/packages/@aws-cdk/aws-apigatewayv2-integrations/lib/http/lambda.ts b/packages/@aws-cdk/aws-apigatewayv2-integrations/lib/http/lambda.ts index 2417fffe1610d..69019e0c2866a 100644 --- a/packages/@aws-cdk/aws-apigatewayv2-integrations/lib/http/lambda.ts +++ b/packages/@aws-cdk/aws-apigatewayv2-integrations/lib/http/lambda.ts @@ -50,7 +50,7 @@ export class HttpLambdaIntegration extends HttpRouteIntegration { this._id = id; } - public bind(options: HttpRouteIntegrationBindOptions): HttpRouteIntegrationConfig { + protected completeBind(options: HttpRouteIntegrationBindOptions) { const route = options.route; this.handler.addPermission(`${this._id}-Permission`, { scope: options.scope, @@ -61,7 +61,9 @@ export class HttpLambdaIntegration extends HttpRouteIntegration { resourceName: `*/*${route.path ?? ''}`, // empty string in the case of the catch-all route $default }), }); + } + public bind(_: HttpRouteIntegrationBindOptions): HttpRouteIntegrationConfig { return { type: HttpIntegrationType.AWS_PROXY, uri: this.handler.functionArn, diff --git a/packages/@aws-cdk/aws-apigatewayv2-integrations/package.json b/packages/@aws-cdk/aws-apigatewayv2-integrations/package.json index 2adf4f6882119..749d5fb08b479 100644 --- a/packages/@aws-cdk/aws-apigatewayv2-integrations/package.json +++ b/packages/@aws-cdk/aws-apigatewayv2-integrations/package.json @@ -81,7 +81,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/aws-apigatewayv2": "0.0.0", diff --git a/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/lambda.test.ts b/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/lambda.test.ts index 5c318e1629842..f832921ad995b 100644 --- a/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/lambda.test.ts +++ b/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/lambda.test.ts @@ -1,4 +1,4 @@ -import { Template } from '@aws-cdk/assertions'; +import { Match, Template } from '@aws-cdk/assertions'; import { HttpApi, HttpRoute, HttpRouteKey, MappingValue, ParameterMapping, PayloadFormatVersion } from '@aws-cdk/aws-apigatewayv2'; import { Code, Function, Runtime } from '@aws-cdk/aws-lambda'; import { App, Stack } from '@aws-cdk/core'; @@ -71,6 +71,41 @@ describe('LambdaProxyIntegration', () => { expect(() => app.synth()).not.toThrow(); }); + + test('multiple routes for the same lambda integration', () => { + const app = new App(); + const lambdaStack = new Stack(app, 'lambdaStack'); + const fooFn = fooFunction(lambdaStack, 'Fn'); + + const stack = new Stack(app, 'apigwStack'); + const api = new HttpApi(stack, 'httpApi'); + const integration = new HttpLambdaIntegration('Integration', fooFn); + + api.addRoutes({ + path: '/foo', + integration, + }); + + api.addRoutes({ + path: '/bar', + integration, + }); + + // Make sure we have two permissions -- one for each method -- but a single integration + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Permission', { + SourceArn: { + 'Fn::Join': ['', Match.arrayWith([':execute-api:', '/*/*/foo'])], + }, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Permission', { + SourceArn: { + 'Fn::Join': ['', Match.arrayWith([':execute-api:', '/*/*/bar'])], + }, + }); + + Template.fromStack(stack).resourceCountIs('AWS::ApiGatewayV2::Integration', 1); + }); }); function fooFunction(stack: Stack, id: string) { diff --git a/packages/@aws-cdk/aws-apigatewayv2/README.md b/packages/@aws-cdk/aws-apigatewayv2/README.md index 5e0a110082ab9..040ee20d0bf6a 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/README.md +++ b/packages/@aws-cdk/aws-apigatewayv2/README.md @@ -404,6 +404,12 @@ webSocketApi.addRoute('sendmessage', { }); ``` +To import an existing WebSocketApi: + +```ts +const webSocketApi = apigwv2.WebSocketApi.fromWebSocketApiAttributes(this, 'mywsapi', { webSocketId: 'api-1234' }); +``` + ### Manage Connections Permission Grant permission to use API Gateway Management API of a WebSocket API by calling the `grantManageConnections` API. diff --git a/packages/@aws-cdk/aws-apigatewayv2/lib/http/integration.ts b/packages/@aws-cdk/aws-apigatewayv2/lib/http/integration.ts index 58e9c9a60879a..9667f072d9036 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/lib/http/integration.ts +++ b/packages/@aws-cdk/aws-apigatewayv2/lib/http/integration.ts @@ -332,9 +332,22 @@ export abstract class HttpRouteIntegration { credentials: config.credentials, }); } + this.completeBind(options); return { integrationId: this.integration.integrationId }; } + /** + * Complete the binding of the integration to the route. In some cases, there is + * some additional work to do, such as adding permissions for the API to access + * the target. This work is necessary whether the integration has just been + * created for this route or it is an existing one, previously created for other + * routes. In most cases, however, concrete implementations do not need to + * override this method. + */ + protected completeBind(_options: HttpRouteIntegrationBindOptions): void { + // no-op by default + } + /** * Bind this integration to the route. */ diff --git a/packages/@aws-cdk/aws-apigatewayv2/lib/websocket/api.ts b/packages/@aws-cdk/aws-apigatewayv2/lib/websocket/api.ts index da740d582bbad..f81eb7b899f1f 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/lib/websocket/api.ts +++ b/packages/@aws-cdk/aws-apigatewayv2/lib/websocket/api.ts @@ -85,11 +85,47 @@ export interface WebSocketApiProps { readonly defaultRouteOptions?: WebSocketRouteOptions; } +/** + * Attributes for importing a WebSocketApi into the CDK + */ +export interface WebSocketApiAttributes { + /** + * The identifier of the WebSocketApi + */ + readonly webSocketId: string; + + /** + * The endpoint URL of the WebSocketApi + * @default - throw san error if apiEndpoint is accessed. + */ + readonly apiEndpoint?: string; +} + + /** * Create a new API Gateway WebSocket API endpoint. * @resource AWS::ApiGatewayV2::Api */ export class WebSocketApi extends ApiBase implements IWebSocketApi { + /** + * Import an existing WebSocket API into this CDK app. + */ + public static fromWebSocketApiAttributes(scope: Construct, id: string, attrs: WebSocketApiAttributes): IWebSocketApi { + class Import extends ApiBase { + public readonly apiId = attrs.webSocketId; + public readonly websocketApiId = attrs.webSocketId; + private readonly _apiEndpoint = attrs.apiEndpoint; + + public get apiEndpoint(): string { + if (!this._apiEndpoint) { + throw new Error('apiEndpoint is not configured on the imported WebSocketApi.'); + } + return this._apiEndpoint; + } + } + return new Import(scope, id); + } + public readonly apiId: string; public readonly apiEndpoint: string; diff --git a/packages/@aws-cdk/aws-apigatewayv2/package.json b/packages/@aws-cdk/aws-apigatewayv2/package.json index 31ec578d85b51..088009ce5a483 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/package.json +++ b/packages/@aws-cdk/aws-apigatewayv2/package.json @@ -89,7 +89,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/aws-certificatemanager": "0.0.0", diff --git a/packages/@aws-cdk/aws-apigatewayv2/test/websocket/api.test.ts b/packages/@aws-cdk/aws-apigatewayv2/test/websocket/api.test.ts index 1ac6cfbae315f..f9fb740c0e190 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/test/websocket/api.test.ts +++ b/packages/@aws-cdk/aws-apigatewayv2/test/websocket/api.test.ts @@ -107,6 +107,25 @@ describe('WebSocketApi', () => { }); }); + test('import', () => { + // GIVEN + const stack = new Stack(); + const imported = WebSocketApi.fromWebSocketApiAttributes(stack, 'imported', { webSocketId: 'ws-1234', apiEndpoint: 'api-endpoint' }); + + // THEN + expect(imported.apiId).toEqual('ws-1234'); + expect(imported.apiEndpoint).toEqual('api-endpoint'); + }); + + test('apiEndpoint for imported', () => { + // GIVEN + const stack = new Stack(); + const api = WebSocketApi.fromWebSocketApiAttributes(stack, 'imported', { webSocketId: 'api-1234' }); + + // THEN + expect(() => api.apiEndpoint).toThrow(/apiEndpoint is not configured/); + }); + describe('grantManageConnections', () => { test('adds an IAM policy to the principal', () => { // GIVEN diff --git a/packages/@aws-cdk/aws-appconfig/package.json b/packages/@aws-cdk/aws-appconfig/package.json index 4f4abaaf6dc40..59a35b9f2f241 100644 --- a/packages/@aws-cdk/aws-appconfig/package.json +++ b/packages/@aws-cdk/aws-appconfig/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-appflow/package.json b/packages/@aws-cdk/aws-appflow/package.json index fd0648da5f582..e401c2c7c98de 100644 --- a/packages/@aws-cdk/aws-appflow/package.json +++ b/packages/@aws-cdk/aws-appflow/package.json @@ -82,7 +82,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-appintegrations/package.json b/packages/@aws-cdk/aws-appintegrations/package.json index cd4ecf81dd7c5..d0615ae38682c 100644 --- a/packages/@aws-cdk/aws-appintegrations/package.json +++ b/packages/@aws-cdk/aws-appintegrations/package.json @@ -87,7 +87,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-applicationautoscaling/package.json b/packages/@aws-cdk/aws-applicationautoscaling/package.json index c04efc88262d7..95e7c514ff6f7 100644 --- a/packages/@aws-cdk/aws-applicationautoscaling/package.json +++ b/packages/@aws-cdk/aws-applicationautoscaling/package.json @@ -83,7 +83,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "fast-check": "^2.22.0", "jest": "^27.5.1" }, diff --git a/packages/@aws-cdk/aws-applicationinsights/package.json b/packages/@aws-cdk/aws-applicationinsights/package.json index 38d8d1d6311c1..70ecad632f81f 100644 --- a/packages/@aws-cdk/aws-applicationinsights/package.json +++ b/packages/@aws-cdk/aws-applicationinsights/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-appmesh/package.json b/packages/@aws-cdk/aws-appmesh/package.json index 491d5c31445de..81b3eff008d13 100644 --- a/packages/@aws-cdk/aws-appmesh/package.json +++ b/packages/@aws-cdk/aws-appmesh/package.json @@ -89,7 +89,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-apprunner/package.json b/packages/@aws-cdk/aws-apprunner/package.json index 0627cfbcc38fa..be5b3afe4c9cc 100644 --- a/packages/@aws-cdk/aws-apprunner/package.json +++ b/packages/@aws-cdk/aws-apprunner/package.json @@ -88,7 +88,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/aws-ecr": "0.0.0", diff --git a/packages/@aws-cdk/aws-appstream/package.json b/packages/@aws-cdk/aws-appstream/package.json index 059821e8a6b4b..0069735f46906 100644 --- a/packages/@aws-cdk/aws-appstream/package.json +++ b/packages/@aws-cdk/aws-appstream/package.json @@ -84,7 +84,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-appsync/package.json b/packages/@aws-cdk/aws-appsync/package.json index 29617fbae6289..f158ec0f97599 100644 --- a/packages/@aws-cdk/aws-appsync/package.json +++ b/packages/@aws-cdk/aws-appsync/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-appsync/test/integ.api-import.expected.json b/packages/@aws-cdk/aws-appsync/test/integ.api-import.expected.json index e4b54f04116fc..269f986d16838 100644 --- a/packages/@aws-cdk/aws-appsync/test/integ.api-import.expected.json +++ b/packages/@aws-cdk/aws-appsync/test/integ.api-import.expected.json @@ -85,7 +85,8 @@ "dynamodb:BatchWriteItem", "dynamodb:PutItem", "dynamodb:UpdateItem", - "dynamodb:DeleteItem" + "dynamodb:DeleteItem", + "dynamodb:DescribeTable" ], "Effect": "Allow", "Resource": [ diff --git a/packages/@aws-cdk/aws-appsync/test/integ.auth-apikey.expected.json b/packages/@aws-cdk/aws-appsync/test/integ.auth-apikey.expected.json index ed0307de0e72f..2eb81b6793f66 100644 --- a/packages/@aws-cdk/aws-appsync/test/integ.auth-apikey.expected.json +++ b/packages/@aws-cdk/aws-appsync/test/integ.auth-apikey.expected.json @@ -68,7 +68,8 @@ "dynamodb:BatchWriteItem", "dynamodb:PutItem", "dynamodb:UpdateItem", - "dynamodb:DeleteItem" + "dynamodb:DeleteItem", + "dynamodb:DescribeTable" ], "Effect": "Allow", "Resource": [ diff --git a/packages/@aws-cdk/aws-appsync/test/integ.graphql-iam.expected.json b/packages/@aws-cdk/aws-appsync/test/integ.graphql-iam.expected.json index 374a89dc33d14..91af2e3102a2a 100644 --- a/packages/@aws-cdk/aws-appsync/test/integ.graphql-iam.expected.json +++ b/packages/@aws-cdk/aws-appsync/test/integ.graphql-iam.expected.json @@ -99,7 +99,8 @@ "dynamodb:BatchWriteItem", "dynamodb:PutItem", "dynamodb:UpdateItem", - "dynamodb:DeleteItem" + "dynamodb:DeleteItem", + "dynamodb:DescribeTable" ], "Effect": "Allow", "Resource": [ diff --git a/packages/@aws-cdk/aws-appsync/test/integ.graphql-schema.expected.json b/packages/@aws-cdk/aws-appsync/test/integ.graphql-schema.expected.json index a6e5ff5764331..44c75a74f0f8f 100644 --- a/packages/@aws-cdk/aws-appsync/test/integ.graphql-schema.expected.json +++ b/packages/@aws-cdk/aws-appsync/test/integ.graphql-schema.expected.json @@ -67,7 +67,8 @@ "dynamodb:BatchWriteItem", "dynamodb:PutItem", "dynamodb:UpdateItem", - "dynamodb:DeleteItem" + "dynamodb:DeleteItem", + "dynamodb:DescribeTable" ], "Effect": "Allow", "Resource": [ diff --git a/packages/@aws-cdk/aws-appsync/test/integ.graphql.expected.json b/packages/@aws-cdk/aws-appsync/test/integ.graphql.expected.json index e14c0af7a5450..ca8ee1a1c7b5b 100644 --- a/packages/@aws-cdk/aws-appsync/test/integ.graphql.expected.json +++ b/packages/@aws-cdk/aws-appsync/test/integ.graphql.expected.json @@ -147,7 +147,8 @@ "dynamodb:BatchWriteItem", "dynamodb:PutItem", "dynamodb:UpdateItem", - "dynamodb:DeleteItem" + "dynamodb:DeleteItem", + "dynamodb:DescribeTable" ], "Effect": "Allow", "Resource": [ @@ -360,7 +361,8 @@ "dynamodb:BatchWriteItem", "dynamodb:PutItem", "dynamodb:UpdateItem", - "dynamodb:DeleteItem" + "dynamodb:DeleteItem", + "dynamodb:DescribeTable" ], "Effect": "Allow", "Resource": [ @@ -752,7 +754,8 @@ "dynamodb:BatchWriteItem", "dynamodb:PutItem", "dynamodb:UpdateItem", - "dynamodb:DeleteItem" + "dynamodb:DeleteItem", + "dynamodb:DescribeTable" ], "Effect": "Allow", "Resource": [ diff --git a/packages/@aws-cdk/aws-aps/package.json b/packages/@aws-cdk/aws-aps/package.json index a63226c0a8148..7fbef265f7a3b 100644 --- a/packages/@aws-cdk/aws-aps/package.json +++ b/packages/@aws-cdk/aws-aps/package.json @@ -87,7 +87,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-athena/package.json b/packages/@aws-cdk/aws-athena/package.json index 1ad3e27f861c2..134a9cdbe2bdf 100644 --- a/packages/@aws-cdk/aws-athena/package.json +++ b/packages/@aws-cdk/aws-athena/package.json @@ -84,7 +84,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-auditmanager/package.json b/packages/@aws-cdk/aws-auditmanager/package.json index a9a3738209a4d..16fe6cc71fd69 100644 --- a/packages/@aws-cdk/aws-auditmanager/package.json +++ b/packages/@aws-cdk/aws-auditmanager/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-autoscaling-common/package.json b/packages/@aws-cdk/aws-autoscaling-common/package.json index f1b5163a378e7..69fd192599983 100644 --- a/packages/@aws-cdk/aws-autoscaling-common/package.json +++ b/packages/@aws-cdk/aws-autoscaling-common/package.json @@ -74,7 +74,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "fast-check": "^2.22.0", "jest": "^27.5.1" }, diff --git a/packages/@aws-cdk/aws-autoscaling-hooktargets/package.json b/packages/@aws-cdk/aws-autoscaling-hooktargets/package.json index 9772f5697f278..164d2d933695c 100644 --- a/packages/@aws-cdk/aws-autoscaling-hooktargets/package.json +++ b/packages/@aws-cdk/aws-autoscaling-hooktargets/package.json @@ -77,7 +77,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-autoscaling/package.json b/packages/@aws-cdk/aws-autoscaling/package.json index 0a1e455a1e4ac..09a081cdbd9fe 100644 --- a/packages/@aws-cdk/aws-autoscaling/package.json +++ b/packages/@aws-cdk/aws-autoscaling/package.json @@ -86,7 +86,7 @@ "@aws-cdk/cloud-assembly-schema": "0.0.0", "@aws-cdk/cx-api": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-autoscalingplans/package.json b/packages/@aws-cdk/aws-autoscalingplans/package.json index 6de1130ba56bb..26c9be8cc368f 100644 --- a/packages/@aws-cdk/aws-autoscalingplans/package.json +++ b/packages/@aws-cdk/aws-autoscalingplans/package.json @@ -83,7 +83,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-backup/package.json b/packages/@aws-cdk/aws-backup/package.json index 5f0d0088cff3e..5462be05a3813 100644 --- a/packages/@aws-cdk/aws-backup/package.json +++ b/packages/@aws-cdk/aws-backup/package.json @@ -86,7 +86,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/aws-dynamodb": "0.0.0", diff --git a/packages/@aws-cdk/aws-batch/package.json b/packages/@aws-cdk/aws-batch/package.json index 58db51b199e36..0c405c1a720f5 100644 --- a/packages/@aws-cdk/aws-batch/package.json +++ b/packages/@aws-cdk/aws-batch/package.json @@ -84,7 +84,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-budgets/package.json b/packages/@aws-cdk/aws-budgets/package.json index 7b0506935bdb3..3da84da4dcca0 100644 --- a/packages/@aws-cdk/aws-budgets/package.json +++ b/packages/@aws-cdk/aws-budgets/package.json @@ -83,7 +83,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-cassandra/package.json b/packages/@aws-cdk/aws-cassandra/package.json index 70e21b61df3e3..5325bf8bfe1bf 100644 --- a/packages/@aws-cdk/aws-cassandra/package.json +++ b/packages/@aws-cdk/aws-cassandra/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-ce/package.json b/packages/@aws-cdk/aws-ce/package.json index 6332fc8cffd14..ff751b12bb50d 100644 --- a/packages/@aws-cdk/aws-ce/package.json +++ b/packages/@aws-cdk/aws-ce/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-certificatemanager/package.json b/packages/@aws-cdk/aws-certificatemanager/package.json index 86685caaf49ff..b2dcdedca636d 100644 --- a/packages/@aws-cdk/aws-certificatemanager/package.json +++ b/packages/@aws-cdk/aws-certificatemanager/package.json @@ -83,7 +83,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/aws-acmpca": "0.0.0", diff --git a/packages/@aws-cdk/aws-chatbot/package.json b/packages/@aws-cdk/aws-chatbot/package.json index 35a6887f3b5cb..259cf25fb4985 100644 --- a/packages/@aws-cdk/aws-chatbot/package.json +++ b/packages/@aws-cdk/aws-chatbot/package.json @@ -86,7 +86,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/aws-cloudwatch": "0.0.0", diff --git a/packages/@aws-cdk/aws-cloud9/package.json b/packages/@aws-cdk/aws-cloud9/package.json index 7078ef97f408e..2fd6aab3799e2 100644 --- a/packages/@aws-cdk/aws-cloud9/package.json +++ b/packages/@aws-cdk/aws-cloud9/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/aws-codecommit": "0.0.0", diff --git a/packages/@aws-cdk/aws-cloudformation/package.json b/packages/@aws-cdk/aws-cloudformation/package.json index ea4d03a27baef..710300daaacde 100644 --- a/packages/@aws-cdk/aws-cloudformation/package.json +++ b/packages/@aws-cdk/aws-cloudformation/package.json @@ -87,7 +87,7 @@ "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", "@types/aws-lambda": "^8.10.92", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-cloudformation/test/nested-stack.test.ts b/packages/@aws-cdk/aws-cloudformation/test/nested-stack.test.ts index a625012eba58a..2b0445fb34d3b 100644 --- a/packages/@aws-cdk/aws-cloudformation/test/nested-stack.test.ts +++ b/packages/@aws-cdk/aws-cloudformation/test/nested-stack.test.ts @@ -4,7 +4,7 @@ import { Template } from '@aws-cdk/assertions'; import * as s3_assets from '@aws-cdk/aws-s3-assets'; import * as sns from '@aws-cdk/aws-sns'; import { describeDeprecated } from '@aws-cdk/cdk-build-tools'; -import { App, CfnParameter, CfnResource, ContextProvider, LegacyStackSynthesizer, Names, Stack } from '@aws-cdk/core'; +import { App, CfnParameter, CfnResource, ContextProvider, LegacyStackSynthesizer, Names, Stack, Tags } from '@aws-cdk/core'; import { NestedStack } from '../lib/nested-stack'; // keep this import separate from other imports to reduce chance for merge conflicts with v2-main @@ -1085,4 +1085,49 @@ describeDeprecated('NestedStack', () => { }); }); + test('nested stack should get the tags added in root stack', () =>{ + const app = new App(); + const parentStack = new Stack(app, 'parent-stack'); + const nestedStack = new NestedStack(parentStack, 'MyNestedStack'); + + // add tags + Tags.of(nestedStack).add('tag-1', '22'); + Tags.of(nestedStack).add('tag-2', '33'); + + new sns.Topic(nestedStack, 'MyTopic'); + + // THEN + Template.fromStack(parentStack).hasResourceProperties( + 'AWS::CloudFormation::Stack', + { + Tags: [ + { + Key: 'tag-1', + Value: '22', + }, + { + Key: 'tag-2', + Value: '33', + }, + ], + }, + ); + + Template.fromStack(nestedStack).hasResourceProperties( + 'AWS::SNS::Topic', + { + Tags: [ + { + Key: 'tag-1', + Value: '22', + }, + { + Key: 'tag-2', + Value: '33', + }, + ], + }, + ); + }); + }); diff --git a/packages/@aws-cdk/aws-cloudfront-origins/README.md b/packages/@aws-cdk/aws-cloudfront-origins/README.md index f88a7e7111b1b..d4e948b1e887e 100644 --- a/packages/@aws-cdk/aws-cloudfront-origins/README.md +++ b/packages/@aws-cdk/aws-cloudfront-origins/README.md @@ -76,11 +76,12 @@ const origin = new origins.LoadBalancerV2Origin(loadBalancer, { connectionAttempts: 3, connectionTimeout: Duration.seconds(5), readTimeout: Duration.seconds(45), + keepaliveTimeout: Duration.seconds(45), protocolPolicy: cloudfront.OriginProtocolPolicy.MATCH_VIEWER, }); ``` -Note that the `readTimeout` property can extend its value over 60 seconds only if a limit increase request for CloudFront origin response timeout +Note that the `readTimeout` and `keepaliveTimeout` properties can extend their values over 60 seconds only if a limit increase request for CloudFront origin response timeout quota has been approved in the target account; otherwise, values over 60 seconds will produce an error at deploy time. Consider that this value is still limited to a maximum value of 180 seconds, which is a hard limit for that quota. diff --git a/packages/@aws-cdk/aws-cloudfront-origins/lib/http-origin.ts b/packages/@aws-cdk/aws-cloudfront-origins/lib/http-origin.ts index 50b94b0c52191..e4d6ac190dcff 100644 --- a/packages/@aws-cdk/aws-cloudfront-origins/lib/http-origin.ts +++ b/packages/@aws-cdk/aws-cloudfront-origins/lib/http-origin.ts @@ -46,7 +46,10 @@ export interface HttpOriginProps extends cloudfront.OriginProps { /** * Specifies how long, in seconds, CloudFront persists its connection to the origin. - * The valid range is from 1 to 60 seconds, inclusive. + * The valid range is from 1 to 180 seconds, inclusive. + * + * Note that values over 60 seconds are possible only after a limit increase request for the origin response timeout quota + * has been approved in the target account; otherwise, values over 60 seconds will produce an error at deploy time. * * @default Duration.seconds(5) */ @@ -62,7 +65,7 @@ export class HttpOrigin extends cloudfront.OriginBase { super(domainName, props); validateSecondsInRangeOrUndefined('readTimeout', 1, 180, props.readTimeout); - validateSecondsInRangeOrUndefined('keepaliveTimeout', 1, 60, props.keepaliveTimeout); + validateSecondsInRangeOrUndefined('keepaliveTimeout', 1, 180, props.keepaliveTimeout); } protected renderCustomOriginConfig(): cloudfront.CfnDistribution.CustomOriginConfigProperty | undefined { diff --git a/packages/@aws-cdk/aws-cloudfront-origins/package.json b/packages/@aws-cdk/aws-cloudfront-origins/package.json index a7fd2e966e6fd..d7bea5cd1ecca 100644 --- a/packages/@aws-cdk/aws-cloudfront-origins/package.json +++ b/packages/@aws-cdk/aws-cloudfront-origins/package.json @@ -82,7 +82,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "aws-sdk": "^2.848.0" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-cloudfront-origins/test/http-origin.test.ts b/packages/@aws-cdk/aws-cloudfront-origins/test/http-origin.test.ts index df149f56753b2..f1109a7f8c7db 100644 --- a/packages/@aws-cdk/aws-cloudfront-origins/test/http-origin.test.ts +++ b/packages/@aws-cdk/aws-cloudfront-origins/test/http-origin.test.ts @@ -84,12 +84,12 @@ test.each([ Duration.seconds(0), Duration.seconds(0.5), Duration.seconds(60.5), - Duration.seconds(61), + Duration.seconds(181), Duration.minutes(5), -])('validates keepaliveTimeout is an integer between 1 and 60 seconds', (keepaliveTimeout) => { +])('validates keepaliveTimeout is an integer between 1 and 180 seconds', (keepaliveTimeout) => { expect(() => { new HttpOrigin('www.example.com', { keepaliveTimeout, }); - }).toThrow(`keepaliveTimeout: Must be an int between 1 and 60 seconds (inclusive); received ${keepaliveTimeout.toSeconds()}.`); + }).toThrow(`keepaliveTimeout: Must be an int between 1 and 180 seconds (inclusive); received ${keepaliveTimeout.toSeconds()}.`); }); diff --git a/packages/@aws-cdk/aws-cloudfront/README.md b/packages/@aws-cdk/aws-cloudfront/README.md index bf3711f7da8b4..3a727d6c1763f 100644 --- a/packages/@aws-cdk/aws-cloudfront/README.md +++ b/packages/@aws-cdk/aws-cloudfront/README.md @@ -859,7 +859,7 @@ new cloudfront.CloudFrontWebDistribution(this, 'MyDistribution', { behaviors : [ {isDefaultBehavior: true}], }, ], - geoRestriction: cloudfront.GeoRestriction.whitelist('US', 'UK'), + geoRestriction: cloudfront.GeoRestriction.allowlist('US', 'GB'), }); ``` diff --git a/packages/@aws-cdk/aws-cloudfront/lib/cache-policy.ts b/packages/@aws-cdk/aws-cloudfront/lib/cache-policy.ts index 533ccbd5d78b9..e870a538fc887 100644 --- a/packages/@aws-cdk/aws-cloudfront/lib/cache-policy.ts +++ b/packages/@aws-cdk/aws-cloudfront/lib/cache-policy.ts @@ -129,9 +129,14 @@ export class CachePolicy extends Resource implements ICachePolicy { physicalName: props.cachePolicyName, }); - const cachePolicyName = props.cachePolicyName ?? `${Names.uniqueId(this)}-${Stack.of(this).region}`; + const cachePolicyName = props.cachePolicyName ?? `${Names.uniqueId(this).slice(0, 110)}-${Stack.of(this).region}`; + if (!Token.isUnresolved(cachePolicyName) && !cachePolicyName.match(/^[\w-]+$/i)) { - throw new Error(`'cachePolicyName' can only include '-', '_', and alphanumeric characters, got: '${props.cachePolicyName}'`); + throw new Error(`'cachePolicyName' can only include '-', '_', and alphanumeric characters, got: '${cachePolicyName}'`); + } + + if (cachePolicyName.length > 128) { + throw new Error(`'cachePolicyName' cannot be longer than 128 characters, got: '${cachePolicyName.length}'`); } const minTtl = (props.minTtl ?? Duration.seconds(0)).toSeconds(); diff --git a/packages/@aws-cdk/aws-cloudfront/lib/distribution.ts b/packages/@aws-cdk/aws-cloudfront/lib/distribution.ts index c593edd9efec7..bd9fb1cb50202 100644 --- a/packages/@aws-cdk/aws-cloudfront/lib/distribution.ts +++ b/packages/@aws-cdk/aws-cloudfront/lib/distribution.ts @@ -285,7 +285,7 @@ export class Distribution extends Resource implements IDistribution { // Comments have an undocumented limit of 128 characters const trimmedComment = props.comment && props.comment.length > 128 - ? `${props.comment.substr(0, 128 - 3)}...` + ? `${props.comment.slice(0, 128 - 3)}...` : props.comment; const distribution = new CfnDistribution(this, 'Resource', { diff --git a/packages/@aws-cdk/aws-cloudfront/package.json b/packages/@aws-cdk/aws-cloudfront/package.json index 66aa20bc41801..37ee6edb996a2 100644 --- a/packages/@aws-cdk/aws-cloudfront/package.json +++ b/packages/@aws-cdk/aws-cloudfront/package.json @@ -84,7 +84,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "aws-sdk": "^2.848.0", "jest": "^27.5.1" }, diff --git a/packages/@aws-cdk/aws-cloudfront/test/cache-policy.test.ts b/packages/@aws-cdk/aws-cloudfront/test/cache-policy.test.ts index 47e9b0ee46fb9..2abeffd3cc39b 100644 --- a/packages/@aws-cdk/aws-cloudfront/test/cache-policy.test.ts +++ b/packages/@aws-cdk/aws-cloudfront/test/cache-policy.test.ts @@ -85,7 +85,12 @@ describe('CachePolicy', () => { }); }); - test('throws if given a cachePolicyName with invalid characters', () => { + test('throws on long policy names over 128 characters', () => { + const errorMessage = /'cachePolicyName' cannot be longer than 128 characters/; + expect(() => new CachePolicy(stack, 'CachePolicy1', { cachePolicyName: 'FooBarBaz'.repeat(15) })).toThrow(errorMessage); + }); + + test('throws if cachePolicyName contains invalid characters', () => { const errorMessage = /'cachePolicyName' can only include '-', '_', and alphanumeric characters/; expect(() => new CachePolicy(stack, 'CachePolicy1', { cachePolicyName: 'My Policy' })).toThrow(errorMessage); expect(() => new CachePolicy(stack, 'CachePolicy2', { cachePolicyName: 'MyPolicy!' })).toThrow(errorMessage); diff --git a/packages/@aws-cdk/aws-cloudtrail/package.json b/packages/@aws-cdk/aws-cloudtrail/package.json index 6997064a6f53d..d5b30cb2c16c8 100644 --- a/packages/@aws-cdk/aws-cloudtrail/package.json +++ b/packages/@aws-cdk/aws-cloudtrail/package.json @@ -84,7 +84,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "aws-sdk": "^2.848.0", "jest": "^27.5.1" }, diff --git a/packages/@aws-cdk/aws-cloudwatch-actions/package.json b/packages/@aws-cdk/aws-cloudwatch-actions/package.json index bddb930d555fb..a54a582f66548 100644 --- a/packages/@aws-cdk/aws-cloudwatch-actions/package.json +++ b/packages/@aws-cdk/aws-cloudwatch-actions/package.json @@ -77,7 +77,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-cloudwatch/package.json b/packages/@aws-cdk/aws-cloudwatch/package.json index 0502a3a1cdcda..f263def7dfcd2 100644 --- a/packages/@aws-cdk/aws-cloudwatch/package.json +++ b/packages/@aws-cdk/aws-cloudwatch/package.json @@ -84,7 +84,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-codeartifact/package.json b/packages/@aws-cdk/aws-codeartifact/package.json index 943a1e3a421a7..9303cee955029 100644 --- a/packages/@aws-cdk/aws-codeartifact/package.json +++ b/packages/@aws-cdk/aws-codeartifact/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-codebuild/README.md b/packages/@aws-cdk/aws-codebuild/README.md index 4bccbbc68cfa1..3be027de2404c 100644 --- a/packages/@aws-cdk/aws-codebuild/README.md +++ b/packages/@aws-cdk/aws-codebuild/README.md @@ -280,11 +280,12 @@ can use the `environment` property to customize the build environment: ## Images The CodeBuild library supports both Linux and Windows images via the -`LinuxBuildImage` and `WindowsBuildImage` classes, respectively. +`LinuxBuildImage` (or `LinuxArmBuildImage`), and `WindowsBuildImage` classes, respectively. You can specify one of the predefined Windows/Linux images by using one of the constants such as `WindowsBuildImage.WIN_SERVER_CORE_2019_BASE`, -`WindowsBuildImage.WINDOWS_BASE_2_0` or `LinuxBuildImage.STANDARD_2_0`. +`WindowsBuildImage.WINDOWS_BASE_2_0`, `LinuxBuildImage.STANDARD_2_0`, or +`LinuxArmBuildImage.AMAZON_LINUX_2_ARM`. Alternatively, you can specify a custom image using one of the static methods on `LinuxBuildImage`: @@ -302,6 +303,10 @@ or one of the corresponding methods on `WindowsBuildImage`: * `WindowsBuildImage.fromEcrRepository(repo[, tag, imageType])` * `WindowsBuildImage.fromAsset(parent, id, props, [, imageType])` +or one of the corresponding methods on `LinuxArmBuildImage`: + +* `LinuxArmBuildImage.fromEcrRepository(repo[, tag])` + Note that the `WindowsBuildImage` version of the static methods accepts an optional parameter of type `WindowsImageType`, which can be either `WindowsImageType.STANDARD`, the default, or `WindowsImageType.SERVER_2019`: diff --git a/packages/@aws-cdk/aws-codebuild/lib/index.ts b/packages/@aws-cdk/aws-codebuild/lib/index.ts index 5c2de5f3119c2..e2abd2da98db8 100644 --- a/packages/@aws-cdk/aws-codebuild/lib/index.ts +++ b/packages/@aws-cdk/aws-codebuild/lib/index.ts @@ -11,6 +11,7 @@ export * from './build-spec'; export * from './file-location'; export * from './linux-gpu-build-image'; export * from './untrusted-code-boundary-policy'; +export * from './linux-arm-build-image'; // AWS::CodeBuild CloudFormation Resources: export * from './codebuild.generated'; diff --git a/packages/@aws-cdk/aws-codebuild/lib/linux-arm-build-image.ts b/packages/@aws-cdk/aws-codebuild/lib/linux-arm-build-image.ts new file mode 100644 index 0000000000000..12a7d2e54daf6 --- /dev/null +++ b/packages/@aws-cdk/aws-codebuild/lib/linux-arm-build-image.ts @@ -0,0 +1,105 @@ +import * as ecr from '@aws-cdk/aws-ecr'; +import * as secretsmanager from '@aws-cdk/aws-secretsmanager'; +import { BuildSpec } from './build-spec'; +import { runScriptLinuxBuildSpec } from './private/run-script-linux-build-spec'; +import { BuildEnvironment, ComputeType, IBuildImage, ImagePullPrincipalType } from './project'; + +/** + * Construction properties of {@link LinuxArmBuildImage}. + * Module-private, as the constructor of {@link LinuxArmBuildImage} is private. + */ +interface LinuxArmBuildImageProps { + readonly imageId: string; + readonly imagePullPrincipalType?: ImagePullPrincipalType; + readonly secretsManagerCredentials?: secretsmanager.ISecret; + readonly repository?: ecr.IRepository; +} + +/** + * A CodeBuild image running aarch64 Linux. + * + * This class has a bunch of public constants that represent the CodeBuild ARM images. + * + * You can also specify a custom image using the static method: + * + * - LinuxBuildImage.fromEcrRepository(repo[, tag]) + * + * + * @see https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-available.html + */ +export class LinuxArmBuildImage implements IBuildImage { + /** Image "aws/codebuild/amazonlinux2-aarch64-standard:1.0". */ + public static readonly AMAZON_LINUX_2_STANDARD_1_0 = LinuxArmBuildImage.fromCodeBuildImageId('aws/codebuild/amazonlinux2-aarch64-standard:1.0'); + /** Image "aws/codebuild/amazonlinux2-aarch64-standard:2.0". */ + public static readonly AMAZON_LINUX_2_STANDARD_2_0 = LinuxArmBuildImage.fromCodeBuildImageId('aws/codebuild/amazonlinux2-aarch64-standard:2.0'); + + /** + * Returns an ARM image running Linux from an ECR repository. + * + * NOTE: if the repository is external (i.e. imported), then we won't be able to add + * a resource policy statement for it so CodeBuild can pull the image. + * + * @see https://docs.aws.amazon.com/codebuild/latest/userguide/sample-ecr.html + * + * @param repository The ECR repository + * @param tag Image tag (default "latest") + * @returns An aarch64 Linux build image from an ECR repository. + */ + public static fromEcrRepository(repository: ecr.IRepository, tag: string = 'latest'): IBuildImage { + return new LinuxArmBuildImage({ + imageId: repository.repositoryUriForTag(tag), + imagePullPrincipalType: ImagePullPrincipalType.SERVICE_ROLE, + repository, + }); + } + + /** + * Uses a Docker image provided by CodeBuild. + * + * @see https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-available.html + * + * @param id The image identifier + * @example 'aws/codebuild/amazonlinux2-aarch64-standard:1.0' + * @returns A Docker image provided by CodeBuild. + */ + public static fromCodeBuildImageId(id: string): IBuildImage { + return new LinuxArmBuildImage({ + imageId: id, + imagePullPrincipalType: ImagePullPrincipalType.CODEBUILD, + }); + } + + public readonly type = 'ARM_CONTAINER'; + public readonly defaultComputeType = ComputeType.LARGE; + public readonly imageId: string; + public readonly imagePullPrincipalType?: ImagePullPrincipalType; + public readonly secretsManagerCredentials?: secretsmanager.ISecret; + public readonly repository?: ecr.IRepository; + + private constructor(props: LinuxArmBuildImageProps) { + this.imageId = props.imageId; + this.imagePullPrincipalType = props.imagePullPrincipalType; + this.secretsManagerCredentials = props.secretsManagerCredentials; + this.repository = props.repository; + } + + /** + * Validates by checking the BuildEnvironment computeType as aarch64 images only support ComputeType.SMALL and + * ComputeType.LARGE + * @param buildEnvironment BuildEnvironment + */ + public validate(buildEnvironment: BuildEnvironment): string[] { + const ret = []; + if (buildEnvironment.computeType && + buildEnvironment.computeType !== ComputeType.SMALL && + buildEnvironment.computeType !== ComputeType.LARGE) { + ret.push(`ARM images only support ComputeTypes '${ComputeType.SMALL}' and '${ComputeType.LARGE}' - ` + + `'${buildEnvironment.computeType}' was given`); + } + return ret; + } + + public runScriptBuildspec(entrypoint: string): BuildSpec { + return runScriptLinuxBuildSpec(entrypoint); + } +} diff --git a/packages/@aws-cdk/aws-codebuild/lib/project.ts b/packages/@aws-cdk/aws-codebuild/lib/project.ts index c6a816e3aedd2..e3ea5ac394f4c 100644 --- a/packages/@aws-cdk/aws-codebuild/lib/project.ts +++ b/packages/@aws-cdk/aws-codebuild/lib/project.ts @@ -1642,32 +1642,6 @@ export interface IBindableBuildImage extends IBuildImage { bind(scope: CoreConstruct, project: IProject, options: BuildImageBindOptions): BuildImageConfig; } -class ArmBuildImage implements IBuildImage { - public readonly type = 'ARM_CONTAINER'; - public readonly defaultComputeType = ComputeType.LARGE; - public readonly imagePullPrincipalType = ImagePullPrincipalType.CODEBUILD; - public readonly imageId: string; - - constructor(imageId: string) { - this.imageId = imageId; - } - - public validate(buildEnvironment: BuildEnvironment): string[] { - const ret = []; - if (buildEnvironment.computeType && - buildEnvironment.computeType !== ComputeType.SMALL && - buildEnvironment.computeType !== ComputeType.LARGE) { - ret.push(`ARM images only support ComputeTypes '${ComputeType.SMALL}' and '${ComputeType.LARGE}' - ` + - `'${buildEnvironment.computeType}' was given`); - } - return ret; - } - - public runScriptBuildspec(entrypoint: string): BuildSpec { - return runScriptLinuxBuildSpec(entrypoint); - } -} - /** * The options when creating a CodeBuild Docker build image * using {@link LinuxBuildImage.fromDockerRegistry} @@ -1695,8 +1669,12 @@ interface LinuxBuildImageProps { readonly repository?: ecr.IRepository; } +// Keep around to resolve a circular dependency until removing deprecated ARM image constants from LinuxBuildImage +// eslint-disable-next-line no-duplicate-imports, import/order +import { LinuxArmBuildImage } from './linux-arm-build-image'; + /** - * A CodeBuild image running Linux. + * A CodeBuild image running x86-64 Linux. * * This class has a bunch of public constants that represent the most popular images. * @@ -1723,9 +1701,13 @@ export class LinuxBuildImage implements IBuildImage { /** The Amazon Linux 2 x86_64 standard image, version `3.0`. */ public static readonly AMAZON_LINUX_2_3 = LinuxBuildImage.codeBuildImage('aws/codebuild/amazonlinux2-x86_64-standard:3.0'); - public static readonly AMAZON_LINUX_2_ARM: IBuildImage = new ArmBuildImage('aws/codebuild/amazonlinux2-aarch64-standard:1.0'); - /** Image "aws/codebuild/amazonlinux2-aarch64-standard:2.0". */ - public static readonly AMAZON_LINUX_2_ARM_2: IBuildImage = new ArmBuildImage('aws/codebuild/amazonlinux2-aarch64-standard:2.0'); + /** @deprecated Use LinuxArmBuildImage.AMAZON_LINUX_2_STANDARD_1_0 instead. */ + public static readonly AMAZON_LINUX_2_ARM = LinuxArmBuildImage.AMAZON_LINUX_2_STANDARD_1_0; + /** + * Image "aws/codebuild/amazonlinux2-aarch64-standard:2.0". + * @deprecated Use LinuxArmBuildImage.AMAZON_LINUX_2_STANDARD_2_0 instead. + * */ + public static readonly AMAZON_LINUX_2_ARM_2 = LinuxArmBuildImage.AMAZON_LINUX_2_STANDARD_2_0; /** @deprecated Use {@link STANDARD_2_0} and specify runtime in buildspec runtime-versions section */ public static readonly UBUNTU_14_04_BASE = LinuxBuildImage.codeBuildImage('aws/codebuild/ubuntu-base:14.04'); @@ -1789,7 +1771,7 @@ export class LinuxBuildImage implements IBuildImage { public static readonly UBUNTU_14_04_DOTNET_CORE_2_1 = LinuxBuildImage.codeBuildImage('aws/codebuild/dot-net:core-2.1'); /** - * @returns a Linux build image from a Docker Hub image. + * @returns a x86-64 Linux build image from a Docker Hub image. */ public static fromDockerRegistry(name: string, options: DockerImageOptions = {}): IBuildImage { return new LinuxBuildImage({ @@ -1800,7 +1782,7 @@ export class LinuxBuildImage implements IBuildImage { } /** - * @returns A Linux build image from an ECR repository. + * @returns A x86-64 Linux build image from an ECR repository. * * NOTE: if the repository is external (i.e. imported), then we won't be able to add * a resource policy statement for it so CodeBuild can pull the image. @@ -1819,7 +1801,7 @@ export class LinuxBuildImage implements IBuildImage { } /** - * Uses an Docker image asset as a Linux build image. + * Uses an Docker image asset as a x86-64 Linux build image. */ public static fromAsset(scope: Construct, id: string, props: DockerImageAssetProps): IBuildImage { const asset = new DockerImageAsset(scope, id, props); @@ -1961,7 +1943,7 @@ export class WindowsBuildImage implements IBuildImage { } /** - * @returns A Linux build image from an ECR repository. + * @returns A Windows build image from an ECR repository. * * NOTE: if the repository is external (i.e. imported), then we won't be able to add * a resource policy statement for it so CodeBuild can pull the image. @@ -2125,4 +2107,4 @@ export enum ProjectNotificationEvents { function isBindableBuildImage(x: unknown): x is IBindableBuildImage { return typeof x === 'object' && !!x && !!(x as any).bind; -} \ No newline at end of file +} diff --git a/packages/@aws-cdk/aws-codebuild/package.json b/packages/@aws-cdk/aws-codebuild/package.json index 4192c4d0a32e7..5f43a603aaa62 100644 --- a/packages/@aws-cdk/aws-codebuild/package.json +++ b/packages/@aws-cdk/aws-codebuild/package.json @@ -90,7 +90,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "aws-sdk": "^2.848.0", "jest": "^27.5.1" }, diff --git a/packages/@aws-cdk/aws-codebuild/test/linux-arm-build-image.test.ts b/packages/@aws-cdk/aws-codebuild/test/linux-arm-build-image.test.ts new file mode 100644 index 0000000000000..389fbc0529b22 --- /dev/null +++ b/packages/@aws-cdk/aws-codebuild/test/linux-arm-build-image.test.ts @@ -0,0 +1,328 @@ +import { Match, Template } from '@aws-cdk/assertions'; +import * as ecr from '@aws-cdk/aws-ecr'; +import * as cdk from '@aws-cdk/core'; +import * as codebuild from '../lib'; + +describe('Linux ARM build image', () => { + describe('AMAZON_LINUX_2_STANDARD_1_0', () => { + test('has type ARM_CONTAINER and default ComputeType LARGE', () => { + const stack = new cdk.Stack(); + new codebuild.PipelineProject(stack, 'Project', { + environment: { + buildImage: codebuild.LinuxArmBuildImage.AMAZON_LINUX_2_STANDARD_1_0, + }, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::CodeBuild::Project', { + Environment: { + Type: 'ARM_CONTAINER', + ComputeType: 'BUILD_GENERAL1_LARGE', + }, + }); + }); + + test('can be used with ComputeType SMALL', () => { + const stack = new cdk.Stack(); + new codebuild.PipelineProject(stack, 'Project', { + environment: { + computeType: codebuild.ComputeType.SMALL, + buildImage: codebuild.LinuxArmBuildImage.AMAZON_LINUX_2_STANDARD_1_0, + }, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::CodeBuild::Project', { + Environment: { + Type: 'ARM_CONTAINER', + ComputeType: 'BUILD_GENERAL1_SMALL', + }, + }); + }); + + test('cannot be used in conjunction with ComputeType MEDIUM', () => { + const stack = new cdk.Stack(); + + expect(() => { + new codebuild.PipelineProject(stack, 'Project', { + environment: { + buildImage: codebuild.LinuxArmBuildImage.AMAZON_LINUX_2_STANDARD_1_0, + computeType: codebuild.ComputeType.MEDIUM, + }, + }); + }).toThrow(/ARM images only support ComputeTypes 'BUILD_GENERAL1_SMALL' and 'BUILD_GENERAL1_LARGE' - 'BUILD_GENERAL1_MEDIUM' was given/); + }); + + test('can be used with ComputeType LARGE', () => { + const stack = new cdk.Stack(); + new codebuild.PipelineProject(stack, 'Project', { + environment: { + computeType: codebuild.ComputeType.LARGE, + buildImage: codebuild.LinuxArmBuildImage.AMAZON_LINUX_2_STANDARD_1_0, + }, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::CodeBuild::Project', { + Environment: { + Type: 'ARM_CONTAINER', + ComputeType: 'BUILD_GENERAL1_LARGE', + }, + }); + }); + + test('cannot be used in conjunction with ComputeType X2_LARGE', () => { + const stack = new cdk.Stack(); + + expect(() => { + new codebuild.PipelineProject(stack, 'Project', { + environment: { + buildImage: codebuild.LinuxArmBuildImage.AMAZON_LINUX_2_STANDARD_1_0, + computeType: codebuild.ComputeType.X2_LARGE, + }, + }); + }).toThrow(/ARM images only support ComputeTypes 'BUILD_GENERAL1_SMALL' and 'BUILD_GENERAL1_LARGE' - 'BUILD_GENERAL1_2XLARGE' was given/); + }); + }); + + describe('AMAZON_LINUX_2_STANDARD_2_0', () => { + test('has type ARM_CONTAINER and default ComputeType LARGE', () => { + const stack = new cdk.Stack(); + new codebuild.PipelineProject(stack, 'Project', { + environment: { + buildImage: codebuild.LinuxArmBuildImage.AMAZON_LINUX_2_STANDARD_2_0, + }, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::CodeBuild::Project', { + Environment: { + Type: 'ARM_CONTAINER', + ComputeType: 'BUILD_GENERAL1_LARGE', + }, + }); + }); + + test('can be used with ComputeType SMALL', () => { + const stack = new cdk.Stack(); + new codebuild.PipelineProject(stack, 'Project', { + environment: { + computeType: codebuild.ComputeType.SMALL, + buildImage: codebuild.LinuxArmBuildImage.AMAZON_LINUX_2_STANDARD_2_0, + }, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::CodeBuild::Project', { + Environment: { + Type: 'ARM_CONTAINER', + ComputeType: 'BUILD_GENERAL1_SMALL', + }, + }); + }); + + test('cannot be used in conjunction with ComputeType MEDIUM', () => { + const stack = new cdk.Stack(); + + expect(() => { + new codebuild.PipelineProject(stack, 'Project', { + environment: { + buildImage: codebuild.LinuxArmBuildImage.AMAZON_LINUX_2_STANDARD_2_0, + computeType: codebuild.ComputeType.MEDIUM, + }, + }); + }).toThrow(/ARM images only support ComputeTypes 'BUILD_GENERAL1_SMALL' and 'BUILD_GENERAL1_LARGE' - 'BUILD_GENERAL1_MEDIUM' was given/); + }); + + test('can be used with ComputeType LARGE', () => { + const stack = new cdk.Stack(); + new codebuild.PipelineProject(stack, 'Project', { + environment: { + computeType: codebuild.ComputeType.LARGE, + buildImage: codebuild.LinuxArmBuildImage.AMAZON_LINUX_2_STANDARD_2_0, + }, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::CodeBuild::Project', { + Environment: { + Type: 'ARM_CONTAINER', + ComputeType: 'BUILD_GENERAL1_LARGE', + }, + }); + }); + + test('cannot be used in conjunction with ComputeType X2_LARGE', () => { + const stack = new cdk.Stack(); + + expect(() => { + new codebuild.PipelineProject(stack, 'Project', { + environment: { + buildImage: codebuild.LinuxArmBuildImage.AMAZON_LINUX_2_STANDARD_2_0, + computeType: codebuild.ComputeType.X2_LARGE, + }, + }); + }).toThrow(/ARM images only support ComputeTypes 'BUILD_GENERAL1_SMALL' and 'BUILD_GENERAL1_LARGE' - 'BUILD_GENERAL1_2XLARGE' was given/); + }); + }); + + describe('ECR Repository', () => { + test('allows creating a build image from a new ECR repository', () => { + const stack = new cdk.Stack(); + + const repository = new ecr.Repository(stack, 'my-repo'); + + new codebuild.Project(stack, 'Project', { + buildSpec: codebuild.BuildSpec.fromObject({ + version: '0.2', + phases: { + build: { commands: ['ls'] }, + }, + }), + environment: { + buildImage: codebuild.LinuxArmBuildImage.fromEcrRepository(repository, 'v1'), + }, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::CodeBuild::Project', { + Environment: { + ComputeType: 'BUILD_GENERAL1_LARGE', + Image: { + 'Fn::Join': ['', [ + { + 'Fn::Select': [4, { + 'Fn::Split': [':', { + 'Fn::GetAtt': ['myrepo5DFA62E5', 'Arn'], + }], + }], + }, + '.dkr.ecr.', + { + 'Fn::Select': [3, { + 'Fn::Split': [':', { + 'Fn::GetAtt': ['myrepo5DFA62E5', 'Arn'], + }], + }], + }, + '.', + { Ref: 'AWS::URLSuffix' }, + '/', + { Ref: 'myrepo5DFA62E5' }, + ':v1', + ]], + }, + }, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: Match.arrayWith([Match.objectLike({ + Action: [ + 'ecr:BatchCheckLayerAvailability', + 'ecr:GetDownloadUrlForLayer', + 'ecr:BatchGetImage', + ], + Resource: { + 'Fn::GetAtt': ['myrepo5DFA62E5', 'Arn'], + }, + })]), + }, + }); + }); + + test('allows creating a build image from an existing ECR repository', () => { + const stack = new cdk.Stack(); + + const repository = ecr.Repository.fromRepositoryName(stack, 'my-imported-repo', 'test-repo'); + + new codebuild.Project(stack, 'Project', { + buildSpec: codebuild.BuildSpec.fromObject({ + version: '0.2', + phases: { + build: { commands: ['ls'] }, + }, + }), + environment: { + buildImage: codebuild.LinuxArmBuildImage.fromEcrRepository(repository), + }, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::CodeBuild::Project', { + Environment: { + ComputeType: 'BUILD_GENERAL1_LARGE', + Image: { + 'Fn::Join': ['', [ + { Ref: 'AWS::AccountId' }, + '.dkr.ecr.', + { Ref: 'AWS::Region' }, + '.', + { Ref: 'AWS::URLSuffix' }, + '/test-repo:latest', + ]], + }, + }, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: Match.arrayWith([Match.objectLike({ + Action: [ + 'ecr:BatchCheckLayerAvailability', + 'ecr:GetDownloadUrlForLayer', + 'ecr:BatchGetImage', + ], + Resource: { + 'Fn::Join': ['', [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':ecr:', + { Ref: 'AWS::Region' }, + ':', + { Ref: 'AWS::AccountId' }, + ':repository/test-repo', + ]], + }, + })]), + }, + }); + }); + + test('allows creating a build image from an existing cross-account ECR repository', () => { + const stack = new cdk.Stack(); + + const repository = ecr.Repository.fromRepositoryArn(stack, 'my-cross-acount-repo', 'arn:aws:ecr:us-east-1:585695036304:repository/foo/bar/foo/fooo'); + + new codebuild.Project(stack, 'Project', { + buildSpec: codebuild.BuildSpec.fromObject({ + version: '0.2', + phases: { + build: { commands: ['ls'] }, + }, + }), + environment: { + buildImage: codebuild.LinuxArmBuildImage.fromEcrRepository(repository), + }, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::CodeBuild::Project', { + Environment: { + ComputeType: 'BUILD_GENERAL1_LARGE', + Image: { + 'Fn::Join': ['', [ + '585695036304.dkr.ecr.us-east-1.', + { Ref: 'AWS::URLSuffix' }, + '/foo/bar/foo/fooo:latest', + ]], + }, + }, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: Match.arrayWith([Match.objectLike({ + Action: [ + 'ecr:BatchCheckLayerAvailability', + 'ecr:GetDownloadUrlForLayer', + 'ecr:BatchGetImage', + ], + Resource: 'arn:aws:ecr:us-east-1:585695036304:repository/foo/bar/foo/fooo', + })]), + }, + }); + }); + }); +}); diff --git a/packages/@aws-cdk/aws-codecommit/package.json b/packages/@aws-cdk/aws-codecommit/package.json index 9954ebae62d7b..108604988db31 100644 --- a/packages/@aws-cdk/aws-codecommit/package.json +++ b/packages/@aws-cdk/aws-codecommit/package.json @@ -91,7 +91,7 @@ "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/cloud-assembly-schema": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "aws-sdk": "^2.848.0", "jest": "^27.5.1" }, diff --git a/packages/@aws-cdk/aws-codedeploy/package.json b/packages/@aws-cdk/aws-codedeploy/package.json index ec6d681fe9112..ff289e51bbe4c 100644 --- a/packages/@aws-cdk/aws-codedeploy/package.json +++ b/packages/@aws-cdk/aws-codedeploy/package.json @@ -87,7 +87,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-codeguruprofiler/package.json b/packages/@aws-cdk/aws-codeguruprofiler/package.json index e0ca94e657487..65ab5a7d206dc 100644 --- a/packages/@aws-cdk/aws-codeguruprofiler/package.json +++ b/packages/@aws-cdk/aws-codeguruprofiler/package.json @@ -86,7 +86,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/aws-iam": "0.0.0", diff --git a/packages/@aws-cdk/aws-codegurureviewer/package.json b/packages/@aws-cdk/aws-codegurureviewer/package.json index 6c72bd475e6ed..e0e2d1748e1ae 100644 --- a/packages/@aws-cdk/aws-codegurureviewer/package.json +++ b/packages/@aws-cdk/aws-codegurureviewer/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-codepipeline-actions/lib/cloudformation/private/singleton-policy.ts b/packages/@aws-cdk/aws-codepipeline-actions/lib/cloudformation/private/singleton-policy.ts index d015d40f4d03c..7a9a3efdde784 100644 --- a/packages/@aws-cdk/aws-codepipeline-actions/lib/cloudformation/private/singleton-policy.ts +++ b/packages/@aws-cdk/aws-codepipeline-actions/lib/cloudformation/private/singleton-policy.ts @@ -32,7 +32,7 @@ export class SingletonPolicy extends Construct implements iam.IGrantable { private statements: { [key: string]: iam.PolicyStatement } = {}; private constructor(private readonly role: iam.IRole) { - super(role as unknown as cdk.Construct, SingletonPolicy.UUID); + super(role as unknown as Construct, SingletonPolicy.UUID); this.grantPrincipal = role; } diff --git a/packages/@aws-cdk/aws-codepipeline-actions/package.json b/packages/@aws-cdk/aws-codepipeline-actions/package.json index 26bbb00b9905f..1bf26f89562e6 100644 --- a/packages/@aws-cdk/aws-codepipeline-actions/package.json +++ b/packages/@aws-cdk/aws-codepipeline-actions/package.json @@ -83,7 +83,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cx-api": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "@types/lodash": "^4.14.178", "jest": "^27.5.1", "lodash": "^4.17.21" diff --git a/packages/@aws-cdk/aws-codepipeline/package.json b/packages/@aws-cdk/aws-codepipeline/package.json index 9172b869a89ee..8d3f6978b445a 100644 --- a/packages/@aws-cdk/aws-codepipeline/package.json +++ b/packages/@aws-cdk/aws-codepipeline/package.json @@ -90,7 +90,7 @@ "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/cx-api": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-codestar/package.json b/packages/@aws-cdk/aws-codestar/package.json index a2ae9b1cbd339..478f09bef3b9d 100644 --- a/packages/@aws-cdk/aws-codestar/package.json +++ b/packages/@aws-cdk/aws-codestar/package.json @@ -86,7 +86,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/aws-s3": "0.0.0", diff --git a/packages/@aws-cdk/aws-codestarconnections/package.json b/packages/@aws-cdk/aws-codestarconnections/package.json index 9d06e3ea4db51..2e8cfc5deac99 100644 --- a/packages/@aws-cdk/aws-codestarconnections/package.json +++ b/packages/@aws-cdk/aws-codestarconnections/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-codestarnotifications/package.json b/packages/@aws-cdk/aws-codestarnotifications/package.json index e6d2bf301f3b4..5e181702720cf 100644 --- a/packages/@aws-cdk/aws-codestarnotifications/package.json +++ b/packages/@aws-cdk/aws-codestarnotifications/package.json @@ -86,7 +86,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-cognito-identitypool/package.json b/packages/@aws-cdk/aws-cognito-identitypool/package.json index d17fa7b5a2c14..19171391ad7be 100644 --- a/packages/@aws-cdk/aws-cognito-identitypool/package.json +++ b/packages/@aws-cdk/aws-cognito-identitypool/package.json @@ -81,7 +81,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-cognito/package.json b/packages/@aws-cdk/aws-cognito/package.json index 889fcda97db30..7f38517f6abae 100644 --- a/packages/@aws-cdk/aws-cognito/package.json +++ b/packages/@aws-cdk/aws-cognito/package.json @@ -84,7 +84,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "@types/punycode": "^2.1.0", "jest": "^27.5.1" }, diff --git a/packages/@aws-cdk/aws-config/package.json b/packages/@aws-cdk/aws-config/package.json index 14857198dea75..8a121a8927bd4 100644 --- a/packages/@aws-cdk/aws-config/package.json +++ b/packages/@aws-cdk/aws-config/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-connect/package.json b/packages/@aws-cdk/aws-connect/package.json index 0d413aaf0db47..e9d851b1824a9 100644 --- a/packages/@aws-cdk/aws-connect/package.json +++ b/packages/@aws-cdk/aws-connect/package.json @@ -87,7 +87,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-cur/package.json b/packages/@aws-cdk/aws-cur/package.json index c871e8b723bc9..00adc1d4d1602 100644 --- a/packages/@aws-cdk/aws-cur/package.json +++ b/packages/@aws-cdk/aws-cur/package.json @@ -87,7 +87,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-customerprofiles/package.json b/packages/@aws-cdk/aws-customerprofiles/package.json index e73bd86cba198..d9a6f1632efab 100644 --- a/packages/@aws-cdk/aws-customerprofiles/package.json +++ b/packages/@aws-cdk/aws-customerprofiles/package.json @@ -87,7 +87,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-databrew/package.json b/packages/@aws-cdk/aws-databrew/package.json index 66e42d3cd4e94..749abf6bab9b7 100644 --- a/packages/@aws-cdk/aws-databrew/package.json +++ b/packages/@aws-cdk/aws-databrew/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-datapipeline/package.json b/packages/@aws-cdk/aws-datapipeline/package.json index 0aff6f0f1389c..24d3144f7c33d 100644 --- a/packages/@aws-cdk/aws-datapipeline/package.json +++ b/packages/@aws-cdk/aws-datapipeline/package.json @@ -83,7 +83,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-datasync/package.json b/packages/@aws-cdk/aws-datasync/package.json index 1dc0061ea02ec..ff9c4cdd4699b 100644 --- a/packages/@aws-cdk/aws-datasync/package.json +++ b/packages/@aws-cdk/aws-datasync/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-dax/package.json b/packages/@aws-cdk/aws-dax/package.json index c00396c2220ae..2901f449cf06e 100644 --- a/packages/@aws-cdk/aws-dax/package.json +++ b/packages/@aws-cdk/aws-dax/package.json @@ -83,7 +83,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-detective/package.json b/packages/@aws-cdk/aws-detective/package.json index 2522e915d02b3..cc061a9a00648 100644 --- a/packages/@aws-cdk/aws-detective/package.json +++ b/packages/@aws-cdk/aws-detective/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-devopsguru/package.json b/packages/@aws-cdk/aws-devopsguru/package.json index 2082aba14cbd3..9937e175014f4 100644 --- a/packages/@aws-cdk/aws-devopsguru/package.json +++ b/packages/@aws-cdk/aws-devopsguru/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-directoryservice/package.json b/packages/@aws-cdk/aws-directoryservice/package.json index 7e32fa22bdfc5..4d37918cd7b3a 100644 --- a/packages/@aws-cdk/aws-directoryservice/package.json +++ b/packages/@aws-cdk/aws-directoryservice/package.json @@ -83,7 +83,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-dlm/package.json b/packages/@aws-cdk/aws-dlm/package.json index d59d69ba32dc5..f1601bd7cc135 100644 --- a/packages/@aws-cdk/aws-dlm/package.json +++ b/packages/@aws-cdk/aws-dlm/package.json @@ -84,7 +84,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-dms/package.json b/packages/@aws-cdk/aws-dms/package.json index 2c7da4b13bac7..3f20999bb1e0a 100644 --- a/packages/@aws-cdk/aws-dms/package.json +++ b/packages/@aws-cdk/aws-dms/package.json @@ -83,7 +83,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-docdb/package.json b/packages/@aws-cdk/aws-docdb/package.json index 4242c8e2a7622..02721228f2097 100644 --- a/packages/@aws-cdk/aws-docdb/package.json +++ b/packages/@aws-cdk/aws-docdb/package.json @@ -86,7 +86,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/aws-ec2": "0.0.0", diff --git a/packages/@aws-cdk/aws-dynamodb-global/package.json b/packages/@aws-cdk/aws-dynamodb-global/package.json index ccc610c15e2fb..5618565bc6119 100644 --- a/packages/@aws-cdk/aws-dynamodb-global/package.json +++ b/packages/@aws-cdk/aws-dynamodb-global/package.json @@ -67,7 +67,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "peerDependencies": { diff --git a/packages/@aws-cdk/aws-dynamodb/lib/perms.ts b/packages/@aws-cdk/aws-dynamodb/lib/perms.ts index af385e57209f5..29d240d245f75 100644 --- a/packages/@aws-cdk/aws-dynamodb/lib/perms.ts +++ b/packages/@aws-cdk/aws-dynamodb/lib/perms.ts @@ -29,3 +29,5 @@ export const READ_STREAM_DATA_ACTIONS = [ 'dynamodb:GetRecords', 'dynamodb:GetShardIterator', ]; + +export const DESCRIBE_TABLE = 'dynamodb:DescribeTable'; \ No newline at end of file diff --git a/packages/@aws-cdk/aws-dynamodb/lib/table.ts b/packages/@aws-cdk/aws-dynamodb/lib/table.ts index bc4b6ce39c9f0..00dca8dbe31e3 100644 --- a/packages/@aws-cdk/aws-dynamodb/lib/table.ts +++ b/packages/@aws-cdk/aws-dynamodb/lib/table.ts @@ -679,7 +679,7 @@ abstract class TableBase extends Resource implements ITable { /** * Permits an IAM principal all data read operations from this table: - * BatchGetItem, GetRecords, GetShardIterator, Query, GetItem, Scan. + * BatchGetItem, GetRecords, GetShardIterator, Query, GetItem, Scan, DescribeTable. * * Appropriate grants will also be added to the customer-managed KMS key * if one was configured. @@ -687,7 +687,8 @@ abstract class TableBase extends Resource implements ITable { * @param grantee The principal to grant access to */ public grantReadData(grantee: iam.IGrantable): iam.Grant { - return this.combinedGrant(grantee, { keyActions: perms.KEY_READ_ACTIONS, tableActions: perms.READ_DATA_ACTIONS }); + const tableActions = perms.READ_DATA_ACTIONS.concat(perms.DESCRIBE_TABLE); + return this.combinedGrant(grantee, { keyActions: perms.KEY_READ_ACTIONS, tableActions }); } /** @@ -724,7 +725,7 @@ abstract class TableBase extends Resource implements ITable { /** * Permits an IAM principal all data write operations to this table: - * BatchWriteItem, PutItem, UpdateItem, DeleteItem. + * BatchWriteItem, PutItem, UpdateItem, DeleteItem, DescribeTable. * * Appropriate grants will also be added to the customer-managed KMS key * if one was configured. @@ -732,13 +733,15 @@ abstract class TableBase extends Resource implements ITable { * @param grantee The principal to grant access to */ public grantWriteData(grantee: iam.IGrantable): iam.Grant { - return this.combinedGrant(grantee, { keyActions: perms.KEY_WRITE_ACTIONS, tableActions: perms.WRITE_DATA_ACTIONS }); + const tableActions = perms.WRITE_DATA_ACTIONS.concat(perms.DESCRIBE_TABLE); + const keyActions = perms.KEY_READ_ACTIONS.concat(perms.KEY_WRITE_ACTIONS); + return this.combinedGrant(grantee, { keyActions, tableActions }); } /** * Permits an IAM principal to all data read/write operations to this table. * BatchGetItem, GetRecords, GetShardIterator, Query, GetItem, Scan, - * BatchWriteItem, PutItem, UpdateItem, DeleteItem + * BatchWriteItem, PutItem, UpdateItem, DeleteItem, DescribeTable * * Appropriate grants will also be added to the customer-managed KMS key * if one was configured. @@ -746,7 +749,7 @@ abstract class TableBase extends Resource implements ITable { * @param grantee The principal to grant access to */ public grantReadWriteData(grantee: iam.IGrantable): iam.Grant { - const tableActions = perms.READ_DATA_ACTIONS.concat(perms.WRITE_DATA_ACTIONS); + const tableActions = perms.READ_DATA_ACTIONS.concat(perms.WRITE_DATA_ACTIONS).concat(perms.DESCRIBE_TABLE); const keyActions = perms.KEY_READ_ACTIONS.concat(perms.KEY_WRITE_ACTIONS); return this.combinedGrant(grantee, { keyActions, tableActions }); } diff --git a/packages/@aws-cdk/aws-dynamodb/package.json b/packages/@aws-cdk/aws-dynamodb/package.json index 0f6067d29fe8a..f058c3d573fff 100644 --- a/packages/@aws-cdk/aws-dynamodb/package.json +++ b/packages/@aws-cdk/aws-dynamodb/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", "@types/aws-lambda": "^8.10.92", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "@types/sinon": "^9.0.11", "aws-sdk": "^2.848.0", "aws-sdk-mock": "5.6.0", diff --git a/packages/@aws-cdk/aws-dynamodb/test/dynamodb.test.ts b/packages/@aws-cdk/aws-dynamodb/test/dynamodb.test.ts index 6ca8b3bd0cf65..cb564d875aea5 100644 --- a/packages/@aws-cdk/aws-dynamodb/test/dynamodb.test.ts +++ b/packages/@aws-cdk/aws-dynamodb/test/dynamodb.test.ts @@ -643,6 +643,7 @@ testLegacyBehavior('if an encryption key is included, encrypt/decrypt permission 'dynamodb:PutItem', 'dynamodb:UpdateItem', 'dynamodb:DeleteItem', + 'dynamodb:DescribeTable', ], Effect: 'Allow', Resource: [ @@ -720,6 +721,38 @@ test('if an encryption key is included, encrypt/decrypt permissions are added to }); }); +test('if an encryption key is included, encrypt/decrypt permissions are added to the principal for grantWriteData', () => { + const stack = new Stack(); + const table = new Table(stack, 'Table A', { + tableName: TABLE_NAME, + partitionKey: TABLE_PARTITION_KEY, + encryption: TableEncryption.CUSTOMER_MANAGED, + }); + const user = new iam.User(stack, 'MyUser'); + table.grantWriteData(user); + + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: Match.arrayWith([{ + Action: [ + 'kms:Decrypt', + 'kms:DescribeKey', + 'kms:Encrypt', + 'kms:ReEncrypt*', + 'kms:GenerateDataKey*', + ], + Effect: 'Allow', + Resource: { + 'Fn::GetAtt': [ + 'TableAKey07CC09EC', + 'Arn', + ], + }, + }]), + }, + }); +}); + test('when specifying STANDARD_INFREQUENT_ACCESS table class', () => { const stack = new Stack(); new Table(stack, CONSTRUCT_NAME, { @@ -1887,18 +1920,18 @@ describe('grants', () => { test('"grantReadData" allows the principal to read data from the table', () => { testGrant( - ['BatchGetItem', 'GetRecords', 'GetShardIterator', 'Query', 'GetItem', 'Scan', 'ConditionCheckItem'], (p, t) => t.grantReadData(p)); + ['BatchGetItem', 'GetRecords', 'GetShardIterator', 'Query', 'GetItem', 'Scan', 'ConditionCheckItem', 'DescribeTable'], (p, t) => t.grantReadData(p)); }); test('"grantWriteData" allows the principal to write data to the table', () => { testGrant( - ['BatchWriteItem', 'PutItem', 'UpdateItem', 'DeleteItem'], (p, t) => t.grantWriteData(p)); + ['BatchWriteItem', 'PutItem', 'UpdateItem', 'DeleteItem', 'DescribeTable'], (p, t) => t.grantWriteData(p)); }); test('"grantReadWriteData" allows the principal to read/write data', () => { testGrant([ 'BatchGetItem', 'GetRecords', 'GetShardIterator', 'Query', 'GetItem', 'Scan', - 'ConditionCheckItem', 'BatchWriteItem', 'PutItem', 'UpdateItem', 'DeleteItem', + 'ConditionCheckItem', 'BatchWriteItem', 'PutItem', 'UpdateItem', 'DeleteItem', 'DescribeTable', ], (p, t) => t.grantReadWriteData(p)); }); @@ -2060,6 +2093,7 @@ describe('grants', () => { 'dynamodb:GetItem', 'dynamodb:Scan', 'dynamodb:ConditionCheckItem', + 'dynamodb:DescribeTable', ], 'Effect': 'Allow', 'Resource': [ @@ -2212,6 +2246,7 @@ describe('import', () => { 'dynamodb:GetItem', 'dynamodb:Scan', 'dynamodb:ConditionCheckItem', + 'dynamodb:DescribeTable', ], 'Effect': 'Allow', 'Resource': [ @@ -2258,6 +2293,7 @@ describe('import', () => { 'dynamodb:PutItem', 'dynamodb:UpdateItem', 'dynamodb:DeleteItem', + 'dynamodb:DescribeTable', ], 'Effect': 'Allow', 'Resource': [ @@ -2400,6 +2436,7 @@ describe('import', () => { 'dynamodb:GetItem', 'dynamodb:Scan', 'dynamodb:ConditionCheckItem', + 'dynamodb:DescribeTable', ], Resource: [ { @@ -2574,6 +2611,7 @@ describe('global', () => { 'dynamodb:GetItem', 'dynamodb:Scan', 'dynamodb:ConditionCheckItem', + 'dynamodb:DescribeTable', ], Effect: 'Allow', Resource: [ @@ -2728,6 +2766,7 @@ describe('global', () => { 'dynamodb:GetItem', 'dynamodb:Scan', 'dynamodb:ConditionCheckItem', + 'dynamodb:DescribeTable', ], Effect: 'Allow', Resource: [ diff --git a/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.expected.json b/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.expected.json index d20e923f3d55e..9d33338172a7a 100644 --- a/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.expected.json +++ b/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.expected.json @@ -387,7 +387,8 @@ "dynamodb:Query", "dynamodb:GetItem", "dynamodb:Scan", - "dynamodb:ConditionCheckItem" + "dynamodb:ConditionCheckItem", + "dynamodb:DescribeTable" ], "Effect": "Allow", "Resource": [ @@ -410,7 +411,8 @@ "dynamodb:Query", "dynamodb:GetItem", "dynamodb:Scan", - "dynamodb:ConditionCheckItem" + "dynamodb:ConditionCheckItem", + "dynamodb:DescribeTable" ], "Effect": "Allow", "Resource": [ diff --git a/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.sse.expected.json b/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.sse.expected.json index 879532d0a8879..7c07d9a4339c9 100644 --- a/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.sse.expected.json +++ b/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.sse.expected.json @@ -497,7 +497,8 @@ "dynamodb:Query", "dynamodb:GetItem", "dynamodb:Scan", - "dynamodb:ConditionCheckItem" + "dynamodb:ConditionCheckItem", + "dynamodb:DescribeTable" ], "Effect": "Allow", "Resource": [ @@ -533,7 +534,8 @@ "dynamodb:Query", "dynamodb:GetItem", "dynamodb:Scan", - "dynamodb:ConditionCheckItem" + "dynamodb:ConditionCheckItem", + "dynamodb:DescribeTable" ], "Effect": "Allow", "Resource": [ diff --git a/packages/@aws-cdk/aws-ec2/README.md b/packages/@aws-cdk/aws-ec2/README.md index fb2db769617e7..af8c5ff64594e 100644 --- a/packages/@aws-cdk/aws-ec2/README.md +++ b/packages/@aws-cdk/aws-ec2/README.md @@ -601,6 +601,73 @@ const sg = ec2.SecurityGroup.fromLookupById(this, 'SecurityGroupLookup', 'sg-123 The result of `SecurityGroup.fromLookupByName` and `SecurityGroup.fromLookupById` operations will be written to a file called `cdk.context.json`. You must commit this file to source control so that the lookup values are available in non-privileged environments such as CI build steps, and to ensure your template builds are repeatable. +### Cross Stack Connections + +If you are attempting to add a connection from a peer in one stack to a peer in a different stack, sometimes it is necessary to ensure that you are making the connection in +a specific stack in order to avoid a cyclic reference. If there are no other dependencies between stacks then it will not matter in which stack you make +the connection, but if there are existing dependencies (i.e. stack1 already depends on stack2), then it is important to make the connection in the dependent stack (i.e. stack1). + +Whenever you make a `connections` function call, the ingress and egress security group rules will be added to the stack that the calling object exists in. +So if you are doing something like `peer1.connections.allowFrom(peer2)`, then the security group rules (both ingress and egress) will be created in `peer1`'s Stack. + +As an example, if we wanted to allow a connection from a security group in one stack (egress) to a security group in a different stack (ingress), +we would make the connection like: + +**If Stack1 depends on Stack2** + +```ts fixture=with-vpc +// Stack 1 +declare const stack1: Stack; +declare const stack2: Stack; + +const sg1 = new ec2.SecurityGroup(stack1, 'SG1', { + allowAllOutbound: false, // if this is `true` then no egress rule will be created + vpc, +}); + +// Stack 2 +const sg2 = new ec2.SecurityGroup(stack2, 'SG2', { + allowAllOutbound: false, // if this is `true` then no egress rule will be created + vpc, +}); + + +// `connections.allowTo` on `sg1` since we want the +// rules to be created in Stack1 +sg1.connections.allowTo(sg2, ec2.Port.tcp(3333)); +``` + +In this case both the Ingress Rule for `sg2` and the Egress Rule for `sg1` will both be created +in `Stack 1` which avoids the cyclic reference. + + +**If Stack2 depends on Stack1** + +```ts fixture=with-vpc +// Stack 1 +declare const stack1: Stack; +declare const stack2: Stack; + +const sg1 = new ec2.SecurityGroup(stack1, 'SG1', { + allowAllOutbound: false, // if this is `true` then no egress rule will be created + vpc, +}); + +// Stack 2 +const sg2 = new ec2.SecurityGroup(stack2, 'SG2', { + allowAllOutbound: false, // if this is `true` then no egress rule will be created + vpc, +}); + + +// `connections.allowFrom` on `sg2` since we want the +// rules to be created in Stack2 +sg2.connections.allowFrom(sg1, ec2.Port.tcp(3333)); +``` + +In this case both the Ingress Rule for `sg2` and the Egress Rule for `sg1` will both be created +in `Stack 2` which avoids the cyclic reference. + ## Machine Images (AMIs) AMIs control the OS that gets launched when you start your EC2 instance. The EC2 @@ -663,7 +730,7 @@ vpc.addVpnConnection('Dynamic', { ``` By default, routes will be propagated on the route tables associated with the private subnets. If no -private subnets exists, isolated subnets are used. If no isolated subnets exists, public subnets are +private subnets exist, isolated subnets are used. If no isolated subnets exist, public subnets are used. Use the `Vpc` property `vpnRoutePropagation` to customize this behavior. VPN connections expose [metrics (cloudwatch.Metric)](https://github.com/aws/aws-cdk/blob/master/packages/%40aws-cdk/aws-cloudwatch/README.md) across all tunnels in the account/region and per connection: @@ -810,7 +877,7 @@ The endpoint must use at least one [authentication method](https://docs.aws.amaz If user-based authentication is used, the [self-service portal URL](https://docs.aws.amazon.com/vpn/latest/clientvpn-user/self-service-portal.html) is made available via a CloudFormation output. -By default, a new security group is created and logging is enabled. Moreover, a rule to +By default, a new security group is created, and logging is enabled. Moreover, a rule to authorize all users to the VPC CIDR is created. To customize authorization rules, set the `authorizeAllUsersToVpcCidr` prop to `false` @@ -898,7 +965,7 @@ new ec2.Instance(this, 'Instance4', { CloudFormation Init allows you to configure your instances by writing files to them, installing software packages, starting services and running arbitrary commands. By default, if any of the instance setup -commands throw an error, the deployment will fail and roll back to the previously known good state. +commands throw an error; the deployment will fail and roll back to the previously known good state. The following documentation also applies to `AutoScalingGroup`s. For the full set of capabilities of this system, see the documentation for @@ -1201,7 +1268,7 @@ Aspects.of(this).add(aspect); VPC Flow Logs is a feature that enables you to capture information about the IP traffic going to and from network interfaces in your VPC. Flow log data can be published to Amazon CloudWatch Logs and Amazon S3. After you've created a flow log, you can retrieve and view its data in the chosen destination. (). -By default a flow log will be created with CloudWatch Logs as the destination. +By default, a flow log will be created with CloudWatch Logs as the destination. You can create a flow log like this: @@ -1235,7 +1302,7 @@ vpc.addFlowLog('FlowLogCloudWatch', { }); ``` -By default the CDK will create the necessary resources for the destination. For the CloudWatch Logs destination +By default, the CDK will create the necessary resources for the destination. For the CloudWatch Logs destination it will create a CloudWatch Logs Log Group as well as the IAM role with the necessary permissions to publish to the log group. In the case of an S3 destination, it will create the S3 bucket. @@ -1311,9 +1378,9 @@ from separate parts forming archive. The most common parts are scripts executed kinds, too. The advantage of multipart archive is in flexibility when it's needed to add additional parts or to use specialized parts to -fine tune instance startup. Some services (like AWS Batch) supports only `MultipartUserData`. +fine tune instance startup. Some services (like AWS Batch) support only `MultipartUserData`. -The parts can be executed at different moment of instance start-up and can serve a different purposes. This is controlled by `contentType` property. +The parts can be executed at different moment of instance start-up and can serve a different purpose. This is controlled by `contentType` property. For common scripts, `text/x-shellscript; charset="utf-8"` can be used as content type. In order to create archive the `MultipartUserData` has to be instantiated. Than, user can add parts to multipart archive using `addPart`. The `MultipartBody` contains methods supporting creation of body parts. diff --git a/packages/@aws-cdk/aws-ec2/lib/instance-types.ts b/packages/@aws-cdk/aws-ec2/lib/instance-types.ts index cf82f9b8e40a5..323af5d58a690 100644 --- a/packages/@aws-cdk/aws-ec2/lib/instance-types.ts +++ b/packages/@aws-cdk/aws-ec2/lib/instance-types.ts @@ -298,16 +298,6 @@ export enum InstanceClass { */ C5 = 'c5', - /** - * Compute optimized instances, 6th generation - */ - COMPUTE6_INTEL = 'c6i', - - /** - * Compute optimized instances, 6th generation - */ - C6I = 'c6i', - /** * Compute optimized instances with local NVME drive, 5th generation */ @@ -319,7 +309,7 @@ export enum InstanceClass { C5D = 'c5d', /** - * Compute optimized instances based on AMD EPYC, 5th generation. + * Compute optimized instances based on AMD EPYC, 5th generation */ COMPUTE5_AMD = 'c5a', @@ -329,12 +319,12 @@ export enum InstanceClass { C5A = 'c5a', /** - * Compute optimized instances with local NVME drive based on AMD EPYC, 5th generation. + * Compute optimized instances with local NVME drive based on AMD EPYC, 5th generation */ COMPUTE5_AMD_NVME_DRIVE = 'c5ad', /** - * Compute optimized instances with local NVME drive based on AMD EPYC, 5th generation. + * Compute optimized instances with local NVME drive based on AMD EPYC, 5th generation */ C5AD = 'c5ad', @@ -348,6 +338,26 @@ export enum InstanceClass { */ C5N = 'c5n', + /** + * Compute optimized instances, 6th generation + */ + COMPUTE6_INTEL = 'c6i', + + /** + * Compute optimized instances, 6th generation + */ + C6I = 'c6i', + + /** + * Compute optimized instances based on AMD EPYC (codename Milan), 6th generation + */ + COMPUTE6_AMD = 'c6a', + + /** + * Compute optimized instances based on AMD EPYC (codename Milan), 6th generation + */ + C6A = 'c6a', + /** * Compute optimized instances for high performance computing, 6th generation with Graviton2 processors */ diff --git a/packages/@aws-cdk/aws-ec2/lib/private/ebs-util.ts b/packages/@aws-cdk/aws-ec2/lib/private/ebs-util.ts index 52c7738afdbef..d66dc01f31398 100644 --- a/packages/@aws-cdk/aws-ec2/lib/private/ebs-util.ts +++ b/packages/@aws-cdk/aws-ec2/lib/private/ebs-util.ts @@ -31,11 +31,11 @@ function synthesizeBlockDeviceMappings(construct: Construct, blockDevic const { iops, volumeType, kmsKey, ...rest } = ebs; if (!iops) { - if (volumeType === EbsDeviceVolumeType.IO1) { - throw new Error('iops property is required with volumeType: EbsDeviceVolumeType.IO1'); + if (volumeType === EbsDeviceVolumeType.IO1 || volumeType === EbsDeviceVolumeType.IO2) { + throw new Error('iops property is required with volumeType: EbsDeviceVolumeType.IO1 and EbsDeviceVolumeType.IO2'); } - } else if (volumeType !== EbsDeviceVolumeType.IO1) { - Annotations.of(construct).addWarning('iops will be ignored without volumeType: EbsDeviceVolumeType.IO1'); + } else if (volumeType !== EbsDeviceVolumeType.IO1 && volumeType !== EbsDeviceVolumeType.IO2 && volumeType !== EbsDeviceVolumeType.GP3) { + Annotations.of(construct).addWarning('iops will be ignored without volumeType: IO1, IO2, or GP3'); } /** diff --git a/packages/@aws-cdk/aws-ec2/lib/vpc.ts b/packages/@aws-cdk/aws-ec2/lib/vpc.ts index 8c8d6795fa23c..741a6ceba4f07 100644 --- a/packages/@aws-cdk/aws-ec2/lib/vpc.ts +++ b/packages/@aws-cdk/aws-ec2/lib/vpc.ts @@ -2222,6 +2222,24 @@ const DUMMY_VPC_PROPS: cxapi.VpcContextResponse = { }, ], }, + { + name: 'Isolated', + type: cxapi.VpcSubnetGroupType.ISOLATED, + subnets: [ + { + availabilityZone: 'dummy1a', + subnetId: 'p-12345', + routeTableId: 'rtb-12345p', + cidr: '1.2.3.4/5', + }, + { + availabilityZone: 'dummy1b', + subnetId: 'p-67890', + routeTableId: 'rtb-57890p', + cidr: '1.2.3.4/5', + }, + ], + }, ], vpcId: 'vpc-12345', }; diff --git a/packages/@aws-cdk/aws-ec2/package.json b/packages/@aws-cdk/aws-ec2/package.json index 28e2500a32292..a874249bf5736 100644 --- a/packages/@aws-cdk/aws-ec2/package.json +++ b/packages/@aws-cdk/aws-ec2/package.json @@ -87,7 +87,7 @@ "@aws-cdk/cx-api": "0.0.0", "@aws-cdk/pkglint": "0.0.0", "@types/aws-lambda": "^8.10.92", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-ec2/test/instance.test.ts b/packages/@aws-cdk/aws-ec2/test/instance.test.ts index 7f40cd8f202a0..3c945a84d342b 100644 --- a/packages/@aws-cdk/aws-ec2/test/instance.test.ts +++ b/packages/@aws-cdk/aws-ec2/test/instance.test.ts @@ -199,6 +199,15 @@ describe('instance', () => { volumeType: EbsDeviceVolumeType.IO1, iops: 5000, }), + }, { + deviceName: 'ebs-gp3', + mappingEnabled: true, + volume: BlockDeviceVolume.ebs(15, { + deleteOnTermination: true, + encrypted: true, + volumeType: EbsDeviceVolumeType.GP3, + iops: 5000, + }), }, { deviceName: 'ebs-cmk', mappingEnabled: true, @@ -236,6 +245,16 @@ describe('instance', () => { VolumeType: 'io1', }, }, + { + DeviceName: 'ebs-gp3', + Ebs: { + DeleteOnTermination: true, + Encrypted: true, + Iops: 5000, + VolumeSize: 15, + VolumeType: 'gp3', + }, + }, { DeviceName: 'ebs-cmk', Ebs: { @@ -306,8 +325,25 @@ describe('instance', () => { }], }); }).toThrow(/ops property is required with volumeType: EbsDeviceVolumeType.IO1/); + }); - + test('throws if volumeType === IO2 without iops', () => { + // THEN + expect(() => { + new Instance(stack, 'Instance', { + vpc, + machineImage: new AmazonLinuxImage(), + instanceType: InstanceType.of(InstanceClass.T3, InstanceSize.LARGE), + blockDevices: [{ + deviceName: 'ebs', + volume: BlockDeviceVolume.ebs(15, { + deleteOnTermination: true, + encrypted: true, + volumeType: EbsDeviceVolumeType.IO2, + }), + }], + }); + }).toThrow(/ops property is required with volumeType: EbsDeviceVolumeType.IO1 and EbsDeviceVolumeType.IO2/); }); test('warning if iops without volumeType', () => { @@ -327,12 +363,10 @@ describe('instance', () => { // THEN expect(instance.node.metadataEntry[0].type).toEqual(cxschema.ArtifactMetadataEntryType.WARN); - expect(instance.node.metadataEntry[0].data).toEqual('iops will be ignored without volumeType: EbsDeviceVolumeType.IO1'); - - + expect(instance.node.metadataEntry[0].data).toEqual('iops will be ignored without volumeType: IO1, IO2, or GP3'); }); - test('warning if iops and volumeType !== IO1', () => { + test('warning if iops and invalid volumeType', () => { const instance = new Instance(stack, 'Instance', { vpc, machineImage: new AmazonLinuxImage(), @@ -350,9 +384,7 @@ describe('instance', () => { // THEN expect(instance.node.metadataEntry[0].type).toEqual(cxschema.ArtifactMetadataEntryType.WARN); - expect(instance.node.metadataEntry[0].data).toEqual('iops will be ignored without volumeType: EbsDeviceVolumeType.IO1'); - - + expect(instance.node.metadataEntry[0].data).toEqual('iops will be ignored without volumeType: IO1, IO2, or GP3'); }); }); diff --git a/packages/@aws-cdk/aws-ecr-assets/package.json b/packages/@aws-cdk/aws-ecr-assets/package.json index f8286a488a1fc..75fb178adb95a 100644 --- a/packages/@aws-cdk/aws-ecr-assets/package.json +++ b/packages/@aws-cdk/aws-ecr-assets/package.json @@ -77,7 +77,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cloud-assembly-schema": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "@types/proxyquire": "^1.3.28", "aws-cdk": "0.0.0", "jest": "^27.5.1", diff --git a/packages/@aws-cdk/aws-ecr/package.json b/packages/@aws-cdk/aws-ecr/package.json index 3141f0c8dc6d1..ae13302f8642e 100644 --- a/packages/@aws-cdk/aws-ecr/package.json +++ b/packages/@aws-cdk/aws-ecr/package.json @@ -88,7 +88,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/aws-events": "0.0.0", diff --git a/packages/@aws-cdk/aws-ecs-patterns/package.json b/packages/@aws-cdk/aws-ecs-patterns/package.json index f4b65d4f204be..72d98e55f86d1 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/package.json +++ b/packages/@aws-cdk/aws-ecs-patterns/package.json @@ -77,7 +77,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-ecs/README.md b/packages/@aws-cdk/aws-ecs/README.md index d99b830aad6dd..d0d091eda612e 100644 --- a/packages/@aws-cdk/aws-ecs/README.md +++ b/packages/@aws-cdk/aws-ecs/README.md @@ -427,6 +427,7 @@ const newContainer = taskDefinition.addContainer('container', { secrets: { // Retrieved from AWS Secrets Manager or AWS Systems Manager Parameter Store at container start-up. SECRET: ecs.Secret.fromSecretsManager(secret), DB_PASSWORD: ecs.Secret.fromSecretsManager(dbSecret, 'password'), // Reference a specific JSON field, (requires platform version 1.4.0 or later for Fargate tasks) + API_KEY: ecs.Secret.fromSecretsManagerVersion(secret, { versionId: '12345' }, 'apiKey'), // Reference a specific version of the secret by its version id or version stage (requires platform version 1.4.0 or later for Fargate tasks) PARAMETER: ecs.Secret.fromSsmParameter(parameter), }, }); diff --git a/packages/@aws-cdk/aws-ecs/lib/container-definition.ts b/packages/@aws-cdk/aws-ecs/lib/container-definition.ts index b46e66df585fa..0ee433ff951e7 100644 --- a/packages/@aws-cdk/aws-ecs/lib/container-definition.ts +++ b/packages/@aws-cdk/aws-ecs/lib/container-definition.ts @@ -14,6 +14,24 @@ import { LogDriver, LogDriverConfig } from './log-drivers/log-driver'; // eslint-disable-next-line no-duplicate-imports, import/order import { Construct as CoreConstruct } from '@aws-cdk/core'; +/** + * Specify the secret's version id or version stage + */ +export interface SecretVersionInfo { + /** + * version id of the secret + * + * @default - use default version id + */ + readonly versionId?: string; + /** + * version stage of the secret + * + * @default - use default version stage + */ + readonly versionStage?: string; +} + /** * A secret environment variable. */ @@ -47,6 +65,25 @@ export abstract class Secret { }; } + /** + * Creates a environment variable value from a secret stored in AWS Secrets + * Manager. + * + * @param secret the secret stored in AWS Secrets Manager + * @param versionInfo the version information to reference the secret + * @param field the name of the field with the value that you want to set as + * the environment variable value. Only values in JSON format are supported. + * If you do not specify a JSON field, then the full content of the secret is + * used. + */ + public static fromSecretsManagerVersion(secret: secretsmanager.ISecret, versionInfo: SecretVersionInfo, field?: string): Secret { + return { + arn: `${secret.secretArn}:${field ?? ''}:${versionInfo.versionStage ?? ''}:${versionInfo.versionId ?? ''}`, + hasField: !!field, + grantRead: grantee => secret.grantRead(grantee), + }; + } + /** * The ARN of the secret */ diff --git a/packages/@aws-cdk/aws-ecs/package.json b/packages/@aws-cdk/aws-ecs/package.json index 9eafbc50b4833..931a7d1b4ae1b 100644 --- a/packages/@aws-cdk/aws-ecs/package.json +++ b/packages/@aws-cdk/aws-ecs/package.json @@ -86,7 +86,7 @@ "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/cx-api": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "@types/proxyquire": "^1.3.28", "jest": "^27.5.1", "proxyquire": "^2.1.3" diff --git a/packages/@aws-cdk/aws-ecs/test/container-definition.test.ts b/packages/@aws-cdk/aws-ecs/test/container-definition.test.ts index 7bee00a722c40..1aed207c1cdd5 100644 --- a/packages/@aws-cdk/aws-ecs/test/container-definition.test.ts +++ b/packages/@aws-cdk/aws-ecs/test/container-definition.test.ts @@ -1261,6 +1261,8 @@ describe('container definition', () => { secrets: { SECRET: ecs.Secret.fromSecretsManager(secret), PARAMETER: ecs.Secret.fromSsmParameter(parameter), + SECRET_ID: ecs.Secret.fromSecretsManagerVersion(secret, { versionId: 'version-id' }), + SECRET_STAGE: ecs.Secret.fromSecretsManagerVersion(secret, { versionStage: 'version-stage' }), }, }); @@ -1298,6 +1300,34 @@ describe('container definition', () => { ], }, }, + { + Name: 'SECRET_ID', + ValueFrom: { + 'Fn::Join': [ + '', + [ + { + Ref: 'SecretA720EF05', + }, + ':::version-id', + ], + ], + }, + }, + { + Name: 'SECRET_STAGE', + ValueFrom: { + 'Fn::Join': [ + '', + [ + { + Ref: 'SecretA720EF05', + }, + '::version-stage:', + ], + ], + }, + }, ], }), ], @@ -1405,6 +1435,8 @@ describe('container definition', () => { memoryLimitMiB: 1024, secrets: { SECRET_KEY: ecs.Secret.fromSecretsManager(secret, 'specificKey'), + SECRET_KEY_ID: ecs.Secret.fromSecretsManagerVersion(secret, { versionId: 'version-id' }, 'specificKey'), + SECRET_KEY_STAGE: ecs.Secret.fromSecretsManagerVersion(secret, { versionStage: 'version-stage' }, 'specificKey'), }, }); @@ -1427,6 +1459,34 @@ describe('container definition', () => { ], }, }, + { + Name: 'SECRET_KEY_ID', + ValueFrom: { + 'Fn::Join': [ + '', + [ + { + Ref: 'SecretA720EF05', + }, + ':specificKey::version-id', + ], + ], + }, + }, + { + Name: 'SECRET_KEY_STAGE', + ValueFrom: { + 'Fn::Join': [ + '', + [ + { + Ref: 'SecretA720EF05', + }, + ':specificKey:version-stage:', + ], + ], + }, + }, ], }), ], diff --git a/packages/@aws-cdk/aws-efs/lib/efs-file-system.ts b/packages/@aws-cdk/aws-efs/lib/efs-file-system.ts index 9abe09c49e8a2..59344e3b81692 100644 --- a/packages/@aws-cdk/aws-efs/lib/efs-file-system.ts +++ b/packages/@aws-cdk/aws-efs/lib/efs-file-system.ts @@ -341,15 +341,21 @@ export class FileSystem extends FileSystemBase { const encrypted = props.encrypted ?? (FeatureFlags.of(this).isEnabled( cxapi.EFS_DEFAULT_ENCRYPTION_AT_REST) ? true : undefined); + // LifecyclePolicies is an array of lists containing a single policy + let lifecyclePolicies = []; + + if (props.lifecyclePolicy) { + lifecyclePolicies.push({ transitionToIa: props.lifecyclePolicy }); + } + + if (props.outOfInfrequentAccessPolicy) { + lifecyclePolicies.push({ transitionToPrimaryStorageClass: props.outOfInfrequentAccessPolicy }); + } + const filesystem = new CfnFileSystem(this, 'Resource', { encrypted: encrypted, kmsKeyId: props.kmsKey?.keyArn, - lifecyclePolicies: ( - (props.lifecyclePolicy || props.outOfInfrequentAccessPolicy) ? - [{ - transitionToIa: props.lifecyclePolicy, - transitionToPrimaryStorageClass: props.outOfInfrequentAccessPolicy, - }] : undefined), + lifecyclePolicies: lifecyclePolicies.length > 0 ? lifecyclePolicies : undefined, performanceMode: props.performanceMode, throughputMode: props.throughputMode, provisionedThroughputInMibps: props.provisionedThroughputPerSecond?.toMebibytes(), diff --git a/packages/@aws-cdk/aws-efs/package.json b/packages/@aws-cdk/aws-efs/package.json index 09d1c1f6f2ca6..73151d18d3aff 100644 --- a/packages/@aws-cdk/aws-efs/package.json +++ b/packages/@aws-cdk/aws-efs/package.json @@ -84,7 +84,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/aws-ec2": "0.0.0", diff --git a/packages/@aws-cdk/aws-efs/test/efs-file-system.test.ts b/packages/@aws-cdk/aws-efs/test/efs-file-system.test.ts index 7e22cd7602472..f6eb888575078 100644 --- a/packages/@aws-cdk/aws-efs/test/efs-file-system.test.ts +++ b/packages/@aws-cdk/aws-efs/test/efs-file-system.test.ts @@ -137,10 +137,14 @@ test('file system is created correctly with a life cycle property and out of inf }); // THEN Template.fromStack(stack).hasResourceProperties('AWS::EFS::FileSystem', { - LifecyclePolicies: [{ - TransitionToIA: 'AFTER_7_DAYS', - TransitionToPrimaryStorageClass: 'AFTER_1_ACCESS', - }], + LifecyclePolicies: [ + { + TransitionToIA: 'AFTER_7_DAYS', + }, + { + TransitionToPrimaryStorageClass: 'AFTER_1_ACCESS', + }, + ], }); }); diff --git a/packages/@aws-cdk/aws-eks-legacy/package.json b/packages/@aws-cdk/aws-eks-legacy/package.json index 0ce369f8479fe..ede28f6869cdf 100644 --- a/packages/@aws-cdk/aws-eks-legacy/package.json +++ b/packages/@aws-cdk/aws-eks-legacy/package.json @@ -82,7 +82,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-eks/README.md b/packages/@aws-cdk/aws-eks/README.md index 668c70fd96d98..001a2cbb3022a 100644 --- a/packages/@aws-cdk/aws-eks/README.md +++ b/packages/@aws-cdk/aws-eks/README.md @@ -1144,6 +1144,24 @@ cluster.addHelmChart('test-chart', { }); ``` +### OCI Charts + +OCI charts are also supported. +Also replace the `${VARS}` with appropriate values. + +```ts +declare const cluster: eks.Cluster; +// option 1: use a construct +new eks.HelmChart(this, 'MyOCIChart', { + cluster, + chart: 'some-chart', + repository: 'oci://${ACCOUNT_ID}.dkr.ecr.${ACCOUNT_REGION}.amazonaws.com/${REPO_NAME}', + namespace: 'oci', + version: '0.0.1' +}); + +``` + Helm charts are implemented as CloudFormation resources in CDK. This means that if the chart is deleted from your code (or the stack is deleted), the next `cdk deploy` will issue a `helm uninstall` command and the diff --git a/packages/@aws-cdk/aws-eks/lib/cluster.ts b/packages/@aws-cdk/aws-eks/lib/cluster.ts index f4449ff30e9a8..66821aed579e9 100644 --- a/packages/@aws-cdk/aws-eks/lib/cluster.ts +++ b/packages/@aws-cdk/aws-eks/lib/cluster.ts @@ -946,7 +946,7 @@ abstract class ClusterBase extends Resource implements ICluster { if (!this._spotInterruptHandler) { this._spotInterruptHandler = this.addHelmChart('spot-interrupt-handler', { chart: 'aws-node-termination-handler', - version: '0.13.2', + version: '1.14.1', repository: 'https://aws.github.io/eks-charts', namespace: 'kube-system', values: { diff --git a/packages/@aws-cdk/aws-eks/lib/kubectl-handler/helm/__init__.py b/packages/@aws-cdk/aws-eks/lib/kubectl-handler/helm/__init__.py index f83fc204b73e3..8ede6a23a07e8 100644 --- a/packages/@aws-cdk/aws-eks/lib/kubectl-handler/helm/__init__.py +++ b/packages/@aws-cdk/aws-eks/lib/kubectl-handler/helm/__init__.py @@ -1,8 +1,10 @@ import json import logging import os +import re import subprocess import shutil +import tempfile import zipfile from urllib.parse import urlparse, unquote @@ -78,6 +80,11 @@ def helm_handler(event, context): # future work: support versions from s3 assets chart = get_chart_asset_from_url(chart_asset_url) + if repository is not None and repository.startswith('oci://'): + tmpdir = tempfile.TemporaryDirectory() + chart_dir = get_chart_from_oci(tmpdir.name, release, repository, version) + chart = chart_dir + helm('upgrade', release, chart, repository, values_file, namespace, version, wait, timeout, create_namespace) elif request_type == "Delete": try: @@ -85,6 +92,58 @@ def helm_handler(event, context): except Exception as e: logger.info("delete error: %s" % e) + +def get_oci_cmd(repository, version): + + cmnd = [] + pattern = '\d+.dkr.ecr.[a-z]+-[a-z]+-\d.amazonaws.com' + + registry = repository.rsplit('/', 1)[0].replace('oci://', '') + + if re.fullmatch(pattern, registry) is not None: + region = registry.replace('.amazonaws.com', '').split('.')[-1] + cmnd = [ + f"aws ecr get-login-password --region {region} | " \ + f"helm registry login --username AWS --password-stdin {registry}; helm pull {repository} --version {version} --untar" + ] + else: + logger.info("Non AWS OCI repository found") + cmnd = ['HELM_EXPERIMENTAL_OCI=1', 'helm', 'pull', repository, '--version', version, '--untar'] + + return cmnd + + +def get_chart_from_oci(tmpdir, release, repository = None, version = None): + + cmnd = get_oci_cmd(repository, version) + + maxAttempts = 3 + retry = maxAttempts + while retry > 0: + try: + logger.info(cmnd) + env = get_env_with_oci_flag() + output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=tmpdir, env=env, shell=True) + logger.info(output) + + return os.path.join(tmpdir, release) + except subprocess.CalledProcessError as exc: + output = exc.output + if b'Broken pipe' in output: + retry = retry - 1 + logger.info("Broken pipe, retries left: %s" % retry) + else: + raise Exception(output) + raise Exception(f'Operation failed after {maxAttempts} attempts: {output}') + + +def get_env_with_oci_flag(): + env = os.environ.copy() + env['HELM_EXPERIMENTAL_OCI'] = '1' + + return env + + def helm(verb, release, chart = None, repo = None, file = None, namespace = None, version = None, wait = False, timeout = None, create_namespace = None): import subprocess @@ -113,7 +172,8 @@ def helm(verb, release, chart = None, repo = None, file = None, namespace = None retry = maxAttempts while retry > 0: try: - output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=outdir) + env = get_env_with_oci_flag() + output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=outdir, env=env) logger.info(output) return except subprocess.CalledProcessError as exc: diff --git a/packages/@aws-cdk/aws-eks/lib/kubectl-provider.ts b/packages/@aws-cdk/aws-eks/lib/kubectl-provider.ts index 161ef77cfe3f3..eef07598abf27 100644 --- a/packages/@aws-cdk/aws-eks/lib/kubectl-provider.ts +++ b/packages/@aws-cdk/aws-eks/lib/kubectl-provider.ts @@ -168,6 +168,11 @@ export class KubectlProvider extends NestedStack implements IKubectlProvider { resources: [cluster.clusterArn], })); + // For OCI helm chart authorization. + this.handlerRole.addManagedPolicy( + iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonEC2ContainerRegistryReadOnly'), + ); + // allow this handler to assume the kubectl role cluster.kubectlRole.grant(this.handlerRole, 'sts:AssumeRole'); diff --git a/packages/@aws-cdk/aws-eks/lib/service-account.ts b/packages/@aws-cdk/aws-eks/lib/service-account.ts index c49e2a944a765..a330aa41e0df5 100644 --- a/packages/@aws-cdk/aws-eks/lib/service-account.ts +++ b/packages/@aws-cdk/aws-eks/lib/service-account.ts @@ -14,12 +14,18 @@ import { Construct as CoreConstruct } from '@aws-cdk/core'; export interface ServiceAccountOptions { /** * The name of the service account. + * + * The name of a ServiceAccount object must be a valid DNS subdomain name. + * https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ * @default - If no name is given, it will use the id of the resource. */ readonly name?: string; /** * The namespace of the service account. + * + * All namespace names must be valid RFC 1123 DNS labels. + * https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/#namespaces-and-dns * @default "default" */ readonly namespace?: string; @@ -65,6 +71,16 @@ export class ServiceAccount extends CoreConstruct implements IPrincipal { this.serviceAccountName = props.name ?? Names.uniqueId(this).toLowerCase(); this.serviceAccountNamespace = props.namespace ?? 'default'; + // From K8s docs: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ + if (!this.isValidDnsSubdomainName(this.serviceAccountName)) { + throw RangeError('The name of a ServiceAccount object must be a valid DNS subdomain name.'); + } + + // From K8s docs: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/#namespaces-and-dns + if (!this.isValidDnsLabelName(this.serviceAccountNamespace)) { + throw RangeError('All namespace names must be valid RFC 1123 DNS labels.'); + } + /* Add conditions to the role to improve security. This prevents other pods in the same namespace to assume the role. * See documentation: https://docs.aws.amazon.com/eks/latest/userguide/create-service-account-iam-policy-and-role.html */ @@ -117,4 +133,22 @@ export class ServiceAccount extends CoreConstruct implements IPrincipal { public addToPrincipalPolicy(statement: PolicyStatement): AddToPrincipalPolicyResult { return this.role.addToPrincipalPolicy(statement); } + + /** + * If the value is a DNS subdomain name as defined in RFC 1123, from K8s docs. + * + * https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#dns-subdomain-names + */ + private isValidDnsSubdomainName(value: string): boolean { + return value.length <= 253 && /^[a-z0-9]+[a-z0-9-.]*[a-z0-9]+$/.test(value); + } + + /** + * If the value follows DNS label standard as defined in RFC 1123, from K8s docs. + * + * https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#dns-label-names + */ + private isValidDnsLabelName(value: string): boolean { + return value.length <= 63 && /^[a-z0-9]+[a-z0-9-]*[a-z0-9]+$/.test(value); + } } diff --git a/packages/@aws-cdk/aws-eks/package.json b/packages/@aws-cdk/aws-eks/package.json index 56fd7729350a3..c20951c1559ac 100644 --- a/packages/@aws-cdk/aws-eks/package.json +++ b/packages/@aws-cdk/aws-eks/package.json @@ -85,12 +85,12 @@ "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", "@types/aws-lambda": "^8.10.92", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "@types/sinon": "^9.0.11", "@types/yaml": "1.9.6", "aws-sdk": "^2.848.0", - "cdk8s": "^1.5.17", - "cdk8s-plus-21": "^1.0.0-beta.84", + "cdk8s": "^1.5.24", + "cdk8s-plus-21": "^1.0.0-beta.90", "jest": "^27.5.1", "sinon": "^9.2.4" }, diff --git a/packages/@aws-cdk/aws-eks/test/cluster.test.ts b/packages/@aws-cdk/aws-eks/test/cluster.test.ts index 77556af1a0da4..5e579c4f2a247 100644 --- a/packages/@aws-cdk/aws-eks/test/cluster.test.ts +++ b/packages/@aws-cdk/aws-eks/test/cluster.test.ts @@ -2107,7 +2107,41 @@ describe('cluster', () => { ], }); - + Template.fromStack(providerStack).hasResourceProperties('AWS::IAM::Role', { + AssumeRolePolicyDocument: { + Statement: [ + { + Action: 'sts:AssumeRole', + Effect: 'Allow', + Principal: { Service: 'lambda.amazonaws.com' }, + }, + ], + Version: '2012-10-17', + }, + ManagedPolicyArns: [ + { + 'Fn::Join': ['', [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':iam::aws:policy/service-role/AWSLambdaBasicExecutionRole', + ]], + }, + { + 'Fn::Join': ['', [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole', + ]], + }, + { + 'Fn::Join': ['', [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':iam::aws:policy/AmazonEC2ContainerRegistryReadOnly', + ]], + }, + ], + }); }); test('coreDnsComputeType will patch the coreDNS configuration to use a "fargate" compute type and restore to "ec2" upon removal', () => { @@ -2274,8 +2308,42 @@ describe('cluster', () => { }, }); + Template.fromStack(providerStack).hasResourceProperties('AWS::IAM::Role', { + AssumeRolePolicyDocument: { + Statement: [ + { + Action: 'sts:AssumeRole', + Effect: 'Allow', + Principal: { Service: 'lambda.amazonaws.com' }, + }, + ], + Version: '2012-10-17', + }, + ManagedPolicyArns: [ + { + 'Fn::Join': ['', [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':iam::aws:policy/service-role/AWSLambdaBasicExecutionRole', + ]], + }, + { + 'Fn::Join': ['', [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole', + ]], + }, + { + 'Fn::Join': ['', [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':iam::aws:policy/AmazonEC2ContainerRegistryReadOnly', + ]], + }, + ], + }); }); - }); test('kubectl provider passes security group to provider', () => { diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.expected.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.expected.json index 1476182e23c37..b38b7937618fc 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.expected.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.expected.json @@ -2712,7 +2712,7 @@ }, "Release": "ksclustertestclusterchartspotinterrupthandlerf41ba997", "Chart": "aws-node-termination-handler", - "Version": "0.13.2", + "Version": "1.14.1", "Values": "{\"nodeSelector\":{\"lifecycle\":\"Ec2Spot\"}}", "Namespace": "kube-system", "Repository": "https://aws.github.io/eks-charts", diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.expected.json b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.expected.json new file mode 100644 index 0000000000000..4b96771565701 --- /dev/null +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.expected.json @@ -0,0 +1,1427 @@ +{ + "Resources": { + "AdminRole38563C57": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::12345678:root" + ] + ] + } + } + } + ], + "Version": "2012-10-17" + } + } + }, + "Vpc8378EB38": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "10.0.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "InstanceTenancy": "default", + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-eks-helm-test/Vpc" + } + ] + } + }, + "VpcPublicSubnet1Subnet5C2D37C4": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "CidrBlock": "10.0.0.0/19", + "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": "kubernetes.io/role/elb", + "Value": "1" + }, + { + "Key": "Name", + "Value": "aws-cdk-eks-helm-test/Vpc/PublicSubnet1" + } + ] + } + }, + "VpcPublicSubnet1RouteTable6C95E38E": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "Tags": [ + { + "Key": "kubernetes.io/role/elb", + "Value": "1" + }, + { + "Key": "Name", + "Value": "aws-cdk-eks-helm-test/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": "kubernetes.io/role/elb", + "Value": "1" + }, + { + "Key": "Name", + "Value": "aws-cdk-eks-helm-test/Vpc/PublicSubnet1" + } + ] + } + }, + "VpcPublicSubnet1NATGateway4D7517AA": { + "Type": "AWS::EC2::NatGateway", + "Properties": { + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, + "AllocationId": { + "Fn::GetAtt": [ + "VpcPublicSubnet1EIPD7E02669", + "AllocationId" + ] + }, + "Tags": [ + { + "Key": "kubernetes.io/role/elb", + "Value": "1" + }, + { + "Key": "Name", + "Value": "aws-cdk-eks-helm-test/Vpc/PublicSubnet1" + } + ] + } + }, + "VpcPublicSubnet2Subnet691E08A3": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "CidrBlock": "10.0.32.0/19", + "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": "kubernetes.io/role/elb", + "Value": "1" + }, + { + "Key": "Name", + "Value": "aws-cdk-eks-helm-test/Vpc/PublicSubnet2" + } + ] + } + }, + "VpcPublicSubnet2RouteTable94F7E489": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "Tags": [ + { + "Key": "kubernetes.io/role/elb", + "Value": "1" + }, + { + "Key": "Name", + "Value": "aws-cdk-eks-helm-test/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" + ] + }, + "VpcPublicSubnet3SubnetBE12F0B6": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "CidrBlock": "10.0.64.0/19", + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "AvailabilityZone": "test-region-1c", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "kubernetes.io/role/elb", + "Value": "1" + }, + { + "Key": "Name", + "Value": "aws-cdk-eks-helm-test/Vpc/PublicSubnet3" + } + ] + } + }, + "VpcPublicSubnet3RouteTable93458DBB": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "Tags": [ + { + "Key": "kubernetes.io/role/elb", + "Value": "1" + }, + { + "Key": "Name", + "Value": "aws-cdk-eks-helm-test/Vpc/PublicSubnet3" + } + ] + } + }, + "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" + }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + } + } + }, + "VpcPublicSubnet3DefaultRoute4697774F": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VpcIGWD7BA715C" + } + }, + "DependsOn": [ + "VpcVPCGWBF912B6E" + ] + }, + "VpcPrivateSubnet1Subnet536B997A": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "CidrBlock": "10.0.96.0/19", + "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": "kubernetes.io/role/internal-elb", + "Value": "1" + }, + { + "Key": "Name", + "Value": "aws-cdk-eks-helm-test/Vpc/PrivateSubnet1" + } + ] + } + }, + "VpcPrivateSubnet1RouteTableB2C5B500": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "Tags": [ + { + "Key": "kubernetes.io/role/internal-elb", + "Value": "1" + }, + { + "Key": "Name", + "Value": "aws-cdk-eks-helm-test/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.128.0/19", + "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": "kubernetes.io/role/internal-elb", + "Value": "1" + }, + { + "Key": "Name", + "Value": "aws-cdk-eks-helm-test/Vpc/PrivateSubnet2" + } + ] + } + }, + "VpcPrivateSubnet2RouteTableA678073B": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "Tags": [ + { + "Key": "kubernetes.io/role/internal-elb", + "Value": "1" + }, + { + "Key": "Name", + "Value": "aws-cdk-eks-helm-test/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": "VpcPublicSubnet1NATGateway4D7517AA" + } + } + }, + "VpcPrivateSubnet3SubnetF258B56E": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "CidrBlock": "10.0.160.0/19", + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "AvailabilityZone": "test-region-1c", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" + }, + { + "Key": "kubernetes.io/role/internal-elb", + "Value": "1" + }, + { + "Key": "Name", + "Value": "aws-cdk-eks-helm-test/Vpc/PrivateSubnet3" + } + ] + } + }, + "VpcPrivateSubnet3RouteTableD98824C7": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "Tags": [ + { + "Key": "kubernetes.io/role/internal-elb", + "Value": "1" + }, + { + "Key": "Name", + "Value": "aws-cdk-eks-helm-test/Vpc/PrivateSubnet3" + } + ] + } + }, + "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" + }, + "SubnetId": { + "Ref": "VpcPrivateSubnet3SubnetF258B56E" + } + } + }, + "VpcPrivateSubnet3DefaultRoute94B74F0D": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + } + } + }, + "VpcIGWD7BA715C": { + "Type": "AWS::EC2::InternetGateway", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-eks-helm-test/Vpc" + } + ] + } + }, + "VpcVPCGWBF912B6E": { + "Type": "AWS::EC2::VPCGatewayAttachment", + "Properties": { + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "InternetGatewayId": { + "Ref": "VpcIGWD7BA715C" + } + } + }, + "ClusterRoleFA261979": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "eks.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonEKSClusterPolicy" + ] + ] + } + ] + } + }, + "ClusterControlPlaneSecurityGroupD274242C": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "EKS Control Plane Security Group", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "ClusterCreationRole360249B6": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::12345678:root" + ] + ] + } + } + } + ], + "Version": "2012-10-17" + } + }, + "DependsOn": [ + "VpcIGWD7BA715C", + "VpcPrivateSubnet1DefaultRouteBE02A9ED", + "VpcPrivateSubnet1RouteTableB2C5B500", + "VpcPrivateSubnet1RouteTableAssociation70C59FA6", + "VpcPrivateSubnet1Subnet536B997A", + "VpcPrivateSubnet2DefaultRoute060D2087", + "VpcPrivateSubnet2RouteTableA678073B", + "VpcPrivateSubnet2RouteTableAssociationA89CAD56", + "VpcPrivateSubnet2Subnet3788AAA1", + "VpcPrivateSubnet3DefaultRoute94B74F0D", + "VpcPrivateSubnet3RouteTableD98824C7", + "VpcPrivateSubnet3RouteTableAssociation16BDDC43", + "VpcPrivateSubnet3SubnetF258B56E", + "VpcPublicSubnet1DefaultRoute3DA9E72A", + "VpcPublicSubnet1EIPD7E02669", + "VpcPublicSubnet1NATGateway4D7517AA", + "VpcPublicSubnet1RouteTable6C95E38E", + "VpcPublicSubnet1RouteTableAssociation97140677", + "VpcPublicSubnet1Subnet5C2D37C4", + "VpcPublicSubnet2DefaultRoute97F91067", + "VpcPublicSubnet2RouteTable94F7E489", + "VpcPublicSubnet2RouteTableAssociationDD5762D8", + "VpcPublicSubnet2Subnet691E08A3", + "VpcPublicSubnet3DefaultRoute4697774F", + "VpcPublicSubnet3RouteTable93458DBB", + "VpcPublicSubnet3RouteTableAssociation1F1EDF02", + "VpcPublicSubnet3SubnetBE12F0B6", + "Vpc8378EB38", + "VpcVPCGWBF912B6E" + ] + }, + "ClusterCreationRoleDefaultPolicyE8BDFC7B": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "iam:PassRole", + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "ClusterRoleFA261979", + "Arn" + ] + } + }, + { + "Action": [ + "eks:CreateCluster", + "eks:DescribeCluster", + "eks:DescribeUpdate", + "eks:DeleteCluster", + "eks:UpdateClusterVersion", + "eks:UpdateClusterConfig", + "eks:CreateFargateProfile", + "eks:TagResource", + "eks:UntagResource" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "eks:DescribeFargateProfile", + "eks:DeleteFargateProfile" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "iam:GetRole", + "iam:listAttachedRolePolicies" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "iam:CreateServiceLinkedRole", + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ec2:DescribeInstances", + "ec2:DescribeNetworkInterfaces", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSubnets", + "ec2:DescribeRouteTables", + "ec2:DescribeDhcpOptions", + "ec2:DescribeVpcs" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "ClusterCreationRoleDefaultPolicyE8BDFC7B", + "Roles": [ + { + "Ref": "ClusterCreationRole360249B6" + } + ] + }, + "DependsOn": [ + "VpcIGWD7BA715C", + "VpcPrivateSubnet1DefaultRouteBE02A9ED", + "VpcPrivateSubnet1RouteTableB2C5B500", + "VpcPrivateSubnet1RouteTableAssociation70C59FA6", + "VpcPrivateSubnet1Subnet536B997A", + "VpcPrivateSubnet2DefaultRoute060D2087", + "VpcPrivateSubnet2RouteTableA678073B", + "VpcPrivateSubnet2RouteTableAssociationA89CAD56", + "VpcPrivateSubnet2Subnet3788AAA1", + "VpcPrivateSubnet3DefaultRoute94B74F0D", + "VpcPrivateSubnet3RouteTableD98824C7", + "VpcPrivateSubnet3RouteTableAssociation16BDDC43", + "VpcPrivateSubnet3SubnetF258B56E", + "VpcPublicSubnet1DefaultRoute3DA9E72A", + "VpcPublicSubnet1EIPD7E02669", + "VpcPublicSubnet1NATGateway4D7517AA", + "VpcPublicSubnet1RouteTable6C95E38E", + "VpcPublicSubnet1RouteTableAssociation97140677", + "VpcPublicSubnet1Subnet5C2D37C4", + "VpcPublicSubnet2DefaultRoute97F91067", + "VpcPublicSubnet2RouteTable94F7E489", + "VpcPublicSubnet2RouteTableAssociationDD5762D8", + "VpcPublicSubnet2Subnet691E08A3", + "VpcPublicSubnet3DefaultRoute4697774F", + "VpcPublicSubnet3RouteTable93458DBB", + "VpcPublicSubnet3RouteTableAssociation1F1EDF02", + "VpcPublicSubnet3SubnetBE12F0B6", + "Vpc8378EB38", + "VpcVPCGWBF912B6E" + ] + }, + "Cluster9EE0221C": { + "Type": "Custom::AWSCDK-EKS-Cluster", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "awscdkawseksClusterResourceProviderNestedStackawscdkawseksClusterResourceProviderNestedStackResource9827C454", + "Outputs.awscdkekshelmtestawscdkawseksClusterResourceProviderframeworkonEventFCDC8710Arn" + ] + }, + "Config": { + "version": "1.21", + "roleArn": { + "Fn::GetAtt": [ + "ClusterRoleFA261979", + "Arn" + ] + }, + "resourcesVpcConfig": { + "subnetIds": [ + { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, + { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, + { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, + { + "Ref": "VpcPrivateSubnet1Subnet536B997A" + }, + { + "Ref": "VpcPrivateSubnet2Subnet3788AAA1" + }, + { + "Ref": "VpcPrivateSubnet3SubnetF258B56E" + } + ], + "securityGroupIds": [ + { + "Fn::GetAtt": [ + "ClusterControlPlaneSecurityGroupD274242C", + "GroupId" + ] + } + ], + "endpointPublicAccess": true, + "endpointPrivateAccess": true + }, + "tags": { + "foo": "bar" + }, + "logging": { + "clusterLogging": [ + { + "enabled": true, + "types": [ + "api", + "authenticator", + "scheduler" + ] + } + ] + } + }, + "AssumeRoleArn": { + "Fn::GetAtt": [ + "ClusterCreationRole360249B6", + "Arn" + ] + }, + "AttributesRevision": 2 + }, + "DependsOn": [ + "ClusterCreationRoleDefaultPolicyE8BDFC7B", + "ClusterCreationRole360249B6", + "VpcIGWD7BA715C", + "VpcPrivateSubnet1DefaultRouteBE02A9ED", + "VpcPrivateSubnet1RouteTableB2C5B500", + "VpcPrivateSubnet1RouteTableAssociation70C59FA6", + "VpcPrivateSubnet1Subnet536B997A", + "VpcPrivateSubnet2DefaultRoute060D2087", + "VpcPrivateSubnet2RouteTableA678073B", + "VpcPrivateSubnet2RouteTableAssociationA89CAD56", + "VpcPrivateSubnet2Subnet3788AAA1", + "VpcPrivateSubnet3DefaultRoute94B74F0D", + "VpcPrivateSubnet3RouteTableD98824C7", + "VpcPrivateSubnet3RouteTableAssociation16BDDC43", + "VpcPrivateSubnet3SubnetF258B56E", + "VpcPublicSubnet1DefaultRoute3DA9E72A", + "VpcPublicSubnet1EIPD7E02669", + "VpcPublicSubnet1NATGateway4D7517AA", + "VpcPublicSubnet1RouteTable6C95E38E", + "VpcPublicSubnet1RouteTableAssociation97140677", + "VpcPublicSubnet1Subnet5C2D37C4", + "VpcPublicSubnet2DefaultRoute97F91067", + "VpcPublicSubnet2RouteTable94F7E489", + "VpcPublicSubnet2RouteTableAssociationDD5762D8", + "VpcPublicSubnet2Subnet691E08A3", + "VpcPublicSubnet3DefaultRoute4697774F", + "VpcPublicSubnet3RouteTable93458DBB", + "VpcPublicSubnet3RouteTableAssociation1F1EDF02", + "VpcPublicSubnet3SubnetBE12F0B6", + "Vpc8378EB38", + "VpcVPCGWBF912B6E" + ], + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "ClusterKubectlReadyBarrier200052AF": { + "Type": "AWS::SSM::Parameter", + "Properties": { + "Type": "String", + "Value": "aws:cdk:eks:kubectl-ready" + }, + "DependsOn": [ + "ClusterCreationRoleDefaultPolicyE8BDFC7B", + "ClusterCreationRole360249B6", + "Cluster9EE0221C" + ] + }, + "ClusterAwsAuthmanifestFE51F8AE": { + "Type": "Custom::AWSCDK-EKS-KubernetesResource", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "awscdkawseksKubectlProviderNestedStackawscdkawseksKubectlProviderNestedStackResourceA7AEBA6B", + "Outputs.awscdkekshelmtestawscdkawseksKubectlProviderframeworkonEvent9D93C644Arn" + ] + }, + "Manifest": { + "Fn::Join": [ + "", + [ + "[{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"aws-auth\",\"namespace\":\"kube-system\",\"labels\":{\"aws.cdk.eks/prune-c8d0612c947a128ccc926ff6124bd5462ab86f86d6\":\"\"}},\"data\":{\"mapRoles\":\"[{\\\"rolearn\\\":\\\"", + { + "Fn::GetAtt": [ + "AdminRole38563C57", + "Arn" + ] + }, + "\\\",\\\"username\\\":\\\"", + { + "Fn::GetAtt": [ + "AdminRole38563C57", + "Arn" + ] + }, + "\\\",\\\"groups\\\":[\\\"system:masters\\\"]},{\\\"rolearn\\\":\\\"", + { + "Fn::GetAtt": [ + "ClusterNodegroupDefaultCapacityNodeGroupRole55953B04", + "Arn" + ] + }, + "\\\",\\\"username\\\":\\\"system:node:{{EC2PrivateDNSName}}\\\",\\\"groups\\\":[\\\"system:bootstrappers\\\",\\\"system:nodes\\\"]}]\",\"mapUsers\":\"[]\",\"mapAccounts\":\"[]\"}}]" + ] + ] + }, + "ClusterName": { + "Ref": "Cluster9EE0221C" + }, + "RoleArn": { + "Fn::GetAtt": [ + "ClusterCreationRole360249B6", + "Arn" + ] + }, + "PruneLabel": "aws.cdk.eks/prune-c8d0612c947a128ccc926ff6124bd5462ab86f86d6", + "Overwrite": true + }, + "DependsOn": [ + "ClusterKubectlReadyBarrier200052AF" + ], + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "ClusterNodegroupDefaultCapacityNodeGroupRole55953B04": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": { + "Fn::Join": [ + "", + [ + "ec2.", + { + "Ref": "AWS::URLSuffix" + } + ] + ] + } + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonEKSWorkerNodePolicy" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonEKS_CNI_Policy" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" + ] + ] + } + ] + } + }, + "ClusterNodegroupDefaultCapacityDA0920A3": { + "Type": "AWS::EKS::Nodegroup", + "Properties": { + "ClusterName": { + "Ref": "Cluster9EE0221C" + }, + "NodeRole": { + "Fn::GetAtt": [ + "ClusterNodegroupDefaultCapacityNodeGroupRole55953B04", + "Arn" + ] + }, + "Subnets": [ + { + "Ref": "VpcPrivateSubnet1Subnet536B997A" + }, + { + "Ref": "VpcPrivateSubnet2Subnet3788AAA1" + }, + { + "Ref": "VpcPrivateSubnet3SubnetF258B56E" + } + ], + "AmiType": "AL2_x86_64", + "ForceUpdateEnabled": true, + "InstanceTypes": [ + "m5.large" + ], + "ScalingConfig": { + "DesiredSize": 2, + "MaxSize": 2, + "MinSize": 2 + } + } + }, + "Clustercharttestchart9FD698EB": { + "Type": "Custom::AWSCDK-EKS-HelmChart", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "awscdkawseksKubectlProviderNestedStackawscdkawseksKubectlProviderNestedStackResourceA7AEBA6B", + "Outputs.awscdkekshelmtestawscdkawseksKubectlProviderframeworkonEvent9D93C644Arn" + ] + }, + "ClusterName": { + "Ref": "Cluster9EE0221C" + }, + "RoleArn": { + "Fn::GetAtt": [ + "ClusterCreationRole360249B6", + "Arn" + ] + }, + "Release": "awscdkekshelmtestclustercharttestchart0449715f", + "ChartAssetURL": { + "Fn::Join": [ + "", + [ + "s3://", + { + "Ref": "AssetParametersd65fbdc11b108e0386ed8577c454d4544f6d4e7960f84a0d2e211478d6324dbfS3BucketBFD29DFB" + }, + "/", + { + "Fn::Select": [ + 0, + { + "Fn::Split": [ + "||", + { + "Ref": "AssetParametersd65fbdc11b108e0386ed8577c454d4544f6d4e7960f84a0d2e211478d6324dbfS3VersionKeyD1F874DF" + } + ] + } + ] + }, + { + "Fn::Select": [ + 1, + { + "Fn::Split": [ + "||", + { + "Ref": "AssetParametersd65fbdc11b108e0386ed8577c454d4544f6d4e7960f84a0d2e211478d6324dbfS3VersionKeyD1F874DF" + } + ] + } + ] + } + ] + ] + }, + "Namespace": "default", + "CreateNamespace": true + }, + "DependsOn": [ + "ClusterKubectlReadyBarrier200052AF" + ], + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "awscdkawseksClusterResourceProviderNestedStackawscdkawseksClusterResourceProviderNestedStackResource9827C454": { + "Type": "AWS::CloudFormation::Stack", + "Properties": { + "TemplateURL": { + "Fn::Join": [ + "", + [ + "https://s3.test-region.", + { + "Ref": "AWS::URLSuffix" + }, + "/", + { + "Ref": "AssetParameters1128123ffb1dc85ad3dfc732c68f74860898a0f33e3fced3b87855e52ecff1b6S3Bucket93357965" + }, + "/", + { + "Fn::Select": [ + 0, + { + "Fn::Split": [ + "||", + { + "Ref": "AssetParameters1128123ffb1dc85ad3dfc732c68f74860898a0f33e3fced3b87855e52ecff1b6S3VersionKey5F602037" + } + ] + } + ] + }, + { + "Fn::Select": [ + 1, + { + "Fn::Split": [ + "||", + { + "Ref": "AssetParameters1128123ffb1dc85ad3dfc732c68f74860898a0f33e3fced3b87855e52ecff1b6S3VersionKey5F602037" + } + ] + } + ] + } + ] + ] + }, + "Parameters": { + "referencetoawscdkekshelmtestAssetParameters4288ebb3652acdf2d828b7db7ca44a7162a401ace50ebb4026e84b18a02a06eeS3Bucket085ACFA1Ref": { + "Ref": "AssetParameters4288ebb3652acdf2d828b7db7ca44a7162a401ace50ebb4026e84b18a02a06eeS3Bucket4E7CD097" + }, + "referencetoawscdkekshelmtestAssetParameters4288ebb3652acdf2d828b7db7ca44a7162a401ace50ebb4026e84b18a02a06eeS3VersionKey455E4CBARef": { + "Ref": "AssetParameters4288ebb3652acdf2d828b7db7ca44a7162a401ace50ebb4026e84b18a02a06eeS3VersionKey93D16224" + }, + "referencetoawscdkekshelmtestClusterCreationRole906A8995Arn": { + "Fn::GetAtt": [ + "ClusterCreationRole360249B6", + "Arn" + ] + }, + "referencetoawscdkekshelmtestAssetParameters8b11ea303df4b9db9feef6ed5f901a2d1185023a40c80c9630cf5c36559ae647S3BucketE22C6D82Ref": { + "Ref": "AssetParameters8b11ea303df4b9db9feef6ed5f901a2d1185023a40c80c9630cf5c36559ae647S3Bucket05488C5E" + }, + "referencetoawscdkekshelmtestAssetParameters8b11ea303df4b9db9feef6ed5f901a2d1185023a40c80c9630cf5c36559ae647S3VersionKey73B77719Ref": { + "Ref": "AssetParameters8b11ea303df4b9db9feef6ed5f901a2d1185023a40c80c9630cf5c36559ae647S3VersionKey174B23DF" + }, + "referencetoawscdkekshelmtestAssetParametersb52e342969e05acfb4d852a41c8384d0ce054b2072fc68944e8b07f5012a9a6fS3Bucket6D20CD58Ref": { + "Ref": "AssetParametersb52e342969e05acfb4d852a41c8384d0ce054b2072fc68944e8b07f5012a9a6fS3Bucket992EFD1F" + }, + "referencetoawscdkekshelmtestAssetParametersb52e342969e05acfb4d852a41c8384d0ce054b2072fc68944e8b07f5012a9a6fS3VersionKey3510C847Ref": { + "Ref": "AssetParametersb52e342969e05acfb4d852a41c8384d0ce054b2072fc68944e8b07f5012a9a6fS3VersionKey8252F880" + } + } + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "awscdkawseksKubectlProviderNestedStackawscdkawseksKubectlProviderNestedStackResourceA7AEBA6B": { + "Type": "AWS::CloudFormation::Stack", + "Properties": { + "TemplateURL": { + "Fn::Join": [ + "", + [ + "https://s3.test-region.", + { + "Ref": "AWS::URLSuffix" + }, + "/", + { + "Ref": "AssetParameters0a074e6b19e042d638d8777cefd9215b3bda798c63cb94adf6a1bfc2e16725f3S3Bucket7637BBAA" + }, + "/", + { + "Fn::Select": [ + 0, + { + "Fn::Split": [ + "||", + { + "Ref": "AssetParameters0a074e6b19e042d638d8777cefd9215b3bda798c63cb94adf6a1bfc2e16725f3S3VersionKey0CE04E83" + } + ] + } + ] + }, + { + "Fn::Select": [ + 1, + { + "Fn::Split": [ + "||", + { + "Ref": "AssetParameters0a074e6b19e042d638d8777cefd9215b3bda798c63cb94adf6a1bfc2e16725f3S3VersionKey0CE04E83" + } + ] + } + ] + } + ] + ] + }, + "Parameters": { + "referencetoawscdkekshelmtestCluster35BA672BArn": { + "Fn::GetAtt": [ + "Cluster9EE0221C", + "Arn" + ] + }, + "referencetoawscdkekshelmtestClusterCreationRole906A8995Arn": { + "Fn::GetAtt": [ + "ClusterCreationRole360249B6", + "Arn" + ] + }, + "referencetoawscdkekshelmtestAssetParametersd65fbdc11b108e0386ed8577c454d4544f6d4e7960f84a0d2e211478d6324dbfS3Bucket5EAB45FARef": { + "Ref": "AssetParametersd65fbdc11b108e0386ed8577c454d4544f6d4e7960f84a0d2e211478d6324dbfS3BucketBFD29DFB" + }, + "referencetoawscdkekshelmtestAssetParametersa70c48e7047fb793b2378668accb1dc2d92f2d7b1fff80c9c718f4964dc69cb8S3BucketC59436A3Ref": { + "Ref": "AssetParametersa70c48e7047fb793b2378668accb1dc2d92f2d7b1fff80c9c718f4964dc69cb8S3Bucket4CD5FFC3" + }, + "referencetoawscdkekshelmtestAssetParametersa70c48e7047fb793b2378668accb1dc2d92f2d7b1fff80c9c718f4964dc69cb8S3VersionKey5ECB4296Ref": { + "Ref": "AssetParametersa70c48e7047fb793b2378668accb1dc2d92f2d7b1fff80c9c718f4964dc69cb8S3VersionKeyE06BA291" + }, + "referencetoawscdkekshelmtestVpcPrivateSubnet1Subnet3D2B5C0BRef": { + "Ref": "VpcPrivateSubnet1Subnet536B997A" + }, + "referencetoawscdkekshelmtestVpcPrivateSubnet2SubnetF5E4AFE9Ref": { + "Ref": "VpcPrivateSubnet2Subnet3788AAA1" + }, + "referencetoawscdkekshelmtestVpcPrivateSubnet3Subnet7C40A2F3Ref": { + "Ref": "VpcPrivateSubnet3SubnetF258B56E" + }, + "referencetoawscdkekshelmtestCluster35BA672BClusterSecurityGroupId": { + "Fn::GetAtt": [ + "Cluster9EE0221C", + "ClusterSecurityGroupId" + ] + }, + "referencetoawscdkekshelmtestAssetParameters239a256fd14898783bad551f24c0b5914fef63365eed1afd090e27ab9730b063S3Bucket7F65D9C6Ref": { + "Ref": "AssetParameters239a256fd14898783bad551f24c0b5914fef63365eed1afd090e27ab9730b063S3BucketC8A15681" + }, + "referencetoawscdkekshelmtestAssetParameters239a256fd14898783bad551f24c0b5914fef63365eed1afd090e27ab9730b063S3VersionKey4DA2E07ARef": { + "Ref": "AssetParameters239a256fd14898783bad551f24c0b5914fef63365eed1afd090e27ab9730b063S3VersionKey06DEE4C0" + }, + "referencetoawscdkekshelmtestAssetParametersea17febe6d04c66048f3e8e060c71685c0cb53122abceff44842d27bc0d4a03eS3Bucket355FB348Ref": { + "Ref": "AssetParametersea17febe6d04c66048f3e8e060c71685c0cb53122abceff44842d27bc0d4a03eS3BucketD3288998" + }, + "referencetoawscdkekshelmtestAssetParametersea17febe6d04c66048f3e8e060c71685c0cb53122abceff44842d27bc0d4a03eS3VersionKeyA7F169F4Ref": { + "Ref": "AssetParametersea17febe6d04c66048f3e8e060c71685c0cb53122abceff44842d27bc0d4a03eS3VersionKeyB00C0565" + }, + "referencetoawscdkekshelmtestAssetParametersb52e342969e05acfb4d852a41c8384d0ce054b2072fc68944e8b07f5012a9a6fS3Bucket6D20CD58Ref": { + "Ref": "AssetParametersb52e342969e05acfb4d852a41c8384d0ce054b2072fc68944e8b07f5012a9a6fS3Bucket992EFD1F" + }, + "referencetoawscdkekshelmtestAssetParametersb52e342969e05acfb4d852a41c8384d0ce054b2072fc68944e8b07f5012a9a6fS3VersionKey3510C847Ref": { + "Ref": "AssetParametersb52e342969e05acfb4d852a41c8384d0ce054b2072fc68944e8b07f5012a9a6fS3VersionKey8252F880" + } + } + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + } + }, + "Outputs": { + "ClusterConfigCommand43AAE40F": { + "Value": { + "Fn::Join": [ + "", + [ + "aws eks update-kubeconfig --name ", + { + "Ref": "Cluster9EE0221C" + }, + " --region test-region --role-arn ", + { + "Fn::GetAtt": [ + "AdminRole38563C57", + "Arn" + ] + } + ] + ] + } + }, + "ClusterGetTokenCommand06AE992E": { + "Value": { + "Fn::Join": [ + "", + [ + "aws eks get-token --cluster-name ", + { + "Ref": "Cluster9EE0221C" + }, + " --region test-region --role-arn ", + { + "Fn::GetAtt": [ + "AdminRole38563C57", + "Arn" + ] + } + ] + ] + } + } + }, + "Parameters": { + "AssetParameters4288ebb3652acdf2d828b7db7ca44a7162a401ace50ebb4026e84b18a02a06eeS3Bucket4E7CD097": { + "Type": "String", + "Description": "S3 bucket for asset \"4288ebb3652acdf2d828b7db7ca44a7162a401ace50ebb4026e84b18a02a06ee\"" + }, + "AssetParameters4288ebb3652acdf2d828b7db7ca44a7162a401ace50ebb4026e84b18a02a06eeS3VersionKey93D16224": { + "Type": "String", + "Description": "S3 key for asset version \"4288ebb3652acdf2d828b7db7ca44a7162a401ace50ebb4026e84b18a02a06ee\"" + }, + "AssetParameters4288ebb3652acdf2d828b7db7ca44a7162a401ace50ebb4026e84b18a02a06eeArtifactHash515E16AE": { + "Type": "String", + "Description": "Artifact hash for asset \"4288ebb3652acdf2d828b7db7ca44a7162a401ace50ebb4026e84b18a02a06ee\"" + }, + "AssetParameters8b11ea303df4b9db9feef6ed5f901a2d1185023a40c80c9630cf5c36559ae647S3Bucket05488C5E": { + "Type": "String", + "Description": "S3 bucket for asset \"8b11ea303df4b9db9feef6ed5f901a2d1185023a40c80c9630cf5c36559ae647\"" + }, + "AssetParameters8b11ea303df4b9db9feef6ed5f901a2d1185023a40c80c9630cf5c36559ae647S3VersionKey174B23DF": { + "Type": "String", + "Description": "S3 key for asset version \"8b11ea303df4b9db9feef6ed5f901a2d1185023a40c80c9630cf5c36559ae647\"" + }, + "AssetParameters8b11ea303df4b9db9feef6ed5f901a2d1185023a40c80c9630cf5c36559ae647ArtifactHashE94F67E3": { + "Type": "String", + "Description": "Artifact hash for asset \"8b11ea303df4b9db9feef6ed5f901a2d1185023a40c80c9630cf5c36559ae647\"" + }, + "AssetParametersb52e342969e05acfb4d852a41c8384d0ce054b2072fc68944e8b07f5012a9a6fS3Bucket992EFD1F": { + "Type": "String", + "Description": "S3 bucket for asset \"b52e342969e05acfb4d852a41c8384d0ce054b2072fc68944e8b07f5012a9a6f\"" + }, + "AssetParametersb52e342969e05acfb4d852a41c8384d0ce054b2072fc68944e8b07f5012a9a6fS3VersionKey8252F880": { + "Type": "String", + "Description": "S3 key for asset version \"b52e342969e05acfb4d852a41c8384d0ce054b2072fc68944e8b07f5012a9a6f\"" + }, + "AssetParametersb52e342969e05acfb4d852a41c8384d0ce054b2072fc68944e8b07f5012a9a6fArtifactHashC69EDCB8": { + "Type": "String", + "Description": "Artifact hash for asset \"b52e342969e05acfb4d852a41c8384d0ce054b2072fc68944e8b07f5012a9a6f\"" + }, + "AssetParametersa70c48e7047fb793b2378668accb1dc2d92f2d7b1fff80c9c718f4964dc69cb8S3Bucket4CD5FFC3": { + "Type": "String", + "Description": "S3 bucket for asset \"a70c48e7047fb793b2378668accb1dc2d92f2d7b1fff80c9c718f4964dc69cb8\"" + }, + "AssetParametersa70c48e7047fb793b2378668accb1dc2d92f2d7b1fff80c9c718f4964dc69cb8S3VersionKeyE06BA291": { + "Type": "String", + "Description": "S3 key for asset version \"a70c48e7047fb793b2378668accb1dc2d92f2d7b1fff80c9c718f4964dc69cb8\"" + }, + "AssetParametersa70c48e7047fb793b2378668accb1dc2d92f2d7b1fff80c9c718f4964dc69cb8ArtifactHashA4AB6609": { + "Type": "String", + "Description": "Artifact hash for asset \"a70c48e7047fb793b2378668accb1dc2d92f2d7b1fff80c9c718f4964dc69cb8\"" + }, + "AssetParameters239a256fd14898783bad551f24c0b5914fef63365eed1afd090e27ab9730b063S3BucketC8A15681": { + "Type": "String", + "Description": "S3 bucket for asset \"239a256fd14898783bad551f24c0b5914fef63365eed1afd090e27ab9730b063\"" + }, + "AssetParameters239a256fd14898783bad551f24c0b5914fef63365eed1afd090e27ab9730b063S3VersionKey06DEE4C0": { + "Type": "String", + "Description": "S3 key for asset version \"239a256fd14898783bad551f24c0b5914fef63365eed1afd090e27ab9730b063\"" + }, + "AssetParameters239a256fd14898783bad551f24c0b5914fef63365eed1afd090e27ab9730b063ArtifactHash5EDABC65": { + "Type": "String", + "Description": "Artifact hash for asset \"239a256fd14898783bad551f24c0b5914fef63365eed1afd090e27ab9730b063\"" + }, + "AssetParametersea17febe6d04c66048f3e8e060c71685c0cb53122abceff44842d27bc0d4a03eS3BucketD3288998": { + "Type": "String", + "Description": "S3 bucket for asset \"ea17febe6d04c66048f3e8e060c71685c0cb53122abceff44842d27bc0d4a03e\"" + }, + "AssetParametersea17febe6d04c66048f3e8e060c71685c0cb53122abceff44842d27bc0d4a03eS3VersionKeyB00C0565": { + "Type": "String", + "Description": "S3 key for asset version \"ea17febe6d04c66048f3e8e060c71685c0cb53122abceff44842d27bc0d4a03e\"" + }, + "AssetParametersea17febe6d04c66048f3e8e060c71685c0cb53122abceff44842d27bc0d4a03eArtifactHash4654D012": { + "Type": "String", + "Description": "Artifact hash for asset \"ea17febe6d04c66048f3e8e060c71685c0cb53122abceff44842d27bc0d4a03e\"" + }, + "AssetParametersd65fbdc11b108e0386ed8577c454d4544f6d4e7960f84a0d2e211478d6324dbfS3BucketBFD29DFB": { + "Type": "String", + "Description": "S3 bucket for asset \"d65fbdc11b108e0386ed8577c454d4544f6d4e7960f84a0d2e211478d6324dbf\"" + }, + "AssetParametersd65fbdc11b108e0386ed8577c454d4544f6d4e7960f84a0d2e211478d6324dbfS3VersionKeyD1F874DF": { + "Type": "String", + "Description": "S3 key for asset version \"d65fbdc11b108e0386ed8577c454d4544f6d4e7960f84a0d2e211478d6324dbf\"" + }, + "AssetParametersd65fbdc11b108e0386ed8577c454d4544f6d4e7960f84a0d2e211478d6324dbfArtifactHash5A9B7775": { + "Type": "String", + "Description": "Artifact hash for asset \"d65fbdc11b108e0386ed8577c454d4544f6d4e7960f84a0d2e211478d6324dbf\"" + }, + "AssetParameters1128123ffb1dc85ad3dfc732c68f74860898a0f33e3fced3b87855e52ecff1b6S3Bucket93357965": { + "Type": "String", + "Description": "S3 bucket for asset \"1128123ffb1dc85ad3dfc732c68f74860898a0f33e3fced3b87855e52ecff1b6\"" + }, + "AssetParameters1128123ffb1dc85ad3dfc732c68f74860898a0f33e3fced3b87855e52ecff1b6S3VersionKey5F602037": { + "Type": "String", + "Description": "S3 key for asset version \"1128123ffb1dc85ad3dfc732c68f74860898a0f33e3fced3b87855e52ecff1b6\"" + }, + "AssetParameters1128123ffb1dc85ad3dfc732c68f74860898a0f33e3fced3b87855e52ecff1b6ArtifactHash41C5ADC4": { + "Type": "String", + "Description": "Artifact hash for asset \"1128123ffb1dc85ad3dfc732c68f74860898a0f33e3fced3b87855e52ecff1b6\"" + }, + "AssetParameters0a074e6b19e042d638d8777cefd9215b3bda798c63cb94adf6a1bfc2e16725f3S3Bucket7637BBAA": { + "Type": "String", + "Description": "S3 bucket for asset \"0a074e6b19e042d638d8777cefd9215b3bda798c63cb94adf6a1bfc2e16725f3\"" + }, + "AssetParameters0a074e6b19e042d638d8777cefd9215b3bda798c63cb94adf6a1bfc2e16725f3S3VersionKey0CE04E83": { + "Type": "String", + "Description": "S3 key for asset version \"0a074e6b19e042d638d8777cefd9215b3bda798c63cb94adf6a1bfc2e16725f3\"" + }, + "AssetParameters0a074e6b19e042d638d8777cefd9215b3bda798c63cb94adf6a1bfc2e16725f3ArtifactHash84E3ECC5": { + "Type": "String", + "Description": "Artifact hash for asset \"0a074e6b19e042d638d8777cefd9215b3bda798c63cb94adf6a1bfc2e16725f3\"" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.ts new file mode 100644 index 0000000000000..447ae3dac82b7 --- /dev/null +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.ts @@ -0,0 +1,59 @@ +import * as path from 'path'; +import * as ec2 from '@aws-cdk/aws-ec2'; +import * as iam from '@aws-cdk/aws-iam'; +import { Asset } from '@aws-cdk/aws-s3-assets'; +import { App } from '@aws-cdk/core'; +import * as eks from '../lib/index'; +import { TestStack } from './util'; + +class EksClusterStack extends TestStack { + private cluster: eks.Cluster; + private vpc: ec2.IVpc; + + constructor(scope: App, id: string) { + super(scope, id); + + // allow all account users to assume this role in order to admin the cluster + const mastersRole = new iam.Role(this, 'AdminRole', { + assumedBy: new iam.AccountRootPrincipal(), + }); + + // just need one nat gateway to simplify the test + this.vpc = new ec2.Vpc(this, 'Vpc', { maxAzs: 3, natGateways: 1 }); + + // create the cluster with a default nodegroup capacity + this.cluster = new eks.Cluster(this, 'Cluster', { + vpc: this.vpc, + mastersRole, + defaultCapacity: 2, + version: eks.KubernetesVersion.V1_21, + tags: { + foo: 'bar', + }, + clusterLogging: [ + eks.ClusterLoggingTypes.API, + eks.ClusterLoggingTypes.AUTHENTICATOR, + eks.ClusterLoggingTypes.SCHEDULER, + ], + }); + + this.assertHelmChartAsset(); + } + + private assertHelmChartAsset() { + // get helm chart from Asset + const chartAsset = new Asset(this, 'ChartAsset', { + path: path.join(__dirname, 'test-chart'), + }); + this.cluster.addHelmChart('test-chart', { + chartAsset: chartAsset, + }); + } +} + +const app = new App(); + +new EksClusterStack(app, 'aws-cdk-eks-helm-test'); + +app.synth(); + diff --git a/packages/@aws-cdk/aws-eks/test/service-account.test.ts b/packages/@aws-cdk/aws-eks/test/service-account.test.ts index e4db2f6680a97..7ece468d200d0 100644 --- a/packages/@aws-cdk/aws-eks/test/service-account.test.ts +++ b/packages/@aws-cdk/aws-eks/test/service-account.test.ts @@ -174,4 +174,101 @@ describe('service account', () => { }); }); + + describe('Service Account name must follow Kubernetes spec', () => { + test('throw error on capital letters', () => { + // GIVEN + const { cluster } = testFixtureCluster(); + + // WHEN + expect(() => cluster.addServiceAccount('InvalidServiceAccount', { + name: 'XXX', + })) + // THEN + .toThrowError(RangeError); + }); + test('throw error if ends with dot', () => { + // GIVEN + const { cluster } = testFixtureCluster(); + + // WHEN + expect(() => cluster.addServiceAccount('InvalidServiceAccount', { + name: 'test.', + })) + // THEN + .toThrowError(RangeError); + }); + test('dot in the name is allowed', () => { + // GIVEN + const { cluster } = testFixtureCluster(); + const valueWithDot = 'test.name'; + + // WHEN + const sa = cluster.addServiceAccount('InvalidServiceAccount', { + name: valueWithDot, + }); + + // THEN + expect(sa.serviceAccountName).toEqual(valueWithDot); + }); + test('throw error if name is too long', () => { + // GIVEN + const { cluster } = testFixtureCluster(); + + // WHEN + expect(() => cluster.addServiceAccount('InvalidServiceAccount', { + name: 'x'.repeat(255), + })) + // THEN + .toThrowError(RangeError); + }); + }); + + describe('Service Account namespace must follow Kubernetes spec', () => { + test('throw error on capital letters', () => { + // GIVEN + const { cluster } = testFixtureCluster(); + + // WHEN + expect(() => cluster.addServiceAccount('InvalidServiceAccount', { + namespace: 'XXX', + })) + // THEN + .toThrowError(RangeError); + }); + test('throw error if ends with dot', () => { + // GIVEN + const { cluster } = testFixtureCluster(); + + // WHEN + expect(() => cluster.addServiceAccount('InvalidServiceAccount', { + namespace: 'test.', + })) + // THEN + .toThrowError(RangeError); + }); + test('throw error if dot is in the name', () => { + // GIVEN + const { cluster } = testFixtureCluster(); + const valueWithDot = 'test.name'; + + // WHEN + expect(() => cluster.addServiceAccount('InvalidServiceAccount', { + namespace: valueWithDot, + })) + // THEN + .toThrowError(RangeError); + }); + test('throw error if name is too long', () => { + // GIVEN + const { cluster } = testFixtureCluster(); + + // WHEN + expect(() => cluster.addServiceAccount('InvalidServiceAccount', { + namespace: 'x'.repeat(65), + })) + // THEN + .toThrowError(RangeError); + }); + }); }); diff --git a/packages/@aws-cdk/aws-elasticache/package.json b/packages/@aws-cdk/aws-elasticache/package.json index 61fe8976e0ced..50e6f1e715664 100644 --- a/packages/@aws-cdk/aws-elasticache/package.json +++ b/packages/@aws-cdk/aws-elasticache/package.json @@ -83,7 +83,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-elasticbeanstalk/package.json b/packages/@aws-cdk/aws-elasticbeanstalk/package.json index 46506c219aedb..c3813016c4e6a 100644 --- a/packages/@aws-cdk/aws-elasticbeanstalk/package.json +++ b/packages/@aws-cdk/aws-elasticbeanstalk/package.json @@ -83,7 +83,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-elasticloadbalancing/package.json b/packages/@aws-cdk/aws-elasticloadbalancing/package.json index c43acdd739437..be344c056d66e 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancing/package.json +++ b/packages/@aws-cdk/aws-elasticloadbalancing/package.json @@ -84,7 +84,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/aws-ec2": "0.0.0", diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/package.json b/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/package.json index 68546e4d7b7ab..bc600f17e2974 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/package.json +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/package.json @@ -76,7 +76,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2-targets/package.json b/packages/@aws-cdk/aws-elasticloadbalancingv2-targets/package.json index 7a600e14a6493..b00b793851348 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2-targets/package.json +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2-targets/package.json @@ -76,7 +76,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1", "@aws-cdk/aws-ecs": "0.0.0", "@aws-cdk/aws-ecs-patterns": "0.0.0" diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-listener.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-listener.ts index 2994a437b3929..52bfd666a0ed4 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-listener.ts +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-listener.ts @@ -83,15 +83,15 @@ export interface BaseApplicationListenerProps { readonly defaultAction?: ListenerAction; /** - * Allow anyone to connect to this listener + * Allow anyone to connect to the load balancer on the listener port * - * If this is specified, the listener will be opened up to anyone who can reach it. + * If this is specified, the load balancer will be opened up to anyone who can reach it. * For internal load balancers this is anyone in the same VPC. For public load * balancers, this is anyone on the internet. * * If you want to be more selective about who can access this load * balancer, set this to `false` and use the listener's `connections` - * object to selectively grant access to the listener. + * object to selectively grant access to the load balancer on the listener port. * * @default true */ @@ -858,7 +858,8 @@ export interface AddApplicationTargetsProps extends AddRuleProps { /** * Health check configuration * - * @default No health check + * @default - The default value for each property in this configuration varies depending on the target. + * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticloadbalancingv2-targetgroup.html#aws-resource-elasticloadbalancingv2-targetgroup-properties */ readonly healthCheck?: HealthCheck; diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-target-group.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-target-group.ts index cf34ee5a7857e..98bfdc90796bb 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-target-group.ts +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-target-group.ts @@ -134,6 +134,17 @@ export class ApplicationTargetGroup extends TargetGroupBase implements IApplicat this.protocol = protocol; this.port = port; + // this.targetType is lazy + this.node.addValidation({ + validate: () => { + if (this.targetType === TargetType.LAMBDA && (this.port || this.protocol)) { + return ['port/protocol should not be specified for Lambda targets']; + } else { + return []; + } + }, + }); + this.connectableMembers = []; this.listeners = []; diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/nlb/network-listener.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/nlb/network-listener.ts index 4cfed265217f5..d48dbafc8202a 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/nlb/network-listener.ts +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/nlb/network-listener.ts @@ -361,7 +361,8 @@ export interface AddNetworkTargetsProps { /** * Health check configuration * - * @default No health check + * @default - The default value for each property in this configuration varies depending on the target. + * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticloadbalancingv2-targetgroup.html#aws-resource-elasticloadbalancingv2-targetgroup-properties */ readonly healthCheck?: HealthCheck; } diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/shared/base-target-group.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/shared/base-target-group.ts index e090b61ce2a2f..8897540d7910c 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/shared/base-target-group.ts +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/shared/base-target-group.ts @@ -45,7 +45,8 @@ export interface BaseTargetGroupProps { /** * Health check configuration * - * @default - None. + * @default - The default value for each property in this configuration varies depending on the target. + * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticloadbalancingv2-targetgroup.html#aws-resource-elasticloadbalancingv2-targetgroup-properties */ readonly healthCheck?: HealthCheck; diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/package.json b/packages/@aws-cdk/aws-elasticloadbalancingv2/package.json index 4d98964505e22..1668c5ffc511f 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2/package.json +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/package.json @@ -84,7 +84,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/aws-certificatemanager": "0.0.0", diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/test/alb/target-group.test.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2/test/alb/target-group.test.ts index 98c25a1e5cb70..57a3aabe6a11b 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2/test/alb/target-group.test.ts +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/test/alb/target-group.test.ts @@ -48,6 +48,35 @@ describe('tests', () => { expect(Object.keys(matches).length).toBe(0); }); + test('Lambda target should not have port set', () => { + const app = new cdk.App(); + const stack = new cdk.Stack(app, 'Stack'); + + const tg = new elbv2.ApplicationTargetGroup(stack, 'TG2', { + protocol: elbv2.ApplicationProtocol.HTTPS, + }); + tg.addTarget({ + attachToApplicationTargetGroup(_targetGroup: elbv2.IApplicationTargetGroup): elbv2.LoadBalancerTargetProps { + return { + targetType: elbv2.TargetType.LAMBDA, + targetJson: { id: 'arn:aws:lambda:eu-west-1:123456789012:function:myFn' }, + }; + }, + }); + expect(() => app.synth()).toThrow(/port\/protocol should not be specified for Lambda targets/); + }); + + test('Lambda target should not have protocol set', () => { + const app = new cdk.App(); + const stack = new cdk.Stack(app, 'Stack'); + + new elbv2.ApplicationTargetGroup(stack, 'TG', { + port: 443, + targetType: elbv2.TargetType.LAMBDA, + }); + expect(() => app.synth()).toThrow(/port\/protocol should not be specified for Lambda targets/); + }); + test('Can add self-registering target to imported TargetGroup', () => { // GIVEN const app = new cdk.App(); diff --git a/packages/@aws-cdk/aws-elasticsearch/package.json b/packages/@aws-cdk/aws-elasticsearch/package.json index 0a5e8839a0843..bbcdd5dbe8061 100644 --- a/packages/@aws-cdk/aws-elasticsearch/package.json +++ b/packages/@aws-cdk/aws-elasticsearch/package.json @@ -84,7 +84,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/aws-certificatemanager": "0.0.0", diff --git a/packages/@aws-cdk/aws-emr/package.json b/packages/@aws-cdk/aws-emr/package.json index ae9f2a89744ea..d8638f3174f7a 100644 --- a/packages/@aws-cdk/aws-emr/package.json +++ b/packages/@aws-cdk/aws-emr/package.json @@ -83,7 +83,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-emrcontainers/package.json b/packages/@aws-cdk/aws-emrcontainers/package.json index 5762e656d6761..72b6f669f603a 100644 --- a/packages/@aws-cdk/aws-emrcontainers/package.json +++ b/packages/@aws-cdk/aws-emrcontainers/package.json @@ -87,7 +87,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-events-targets/README.md b/packages/@aws-cdk/aws-events-targets/README.md index d98b08d652086..34157fef412b5 100644 --- a/packages/@aws-cdk/aws-events-targets/README.md +++ b/packages/@aws-cdk/aws-events-targets/README.md @@ -167,13 +167,13 @@ const role = new iam.Role(this, 'Role', { assumedBy: new iam.ServicePrincipal('events.amazonaws.com'), }); const stateMachine = new sfn.StateMachine(this, 'SM', { - definition: new sfn.Wait(this, 'Hello', { time: sfn.WaitTime.duration(cdk.Duration.seconds(10)) }), - role, + definition: new sfn.Wait(this, 'Hello', { time: sfn.WaitTime.duration(cdk.Duration.seconds(10)) }) }); rule.addTarget(new targets.SfnStateMachine(stateMachine, { input: events.RuleTargetInput.fromObject({ SomeParam: 'SomeValue' }), deadLetterQueue: dlq, + role: role })); ``` diff --git a/packages/@aws-cdk/aws-events-targets/package.json b/packages/@aws-cdk/aws-events-targets/package.json index 77a2dea2bfa68..650961f9757ef 100644 --- a/packages/@aws-cdk/aws-events-targets/package.json +++ b/packages/@aws-cdk/aws-events-targets/package.json @@ -86,7 +86,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "aws-sdk": "^2.848.0", "aws-sdk-mock": "5.6.0", "jest": "^27.5.1" diff --git a/packages/@aws-cdk/aws-events-targets/test/stepfunctions/statemachine.test.ts b/packages/@aws-cdk/aws-events-targets/test/stepfunctions/statemachine.test.ts index 158b19f34fa0a..6327213b7a744 100644 --- a/packages/@aws-cdk/aws-events-targets/test/stepfunctions/statemachine.test.ts +++ b/packages/@aws-cdk/aws-events-targets/test/stepfunctions/statemachine.test.ts @@ -68,12 +68,12 @@ test('Existing role can be used for State machine Rule target', () => { }); const stateMachine = new sfn.StateMachine(stack, 'SM', { definition: new sfn.Wait(stack, 'Hello', { time: sfn.WaitTime.duration(cdk.Duration.seconds(10)) }), - role, }); // WHEN rule.addTarget(new targets.SfnStateMachine(stateMachine, { input: events.RuleTargetInput.fromObject({ SomeParam: 'SomeValue' }), + role: role, })); // THEN @@ -125,13 +125,13 @@ test('specifying retry policy', () => { }); const stateMachine = new sfn.StateMachine(stack, 'SM', { definition: new sfn.Wait(stack, 'Hello', { time: sfn.WaitTime.duration(cdk.Duration.seconds(10)) }), - role, }); rule.addTarget(new targets.SfnStateMachine(stateMachine, { input: events.RuleTargetInput.fromObject({ SomeParam: 'SomeValue' }), maxEventAge: cdk.Duration.hours(2), retryAttempts: 2, + role: role, })); // THEN @@ -151,7 +151,7 @@ test('specifying retry policy', () => { }, RoleArn: { 'Fn::GetAtt': [ - 'SMEventsRoleB320A902', + 'Role1ABCC5F0', 'Arn', ], }, @@ -176,13 +176,13 @@ test('use a Dead Letter Queue for the rule target', () => { }); const stateMachine = new sfn.StateMachine(stack, 'SM', { definition: new sfn.Wait(stack, 'Hello', { time: sfn.WaitTime.duration(cdk.Duration.seconds(10)) }), - role, }); // WHEN rule.addTarget(new targets.SfnStateMachine(stateMachine, { input: events.RuleTargetInput.fromObject({ SomeParam: 'SomeValue' }), deadLetterQueue: dlq, + role: role, })); // the Permission resource should be in the event stack @@ -206,7 +206,7 @@ test('use a Dead Letter Queue for the rule target', () => { Input: '{"SomeParam":"SomeValue"}', RoleArn: { 'Fn::GetAtt': [ - 'SMEventsRoleB320A902', + 'Role1ABCC5F0', 'Arn', ], }, diff --git a/packages/@aws-cdk/aws-events/lib/connection.ts b/packages/@aws-cdk/aws-events/lib/connection.ts index 7eafe3b1196a7..fbedd37e8eb39 100644 --- a/packages/@aws-cdk/aws-events/lib/connection.ts +++ b/packages/@aws-cdk/aws-events/lib/connection.ts @@ -65,11 +65,11 @@ export abstract class Authorization { return { authorizationType: AuthorizationType.API_KEY, authParameters: { - ApiKeyAuthParameters: { - ApiKeyName: apiKeyName, - ApiKeyValue: apiKeyValue, + apiKeyAuthParameters: { + apiKeyName: apiKeyName, + apiKeyValue: apiKeyValue.toString(), }, - }, + } as CfnConnection.AuthParametersProperty, }; } }(); @@ -84,11 +84,11 @@ export abstract class Authorization { return { authorizationType: AuthorizationType.BASIC, authParameters: { - BasicAuthParameters: { - Username: username, - Password: password, + basicAuthParameters: { + username: username, + password: password.toString(), }, - }, + } as CfnConnection.AuthParametersProperty, }; } }(); @@ -107,20 +107,20 @@ export abstract class Authorization { return { authorizationType: AuthorizationType.OAUTH_CLIENT_CREDENTIALS, authParameters: { - OAuthParameters: { - AuthorizationEndpoint: props.authorizationEndpoint, - ClientParameters: { - ClientID: props.clientId, - ClientSecret: props.clientSecret, + oAuthParameters: { + authorizationEndpoint: props.authorizationEndpoint, + clientParameters: { + clientId: props.clientId, + clientSecret: props.clientSecret.toString(), }, - HttpMethod: props.httpMethod, - OAuthHttpParameters: { - BodyParameters: renderHttpParameters(props.bodyParameters), - HeaderParameters: renderHttpParameters(props.headerParameters), - QueryStringParameters: renderHttpParameters(props.queryStringParameters), + httpMethod: props.httpMethod, + oAuthHttpParameters: { + bodyParameters: renderHttpParameters(props.bodyParameters), + headerParameters: renderHttpParameters(props.headerParameters), + queryStringParameters: renderHttpParameters(props.queryStringParameters), }, }, - }, + } as CfnConnection.AuthParametersProperty, }; } }(); @@ -197,9 +197,9 @@ export abstract class HttpParameter { return new class extends HttpParameter { public _render(name: string) { return { - Key: name, - Value: value, - }; + key: name, + value, + } as CfnConnection.ParameterProperty; } }(); } @@ -211,10 +211,10 @@ export abstract class HttpParameter { return new class extends HttpParameter { public _render(name: string) { return { - Key: name, - Value: value, - IsSecretValue: true, - }; + key: name, + value: value.toString(), + isValueSecret: true, + } as CfnConnection.ParameterProperty; } }(); } @@ -345,16 +345,16 @@ export class Connection extends Resource implements IConnection { const authBind = props.authorization._bind(); const invocationHttpParameters = !!props.headerParameters || !!props.queryStringParameters || !!props.bodyParameters ? { - BodyParameters: renderHttpParameters(props.bodyParameters), - HeaderParameters: renderHttpParameters(props.headerParameters), - QueryStringParameters: renderHttpParameters(props.queryStringParameters), + bodyParameters: renderHttpParameters(props.bodyParameters), + headerParameters: renderHttpParameters(props.headerParameters), + queryStringParameters: renderHttpParameters(props.queryStringParameters), } : undefined; let connection = new CfnConnection(this, 'Connection', { authorizationType: authBind.authorizationType, authParameters: { ...authBind.authParameters, - InvocationHttpParameters: invocationHttpParameters, + invocationHttpParameters: invocationHttpParameters, }, description: props.description, name: this.physicalName, @@ -415,7 +415,7 @@ enum AuthorizationType { OAUTH_CLIENT_CREDENTIALS = 'OAUTH_CLIENT_CREDENTIALS', } -function renderHttpParameters(ps?: Record) { +function renderHttpParameters(ps?: Record): CfnConnection.ParameterProperty[] | undefined { if (!ps || Object.keys(ps).length === 0) { return undefined; } return Object.entries(ps).map(([name, p]) => p._render(name)); diff --git a/packages/@aws-cdk/aws-events/package.json b/packages/@aws-cdk/aws-events/package.json index e9f0e1917745b..377a1c8ac9df9 100644 --- a/packages/@aws-cdk/aws-events/package.json +++ b/packages/@aws-cdk/aws-events/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-eventschemas/package.json b/packages/@aws-cdk/aws-eventschemas/package.json index d8d89608e6e95..42b0c59bdf000 100644 --- a/packages/@aws-cdk/aws-eventschemas/package.json +++ b/packages/@aws-cdk/aws-eventschemas/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-finspace/package.json b/packages/@aws-cdk/aws-finspace/package.json index 7c3ae60c58506..cdbf1478941c4 100644 --- a/packages/@aws-cdk/aws-finspace/package.json +++ b/packages/@aws-cdk/aws-finspace/package.json @@ -87,7 +87,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-fis/package.json b/packages/@aws-cdk/aws-fis/package.json index 614d64919c252..ca2716b5c2b54 100644 --- a/packages/@aws-cdk/aws-fis/package.json +++ b/packages/@aws-cdk/aws-fis/package.json @@ -87,7 +87,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-fms/package.json b/packages/@aws-cdk/aws-fms/package.json index 1366f66c49454..5ab1866fdca94 100644 --- a/packages/@aws-cdk/aws-fms/package.json +++ b/packages/@aws-cdk/aws-fms/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-forecast/package.json b/packages/@aws-cdk/aws-forecast/package.json index e4431039dc27c..f73f6e685b3f3 100644 --- a/packages/@aws-cdk/aws-forecast/package.json +++ b/packages/@aws-cdk/aws-forecast/package.json @@ -88,7 +88,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-frauddetector/package.json b/packages/@aws-cdk/aws-frauddetector/package.json index b30bf59153cd7..de77f2a097f9f 100644 --- a/packages/@aws-cdk/aws-frauddetector/package.json +++ b/packages/@aws-cdk/aws-frauddetector/package.json @@ -87,7 +87,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-fsx/package.json b/packages/@aws-cdk/aws-fsx/package.json index 0b0c1f0426004..0d1a669039c85 100644 --- a/packages/@aws-cdk/aws-fsx/package.json +++ b/packages/@aws-cdk/aws-fsx/package.json @@ -86,7 +86,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/aws-ec2": "0.0.0", diff --git a/packages/@aws-cdk/aws-gamelift/package.json b/packages/@aws-cdk/aws-gamelift/package.json index 8e0aa9635f092..401b1c4375cd7 100644 --- a/packages/@aws-cdk/aws-gamelift/package.json +++ b/packages/@aws-cdk/aws-gamelift/package.json @@ -83,7 +83,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-globalaccelerator-endpoints/package.json b/packages/@aws-cdk/aws-globalaccelerator-endpoints/package.json index a2247dd577855..ff31bbcb08cee 100644 --- a/packages/@aws-cdk/aws-globalaccelerator-endpoints/package.json +++ b/packages/@aws-cdk/aws-globalaccelerator-endpoints/package.json @@ -80,7 +80,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "aws-sdk": "^2.848.0", "aws-sdk-mock": "5.6.0", "jest": "^27.5.1" diff --git a/packages/@aws-cdk/aws-globalaccelerator/package.json b/packages/@aws-cdk/aws-globalaccelerator/package.json index 14f3c7036f24b..10223d0d40b55 100644 --- a/packages/@aws-cdk/aws-globalaccelerator/package.json +++ b/packages/@aws-cdk/aws-globalaccelerator/package.json @@ -87,7 +87,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/aws-ec2": "0.0.0", diff --git a/packages/@aws-cdk/aws-glue/package.json b/packages/@aws-cdk/aws-glue/package.json index 72d87b20c6ee1..29c190ddeca63 100644 --- a/packages/@aws-cdk/aws-glue/package.json +++ b/packages/@aws-cdk/aws-glue/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/cx-api": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-greengrass/package.json b/packages/@aws-cdk/aws-greengrass/package.json index d4b6a23bc436e..8677a50cafc70 100644 --- a/packages/@aws-cdk/aws-greengrass/package.json +++ b/packages/@aws-cdk/aws-greengrass/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-greengrassv2/package.json b/packages/@aws-cdk/aws-greengrassv2/package.json index af50ddd6ab9c6..4456cac21c5ff 100644 --- a/packages/@aws-cdk/aws-greengrassv2/package.json +++ b/packages/@aws-cdk/aws-greengrassv2/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-groundstation/package.json b/packages/@aws-cdk/aws-groundstation/package.json index faf4496480b5f..a6850e0bcd71a 100644 --- a/packages/@aws-cdk/aws-groundstation/package.json +++ b/packages/@aws-cdk/aws-groundstation/package.json @@ -87,7 +87,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-guardduty/package.json b/packages/@aws-cdk/aws-guardduty/package.json index e802c1d15247d..fd8c3f540cdd6 100644 --- a/packages/@aws-cdk/aws-guardduty/package.json +++ b/packages/@aws-cdk/aws-guardduty/package.json @@ -83,7 +83,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-healthlake/package.json b/packages/@aws-cdk/aws-healthlake/package.json index 20fabb1ffe47f..3c6e25ae6d523 100644 --- a/packages/@aws-cdk/aws-healthlake/package.json +++ b/packages/@aws-cdk/aws-healthlake/package.json @@ -87,7 +87,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-iam/package.json b/packages/@aws-cdk/aws-iam/package.json index 7172a6e453245..5a405fbce243d 100644 --- a/packages/@aws-cdk/aws-iam/package.json +++ b/packages/@aws-cdk/aws-iam/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", "@types/aws-lambda": "^8.10.92", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "@types/sinon": "^9.0.11", "jest": "^27.5.1", "sinon": "^9.2.4" diff --git a/packages/@aws-cdk/aws-imagebuilder/package.json b/packages/@aws-cdk/aws-imagebuilder/package.json index bacd907148a73..6d7581afc8a3f 100644 --- a/packages/@aws-cdk/aws-imagebuilder/package.json +++ b/packages/@aws-cdk/aws-imagebuilder/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-inspector/package.json b/packages/@aws-cdk/aws-inspector/package.json index 5bdb7a30c188c..446b49eec052b 100644 --- a/packages/@aws-cdk/aws-inspector/package.json +++ b/packages/@aws-cdk/aws-inspector/package.json @@ -83,7 +83,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-inspectorv2/package.json b/packages/@aws-cdk/aws-inspectorv2/package.json index 58bc8bd45bf6b..6d3ec7b525446 100644 --- a/packages/@aws-cdk/aws-inspectorv2/package.json +++ b/packages/@aws-cdk/aws-inspectorv2/package.json @@ -88,7 +88,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-iot-actions/package.json b/packages/@aws-cdk/aws-iot-actions/package.json index 2567eea67ecda..a2db6d0529f63 100644 --- a/packages/@aws-cdk/aws-iot-actions/package.json +++ b/packages/@aws-cdk/aws-iot-actions/package.json @@ -82,7 +82,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "constructs": "^3.3.69", "jest": "^27.5.1" }, diff --git a/packages/@aws-cdk/aws-iot/package.json b/packages/@aws-cdk/aws-iot/package.json index 6f153018f0543..e83a310c74109 100644 --- a/packages/@aws-cdk/aws-iot/package.json +++ b/packages/@aws-cdk/aws-iot/package.json @@ -84,7 +84,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-iot1click/package.json b/packages/@aws-cdk/aws-iot1click/package.json index 656dee749a698..d0550686c0a7f 100644 --- a/packages/@aws-cdk/aws-iot1click/package.json +++ b/packages/@aws-cdk/aws-iot1click/package.json @@ -84,7 +84,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-iotanalytics/package.json b/packages/@aws-cdk/aws-iotanalytics/package.json index 534ffed3675a9..081930aad26ad 100644 --- a/packages/@aws-cdk/aws-iotanalytics/package.json +++ b/packages/@aws-cdk/aws-iotanalytics/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-iotcoredeviceadvisor/package.json b/packages/@aws-cdk/aws-iotcoredeviceadvisor/package.json index ecb59fded3ba8..15acc04b2e0f6 100644 --- a/packages/@aws-cdk/aws-iotcoredeviceadvisor/package.json +++ b/packages/@aws-cdk/aws-iotcoredeviceadvisor/package.json @@ -87,7 +87,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-iotevents-actions/.eslintrc.js b/packages/@aws-cdk/aws-iotevents-actions/.eslintrc.js new file mode 100644 index 0000000000000..2658ee8727166 --- /dev/null +++ b/packages/@aws-cdk/aws-iotevents-actions/.eslintrc.js @@ -0,0 +1,3 @@ +const baseConfig = require('@aws-cdk/cdk-build-tools/config/eslintrc'); +baseConfig.parserOptions.project = __dirname + '/tsconfig.json'; +module.exports = baseConfig; diff --git a/packages/@aws-cdk/aws-iotevents-actions/.gitignore b/packages/@aws-cdk/aws-iotevents-actions/.gitignore new file mode 100644 index 0000000000000..266c0684c6844 --- /dev/null +++ b/packages/@aws-cdk/aws-iotevents-actions/.gitignore @@ -0,0 +1,19 @@ +*.js +*.js.map +*.d.ts +tsconfig.json +node_modules +*.generated.ts +dist +.jsii + +.LAST_BUILD +.nyc_output +coverage +nyc.config.js +.LAST_PACKAGE +*.snk +!.eslintrc.js +!jest.config.js + +junit.xml diff --git a/packages/@aws-cdk/aws-iotevents-actions/.npmignore b/packages/@aws-cdk/aws-iotevents-actions/.npmignore new file mode 100644 index 0000000000000..9e51b66a1dba9 --- /dev/null +++ b/packages/@aws-cdk/aws-iotevents-actions/.npmignore @@ -0,0 +1,28 @@ +# Don't include original .ts files when doing `npm pack` +*.ts +!*.d.ts +coverage +.nyc_output +*.tgz + +dist +.LAST_PACKAGE +.LAST_BUILD +!*.js + +# Include .jsii +!.jsii + +*.snk + +*.tsbuildinfo + +tsconfig.json +.eslintrc.js +jest.config.js + +# exclude cdk artifacts +**/cdk.out +junit.xml +test/ +!*.lit.ts diff --git a/packages/@aws-cdk/aws-iotevents-actions/LICENSE b/packages/@aws-cdk/aws-iotevents-actions/LICENSE new file mode 100644 index 0000000000000..82ad00bb02d0b --- /dev/null +++ b/packages/@aws-cdk/aws-iotevents-actions/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2018-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/@aws-cdk/aws-iotevents-actions/NOTICE b/packages/@aws-cdk/aws-iotevents-actions/NOTICE new file mode 100644 index 0000000000000..1b7adbb891265 --- /dev/null +++ b/packages/@aws-cdk/aws-iotevents-actions/NOTICE @@ -0,0 +1,2 @@ +AWS Cloud Development Kit (AWS CDK) +Copyright 2018-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. diff --git a/packages/@aws-cdk/aws-iotevents-actions/README.md b/packages/@aws-cdk/aws-iotevents-actions/README.md new file mode 100644 index 0000000000000..eb88dc82bb3c3 --- /dev/null +++ b/packages/@aws-cdk/aws-iotevents-actions/README.md @@ -0,0 +1,50 @@ +# Actions for AWS::IoTEvents Detector Model + + +--- + +![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. + +--- + + + +This library contains integration classes to specify actions of state events of Detector Model in `@aws-cdk/aws-iotevents`. +Instances of these classes should be passed to `State` defined in `@aws-cdk/aws-iotevents` +You can define built-in actions to use a timer or set a variable, or send data to other AWS resources. + +This library contains integration classes to use a timer or set a variable, or send data to other AWS resources. +AWS IoT Events can trigger actions when it detects a specified event or transition event. + +Currently supported are: + +- Invoke a Lambda function + +## Invoke a Lambda function + +The code snippet below creates an Action that invoke a Lambda function +when it is triggered. + +```ts +import * as iotevents from '@aws-cdk/aws-iotevents'; +import * as actions from '@aws-cdk/aws-iotevents-actions'; +import * as lambda from '@aws-cdk/aws-lambda'; + +declare const input: iotevents.IInput; +declare const func: lambda.IFunction; + +const state = new iotevents.State({ + stateName: 'MyState', + onEnter: [{ + eventName: 'test-event', + condition: iotevents.Expression.currentInput(input), + actions: [new actions.LambdaInvokeAction(func)], + }], +}); +``` diff --git a/packages/@aws-cdk/aws-iotevents-actions/jest.config.js b/packages/@aws-cdk/aws-iotevents-actions/jest.config.js new file mode 100644 index 0000000000000..3a2fd93a1228a --- /dev/null +++ b/packages/@aws-cdk/aws-iotevents-actions/jest.config.js @@ -0,0 +1,2 @@ +const baseConfig = require('@aws-cdk/cdk-build-tools/config/jest.config'); +module.exports = baseConfig; diff --git a/packages/@aws-cdk/aws-iotevents-actions/lib/index.ts b/packages/@aws-cdk/aws-iotevents-actions/lib/index.ts new file mode 100644 index 0000000000000..4b2ec39329315 --- /dev/null +++ b/packages/@aws-cdk/aws-iotevents-actions/lib/index.ts @@ -0,0 +1 @@ +export * from './lambda-invoke-action'; diff --git a/packages/@aws-cdk/aws-iotevents-actions/lib/lambda-invoke-action.ts b/packages/@aws-cdk/aws-iotevents-actions/lib/lambda-invoke-action.ts new file mode 100644 index 0000000000000..af9dec5d32472 --- /dev/null +++ b/packages/@aws-cdk/aws-iotevents-actions/lib/lambda-invoke-action.ts @@ -0,0 +1,25 @@ +import * as iotevents from '@aws-cdk/aws-iotevents'; +import * as lambda from '@aws-cdk/aws-lambda'; +import { Construct } from 'constructs'; + +/** + * The action to write the data to an AWS Lambda function. + */ +export class LambdaInvokeAction implements iotevents.IAction { + /** + * @param func the AWS Lambda function to be invoked by this action + */ + constructor(private readonly func: lambda.IFunction) { + } + + bind(_scope: Construct, options: iotevents.ActionBindOptions): iotevents.ActionConfig { + this.func.grantInvoke(options.role); + return { + configuration: { + lambda: { + functionArn: this.func.functionArn, + }, + }, + }; + } +} diff --git a/packages/@aws-cdk/aws-iotevents-actions/package.json b/packages/@aws-cdk/aws-iotevents-actions/package.json new file mode 100644 index 0000000000000..90a925459abc9 --- /dev/null +++ b/packages/@aws-cdk/aws-iotevents-actions/package.json @@ -0,0 +1,106 @@ +{ + "name": "@aws-cdk/aws-iotevents-actions", + "version": "0.0.0", + "description": "Receipt Detector Model actions for AWS IoT Events", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "jsii": { + "outdir": "dist", + "targets": { + "java": { + "package": "software.amazon.awscdk.services.iotevents.actions", + "maven": { + "groupId": "software.amazon.awscdk", + "artifactId": "iotevents-actions" + } + }, + "dotnet": { + "namespace": "Amazon.CDK.AWS.IoTEvents.Actions", + "packageId": "Amazon.CDK.AWS.IoTEvents.Actions", + "iconUrl": "https://raw.githubusercontent.com/aws/aws-cdk/master/logo/default-256-dark.png" + }, + "python": { + "distName": "aws-cdk.aws-iotevents-actions", + "module": "aws_cdk.aws_iotevents_actions", + "classifiers": [ + "Framework :: AWS CDK", + "Framework :: AWS CDK :: 1" + ] + } + }, + "projectReferences": true + }, + "repository": { + "type": "git", + "url": "https://github.com/aws/aws-cdk.git", + "directory": "packages/@aws-cdk/aws-iotevents-actions" + }, + "scripts": { + "build": "cdk-build", + "watch": "cdk-watch", + "lint": "cdk-lint", + "test": "cdk-test", + "integ": "cdk-integ", + "pkglint": "pkglint -f", + "package": "cdk-package", + "awslint": "cdk-awslint", + "build+test+package": "yarn build+test && yarn package", + "build+test": "yarn build && yarn test", + "compat": "cdk-compat", + "rosetta:extract": "yarn --silent jsii-rosetta extract", + "build+extract": "yarn build && yarn rosetta:extract", + "build+test+extract": "yarn build+test && yarn rosetta:extract" + }, + "cdk-build": { + "env": { + "AWSLINT_BASE_CONSTRUCT": true + } + }, + "keywords": [ + "aws", + "cdk", + "constructs", + "AWS::IoTEvents", + "aws-iotevents-actions" + ], + "author": { + "name": "Amazon Web Services", + "url": "https://aws.amazon.com", + "organization": true + }, + "license": "Apache-2.0", + "devDependencies": { + "@aws-cdk/assertions": "0.0.0", + "@aws-cdk/cdk-build-tools": "0.0.0", + "@aws-cdk/cdk-integ-tools": "0.0.0", + "@aws-cdk/pkglint": "0.0.0", + "@types/jest": "^27.4.1", + "jest": "^27.5.1" + }, + "dependencies": { + "@aws-cdk/aws-iam": "0.0.0", + "@aws-cdk/aws-iotevents": "0.0.0", + "@aws-cdk/aws-lambda": "0.0.0", + "@aws-cdk/core": "0.0.0", + "constructs": "^3.3.69" + }, + "homepage": "https://github.com/aws/aws-cdk", + "peerDependencies": { + "@aws-cdk/aws-iam": "0.0.0", + "@aws-cdk/aws-iotevents": "0.0.0", + "@aws-cdk/aws-lambda": "0.0.0", + "@aws-cdk/core": "0.0.0", + "constructs": "^3.3.69" + }, + "engines": { + "node": ">= 10.13.0 <13 || >=13.7.0" + }, + "stability": "experimental", + "maturity": "experimental", + "awscdkio": { + "announce": false + }, + "publishConfig": { + "tag": "latest" + } +} diff --git a/packages/@aws-cdk/aws-iotevents-actions/test/lambda/integ.lambda-invoke-action.expected.json b/packages/@aws-cdk/aws-iotevents-actions/test/lambda/integ.lambda-invoke-action.expected.json new file mode 100644 index 0000000000000..be70d65360d32 --- /dev/null +++ b/packages/@aws-cdk/aws-iotevents-actions/test/lambda/integ.lambda-invoke-action.expected.json @@ -0,0 +1,162 @@ +{ + "Resources": { + "MyInput08947B23": { + "Type": "AWS::IoTEvents::Input", + "Properties": { + "InputDefinition": { + "Attributes": [ + { + "JsonPath": "payload.deviceId" + } + ] + }, + "InputName": "test_input" + } + }, + "MyFunctionServiceRole3C357FF2": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "MyFunction3BAA72D1": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "\n exports.handler = (event) => {\n console.log(\"It is test for lambda action of AWS IoT Rule.\", event);\n };" + }, + "Role": { + "Fn::GetAtt": [ + "MyFunctionServiceRole3C357FF2", + "Arn" + ] + }, + "Handler": "index.handler", + "Runtime": "nodejs14.x" + }, + "DependsOn": [ + "MyFunctionServiceRole3C357FF2" + ] + }, + "MyDetectorModelDetectorModelRoleF2FB4D88": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "iotevents.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "MyDetectorModelDetectorModelRoleDefaultPolicy82887422": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "lambda:InvokeFunction", + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "MyFunction3BAA72D1", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "MyDetectorModelDetectorModelRoleDefaultPolicy82887422", + "Roles": [ + { + "Ref": "MyDetectorModelDetectorModelRoleF2FB4D88" + } + ] + } + }, + "MyDetectorModel559C0B0E": { + "Type": "AWS::IoTEvents::DetectorModel", + "Properties": { + "DetectorModelDefinition": { + "InitialStateName": "MyState", + "States": [ + { + "OnEnter": { + "Events": [ + { + "Actions": [ + { + "Lambda": { + "FunctionArn": { + "Fn::GetAtt": [ + "MyFunction3BAA72D1", + "Arn" + ] + } + } + } + ], + "Condition": { + "Fn::Join": [ + "", + [ + "currentInput(\"", + { + "Ref": "MyInput08947B23" + }, + "\")" + ] + ] + }, + "EventName": "test-event" + } + ] + }, + "OnInput": {}, + "StateName": "MyState" + } + ] + }, + "RoleArn": { + "Fn::GetAtt": [ + "MyDetectorModelDetectorModelRoleF2FB4D88", + "Arn" + ] + }, + "Key": "payload.deviceId" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-iotevents-actions/test/lambda/integ.lambda-invoke-action.ts b/packages/@aws-cdk/aws-iotevents-actions/test/lambda/integ.lambda-invoke-action.ts new file mode 100644 index 0000000000000..2084f2cb7bd9c --- /dev/null +++ b/packages/@aws-cdk/aws-iotevents-actions/test/lambda/integ.lambda-invoke-action.ts @@ -0,0 +1,48 @@ +/** + * Stack verification steps: + * * put a message + * * aws iotevents-data batch-put-message --messages=messageId=(date | md5),inputName=test_input,payload=(echo '{"payload":{"temperature":31.9,"deviceId":"000"}}' | base64) + * * verify that the lambda logs be put + */ +import * as iotevents from '@aws-cdk/aws-iotevents'; +import * as lambda from '@aws-cdk/aws-lambda'; +import * as cdk from '@aws-cdk/core'; +import * as actions from '../../lib'; + +class TestStack extends cdk.Stack { + constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { + super(scope, id, props); + + const input = new iotevents.Input(this, 'MyInput', { + inputName: 'test_input', + attributeJsonPaths: ['payload.deviceId'], + }); + const func = new lambda.Function(this, 'MyFunction', { + runtime: lambda.Runtime.NODEJS_14_X, + handler: 'index.handler', + code: lambda.Code.fromInline(` + exports.handler = (event) => { + console.log("It is test for lambda action of AWS IoT Rule.", event); + };`, + ), + }); + + const state = new iotevents.State({ + stateName: 'MyState', + onEnter: [{ + eventName: 'test-event', + condition: iotevents.Expression.currentInput(input), + actions: [new actions.LambdaInvokeAction(func)], + }], + }); + + new iotevents.DetectorModel(this, 'MyDetectorModel', { + detectorKey: 'payload.deviceId', + initialState: state, + }); + } +} + +const app = new cdk.App(); +new TestStack(app, 'lambda-invoke-action-test-stack'); +app.synth(); diff --git a/packages/@aws-cdk/aws-iotevents-actions/test/lambda/lambda-invoke-action.test.ts b/packages/@aws-cdk/aws-iotevents-actions/test/lambda/lambda-invoke-action.test.ts new file mode 100644 index 0000000000000..493114dbd3bb5 --- /dev/null +++ b/packages/@aws-cdk/aws-iotevents-actions/test/lambda/lambda-invoke-action.test.ts @@ -0,0 +1,64 @@ +import { Template } from '@aws-cdk/assertions'; +import * as iotevents from '@aws-cdk/aws-iotevents'; +import * as lambda from '@aws-cdk/aws-lambda'; +import * as cdk from '@aws-cdk/core'; +import * as actions from '../../lib'; + +let stack: cdk.Stack; +let input: iotevents.IInput; +let func: lambda.IFunction; +beforeEach(() => { + stack = new cdk.Stack(); + input = iotevents.Input.fromInputName(stack, 'MyInput', 'test-input'); + func = lambda.Function.fromFunctionAttributes(stack, 'MyFunction', { + functionArn: 'arn:aws:lambda:us-east-1:123456789012:function:MyFn', + sameEnvironment: true, + }); +}); + +test('Default property', () => { + // WHEN + new iotevents.DetectorModel(stack, 'MyDetectorModel', { + initialState: new iotevents.State({ + stateName: 'test-state', + onEnter: [{ + eventName: 'test-eventName', + condition: iotevents.Expression.currentInput(input), + actions: [new actions.LambdaInvokeAction(func)], + }], + }), + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::IoTEvents::DetectorModel', { + DetectorModelDefinition: { + States: [{ + OnEnter: { + Events: [{ + Actions: [{ + Lambda: { + FunctionArn: 'arn:aws:lambda:us-east-1:123456789012:function:MyFn', + }, + }], + }], + }, + }], + }, + RoleArn: { + 'Fn::GetAtt': ['MyDetectorModelDetectorModelRoleF2FB4D88', 'Arn'], + }, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [{ + Action: 'lambda:InvokeFunction', + Effect: 'Allow', + Resource: 'arn:aws:lambda:us-east-1:123456789012:function:MyFn', + }], + }, + Roles: [{ + Ref: 'MyDetectorModelDetectorModelRoleF2FB4D88', + }], + }); +}); diff --git a/packages/@aws-cdk/aws-iotevents/README.md b/packages/@aws-cdk/aws-iotevents/README.md index 809bac071ef7d..0c7e491c65fae 100644 --- a/packages/@aws-cdk/aws-iotevents/README.md +++ b/packages/@aws-cdk/aws-iotevents/README.md @@ -46,8 +46,15 @@ The following example creates an AWS IoT Events detector model to your stack. The detector model need a reference to at least one AWS IoT Events input. AWS IoT Events inputs enable the detector to get MQTT payload values from IoT Core rules. +You can define built-in actions to use a timer or set a variable, or send data to other AWS resources. +See also [@aws-cdk/aws-iotevents-actions](https://docs.aws.amazon.com/cdk/api/v1/docs/aws-iotevents-actions-readme.html) for other actions. + ```ts import * as iotevents from '@aws-cdk/aws-iotevents'; +import * as actions from '@aws-cdk/aws-iotevents-actions'; +import * as lambda from '@aws-cdk/aws-lambda'; + +declare const func: lambda.IFunction; const input = new iotevents.Input(this, 'MyInput', { inputName: 'my_input', // optional @@ -59,6 +66,7 @@ const warmState = new iotevents.State({ onEnter: [{ eventName: 'test-event', condition: iotevents.Expression.currentInput(input), + actions: [new actions.LambdaInvokeAction(func)], // optional }], }); const coldState = new iotevents.State({ @@ -72,6 +80,7 @@ warmState.transitionTo(coldState, { iotevents.Expression.inputAttribute(input, 'payload.temperature'), iotevents.Expression.fromString('10'), ), + executing: [new actions.LambdaInvokeAction(func)], // optional }); // transit to warmState when temperature is 20 coldState.transitionTo(warmState, { diff --git a/packages/@aws-cdk/aws-iotevents/lib/action.ts b/packages/@aws-cdk/aws-iotevents/lib/action.ts new file mode 100644 index 0000000000000..f43c6b6c91626 --- /dev/null +++ b/packages/@aws-cdk/aws-iotevents/lib/action.ts @@ -0,0 +1,33 @@ +import * as iam from '@aws-cdk/aws-iam'; +import { Construct } from 'constructs'; +import { CfnDetectorModel } from './iotevents.generated'; + +/** + * Options when binding a Action to a detector model. + */ +export interface ActionBindOptions { + /** + * The IAM role assumed by IoT Events to perform the action. + */ + readonly role: iam.IRole; +} + +/** + * An abstract action for DetectorModel. + */ +export interface IAction { + /** + * Returns the AWS IoT Events action specification. + */ + bind(scope: Construct, options: ActionBindOptions): ActionConfig; +} + +/** + * Properties for a AWS IoT Events action + */ +export interface ActionConfig { + /** + * The configuration for this action. + */ + readonly configuration: CfnDetectorModel.ActionProperty; +} diff --git a/packages/@aws-cdk/aws-iotevents/lib/detector-model.ts b/packages/@aws-cdk/aws-iotevents/lib/detector-model.ts index 35128bc4531e6..1545e8ec69446 100644 --- a/packages/@aws-cdk/aws-iotevents/lib/detector-model.ts +++ b/packages/@aws-cdk/aws-iotevents/lib/detector-model.ts @@ -124,7 +124,7 @@ export class DetectorModel extends Resource implements IDetectorModel { key: props.detectorKey, detectorModelDefinition: { initialStateName: props.initialState.stateName, - states: props.initialState._collectStateJsons(new Set()), + states: props.initialState._collectStateJsons(this, { role }, new Set()), }, roleArn: role.roleArn, }); diff --git a/packages/@aws-cdk/aws-iotevents/lib/event.ts b/packages/@aws-cdk/aws-iotevents/lib/event.ts index 610469db9c32c..fd452686e054e 100644 --- a/packages/@aws-cdk/aws-iotevents/lib/event.ts +++ b/packages/@aws-cdk/aws-iotevents/lib/event.ts @@ -1,7 +1,8 @@ +import { IAction } from './action'; import { Expression } from './expression'; /** - * Specifies the actions to be performed when the condition evaluates to TRUE. + * Specifies the actions to be performed when the condition evaluates to `true`. */ export interface Event { /** @@ -10,9 +11,16 @@ export interface Event { readonly eventName: string; /** - * The Boolean expression that, when TRUE, causes the actions to be performed. + * The Boolean expression that, when `true`, causes the actions to be performed. * * @default - none (the actions are always executed) */ readonly condition?: Expression; + + /** + * The actions to be performed. + * + * @default - no actions will be performed + */ + readonly actions?: IAction[]; } diff --git a/packages/@aws-cdk/aws-iotevents/lib/index.ts b/packages/@aws-cdk/aws-iotevents/lib/index.ts index 24913635ebe50..b949a47454c3a 100644 --- a/packages/@aws-cdk/aws-iotevents/lib/index.ts +++ b/packages/@aws-cdk/aws-iotevents/lib/index.ts @@ -1,3 +1,4 @@ +export * from './action'; export * from './detector-model'; export * from './event'; export * from './expression'; diff --git a/packages/@aws-cdk/aws-iotevents/lib/state.ts b/packages/@aws-cdk/aws-iotevents/lib/state.ts index 67ee6a32802ec..0159628c4a4ff 100644 --- a/packages/@aws-cdk/aws-iotevents/lib/state.ts +++ b/packages/@aws-cdk/aws-iotevents/lib/state.ts @@ -1,3 +1,5 @@ +import { Construct } from 'constructs'; +import { IAction, ActionBindOptions } from './action'; import { Event } from './event'; import { Expression } from './expression'; import { CfnDetectorModel } from './iotevents.generated'; @@ -15,13 +17,20 @@ export interface TransitionOptions { /** * The condition that is used to determine to cause the state transition and the actions. - * When this was evaluated to TRUE, the state transition and the actions are triggered. + * When this was evaluated to `true`, the state transition and the actions are triggered. */ readonly when: Expression; + + /** + * The actions to be performed with the transition. + * + * @default - no actions will be performed + */ + readonly executing?: IAction[]; } /** - * Specifies the state transition and the actions to be performed when the condition evaluates to TRUE. + * Specifies the state transition and the actions to be performed when the condition evaluates to `true`. */ interface TransitionEvent { /** @@ -30,12 +39,19 @@ interface TransitionEvent { readonly eventName: string; /** - * The Boolean expression that, when TRUE, causes the state transition and the actions to be performed. + * The Boolean expression that, when `true`, causes the state transition and the actions to be performed. */ readonly condition: Expression; /** - * The next state to transit to. When the resuld of condition expression is TRUE, the state is transited. + * The actions to be performed. + * + * @default - no actions will be performed + */ + readonly actions?: IAction[]; + + /** + * The next state to transit to. When the resuld of condition expression is `true`, the state is transited. */ readonly nextState: State; } @@ -75,7 +91,7 @@ export class State { /** * Add a transition event to the state. - * The transition event will be triggered if condition is evaluated to TRUE. + * The transition event will be triggered if condition is evaluated to `true`. * * @param targetState the state that will be transit to when the event triggered * @param options transition options including the condition that causes the state transition @@ -90,6 +106,7 @@ export class State { eventName: options.eventName ?? `${this.stateName}_to_${targetState.stateName}`, nextState: targetState, condition: options.when, + actions: options.executing, }); } @@ -100,16 +117,16 @@ export class State { * * @internal */ - public _collectStateJsons(collectedStates: Set): CfnDetectorModel.StateProperty[] { + public _collectStateJsons(scope: Construct, actionBindOptions: ActionBindOptions, collectedStates: Set): CfnDetectorModel.StateProperty[] { if (collectedStates.has(this)) { return []; } collectedStates.add(this); return [ - this.toStateJson(), + this.toStateJson(scope, actionBindOptions), ...this.transitionEvents.flatMap(transitionEvent => { - return transitionEvent.nextState._collectStateJsons(collectedStates); + return transitionEvent.nextState._collectStateJsons(scope, actionBindOptions, collectedStates); }), ]; } @@ -123,26 +140,35 @@ export class State { return this.props.onEnter?.some(event => event.condition) ?? false; } - private toStateJson(): CfnDetectorModel.StateProperty { + private toStateJson(scope: Construct, actionBindOptions: ActionBindOptions): CfnDetectorModel.StateProperty { const { onEnter } = this.props; return { stateName: this.stateName, - onEnter: onEnter && { events: toEventsJson(onEnter) }, + onEnter: onEnter && { events: toEventsJson(scope, actionBindOptions, onEnter) }, onInput: { - transitionEvents: toTransitionEventsJson(this.transitionEvents), + transitionEvents: toTransitionEventsJson(scope, actionBindOptions, this.transitionEvents), }, }; } } -function toEventsJson(events: Event[]): CfnDetectorModel.EventProperty[] { +function toEventsJson( + scope: Construct, + actionBindOptions: ActionBindOptions, + events: Event[], +): CfnDetectorModel.EventProperty[] { return events.map(event => ({ eventName: event.eventName, condition: event.condition?.evaluate(), + actions: event.actions?.map(action => action.bind(scope, actionBindOptions).configuration), })); } -function toTransitionEventsJson(transitionEvents: TransitionEvent[]): CfnDetectorModel.TransitionEventProperty[] | undefined { +function toTransitionEventsJson( + scope: Construct, + actionBindOptions: ActionBindOptions, + transitionEvents: TransitionEvent[], +): CfnDetectorModel.TransitionEventProperty[] | undefined { if (transitionEvents.length === 0) { return undefined; } @@ -150,6 +176,7 @@ function toTransitionEventsJson(transitionEvents: TransitionEvent[]): CfnDetecto return transitionEvents.map(transitionEvent => ({ eventName: transitionEvent.eventName, condition: transitionEvent.condition.evaluate(), + actions: transitionEvent.actions?.map(action => action.bind(scope, actionBindOptions).configuration), nextState: transitionEvent.nextState.stateName, })); } diff --git a/packages/@aws-cdk/aws-iotevents/package.json b/packages/@aws-cdk/aws-iotevents/package.json index 4435cb7d970d2..3b3b352afe429 100644 --- a/packages/@aws-cdk/aws-iotevents/package.json +++ b/packages/@aws-cdk/aws-iotevents/package.json @@ -86,7 +86,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-iotevents/test/detector-model.test.ts b/packages/@aws-cdk/aws-iotevents/test/detector-model.test.ts index c90a10cf34374..ec754f25c1aad 100644 --- a/packages/@aws-cdk/aws-iotevents/test/detector-model.test.ts +++ b/packages/@aws-cdk/aws-iotevents/test/detector-model.test.ts @@ -139,6 +139,138 @@ test('can set multiple events to State', () => { }); }); +test('can set actions to events', () => { + // WHEN + new iotevents.DetectorModel(stack, 'MyDetectorModel', { + initialState: new iotevents.State({ + stateName: 'test-state', + onEnter: [{ + eventName: 'test-eventName1', + condition: iotevents.Expression.currentInput(input), + actions: [{ + bind: () => ({ + configuration: { + lambda: { + functionArn: 'arn:aws:lambda:us-east-1:123456789012:function:MyFn', + }, + }, + }), + }], + }], + }), + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::IoTEvents::DetectorModel', { + DetectorModelDefinition: { + States: [ + Match.objectLike({ + OnEnter: { + Events: [{ + Actions: [{ Lambda: { FunctionArn: 'arn:aws:lambda:us-east-1:123456789012:function:MyFn' } }], + }], + }, + }), + ], + }, + }); +}); + + +test('can set an action to multiple detector models', () => { + // GIVEN an action + const action: iotevents.IAction = { + bind: (_, { role }) => { + role.addToPrincipalPolicy(new iam.PolicyStatement({ + actions: ['lambda:InvokeFunction'], + resources: ['arn:aws:lambda:us-east-1:123456789012:function:MyFn'], + })); + return { + configuration: { + lambda: { functionArn: 'arn:aws:lambda:us-east-1:123456789012:function:MyFn' }, + }, + }; + }, + }; + + // WHEN the action is set to two detector models + new iotevents.DetectorModel(stack, 'MyDetectorModel1', { + detectorModelName: 'MyDetectorModel1', + initialState: new iotevents.State({ + stateName: 'test-state', + onEnter: [{ + eventName: 'test-eventName1', + condition: iotevents.Expression.currentInput(input), + actions: [action], + }], + }), + }); + new iotevents.DetectorModel(stack, 'MyDetectorModel2', { + detectorModelName: 'MyDetectorModel2', + initialState: new iotevents.State({ + stateName: 'test-state', + onEnter: [{ + eventName: 'test-eventName1', + condition: iotevents.Expression.currentInput(input), + actions: [action], + }], + }), + }); + + // THEN creates two detector model resouces and two iam policy resources + Template.fromStack(stack).resourceCountIs('AWS::IoTEvents::DetectorModel', 2); + Template.fromStack(stack).resourceCountIs('AWS::IAM::Policy', 2); + + Template.fromStack(stack).hasResourceProperties('AWS::IoTEvents::DetectorModel', { + DetectorModelName: 'MyDetectorModel1', + DetectorModelDefinition: { + States: [ + Match.objectLike({ + OnEnter: { + Events: [{ + Actions: [{ Lambda: { FunctionArn: 'arn:aws:lambda:us-east-1:123456789012:function:MyFn' } }], + }], + }, + }), + ], + }, + }); + Template.fromStack(stack).hasResourceProperties('AWS::IoTEvents::DetectorModel', { + DetectorModelName: 'MyDetectorModel2', + DetectorModelDefinition: { + States: [ + Match.objectLike({ + OnEnter: { + Events: [{ + Actions: [{ Lambda: { FunctionArn: 'arn:aws:lambda:us-east-1:123456789012:function:MyFn' } }], + }], + }, + }), + ], + }, + }); + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + Roles: [{ Ref: 'MyDetectorModel1DetectorModelRoleB36845CD' }], + PolicyDocument: { + Statement: [{ + Action: 'lambda:InvokeFunction', + Effect: 'Allow', + Resource: 'arn:aws:lambda:us-east-1:123456789012:function:MyFn', + }], + }, + }); + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + Roles: [{ Ref: 'MyDetectorModel2DetectorModelRole3C437E90' }], + PolicyDocument: { + Statement: [{ + Action: 'lambda:InvokeFunction', + Effect: 'Allow', + Resource: 'arn:aws:lambda:us-east-1:123456789012:function:MyFn', + }], + }, + }); +}); + test('can set states with transitions', () => { // GIVEN const firstState = new iotevents.State({ @@ -222,6 +354,47 @@ test('can set states with transitions', () => { }); }); +test('can set actions to transitions', () => { + // GIVEN + const firstState = new iotevents.State({ + stateName: 'firstState', + onEnter: [{ + eventName: 'test-eventName', + condition: iotevents.Expression.currentInput(input), + }], + }); + const secondState = new iotevents.State({ + stateName: 'secondState', + }); + + // WHEN + firstState.transitionTo(secondState, { + when: iotevents.Expression.eq( + iotevents.Expression.inputAttribute(input, 'payload.temperature'), + iotevents.Expression.fromString('12'), + ), + executing: [{ bind: () => ({ configuration: { setTimer: { timerName: 'test-timer' } } }) }], + }); + + new iotevents.DetectorModel(stack, 'MyDetectorModel', { + initialState: firstState, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::IoTEvents::DetectorModel', { + DetectorModelDefinition: { + States: Match.arrayWith([Match.objectLike({ + StateName: 'firstState', + OnInput: { + TransitionEvents: [{ + Actions: [{ SetTimer: { TimerName: 'test-timer' } }], + }], + }, + })]), + }, + }); +}); + test('can set role', () => { // WHEN const role = iam.Role.fromRoleArn(stack, 'test-role', 'arn:aws:iam::123456789012:role/ForTest'); diff --git a/packages/@aws-cdk/aws-iotfleethub/package.json b/packages/@aws-cdk/aws-iotfleethub/package.json index dde15541e17b5..1908aae1aa512 100644 --- a/packages/@aws-cdk/aws-iotfleethub/package.json +++ b/packages/@aws-cdk/aws-iotfleethub/package.json @@ -87,7 +87,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-iotsitewise/package.json b/packages/@aws-cdk/aws-iotsitewise/package.json index d84b4f75d06dc..fabfefa58f1e9 100644 --- a/packages/@aws-cdk/aws-iotsitewise/package.json +++ b/packages/@aws-cdk/aws-iotsitewise/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-iotthingsgraph/package.json b/packages/@aws-cdk/aws-iotthingsgraph/package.json index fd5ffd5531c81..62af6298210fa 100644 --- a/packages/@aws-cdk/aws-iotthingsgraph/package.json +++ b/packages/@aws-cdk/aws-iotthingsgraph/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-iotwireless/package.json b/packages/@aws-cdk/aws-iotwireless/package.json index b5a5f1aee6dc7..684d07c5bd136 100644 --- a/packages/@aws-cdk/aws-iotwireless/package.json +++ b/packages/@aws-cdk/aws-iotwireless/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-ivs/package.json b/packages/@aws-cdk/aws-ivs/package.json index d078cf3eceeaa..4f8235a849a03 100644 --- a/packages/@aws-cdk/aws-ivs/package.json +++ b/packages/@aws-cdk/aws-ivs/package.json @@ -96,7 +96,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-kafkaconnect/package.json b/packages/@aws-cdk/aws-kafkaconnect/package.json index 76f3beafd989e..ec3eb36faaa42 100644 --- a/packages/@aws-cdk/aws-kafkaconnect/package.json +++ b/packages/@aws-cdk/aws-kafkaconnect/package.json @@ -88,7 +88,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-kendra/package.json b/packages/@aws-cdk/aws-kendra/package.json index 2da553adf56a5..805b53e719899 100644 --- a/packages/@aws-cdk/aws-kendra/package.json +++ b/packages/@aws-cdk/aws-kendra/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-kinesis/package.json b/packages/@aws-cdk/aws-kinesis/package.json index 0b1aea08d72df..6cc0092590712 100644 --- a/packages/@aws-cdk/aws-kinesis/package.json +++ b/packages/@aws-cdk/aws-kinesis/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/cx-api": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/aws-cloudwatch": "0.0.0", diff --git a/packages/@aws-cdk/aws-kinesisanalytics-flink/package.json b/packages/@aws-cdk/aws-kinesisanalytics-flink/package.json index 175bbb1087efb..fb639112e35c2 100644 --- a/packages/@aws-cdk/aws-kinesisanalytics-flink/package.json +++ b/packages/@aws-cdk/aws-kinesisanalytics-flink/package.json @@ -77,7 +77,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-kinesisanalytics/package.json b/packages/@aws-cdk/aws-kinesisanalytics/package.json index 637452746b169..bbdb446edb571 100644 --- a/packages/@aws-cdk/aws-kinesisanalytics/package.json +++ b/packages/@aws-cdk/aws-kinesisanalytics/package.json @@ -86,7 +86,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-kinesisanalyticsv2/package.json b/packages/@aws-cdk/aws-kinesisanalyticsv2/package.json index 6efbd4c780c43..5e618783474d5 100644 --- a/packages/@aws-cdk/aws-kinesisanalyticsv2/package.json +++ b/packages/@aws-cdk/aws-kinesisanalyticsv2/package.json @@ -88,7 +88,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-kinesisfirehose-destinations/package.json b/packages/@aws-cdk/aws-kinesisfirehose-destinations/package.json index 968facf5dc44c..ad74666cd287a 100644 --- a/packages/@aws-cdk/aws-kinesisfirehose-destinations/package.json +++ b/packages/@aws-cdk/aws-kinesisfirehose-destinations/package.json @@ -78,7 +78,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-kinesisfirehose/package.json b/packages/@aws-cdk/aws-kinesisfirehose/package.json index 798a95fb5926e..066bfe78a218c 100644 --- a/packages/@aws-cdk/aws-kinesisfirehose/package.json +++ b/packages/@aws-cdk/aws-kinesisfirehose/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/aws-cloudwatch": "0.0.0", diff --git a/packages/@aws-cdk/aws-kinesisvideo/package.json b/packages/@aws-cdk/aws-kinesisvideo/package.json index 6cf6f391297a3..40faddbc9de2f 100644 --- a/packages/@aws-cdk/aws-kinesisvideo/package.json +++ b/packages/@aws-cdk/aws-kinesisvideo/package.json @@ -88,7 +88,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-kms/package.json b/packages/@aws-cdk/aws-kms/package.json index 9b0c7831162cb..333bedc7b8a93 100644 --- a/packages/@aws-cdk/aws-kms/package.json +++ b/packages/@aws-cdk/aws-kms/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/cloud-assembly-schema": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/aws-iam": "0.0.0", diff --git a/packages/@aws-cdk/aws-lakeformation/package.json b/packages/@aws-cdk/aws-lakeformation/package.json index 2c37cb38a608f..c7ceef39cb56d 100644 --- a/packages/@aws-cdk/aws-lakeformation/package.json +++ b/packages/@aws-cdk/aws-lakeformation/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-lambda-destinations/package.json b/packages/@aws-cdk/aws-lambda-destinations/package.json index 862b9a8df52c6..8feb76b2523f3 100644 --- a/packages/@aws-cdk/aws-lambda-destinations/package.json +++ b/packages/@aws-cdk/aws-lambda-destinations/package.json @@ -76,7 +76,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-lambda-event-sources/package.json b/packages/@aws-cdk/aws-lambda-event-sources/package.json index 9d4944ae6aa4e..c7253423991e4 100644 --- a/packages/@aws-cdk/aws-lambda-event-sources/package.json +++ b/packages/@aws-cdk/aws-lambda-event-sources/package.json @@ -75,7 +75,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-lambda-go/package.json b/packages/@aws-cdk/aws-lambda-go/package.json index de8eb177e133d..0383c7c0bbdd2 100644 --- a/packages/@aws-cdk/aws-lambda-go/package.json +++ b/packages/@aws-cdk/aws-lambda-go/package.json @@ -78,7 +78,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/aws-lambda": "0.0.0", diff --git a/packages/@aws-cdk/aws-lambda-nodejs/README.md b/packages/@aws-cdk/aws-lambda-nodejs/README.md index 95d7559cf25f3..1ce7d9786a4d1 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/README.md +++ b/packages/@aws-cdk/aws-lambda-nodejs/README.md @@ -198,6 +198,7 @@ new lambda.NodejsFunction(this, 'my-handler', { charset: lambda.Charset.UTF8, // do not escape non-ASCII characters, defaults to Charset.ASCII format: lambda.OutputFormat.ESM, // ECMAScript module output format, defaults to OutputFormat.CJS (OutputFormat.ESM requires Node.js 14.x) mainFields: ['module', 'main'], // prefer ECMAScript versions of dependencies + inject: ['./my-shim.js', './other-shim.js'] // allows to automatically replace a global variable with an import from another file }, }); ``` diff --git a/packages/@aws-cdk/aws-lambda-nodejs/lib/bundling.ts b/packages/@aws-cdk/aws-lambda-nodejs/lib/bundling.ts index 8a251bf8dda24..ee6b395c5d262 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/lib/bundling.ts +++ b/packages/@aws-cdk/aws-lambda-nodejs/lib/bundling.ts @@ -86,10 +86,10 @@ export class Bundling implements cdk.BundlingOptions { private readonly packageManager: PackageManager; constructor(private readonly props: BundlingProps) { - this.packageManager = PackageManager.fromLockFile(props.depsLockFilePath); + this.packageManager = PackageManager.fromLockFile(props.depsLockFilePath, props.logLevel); Bundling.esbuildInstallation = Bundling.esbuildInstallation ?? PackageInstallation.detect('esbuild'); - Bundling.tscInstallation = Bundling.tscInstallation ?? PackageInstallation.detect('tsc'); + Bundling.tscInstallation = Bundling.tscInstallation ?? PackageInstallation.detect('typescript'); this.projectRoot = props.projectRoot; this.relativeEntryPath = path.relative(this.projectRoot, path.resolve(props.entry)); @@ -198,6 +198,7 @@ export class Bundling implements cdk.BundlingOptions { ...this.props.footer ? [`--footer:js=${JSON.stringify(this.props.footer)}`] : [], ...this.props.charset ? [`--charset=${this.props.charset}`] : [], ...this.props.mainFields ? [`--main-fields=${this.props.mainFields.join(',')}`] : [], + ...this.props.inject ? this.props.inject.map(i => `--inject:${i}`) : [], ]; let depsCommand = ''; diff --git a/packages/@aws-cdk/aws-lambda-nodejs/lib/function.ts b/packages/@aws-cdk/aws-lambda-nodejs/lib/function.ts index 83f135a12a97b..0e17a749c2332 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/lib/function.ts +++ b/packages/@aws-cdk/aws-lambda-nodejs/lib/function.ts @@ -3,7 +3,7 @@ import * as path from 'path'; import * as lambda from '@aws-cdk/aws-lambda'; import { Architecture } from '@aws-cdk/aws-lambda'; import { Bundling } from './bundling'; -import { PackageManager } from './package-manager'; +import { LockFile } from './package-manager'; import { BundlingOptions } from './types'; import { callsites, findUpMultiple } from './util'; @@ -138,9 +138,9 @@ function findLockFile(depsLockFilePath?: string): string { } const lockFiles = findUpMultiple([ - PackageManager.PNPM.lockFile, - PackageManager.YARN.lockFile, - PackageManager.NPM.lockFile, + LockFile.PNPM, + LockFile.YARN, + LockFile.NPM, ]); if (lockFiles.length === 0) { diff --git a/packages/@aws-cdk/aws-lambda-nodejs/lib/package-manager.ts b/packages/@aws-cdk/aws-lambda-nodejs/lib/package-manager.ts index f0206bbd19a99..05ef109993460 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/lib/package-manager.ts +++ b/packages/@aws-cdk/aws-lambda-nodejs/lib/package-manager.ts @@ -1,48 +1,54 @@ import * as os from 'os'; import * as path from 'path'; +import { LogLevel } from './types'; interface PackageManagerProps { readonly lockFile: string; readonly installCommand: string[]; readonly runCommand: string[]; - readonly argsSeparator?: string + readonly argsSeparator?: string; +} + +export enum LockFile { + NPM = 'package-lock.json', + YARN = 'yarn.lock', + PNPM = 'pnpm-lock.yaml', } /** * A node package manager */ export class PackageManager { - public static NPM = new PackageManager({ - lockFile: 'package-lock.json', - installCommand: ['npm', 'ci'], - runCommand: ['npx', '--no-install'], - }); - - public static YARN = new PackageManager({ - lockFile: 'yarn.lock', - installCommand: ['yarn', 'install', '--no-immutable'], - runCommand: ['yarn', 'run'], - }); - - public static PNPM = new PackageManager({ - lockFile: 'pnpm-lock.yaml', - installCommand: ['pnpm', 'install'], - runCommand: ['pnpm', 'exec'], - argsSeparator: '--', - }); - - public static fromLockFile(lockFilePath: string): PackageManager { + /** + * Use a lock file path to determine the package manager to use. Optionally, specify a log level to + * control its verbosity. + * @param lockFilePath Path of the lock file + * @param logLevel optional log level @default LogLevel.INFO + * @returns the right PackageManager for that lock file + */ + public static fromLockFile(lockFilePath: string, logLevel?: LogLevel): PackageManager { const lockFile = path.basename(lockFilePath); switch (lockFile) { - case PackageManager.NPM.lockFile: - return PackageManager.NPM; - case PackageManager.YARN.lockFile: - return PackageManager.YARN; - case PackageManager.PNPM.lockFile: - return PackageManager.PNPM; + case LockFile.YARN: + return new PackageManager({ + lockFile: LockFile.YARN, + installCommand: logLevel && logLevel !== LogLevel.INFO ? ['yarn', 'install', '--no-immutable', '--silent'] : ['yarn', 'install', '--no-immutable'], + runCommand: ['yarn', 'run'], + }); + case LockFile.PNPM: + return new PackageManager({ + lockFile: LockFile.PNPM, + installCommand: logLevel && logLevel !== LogLevel.INFO ? ['pnpm', 'install', '--reporter', 'silent'] : ['pnpm', 'install'], + runCommand: ['pnpm', 'exec'], + argsSeparator: '--', + }); default: - return PackageManager.NPM; + return new PackageManager({ + lockFile: LockFile.NPM, + installCommand: logLevel ? ['npm', 'ci', '--loglevel', logLevel] : ['npm', 'ci'], + runCommand: ['npx', '--no-install'], + }); } } diff --git a/packages/@aws-cdk/aws-lambda-nodejs/lib/types.ts b/packages/@aws-cdk/aws-lambda-nodejs/lib/types.ts index e43dc6d41be1e..7b6b5c642f755 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/lib/types.ts +++ b/packages/@aws-cdk/aws-lambda-nodejs/lib/types.ts @@ -59,7 +59,8 @@ export interface BundlingOptions { readonly loader?: { [ext: string]: string }; /** - * Log level for esbuild + * Log level for esbuild. This is also propagated to the package manager and + * applies to its specific install command. * * @default LogLevel.WARNING */ @@ -278,6 +279,15 @@ export interface BundlingOptions { * @default ['main', 'module'] */ readonly mainFields?: string[]; + + /** + * This option allows you to automatically replace a global variable with an + * import from another file. + * + * @see https://esbuild.github.io/api/#inject + * @default - no code is injected + */ + readonly inject?: string[] } /** @@ -340,7 +350,7 @@ export interface ICommandHooks { } /** - * Log level for esbuild + * Log levels for esbuild and package managers' install commands. */ export enum LogLevel { /** Show everything */ diff --git a/packages/@aws-cdk/aws-lambda-nodejs/package.json b/packages/@aws-cdk/aws-lambda-nodejs/package.json index a18913f7a8353..76f4bdbbd1753 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/package.json +++ b/packages/@aws-cdk/aws-lambda-nodejs/package.json @@ -76,9 +76,9 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "delay": "5.0.0", - "esbuild": "^0.14.21" + "esbuild": "^0.14.23" }, "dependencies": { "@aws-cdk/aws-lambda": "0.0.0", diff --git a/packages/@aws-cdk/aws-lambda-nodejs/test/bundling.test.ts b/packages/@aws-cdk/aws-lambda-nodejs/test/bundling.test.ts index 3224d1afbd014..37e7fa0c94b6b 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/test/bundling.test.ts +++ b/packages/@aws-cdk/aws-lambda-nodejs/test/bundling.test.ts @@ -16,6 +16,7 @@ beforeEach(() => { jest.resetAllMocks(); jest.restoreAllMocks(); Bundling.clearEsbuildInstallationCache(); + Bundling.clearTscInstallationCache(); jest.spyOn(Code, 'fromAsset'); @@ -208,6 +209,7 @@ test('esbuild bundling with esbuild options', () => { 'process.env.STRING': JSON.stringify('this is a "test"'), }, format: OutputFormat.ESM, + inject: ['./my-shim.js'], }); // Correctly bundles with esbuild @@ -224,7 +226,7 @@ test('esbuild bundling with esbuild options', () => { defineInstructions, '--log-level=silent --keep-names --tsconfig=/asset-input/lib/custom-tsconfig.ts', '--metafile=/asset-output/index.meta.json --banner:js="/* comments */" --footer:js="/* comments */"', - '--charset=utf8 --main-fields=module,main', + '--charset=utf8 --main-fields=module,main --inject:./my-shim.js', ].join(' '), ], }), @@ -422,6 +424,7 @@ test('Local bundling', () => { environment: { KEY: 'value', }, + logLevel: LogLevel.ERROR, }); expect(bundler.local).toBeDefined(); @@ -600,6 +603,8 @@ test('esbuild bundling with pre compilations', () => { ], }), }); + + expect(detectPackageInstallationMock).toHaveBeenCalledWith('typescript'); }); test('throws with pre compilation and not found tsconfig', () => { diff --git a/packages/@aws-cdk/aws-lambda-nodejs/test/package-manager.test.ts b/packages/@aws-cdk/aws-lambda-nodejs/test/package-manager.test.ts index 19369bdd07d9a..8bb0682c0d568 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/test/package-manager.test.ts +++ b/packages/@aws-cdk/aws-lambda-nodejs/test/package-manager.test.ts @@ -1,36 +1,62 @@ import * as os from 'os'; -import { PackageManager } from '../lib/package-manager'; +import { LogLevel } from '../lib'; +import { LockFile, PackageManager } from '../lib/package-manager'; test('from a package-lock.json', () => { const packageManager = PackageManager.fromLockFile('/path/to/package-lock.json'); - expect(packageManager).toEqual(PackageManager.NPM); + expect(packageManager.lockFile).toEqual(LockFile.NPM); + expect(packageManager.argsSeparator).toBeUndefined(); + expect(packageManager.installCommand).toEqual(['npm', 'ci']); + expect(packageManager.runCommand).toEqual(['npx', '--no-install']); expect(packageManager.runBinCommand('my-bin')).toBe('npx --no-install my-bin'); }); +test('from a package-lock.json with LogLevel.ERROR', () => { + const logLevel = LogLevel.ERROR; + const packageManager = PackageManager.fromLockFile('/path/to/package-lock.json', logLevel); + expect(packageManager.installCommand).toEqual(['npm', 'ci', '--loglevel', logLevel]); +}); + test('from a yarn.lock', () => { const packageManager = PackageManager.fromLockFile('/path/to/yarn.lock'); - expect(packageManager).toEqual(PackageManager.YARN); + expect(packageManager.lockFile).toEqual(LockFile.YARN); + expect(packageManager.argsSeparator).toBeUndefined(); + expect(packageManager.installCommand).toEqual(['yarn', 'install', '--no-immutable']); + expect(packageManager.runCommand).toEqual(['yarn', 'run']); expect(packageManager.runBinCommand('my-bin')).toBe('yarn run my-bin'); }); +test('from a yarn.lock with LogLevel.ERROR', () => { + const packageManager = PackageManager.fromLockFile('/path/to/yarn.lock', LogLevel.ERROR); + expect(packageManager.installCommand).toEqual(['yarn', 'install', '--no-immutable', '--silent']); +}); + test('from a pnpm-lock.yaml', () => { const packageManager = PackageManager.fromLockFile('/path/to/pnpm-lock.yaml'); - expect(packageManager).toEqual(PackageManager.PNPM); + expect(packageManager.lockFile).toEqual(LockFile.PNPM); + expect(packageManager.argsSeparator).toEqual('--'); + expect(packageManager.installCommand).toEqual(['pnpm', 'install']); + expect(packageManager.runCommand).toEqual(['pnpm', 'exec']); expect(packageManager.runBinCommand('my-bin')).toBe('pnpm exec -- my-bin'); }); +test('from a pnpm-lock.yaml with LogLevel.ERROR', () => { + const packageManager = PackageManager.fromLockFile('/path/to/pnpm-lock.yaml', LogLevel.ERROR); + expect(packageManager.installCommand).toEqual(['pnpm', 'install', '--reporter', 'silent']); +}); + test('defaults to NPM', () => { const packageManager = PackageManager.fromLockFile('/path/to/other.lock'); - expect(packageManager).toEqual(PackageManager.NPM); + expect(packageManager.lockFile).toEqual(LockFile.NPM); }); test('Windows', () => { const osPlatformMock = jest.spyOn(os, 'platform').mockReturnValue('win32'); - const packageManager = PackageManager.NPM; + const packageManager = PackageManager.fromLockFile('/path/to/whatever'); expect(packageManager.runBinCommand('my-bin')).toEqual('npx.cmd --no-install my-bin'); osPlatformMock.mockRestore(); diff --git a/packages/@aws-cdk/aws-lambda-python/lib/bundling.ts b/packages/@aws-cdk/aws-lambda-python/lib/bundling.ts index 678f7638fbe75..27c8d24f83558 100644 --- a/packages/@aws-cdk/aws-lambda-python/lib/bundling.ts +++ b/packages/@aws-cdk/aws-lambda-python/lib/bundling.ts @@ -34,6 +34,13 @@ export interface BundlingProps extends BundlingOptions { * @default Architecture.X86_64 */ readonly architecture?: Architecture; + + /** + * Whether or not the bundling process should be skipped + * + * @default - Does not skip bundling + */ + readonly skip?: boolean; } /** @@ -45,7 +52,7 @@ export class Bundling implements CdkBundlingOptions { assetHash: options.assetHash, assetHashType: options.assetHashType, exclude: DEPENDENCY_EXCLUDES, - bundling: new Bundling(options), + bundling: options.skip ? undefined : new Bundling(options), }); } @@ -70,14 +77,13 @@ export class Bundling implements CdkBundlingOptions { outputDir: outputPath, }); - const defaultImage = DockerImage.fromBuild(path.join(__dirname, '../lib'), { + this.image = image ?? DockerImage.fromBuild(path.join(__dirname, '../lib'), { buildArgs: { - ...props.buildArgs ?? {}, + ...props.buildArgs, IMAGE: runtime.bundlingImage.image, }, platform: architecture.dockerPlatform, }); - this.image = image ?? defaultImage; this.command = ['bash', '-c', chain(bundlingCommands)]; this.environment = props.environment; } diff --git a/packages/@aws-cdk/aws-lambda-python/lib/function.ts b/packages/@aws-cdk/aws-lambda-python/lib/function.ts index 7938c20219f73..15013622d2cbc 100644 --- a/packages/@aws-cdk/aws-lambda-python/lib/function.ts +++ b/packages/@aws-cdk/aws-lambda-python/lib/function.ts @@ -1,6 +1,7 @@ import * as fs from 'fs'; import * as path from 'path'; import { Function, FunctionOptions, Runtime, RuntimeFamily } from '@aws-cdk/aws-lambda'; +import { Stack } from '@aws-cdk/core'; import { Bundling } from './bundling'; import { BundlingOptions } from './types'; @@ -79,6 +80,7 @@ export class PythonFunction extends Function { code: Bundling.bundle({ entry, runtime, + skip: !Stack.of(scope).bundlingRequired, ...props.bundling, }), handler: resolvedHandler, diff --git a/packages/@aws-cdk/aws-lambda-python/lib/layer.ts b/packages/@aws-cdk/aws-lambda-python/lib/layer.ts index d0b9bc6d0f529..516a221b588d8 100644 --- a/packages/@aws-cdk/aws-lambda-python/lib/layer.ts +++ b/packages/@aws-cdk/aws-lambda-python/lib/layer.ts @@ -1,5 +1,6 @@ import * as path from 'path'; import * as lambda from '@aws-cdk/aws-lambda'; +import { Stack } from '@aws-cdk/core'; import { Bundling } from './bundling'; import { BundlingOptions } from './types'; @@ -67,6 +68,7 @@ export class PythonLayerVersion extends lambda.LayerVersion { runtime, architecture, outputPathSuffix: 'python', + skip: !Stack.of(scope).bundlingRequired, ...props.bundling, }), }); diff --git a/packages/@aws-cdk/aws-lambda-python/package.json b/packages/@aws-cdk/aws-lambda-python/package.json index 1d4764316f4c9..74a9d8a8ffc0c 100644 --- a/packages/@aws-cdk/aws-lambda-python/package.json +++ b/packages/@aws-cdk/aws-lambda-python/package.json @@ -75,7 +75,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/aws-ec2": "0.0.0", diff --git a/packages/@aws-cdk/aws-lambda-python/test/bundling.test.ts b/packages/@aws-cdk/aws-lambda-python/test/bundling.test.ts index a75ecc8625960..ca2142cce0667 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/bundling.test.ts +++ b/packages/@aws-cdk/aws-lambda-python/test/bundling.test.ts @@ -211,6 +211,7 @@ test('Bundling a function with custom bundling image', () => { }), })); + expect(DockerImage.fromBuild).toHaveBeenCalledTimes(1); expect(DockerImage.fromBuild).toHaveBeenCalledWith(expect.stringMatching(entry)); }); @@ -248,3 +249,25 @@ test('Bundling with custom environment vars`', () => { }), })); }); + +test('Do not build docker image when skipping bundling', () => { + const entry = path.join(__dirname, 'lambda-handler'); + Bundling.bundle({ + entry: entry, + runtime: Runtime.PYTHON_3_7, + skip: true, + }); + + expect(DockerImage.fromBuild).not.toHaveBeenCalled(); +}); + +test('Build docker image when bundling is not skipped', () => { + const entry = path.join(__dirname, 'lambda-handler'); + Bundling.bundle({ + entry: entry, + runtime: Runtime.PYTHON_3_7, + skip: false, + }); + + expect(DockerImage.fromBuild).toHaveBeenCalled(); +}); diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.test.ts b/packages/@aws-cdk/aws-lambda-python/test/function.test.ts index 7eac6ad3df9ec..6fd12540b78c3 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.test.ts +++ b/packages/@aws-cdk/aws-lambda-python/test/function.test.ts @@ -167,3 +167,35 @@ test('Allows use of custom bundling image', () => { image, })); }); + +test('Skip bundling when stack does not require it', () => { + const spy = jest.spyOn(stack, 'bundlingRequired', 'get').mockReturnValue(false); + const entry = path.join(__dirname, 'lambda-handler'); + + new PythonFunction(stack, 'function', { + entry, + runtime: Runtime.PYTHON_3_8, + }); + + expect(Bundling.bundle).toHaveBeenCalledWith(expect.objectContaining({ + skip: true, + })); + + spy.mockRestore(); +}); + +test('Do not skip bundling when stack requires it', () => { + const spy = jest.spyOn(stack, 'bundlingRequired', 'get').mockReturnValue(true); + const entry = path.join(__dirname, 'lambda-handler'); + + new PythonFunction(stack, 'function', { + entry, + runtime: Runtime.PYTHON_3_8, + }); + + expect(Bundling.bundle).toHaveBeenCalledWith(expect.objectContaining({ + skip: false, + })); + + spy.mockRestore(); +}); diff --git a/packages/@aws-cdk/aws-lambda-python/test/layer.test.ts b/packages/@aws-cdk/aws-lambda-python/test/layer.test.ts index a254e82d48af6..eb12017072030 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/layer.test.ts +++ b/packages/@aws-cdk/aws-lambda-python/test/layer.test.ts @@ -63,3 +63,33 @@ test('Allows use of custom bundling image', () => { image, })); }); + +test('Skip bundling when stack does not require it', () => { + const spy = jest.spyOn(stack, 'bundlingRequired', 'get').mockReturnValue(false); + const entry = path.join(__dirname, 'lambda-handler-project'); + + new PythonLayerVersion(stack, 'layer', { + entry, + }); + + expect(Bundling.bundle).toHaveBeenCalledWith(expect.objectContaining({ + skip: true, + })); + + spy.mockRestore(); +}); + +test('Do not skip bundling when stack requires it', () => { + const spy = jest.spyOn(stack, 'bundlingRequired', 'get').mockReturnValue(true); + const entry = path.join(__dirname, 'lambda-handler-project'); + + new PythonLayerVersion(stack, 'layer', { + entry, + }); + + expect(Bundling.bundle).toHaveBeenCalledWith(expect.objectContaining({ + skip: false, + })); + + spy.mockRestore(); +}); diff --git a/packages/@aws-cdk/aws-lambda/README.md b/packages/@aws-cdk/aws-lambda/README.md index bdf1da7446641..9c9182b174550 100644 --- a/packages/@aws-cdk/aws-lambda/README.md +++ b/packages/@aws-cdk/aws-lambda/README.md @@ -509,10 +509,19 @@ const fn = lambda.Function.fromFunctionAttributes(this, 'Function', { }); ``` +If `fromFunctionArn()` causes an error related to having to provide an account and/or region in a different construct, +and the lambda is in the same account and region as the stack you're importing it into, +you can use `Function.fromFunctionName()` instead: + +```ts +const fn = lambda.Function.fromFunctionName(this, 'Function', 'MyFn'); +``` + ## Lambda with DLQ A dead-letter queue can be automatically created for a Lambda function by -setting the `deadLetterQueueEnabled: true` configuration. +setting the `deadLetterQueueEnabled: true` configuration. In such case CDK creates +a `sqs.Queue` as `deadLetterQueue`. ```ts const fn = new lambda.Function(this, 'MyFunction', { @@ -537,6 +546,20 @@ const fn = new lambda.Function(this, 'MyFunction', { }); ``` +You can also use a `sns.Topic` instead of an `sqs.Queue` as dead-letter queue: + +```ts +import * as sns from '@aws-cdk/aws-sns'; + +const dlt = new sns.Topic(this, 'DLQ'); +const fn = new lambda.Function(this, 'MyFunction', { + runtime: lambda.Runtime.NODEJS_12_X, + handler: 'index.handler', + code: lambda.Code.fromInline('// your code here'), + deadLetterTopic: dlt, +}); +``` + See [the AWS documentation](https://docs.aws.amazon.com/lambda/latest/dg/dlq.html) to learn more about AWS Lambdas and DLQs. 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 172d681d1fef9..7840a465b87b2 100644 --- a/packages/@aws-cdk/aws-lambda/lib/event-source-mapping.ts +++ b/packages/@aws-cdk/aws-lambda/lib/event-source-mapping.ts @@ -91,7 +91,7 @@ export interface EventSourceMappingOptions { * Valid Range: Minimum value of 1. Maximum value of 10000. * * @default - Amazon Kinesis, Amazon DynamoDB, and Amazon MSK is 100 records. - * Both the default and maximum for Amazon SQS are 10 messages. + * The default for Amazon SQS is 10 messages. For standard SQS queues, the maximum is 10,000. For FIFO SQS queues, the maximum is 10. */ readonly batchSize?: number; diff --git a/packages/@aws-cdk/aws-lambda/lib/function.ts b/packages/@aws-cdk/aws-lambda/lib/function.ts index a44d92cff59b4..5bff57e1d43bc 100644 --- a/packages/@aws-cdk/aws-lambda/lib/function.ts +++ b/packages/@aws-cdk/aws-lambda/lib/function.ts @@ -4,8 +4,9 @@ import * as ec2 from '@aws-cdk/aws-ec2'; import * as iam from '@aws-cdk/aws-iam'; import * as kms from '@aws-cdk/aws-kms'; import * as logs from '@aws-cdk/aws-logs'; +import * as sns from '@aws-cdk/aws-sns'; import * as sqs from '@aws-cdk/aws-sqs'; -import { Annotations, ArnFormat, CfnResource, Duration, Fn, Lazy, Names, Stack } from '@aws-cdk/core'; +import { Annotations, ArnFormat, CfnResource, Duration, Fn, Lazy, Names, Stack, Token } from '@aws-cdk/core'; import { Construct } from 'constructs'; import { Architecture } from './architecture'; import { Code, CodeConfig } from './code'; @@ -188,11 +189,21 @@ export interface FunctionOptions extends EventInvokeConfigOptions { /** * The SQS queue to use if DLQ is enabled. + * If SNS topic is desired, specify `deadLetterTopic` property instead. * * @default - SQS queue with 14 day retention period if `deadLetterQueueEnabled` is `true` */ readonly deadLetterQueue?: sqs.IQueue; + /** + * The SNS topic to use as a DLQ. + * Note that if `deadLetterQueueEnabled` is set to `true`, an SQS queue will be created + * rather than an SNS topic. Using an SNS topic as a DLQ requires this property to be set explicitly. + * + * @default - no SNS topic + */ + readonly deadLetterTopic?: sns.ITopic; + /** * Enable AWS X-Ray Tracing for Lambda Function. * @@ -424,6 +435,20 @@ export class Function extends FunctionBase { this._VER_PROPS[propertyName] = locked; } + /** + * Import a lambda function into the CDK using its name + */ + public static fromFunctionName(scope: Construct, id: string, functionName: string): IFunction { + return Function.fromFunctionAttributes(scope, id, { + functionArn: Stack.of(scope).formatArn({ + service: 'lambda', + resource: 'function', + resourceName: functionName, + arnFormat: ArnFormat.COLON_RESOURCE_NAME, + }), + }); + } + /** * Import a lambda function into the CDK using its ARN */ @@ -573,10 +598,15 @@ export class Function extends FunctionBase { public readonly grantPrincipal: iam.IPrincipal; /** - * The DLQ associated with this Lambda Function (this is an optional attribute). + * The DLQ (as queue) associated with this Lambda Function (this is an optional attribute). */ public readonly deadLetterQueue?: sqs.IQueue; + /** + * The DLQ (as topic) associated with this Lambda Function (this is an optional attribute). + */ + public readonly deadLetterTopic?: sns.ITopic; + /** * The architecture of this Lambda Function (this is an optional attribute and defaults to X86_64). */ @@ -611,6 +641,15 @@ export class Function extends FunctionBase { physicalName: props.functionName, }); + if (props.functionName && !Token.isUnresolved(props.functionName)) { + if (props.functionName.length > 64) { + throw new Error(`Function name can not be longer than 64 characters but has ${props.functionName.length} characters.`); + } + if (!/^[a-zA-Z0-9-_]+$/.test(props.functionName)) { + throw new Error(`Function name ${props.functionName} can contain only letters, numbers, hyphens, or underscores with no spaces.`); + } + } + const managedPolicies = new Array(); // the arn is in the form of - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole @@ -673,7 +712,15 @@ export class Function extends FunctionBase { this.addEnvironment(key, value); } - this.deadLetterQueue = this.buildDeadLetterQueue(props); + // DLQ can be either sns.ITopic or sqs.IQueue + const dlqTopicOrQueue = this.buildDeadLetterQueue(props); + if (dlqTopicOrQueue !== undefined) { + if (this.isQueue(dlqTopicOrQueue)) { + this.deadLetterQueue = dlqTopicOrQueue; + } else { + this.deadLetterTopic = dlqTopicOrQueue; + } + } let fileSystemConfigs: CfnFunction.FileSystemConfigProperty[] | undefined = undefined; if (props.filesystem) { @@ -712,7 +759,7 @@ export class Function extends FunctionBase { environment: Lazy.uncachedAny({ produce: () => this.renderEnvironment() }), memorySize: props.memorySize, vpcConfig: this.configureVpc(props), - deadLetterConfig: this.buildDeadLetterConfig(this.deadLetterQueue), + deadLetterConfig: this.buildDeadLetterConfig(dlqTopicOrQueue), tracingConfig: this.buildTracingConfig(props), reservedConcurrentExecutions: props.reservedConcurrentExecutions, imageConfig: undefinedIfNoKeys({ @@ -1031,31 +1078,45 @@ Environment variables can be marked for removal when used in Lambda@Edge by sett }; } - private buildDeadLetterQueue(props: FunctionProps) { + private isQueue(deadLetterQueue: sqs.IQueue | sns.ITopic): deadLetterQueue is sqs.IQueue { + return (deadLetterQueue).queueArn !== undefined; + } + + private buildDeadLetterQueue(props: FunctionProps): sqs.IQueue | sns.ITopic | undefined { + if (!props.deadLetterQueue && !props.deadLetterQueueEnabled && !props.deadLetterTopic) { + return undefined; + } if (props.deadLetterQueue && props.deadLetterQueueEnabled === false) { throw Error('deadLetterQueue defined but deadLetterQueueEnabled explicitly set to false'); } - - if (!props.deadLetterQueue && !props.deadLetterQueueEnabled) { - return undefined; + if (props.deadLetterTopic && (props.deadLetterQueue || props.deadLetterQueueEnabled !== undefined)) { + throw new Error('deadLetterQueue and deadLetterTopic cannot be specified together at the same time'); } - const deadLetterQueue = props.deadLetterQueue || new sqs.Queue(this, 'DeadLetterQueue', { - retentionPeriod: Duration.days(14), - }); - - this.addToRolePolicy(new iam.PolicyStatement({ - actions: ['sqs:SendMessage'], - resources: [deadLetterQueue.queueArn], - })); + let deadLetterQueue: sqs.IQueue | sns.ITopic; + if (props.deadLetterTopic) { + deadLetterQueue = props.deadLetterTopic; + this.addToRolePolicy(new iam.PolicyStatement({ + actions: ['sns:Publish'], + resources: [deadLetterQueue.topicArn], + })); + } else { + deadLetterQueue = props.deadLetterQueue || new sqs.Queue(this, 'DeadLetterQueue', { + retentionPeriod: Duration.days(14), + }); + this.addToRolePolicy(new iam.PolicyStatement({ + actions: ['sqs:SendMessage'], + resources: [deadLetterQueue.queueArn], + })); + } return deadLetterQueue; } - private buildDeadLetterConfig(deadLetterQueue?: sqs.IQueue) { + private buildDeadLetterConfig(deadLetterQueue?: sqs.IQueue | sns.ITopic) { if (deadLetterQueue) { return { - targetArn: deadLetterQueue.queueArn, + targetArn: this.isQueue(deadLetterQueue) ? deadLetterQueue.queueArn : deadLetterQueue.topicArn, }; } else { return undefined; diff --git a/packages/@aws-cdk/aws-lambda/lib/lambda-version.ts b/packages/@aws-cdk/aws-lambda/lib/lambda-version.ts index dbbd1496d8d8c..50a3e5ade12dd 100644 --- a/packages/@aws-cdk/aws-lambda/lib/lambda-version.ts +++ b/packages/@aws-cdk/aws-lambda/lib/lambda-version.ts @@ -93,16 +93,17 @@ export interface VersionAttributes { } /** - * A single newly-deployed version of a Lambda function. + * Tag the current state of a Function with a Version number * - * This object exists to--at deploy time--query the "then-current" version of - * the Lambda function that it refers to. This Version object can then be - * used in `Alias` to refer to a particular deployment of a Lambda. + * Avoid using this resource directly. If you need a Version object, use + * `function.currentVersion` instead. That will add a Version object to your + * template, and make sure the Version is invalidated whenever the Function + * object changes. If you use the `Version` resource directly, you are + * responsible for making sure it is invalidated (by changing its + * logical ID) whenever necessary. * - * This means that for every new update you deploy to your Lambda (using the - * CDK and Aliases), you must always create a new Version object. In - * particular, it must have a different name, so that a new resource is - * created. + * Version resources can then be used in `Alias` resources to refer to a + * particular deployment of a Lambda. * * If you want to ensure that you're associating the right version with * the right deployment, specify the `codeSha256` property while diff --git a/packages/@aws-cdk/aws-lambda/package.json b/packages/@aws-cdk/aws-lambda/package.json index 0d4f8ae462f01..1b9f58b6fcf21 100644 --- a/packages/@aws-cdk/aws-lambda/package.json +++ b/packages/@aws-cdk/aws-lambda/package.json @@ -90,7 +90,7 @@ "@aws-cdk/cfnspec": "0.0.0", "@aws-cdk/pkglint": "0.0.0", "@types/aws-lambda": "^8.10.92", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "@types/lodash": "^4.14.178", "jest": "^27.5.1", "lodash": "^4.17.21" @@ -110,6 +110,7 @@ "@aws-cdk/aws-s3": "0.0.0", "@aws-cdk/aws-s3-assets": "0.0.0", "@aws-cdk/aws-signer": "0.0.0", + "@aws-cdk/aws-sns": "0.0.0", "@aws-cdk/aws-sqs": "0.0.0", "@aws-cdk/core": "0.0.0", "@aws-cdk/cx-api": "0.0.0", @@ -132,6 +133,7 @@ "@aws-cdk/aws-s3": "0.0.0", "@aws-cdk/aws-s3-assets": "0.0.0", "@aws-cdk/aws-signer": "0.0.0", + "@aws-cdk/aws-sns": "0.0.0", "@aws-cdk/aws-sqs": "0.0.0", "@aws-cdk/core": "0.0.0", "@aws-cdk/cx-api": "0.0.0", diff --git a/packages/@aws-cdk/aws-lambda/test/function.test.ts b/packages/@aws-cdk/aws-lambda/test/function.test.ts index 165c09fdea8bc..9c01956493d8b 100644 --- a/packages/@aws-cdk/aws-lambda/test/function.test.ts +++ b/packages/@aws-cdk/aws-lambda/test/function.test.ts @@ -8,6 +8,7 @@ import * as kms from '@aws-cdk/aws-kms'; import * as logs from '@aws-cdk/aws-logs'; import * as s3 from '@aws-cdk/aws-s3'; import * as signer from '@aws-cdk/aws-signer'; +import * as sns from '@aws-cdk/aws-sns'; import * as sqs from '@aws-cdk/aws-sqs'; import { testDeprecated } from '@aws-cdk/cdk-build-tools'; import * as cdk from '@aws-cdk/core'; @@ -296,6 +297,42 @@ describe('function', () => { expect(imported.functionName).toEqual('ProcessKinesisRecords'); }); + test('Function.fromFunctionName', () => { + // GIVEN + const stack = new cdk.Stack(); + + // WHEN + const imported = lambda.Function.fromFunctionName(stack, 'Imported', 'my-function'); + + // THEN + expect(stack.resolve(imported.functionArn)).toStrictEqual({ + 'Fn::Join': ['', [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':lambda:', + { Ref: 'AWS::Region' }, + ':', + { Ref: 'AWS::AccountId' }, + ':function:my-function', + ]], + }); + expect(stack.resolve(imported.functionName)).toStrictEqual({ + 'Fn::Select': [6, { + 'Fn::Split': [':', { + 'Fn::Join': ['', [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':lambda:', + { Ref: 'AWS::Region' }, + ':', + { Ref: 'AWS::AccountId' }, + ':function:my-function', + ]], + }], + }], + }); + }); + describe('Function.fromFunctionAttributes()', () => { let stack: cdk.Stack; @@ -684,6 +721,84 @@ describe('function', () => { })).toThrow(/deadLetterQueue defined but deadLetterQueueEnabled explicitly set to false/); }); + test('default function with SNS DLQ when client provides Topic to be used as DLQ', () => { + const stack = new cdk.Stack(); + + const dlTopic = new sns.Topic(stack, 'DeadLetterTopic'); + + new lambda.Function(stack, 'MyLambda', { + code: new lambda.InlineCode('foo'), + handler: 'index.handler', + runtime: lambda.Runtime.NODEJS_10_X, + deadLetterTopic: dlTopic, + }); + + const template = Template.fromStack(stack); + template.hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: Match.arrayWith([ + { + Action: 'sns:Publish', + Effect: 'Allow', + Resource: { + Ref: 'DeadLetterTopicC237650B', + }, + }, + ]), + }, + }); + template.hasResourceProperties('AWS::Lambda::Function', { + DeadLetterConfig: { + TargetArn: { + Ref: 'DeadLetterTopicC237650B', + }, + }, + }); + }); + + test('error when default function with SNS DLQ when client provides Topic to be used as DLQ and deadLetterQueueEnabled set to false', () => { + const stack = new cdk.Stack(); + + const dlTopic = new sns.Topic(stack, 'DeadLetterTopic'); + + expect(() => new lambda.Function(stack, 'MyLambda', { + code: new lambda.InlineCode('foo'), + handler: 'index.handler', + runtime: lambda.Runtime.NODEJS_10_X, + deadLetterQueueEnabled: false, + deadLetterTopic: dlTopic, + })).toThrow(/deadLetterQueue and deadLetterTopic cannot be specified together at the same time/); + }); + + test('error when default function with SNS DLQ when client provides Topic to be used as DLQ and deadLetterQueueEnabled set to true', () => { + const stack = new cdk.Stack(); + + const dlTopic = new sns.Topic(stack, 'DeadLetterTopic'); + + expect(() => new lambda.Function(stack, 'MyLambda', { + code: new lambda.InlineCode('foo'), + handler: 'index.handler', + runtime: lambda.Runtime.NODEJS_10_X, + deadLetterQueueEnabled: true, + deadLetterTopic: dlTopic, + })).toThrow(/deadLetterQueue and deadLetterTopic cannot be specified together at the same time/); + }); + + test('error when both topic and queue are presented as DLQ', () => { + const stack = new cdk.Stack(); + + const dlQueue = new sqs.Queue(stack, 'DLQ'); + const dlTopic = new sns.Topic(stack, 'DeadLetterTopic'); + + expect(() => new lambda.Function(stack, 'MyLambda', { + code: new lambda.InlineCode('foo'), + handler: 'index.handler', + runtime: lambda.Runtime.NODEJS_10_X, + deadLetterQueue: dlQueue, + deadLetterTopic: dlTopic, + })).toThrow(/deadLetterQueue and deadLetterTopic cannot be specified together at the same time/); + }); + test('default function with Active tracing', () => { const stack = new cdk.Stack(); @@ -1561,7 +1676,7 @@ describe('function', () => { expect(logGroup.logGroupArn).toBeDefined(); }); - test('dlq is returned when provided by user', () => { + test('dlq is returned when provided by user and is Queue', () => { const stack = new cdk.Stack(); const dlQueue = new sqs.Queue(stack, 'DeadLetterQueue', { @@ -1576,12 +1691,37 @@ describe('function', () => { deadLetterQueue: dlQueue, }); const deadLetterQueue = fn.deadLetterQueue; - expect(deadLetterQueue?.queueArn).toBeDefined(); - expect(deadLetterQueue?.queueName).toBeDefined(); - expect(deadLetterQueue?.queueUrl).toBeDefined(); + const deadLetterTopic = fn.deadLetterTopic; + + expect(deadLetterTopic).toBeUndefined(); + + expect(deadLetterQueue).toBeDefined(); + expect(deadLetterQueue).toBeInstanceOf(sqs.Queue); + }); + + test('dlq is returned when provided by user and is Topic', () => { + const stack = new cdk.Stack(); + + const dlTopic = new sns.Topic(stack, 'DeadLetterQueue', { + topicName: 'MyLambda_DLQ', + }); + + const fn = new lambda.Function(stack, 'fn', { + handler: 'foo', + runtime: lambda.Runtime.NODEJS_10_X, + code: lambda.Code.fromInline('foo'), + deadLetterTopic: dlTopic, + }); + const deadLetterQueue = fn.deadLetterQueue; + const deadLetterTopic = fn.deadLetterTopic; + + expect(deadLetterQueue).toBeUndefined(); + + expect(deadLetterTopic).toBeDefined(); + expect(deadLetterTopic).toBeInstanceOf(sns.Topic); }); - test('dlq is returned when setup by cdk', () => { + test('dlq is returned when setup by cdk and is Queue', () => { const stack = new cdk.Stack(); const fn = new lambda.Function(stack, 'fn', { handler: 'foo', @@ -1590,9 +1730,12 @@ describe('function', () => { deadLetterQueueEnabled: true, }); const deadLetterQueue = fn.deadLetterQueue; - expect(deadLetterQueue?.queueArn).toBeDefined(); - expect(deadLetterQueue?.queueName).toBeDefined(); - expect(deadLetterQueue?.queueUrl).toBeDefined(); + const deadLetterTopic = fn.deadLetterTopic; + + expect(deadLetterTopic).toBeUndefined(); + + expect(deadLetterQueue).toBeDefined(); + expect(deadLetterQueue).toBeInstanceOf(sqs.Queue); }); test('dlq is undefined when not setup', () => { @@ -1603,7 +1746,10 @@ describe('function', () => { code: lambda.Code.fromInline('foo'), }); const deadLetterQueue = fn.deadLetterQueue; + const deadLetterTopic = fn.deadLetterTopic; + expect(deadLetterQueue).toBeUndefined(); + expect(deadLetterTopic).toBeUndefined(); }); test('one and only one child LogRetention construct will be created', () => { @@ -2294,6 +2440,45 @@ describe('function', () => { }); expect(fn.architecture?.name).toEqual('arm64'); }); + + test('Error when function name is longer than 64 chars', () => { + const stack = new cdk.Stack(); + expect(() => new lambda.Function(stack, 'MyFunction', { + code: lambda.Code.fromInline('foo'), + runtime: lambda.Runtime.NODEJS_14_X, + handler: 'index.handler', + functionName: 'a'.repeat(65), + })).toThrow(/Function name can not be longer than 64 characters/); + }); + + test('Error when function name contains invalid characters', () => { + const stack = new cdk.Stack(); + [' ', '\n', '\r', '[', ']', '<', '>', '$'].forEach(invalidChar => { + expect(() => { + new lambda.Function(stack, `foo${invalidChar}`, { + code: new lambda.InlineCode('foo'), + handler: 'index.handler', + runtime: lambda.Runtime.NODEJS_14_X, + functionName: `foo${invalidChar}`, + }); + }).toThrow(/can contain only letters, numbers, hyphens, or underscores with no spaces./); + }); + }); + + test('No error when function name is Tokenized and Unresolved', () => { + const stack = new cdk.Stack(); + expect(() => { + const realFunctionName = 'a'.repeat(141); + const tokenizedFunctionName = cdk.Token.asString(new cdk.Intrinsic(realFunctionName)); + + new lambda.Function(stack, 'foo', { + code: new lambda.InlineCode('foo'), + handler: 'index.handler', + runtime: lambda.Runtime.NODEJS_14_X, + functionName: tokenizedFunctionName, + }); + }).not.toThrow(); + }); }); function newTestLambda(scope: constructs.Construct) { diff --git a/packages/@aws-cdk/aws-licensemanager/package.json b/packages/@aws-cdk/aws-licensemanager/package.json index 2a080395c788e..7a41e125ce49d 100644 --- a/packages/@aws-cdk/aws-licensemanager/package.json +++ b/packages/@aws-cdk/aws-licensemanager/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-lightsail/package.json b/packages/@aws-cdk/aws-lightsail/package.json index c99305e2ad42c..8f71c3ebd1192 100644 --- a/packages/@aws-cdk/aws-lightsail/package.json +++ b/packages/@aws-cdk/aws-lightsail/package.json @@ -88,7 +88,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-location/package.json b/packages/@aws-cdk/aws-location/package.json index 7acaf2d81fd60..e686e64f27c41 100644 --- a/packages/@aws-cdk/aws-location/package.json +++ b/packages/@aws-cdk/aws-location/package.json @@ -87,7 +87,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-logs-destinations/package.json b/packages/@aws-cdk/aws-logs-destinations/package.json index 88619b92ba0c4..07e783848cb15 100644 --- a/packages/@aws-cdk/aws-logs-destinations/package.json +++ b/packages/@aws-cdk/aws-logs-destinations/package.json @@ -76,7 +76,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-logs/package.json b/packages/@aws-cdk/aws-logs/package.json index cdc6859dda1cd..770c2ff30e78c 100644 --- a/packages/@aws-cdk/aws-logs/package.json +++ b/packages/@aws-cdk/aws-logs/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", "@types/aws-lambda": "^8.10.92", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "@types/sinon": "^9.0.11", "aws-sdk": "^2.848.0", "aws-sdk-mock": "5.6.0", diff --git a/packages/@aws-cdk/aws-lookoutequipment/package.json b/packages/@aws-cdk/aws-lookoutequipment/package.json index 26dc399bb1d3d..7218c3f7fd95f 100644 --- a/packages/@aws-cdk/aws-lookoutequipment/package.json +++ b/packages/@aws-cdk/aws-lookoutequipment/package.json @@ -87,7 +87,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-lookoutmetrics/package.json b/packages/@aws-cdk/aws-lookoutmetrics/package.json index 257c1ccad03c5..bce07b4f9fed7 100644 --- a/packages/@aws-cdk/aws-lookoutmetrics/package.json +++ b/packages/@aws-cdk/aws-lookoutmetrics/package.json @@ -87,7 +87,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-lookoutvision/package.json b/packages/@aws-cdk/aws-lookoutvision/package.json index 3722553279a80..f24b9b3a26db1 100644 --- a/packages/@aws-cdk/aws-lookoutvision/package.json +++ b/packages/@aws-cdk/aws-lookoutvision/package.json @@ -87,7 +87,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-macie/package.json b/packages/@aws-cdk/aws-macie/package.json index 0db2eaf329169..c24dd63ebd1ba 100644 --- a/packages/@aws-cdk/aws-macie/package.json +++ b/packages/@aws-cdk/aws-macie/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-managedblockchain/package.json b/packages/@aws-cdk/aws-managedblockchain/package.json index 8f8f77907edb4..9190b3c3b9955 100644 --- a/packages/@aws-cdk/aws-managedblockchain/package.json +++ b/packages/@aws-cdk/aws-managedblockchain/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-mediaconnect/package.json b/packages/@aws-cdk/aws-mediaconnect/package.json index ca2d9a593ea5a..5a67e0a1c0942 100644 --- a/packages/@aws-cdk/aws-mediaconnect/package.json +++ b/packages/@aws-cdk/aws-mediaconnect/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-mediaconvert/package.json b/packages/@aws-cdk/aws-mediaconvert/package.json index 0ee4ec64dcbe7..637617e65843e 100644 --- a/packages/@aws-cdk/aws-mediaconvert/package.json +++ b/packages/@aws-cdk/aws-mediaconvert/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-medialive/package.json b/packages/@aws-cdk/aws-medialive/package.json index f87426fc1fd81..dbe092b4b0dfb 100644 --- a/packages/@aws-cdk/aws-medialive/package.json +++ b/packages/@aws-cdk/aws-medialive/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-mediapackage/package.json b/packages/@aws-cdk/aws-mediapackage/package.json index 31e2b39fe0c9a..23f112ba5ae80 100644 --- a/packages/@aws-cdk/aws-mediapackage/package.json +++ b/packages/@aws-cdk/aws-mediapackage/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-mediastore/package.json b/packages/@aws-cdk/aws-mediastore/package.json index ece435e1c014f..73dc4e62f8961 100644 --- a/packages/@aws-cdk/aws-mediastore/package.json +++ b/packages/@aws-cdk/aws-mediastore/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-memorydb/package.json b/packages/@aws-cdk/aws-memorydb/package.json index b85421f3713f9..5db59ada0d550 100644 --- a/packages/@aws-cdk/aws-memorydb/package.json +++ b/packages/@aws-cdk/aws-memorydb/package.json @@ -88,7 +88,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-msk/package.json b/packages/@aws-cdk/aws-msk/package.json index adb6018fb557b..e175174ae9da6 100644 --- a/packages/@aws-cdk/aws-msk/package.json +++ b/packages/@aws-cdk/aws-msk/package.json @@ -86,7 +86,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-mwaa/package.json b/packages/@aws-cdk/aws-mwaa/package.json index f0a0cec6a6877..ab2d6061c871b 100644 --- a/packages/@aws-cdk/aws-mwaa/package.json +++ b/packages/@aws-cdk/aws-mwaa/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-neptune/package.json b/packages/@aws-cdk/aws-neptune/package.json index 27c8c35f6e980..73b0ac6867a50 100644 --- a/packages/@aws-cdk/aws-neptune/package.json +++ b/packages/@aws-cdk/aws-neptune/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/aws-ec2": "0.0.0", diff --git a/packages/@aws-cdk/aws-networkfirewall/package.json b/packages/@aws-cdk/aws-networkfirewall/package.json index 91e96fd0b3a46..937d63aa53730 100644 --- a/packages/@aws-cdk/aws-networkfirewall/package.json +++ b/packages/@aws-cdk/aws-networkfirewall/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-networkmanager/package.json b/packages/@aws-cdk/aws-networkmanager/package.json index 696efca60f8eb..c34d778bac829 100644 --- a/packages/@aws-cdk/aws-networkmanager/package.json +++ b/packages/@aws-cdk/aws-networkmanager/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-nimblestudio/package.json b/packages/@aws-cdk/aws-nimblestudio/package.json index c033e0066f94e..52ab33b43c1ca 100644 --- a/packages/@aws-cdk/aws-nimblestudio/package.json +++ b/packages/@aws-cdk/aws-nimblestudio/package.json @@ -87,7 +87,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-opensearchservice/package.json b/packages/@aws-cdk/aws-opensearchservice/package.json index f0d434006921e..1bece17b44f7a 100644 --- a/packages/@aws-cdk/aws-opensearchservice/package.json +++ b/packages/@aws-cdk/aws-opensearchservice/package.json @@ -89,7 +89,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/aws-certificatemanager": "0.0.0", diff --git a/packages/@aws-cdk/aws-opsworks/package.json b/packages/@aws-cdk/aws-opsworks/package.json index 838ff7003ff62..011fa1d4d0790 100644 --- a/packages/@aws-cdk/aws-opsworks/package.json +++ b/packages/@aws-cdk/aws-opsworks/package.json @@ -83,7 +83,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-opsworkscm/package.json b/packages/@aws-cdk/aws-opsworkscm/package.json index 1220456e3ff0b..f429f37979df0 100644 --- a/packages/@aws-cdk/aws-opsworkscm/package.json +++ b/packages/@aws-cdk/aws-opsworkscm/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-panorama/package.json b/packages/@aws-cdk/aws-panorama/package.json index 37658a09b0c61..f766e427bbffd 100644 --- a/packages/@aws-cdk/aws-panorama/package.json +++ b/packages/@aws-cdk/aws-panorama/package.json @@ -95,7 +95,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-pinpoint/package.json b/packages/@aws-cdk/aws-pinpoint/package.json index 30801027c4e06..b4f9c8565e526 100644 --- a/packages/@aws-cdk/aws-pinpoint/package.json +++ b/packages/@aws-cdk/aws-pinpoint/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-pinpointemail/package.json b/packages/@aws-cdk/aws-pinpointemail/package.json index 26486ee72627b..3c51a3c74abd1 100644 --- a/packages/@aws-cdk/aws-pinpointemail/package.json +++ b/packages/@aws-cdk/aws-pinpointemail/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-qldb/package.json b/packages/@aws-cdk/aws-qldb/package.json index a35637354c0c1..9e4e6e0c90ac0 100644 --- a/packages/@aws-cdk/aws-qldb/package.json +++ b/packages/@aws-cdk/aws-qldb/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-quicksight/package.json b/packages/@aws-cdk/aws-quicksight/package.json index 270c171d3b5cb..79d41343ab08b 100644 --- a/packages/@aws-cdk/aws-quicksight/package.json +++ b/packages/@aws-cdk/aws-quicksight/package.json @@ -87,7 +87,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-ram/package.json b/packages/@aws-cdk/aws-ram/package.json index 1064bb16fc89f..ddf8049356491 100644 --- a/packages/@aws-cdk/aws-ram/package.json +++ b/packages/@aws-cdk/aws-ram/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-rds/README.md b/packages/@aws-cdk/aws-rds/README.md index fa3375fb4d0d1..78d58f64041ec 100644 --- a/packages/@aws-cdk/aws-rds/README.md +++ b/packages/@aws-cdk/aws-rds/README.md @@ -639,7 +639,7 @@ declare const vpc: ec2.Vpc; const cluster = new rds.ServerlessCluster(this, 'AnotherCluster', { engine: rds.DatabaseClusterEngine.AURORA_MYSQL, - vpc, + vpc, // this parameter is optional for serverless Clusters enableDataApi: true, // Optional - will be automatically set if you call grantDataApiAccess() }); @@ -659,3 +659,11 @@ cluster.grantDataApiAccess(fn); **Note**: To invoke the Data API, the resource will need to read the secret associated with the cluster. To learn more about using the Data API, see the [documentation](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/data-api.html). + +### Default VPC + +The `vpc` parameter is optional. + +If not provided, the cluster will be created in the default VPC of the account and region. +As this VPC is not deployed with AWS CDK, you can't configure the `vpcSubnets`, `subnetGroup` or `securityGroups` of the Aurora Serverless Cluster. +If you want to provide one of `vpcSubnets`, `subnetGroup` or `securityGroups` parameter, please provide a `vpc`. diff --git a/packages/@aws-cdk/aws-rds/lib/cluster-engine.ts b/packages/@aws-cdk/aws-rds/lib/cluster-engine.ts index d8d5c91f41507..65e7ed6496e97 100644 --- a/packages/@aws-cdk/aws-rds/lib/cluster-engine.ts +++ b/packages/@aws-cdk/aws-rds/lib/cluster-engine.ts @@ -177,7 +177,11 @@ abstract class MySqlClusterEngineBase extends ClusterEngineBase { }) : config.parameterGroup); if (options.s3ImportRole) { - parameterGroup?.addParameter('aurora_load_from_s3_role', options.s3ImportRole.roleArn); + // major version 8.0 uses a different name for the S3 import parameter + const s3ImportParam = this.engineVersion?.majorVersion === '8.0' + ? 'aws_default_s3_role' + : 'aurora_load_from_s3_role'; + parameterGroup?.addParameter(s3ImportParam, options.s3ImportRole.roleArn); } if (options.s3ExportRole) { parameterGroup?.addParameter('aurora_select_into_s3_role', options.s3ExportRole.roleArn); @@ -340,6 +344,8 @@ export class AuroraMysqlEngineVersion { public static readonly VER_2_10_0 = AuroraMysqlEngineVersion.builtIn_5_7('2.10.0'); /** Version "5.7.mysql_aurora.2.10.1". */ public static readonly VER_2_10_1 = AuroraMysqlEngineVersion.builtIn_5_7('2.10.1'); + /** Version "5.7.mysql_aurora.2.10.2". */ + public static readonly VER_2_10_2 = AuroraMysqlEngineVersion.builtIn_5_7('2.10.2'); /** Version "8.0.mysql_aurora.3.01.0". */ public static readonly VER_3_01_0 = AuroraMysqlEngineVersion.builtIn_8_0('3.01.0'); diff --git a/packages/@aws-cdk/aws-rds/lib/cluster.ts b/packages/@aws-cdk/aws-rds/lib/cluster.ts index 72d922d618a36..76fe7d597b70b 100644 --- a/packages/@aws-cdk/aws-rds/lib/cluster.ts +++ b/packages/@aws-cdk/aws-rds/lib/cluster.ts @@ -250,6 +250,21 @@ interface DatabaseClusterBaseProps { * @default false */ readonly iamAuthentication?: boolean; + + /** + * Whether to enable storage encryption. + * + * @default - true if storageEncryptionKey is provided, false otherwise + */ + readonly storageEncrypted?: boolean + + /** + * The KMS key for storage encryption. + * If specified, {@link storageEncrypted} will be set to `true`. + * + * @default - if storageEncrypted is true then the default master key, no key otherwise + */ + readonly storageEncryptionKey?: kms.IKey; } /** @@ -402,6 +417,9 @@ abstract class DatabaseClusterNew extends DatabaseClusterBase { preferredMaintenanceWindow: props.preferredMaintenanceWindow, databaseName: props.defaultDatabaseName, enableCloudwatchLogsExports: props.cloudwatchLogsExports, + // Encryption + kmsKeyId: props.storageEncryptionKey?.keyArn, + storageEncrypted: props.storageEncryptionKey ? true : props.storageEncrypted, }; } } @@ -479,21 +497,6 @@ export interface DatabaseClusterProps extends DatabaseClusterBaseProps { */ readonly credentials?: Credentials; - /** - * Whether to enable storage encryption. - * - * @default - true if storageEncryptionKey is provided, false otherwise - */ - readonly storageEncrypted?: boolean - - /** - * The KMS key for storage encryption. - * If specified, {@link storageEncrypted} will be set to `true`. - * - * @default - if storageEncrypted is true then the default master key, no key otherwise - */ - readonly storageEncryptionKey?: kms.IKey; - /** * Whether to copy tags to the snapshot when a snapshot is created. * @@ -550,9 +553,7 @@ export class DatabaseCluster extends DatabaseClusterNew { // Admin masterUsername: credentials.username, masterUserPassword: credentials.password?.toString(), - // Encryption - kmsKeyId: props.storageEncryptionKey?.keyArn, - storageEncrypted: props.storageEncryptionKey ? true : props.storageEncrypted, + // Tags copyTagsToSnapshot: props.copyTagsToSnapshot ?? true, }); diff --git a/packages/@aws-cdk/aws-rds/lib/instance.ts b/packages/@aws-cdk/aws-rds/lib/instance.ts index 6236fe0fbc156..f1aa82dd20b3b 100644 --- a/packages/@aws-cdk/aws-rds/lib/instance.ts +++ b/packages/@aws-cdk/aws-rds/lib/instance.ts @@ -1171,12 +1171,18 @@ export class DatabaseInstanceReadReplica extends DatabaseInstanceNew implements throw new Error(`Cannot set 'backupRetention', as engine '${engineDescription(props.sourceDatabaseInstance.engine)}' does not support automatic backups for read replicas`); } + // The read replica instance always uses the same engine as the source instance + // but some CF validations require the engine to be explicitely passed when some + // properties are specified. + const shouldPassEngine = props.domain != null; + const instance = new CfnDBInstance(this, 'Resource', { ...this.newCfnProps, // this must be ARN, not ID, because of https://github.com/terraform-providers/terraform-provider-aws/issues/528#issuecomment-391169012 sourceDbInstanceIdentifier: props.sourceDatabaseInstance.instanceArn, kmsKeyId: props.storageEncryptionKey?.keyArn, storageEncrypted: props.storageEncryptionKey ? true : props.storageEncrypted, + engine: shouldPassEngine ? props.sourceDatabaseInstance.engine?.engineType : undefined, }); this.instanceType = props.instanceType; diff --git a/packages/@aws-cdk/aws-rds/lib/serverless-cluster.ts b/packages/@aws-cdk/aws-rds/lib/serverless-cluster.ts index 0365bfd98c9e9..955b92ac58e5f 100644 --- a/packages/@aws-cdk/aws-rds/lib/serverless-cluster.ts +++ b/packages/@aws-cdk/aws-rds/lib/serverless-cluster.ts @@ -99,11 +99,14 @@ interface ServerlessClusterNewProps { /** * The VPC that this Aurora Serverless cluster has been created in. + * + * @default - the default VPC in the account and region will be used */ - readonly vpc: ec2.IVpc; + readonly vpc?: ec2.IVpc; /** - * Where to place the instances within the VPC + * Where to place the instances within the VPC. + * If provided, the `vpc` property must also be specified. * * @default - the VPC default strategy if not specified. */ @@ -129,7 +132,8 @@ interface ServerlessClusterNewProps { /** * Security group. * - * @default - a new security group is created. + * @default - a new security group is created if `vpc` was provided. + * If the `vpc` property was not provided, no VPC security groups will be associated with the DB cluster. */ readonly securityGroups?: ec2.ISecurityGroup[]; @@ -143,7 +147,8 @@ interface ServerlessClusterNewProps { /** * Existing subnet group for the cluster. * - * @default - a new subnet group will be created. + * @default - a new subnet group is created if `vpc` was provided. + * If the `vpc` property was not provided, no subnet group will be associated with the DB cluster */ readonly subnetGroup?: ISubnetGroup; } @@ -351,19 +356,42 @@ abstract class ServerlessClusterNew extends ServerlessClusterBase { constructor(scope: Construct, id: string, props: ServerlessClusterNewProps) { super(scope, id); - const { subnetIds } = props.vpc.selectSubnets(props.vpcSubnets); - - // Cannot test whether the subnets are in different AZs, but at least we can test the amount. - if (subnetIds.length < 2) { - Annotations.of(this).addError(`Cluster requires at least 2 subnets, got ${subnetIds.length}`); + if (props.vpc === undefined) { + if (props.vpcSubnets !== undefined) { + throw new Error('A VPC is required to use vpcSubnets in ServerlessCluster. Please add a VPC or remove vpcSubnets'); + } + if (props.subnetGroup !== undefined) { + throw new Error('A VPC is required to use subnetGroup in ServerlessCluster. Please add a VPC or remove subnetGroup'); + } + if (props.securityGroups !== undefined) { + throw new Error('A VPC is required to use securityGroups in ServerlessCluster. Please add a VPC or remove securityGroups'); + } } - const subnetGroup = props.subnetGroup ?? new SubnetGroup(this, 'Subnets', { - description: `Subnets for ${id} database`, - vpc: props.vpc, - vpcSubnets: props.vpcSubnets, - removalPolicy: props.removalPolicy === RemovalPolicy.RETAIN ? props.removalPolicy : undefined, - }); + let subnetGroup: ISubnetGroup | undefined = props.subnetGroup; + this.securityGroups = props.securityGroups ?? []; + if (props.vpc !== undefined) { + const { subnetIds } = props.vpc.selectSubnets(props.vpcSubnets); + + // Cannot test whether the subnets are in different AZs, but at least we can test the amount. + if (subnetIds.length < 2) { + Annotations.of(this).addError(`Cluster requires at least 2 subnets, got ${subnetIds.length}`); + } + + subnetGroup = props.subnetGroup ?? new SubnetGroup(this, 'Subnets', { + description: `Subnets for ${id} database`, + vpc: props.vpc, + vpcSubnets: props.vpcSubnets, + removalPolicy: props.removalPolicy === RemovalPolicy.RETAIN ? props.removalPolicy : undefined, + }); + + this.securityGroups = props.securityGroups ?? [ + new ec2.SecurityGroup(this, 'SecurityGroup', { + description: 'RDS security group', + vpc: props.vpc, + }), + ]; + } if (props.backupRetention) { const backupRetentionDays = props.backupRetention.toDays(); @@ -379,12 +407,6 @@ abstract class ServerlessClusterNew extends ServerlessClusterBase { const clusterParameterGroup = props.parameterGroup ?? clusterEngineBindConfig.parameterGroup; const clusterParameterGroupConfig = clusterParameterGroup?.bindToCluster({}); - this.securityGroups = props.securityGroups ?? [ - new ec2.SecurityGroup(this, 'SecurityGroup', { - description: 'RDS security group', - vpc: props.vpc, - }), - ]; const clusterIdentifier = FeatureFlags.of(this).isEnabled(cxapi.RDS_LOWERCASE_DB_IDENTIFIER) ? props.clusterIdentifier?.toLowerCase() @@ -395,7 +417,7 @@ abstract class ServerlessClusterNew extends ServerlessClusterBase { databaseName: props.defaultDatabaseName, dbClusterIdentifier: clusterIdentifier, dbClusterParameterGroupName: clusterParameterGroupConfig?.parameterGroupName, - dbSubnetGroupName: subnetGroup.subnetGroupName, + dbSubnetGroupName: subnetGroup?.subnetGroupName, deletionProtection: defaultDeletionProtection(props.deletionProtection, props.removalPolicy), engine: props.engine.engineType, engineVersion: props.engine.engineVersion?.fullVersion, @@ -476,7 +498,7 @@ export class ServerlessCluster extends ServerlessClusterNew { public readonly secret?: secretsmanager.ISecret; - private readonly vpc: ec2.IVpc; + private readonly vpc?: ec2.IVpc; private readonly vpcSubnets?: ec2.SubnetSelection; private readonly singleUserRotationApplication: secretsmanager.SecretRotationApplication; @@ -525,6 +547,10 @@ export class ServerlessCluster extends ServerlessClusterNew { throw new Error('Cannot add single user rotation for a cluster without secret.'); } + if (this.vpc === undefined) { + throw new Error('Cannot add single user rotation for a cluster without VPC.'); + } + const id = 'RotationSingleUser'; const existing = this.node.tryFindChild(id); if (existing) { @@ -549,6 +575,11 @@ export class ServerlessCluster extends ServerlessClusterNew { if (!this.secret) { throw new Error('Cannot add multi user rotation for a cluster without secret.'); } + + if (this.vpc === undefined) { + throw new Error('Cannot add multi user rotation for a cluster without VPC.'); + } + return new secretsmanager.SecretRotation(this, id, { ...options, excludeCharacters: options.excludeCharacters ?? DEFAULT_PASSWORD_EXCLUDE_CHARS, @@ -680,4 +711,4 @@ export class ServerlessClusterFromSnapshot extends ServerlessClusterNew { this.secret = secret.attach(this); } } -} \ No newline at end of file +} diff --git a/packages/@aws-cdk/aws-rds/package.json b/packages/@aws-cdk/aws-rds/package.json index 174ea5579a8a6..3110738220ab1 100644 --- a/packages/@aws-cdk/aws-rds/package.json +++ b/packages/@aws-cdk/aws-rds/package.json @@ -87,7 +87,7 @@ "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/cx-api": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-rds/test/cluster.test.ts b/packages/@aws-cdk/aws-rds/test/cluster.test.ts index 4ee20a30daffd..ea6123026cca5 100644 --- a/packages/@aws-cdk/aws-rds/test/cluster.test.ts +++ b/packages/@aws-cdk/aws-rds/test/cluster.test.ts @@ -1,6 +1,7 @@ import { Match, Template } from '@aws-cdk/assertions'; import * as ec2 from '@aws-cdk/aws-ec2'; import { ManagedPolicy, Role, ServicePrincipal } from '@aws-cdk/aws-iam'; +import * as iam from '@aws-cdk/aws-iam'; import * as kms from '@aws-cdk/aws-kms'; import * as logs from '@aws-cdk/aws-logs'; import * as s3 from '@aws-cdk/aws-s3'; @@ -953,7 +954,6 @@ describe('cluster', () => { }); }); - test('addRotationSingleUser() with VPC interface endpoint', () => { // GIVEN const stack = new cdk.Stack(); @@ -1707,6 +1707,26 @@ describe('cluster', () => { Template.fromStack(stack).resourceCountIs('AWS::RDS::DBClusterParameterGroup', 0); }); + test('MySQL cluster in version 8.0 uses aws_default_s3_role as a Parameter for S3 import, instead of aurora_load_from_s3_role', () => { + // GIVEN + const stack = testStack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + + // WHEN + new DatabaseCluster(stack, 'Database', { + instanceProps: { vpc }, + engine: DatabaseClusterEngine.auroraMysql({ version: AuroraMysqlEngineVersion.VER_3_01_0 }), + s3ImportRole: iam.Role.fromRoleArn(stack, 'S3ImportRole', 'arn:aws:iam::123456789012:role/my-role'), + }); + + Template.fromStack(stack).hasResourceProperties('AWS::RDS::DBClusterParameterGroup', { + Family: 'aurora-mysql8.0', + Parameters: { + aws_default_s3_role: 'arn:aws:iam::123456789012:role/my-role', + }, + }); + }); + test('throws when s3ExportRole and s3ExportBuckets properties are both specified', () => { // GIVEN const stack = testStack(); @@ -1954,6 +1974,27 @@ describe('cluster', () => { }); }); + test('create a cluster from a snapshot with encrypted storage', () => { + const stack = testStack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + + // WHEN + new DatabaseClusterFromSnapshot(stack, 'Database', { + engine: DatabaseClusterEngine.aurora({ version: AuroraEngineVersion.VER_1_22_2 }), + instanceProps: { + vpc, + }, + snapshotIdentifier: 'mySnapshot', + storageEncryptionKey: kms.Key.fromKeyArn(stack, 'Key', 'arn:aws:kms:us-east-1:456:key/my-key'), + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::RDS::DBCluster', { + KmsKeyId: 'arn:aws:kms:us-east-1:456:key/my-key', + StorageEncrypted: true, + }); + }); + test('reuse an existing subnet group', () => { // GIVEN const stack = testStack(); diff --git a/packages/@aws-cdk/aws-rds/test/instance.test.ts b/packages/@aws-cdk/aws-rds/test/instance.test.ts index 6ba08c6d9f2fb..2cb7e5ebb95fc 100644 --- a/packages/@aws-cdk/aws-rds/test/instance.test.ts +++ b/packages/@aws-cdk/aws-rds/test/instance.test.ts @@ -1617,6 +1617,31 @@ describe('instance', () => { }, }); }); + + test('engine is specified for read replica using domain', () => { + // GIVEN + const instanceType = ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.SMALL); + const engine = rds.DatabaseInstanceEngine.postgres({ version: rds.PostgresEngineVersion.VER_13 }); + const source = new rds.DatabaseInstance(stack, 'Source', { + engine, + instanceType, + vpc, + }); + + // WHEN + new rds.DatabaseInstanceReadReplica(stack, 'Replica', { + sourceDatabaseInstance: source, + instanceType, + vpc, + domain: 'my-domain', + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::RDS::DBInstance', { + SourceDBInstanceIdentifier: Match.anyValue(), + Engine: 'postgres', + }); + }); }); test.each([ diff --git a/packages/@aws-cdk/aws-rds/test/integ.serverless-cluster-no-vpc.expected.json b/packages/@aws-cdk/aws-rds/test/integ.serverless-cluster-no-vpc.expected.json new file mode 100644 index 0000000000000..7d81d78c4e34f --- /dev/null +++ b/packages/@aws-cdk/aws-rds/test/integ.serverless-cluster-no-vpc.expected.json @@ -0,0 +1,18 @@ +{ + "Resources": { + "ServerlessDatabaseWithoutVPC93F9A752": { + "Type": "AWS::RDS::DBCluster", + "Properties": { + "Engine": "aurora-mysql", + "DBClusterParameterGroupName": "default.aurora-mysql5.7", + "EngineMode": "serverless", + "MasterUsername": "admin", + "MasterUserPassword": "7959866cacc02c2d243ecfe177464fe6", + "StorageEncrypted": true, + "VpcSecurityGroupIds": [] + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-rds/test/integ.serverless-cluster-no-vpc.ts b/packages/@aws-cdk/aws-rds/test/integ.serverless-cluster-no-vpc.ts new file mode 100644 index 0000000000000..807cf1a894601 --- /dev/null +++ b/packages/@aws-cdk/aws-rds/test/integ.serverless-cluster-no-vpc.ts @@ -0,0 +1,17 @@ +import * as cdk from '@aws-cdk/core'; +import * as rds from '../lib'; + +const app = new cdk.App(); +const stack = new cdk.Stack(app, 'aws-cdk-sls-cluster-no-vpc-integ'); + +const cluster = new rds.ServerlessCluster(stack, 'Serverless Database Without VPC', { + engine: rds.DatabaseClusterEngine.AURORA_MYSQL, + credentials: { + username: 'admin', + password: cdk.SecretValue.plainText('7959866cacc02c2d243ecfe177464fe6'), + }, + removalPolicy: cdk.RemovalPolicy.DESTROY, +}); +cluster.connections.allowDefaultPortFromAnyIpv4('Open to the world'); + +app.synth(); diff --git a/packages/@aws-cdk/aws-rds/test/serverless-cluster.test.ts b/packages/@aws-cdk/aws-rds/test/serverless-cluster.test.ts index 3849a99cdeb02..a55a23df02421 100644 --- a/packages/@aws-cdk/aws-rds/test/serverless-cluster.test.ts +++ b/packages/@aws-cdk/aws-rds/test/serverless-cluster.test.ts @@ -1,10 +1,10 @@ -import { Template } from '@aws-cdk/assertions'; +import { Template, Match } from '@aws-cdk/assertions'; import * as ec2 from '@aws-cdk/aws-ec2'; import * as iam from '@aws-cdk/aws-iam'; import * as kms from '@aws-cdk/aws-kms'; import * as cdk from '@aws-cdk/core'; import * as cxapi from '@aws-cdk/cx-api'; -import { AuroraPostgresEngineVersion, ServerlessCluster, DatabaseClusterEngine, ParameterGroup, AuroraCapacityUnit, DatabaseSecret } from '../lib'; +import { AuroraPostgresEngineVersion, ServerlessCluster, DatabaseClusterEngine, ParameterGroup, AuroraCapacityUnit, DatabaseSecret, SubnetGroup } from '../lib'; describe('serverless cluster', () => { test('can create a Serverless Cluster with Aurora Postgres database engine', () => { @@ -70,28 +70,18 @@ describe('serverless cluster', () => { }, EngineMode: 'serverless', MasterUsername: { - 'Fn::Join': [ - '', - [ - '{{resolve:secretsmanager:', - { - Ref: 'ServerlessDatabaseSecret1C9BF4F1', - }, - ':SecretString:username::}}', - ], - ], + 'Fn::Join': ['', [ + '{{resolve:secretsmanager:', + { Ref: 'ServerlessDatabaseSecret1C9BF4F1' }, + ':SecretString:username::}}', + ]], }, MasterUserPassword: { - 'Fn::Join': [ - '', - [ - '{{resolve:secretsmanager:', - { - Ref: 'ServerlessDatabaseSecret1C9BF4F1', - }, - ':SecretString:password::}}', - ], - ], + 'Fn::Join': ['', [ + '{{resolve:secretsmanager:', + { Ref: 'ServerlessDatabaseSecret1C9BF4F1' }, + ':SecretString:password::}}', + ]], }, StorageEncrypted: true, VpcSecurityGroupIds: [ @@ -131,28 +121,18 @@ describe('serverless cluster', () => { EngineMode: 'serverless', DBSubnetGroupName: { Ref: 'DatabaseSubnets56F17B9A' }, MasterUsername: { - 'Fn::Join': [ - '', - [ - '{{resolve:secretsmanager:', - { - Ref: 'DatabaseSecret3B817195', - }, - ':SecretString:username::}}', - ], - ], + 'Fn::Join': ['', [ + '{{resolve:secretsmanager:', + { Ref: 'DatabaseSecret3B817195' }, + ':SecretString:username::}}', + ]], }, MasterUserPassword: { - 'Fn::Join': [ - '', - [ - '{{resolve:secretsmanager:', - { - Ref: 'DatabaseSecret3B817195', - }, - ':SecretString:password::}}', - ], - ], + 'Fn::Join': ['', [ + '{{resolve:secretsmanager:', + { Ref: 'DatabaseSecret3B817195' }, + ':SecretString:password::}}', + ]], }, VpcSecurityGroupIds: ['SecurityGroupId12345'], }); @@ -192,28 +172,18 @@ describe('serverless cluster', () => { // THEN Template.fromStack(stack).hasResourceProperties('AWS::RDS::DBCluster', { MasterUsername: { - 'Fn::Join': [ - '', - [ - '{{resolve:secretsmanager:', - { - Ref: 'DatabaseSecret3B817195', - }, - ':SecretString:username::}}', - ], - ], + 'Fn::Join': ['', [ + '{{resolve:secretsmanager:', + { Ref: 'DatabaseSecret3B817195' }, + ':SecretString:username::}}', + ]], }, MasterUserPassword: { - 'Fn::Join': [ - '', - [ - '{{resolve:secretsmanager:', - { - Ref: 'DatabaseSecret3B817195', - }, - ':SecretString:password::}}', - ], - ], + 'Fn::Join': ['', [ + '{{resolve:secretsmanager:', + { Ref: 'DatabaseSecret3B817195' }, + ':SecretString:password::}}', + ]], }, }); @@ -351,7 +321,7 @@ describe('serverless cluster', () => { expect(cluster.clusterReadEndpoint.socketAddress).toEqual('reader-address:3306'); }); - test('throws when trying to add rotation to a serverless cluster without secret', () => { + test('throws when trying to add single-user rotation to a serverless cluster without secret', () => { // GIVEN const stack = new cdk.Stack(); const vpc = new ec2.Vpc(stack, 'VPC'); @@ -387,6 +357,39 @@ describe('serverless cluster', () => { expect(() => cluster.addRotationSingleUser()).toThrow(/A single user rotation was already added to this cluster/); }); + test('throws when trying to add single-user rotation to a serverless cluster without VPC', () => { + // GIVEN + const stack = new cdk.Stack(); + + // WHEN + const cluster = new ServerlessCluster(stack, 'Database', { + engine: DatabaseClusterEngine.AURORA_MYSQL, + }); + + // THEN + expect(() => { + cluster.addRotationSingleUser(); + }).toThrow(/Cannot add single user rotation for a cluster without VPC/); + }); + + test('throws when trying to add multi-user rotation to a serverless cluster without VPC', () => { + // GIVEN + const stack = new cdk.Stack(); + const secret = new DatabaseSecret(stack, 'Secret', { + username: 'admin', + }); + + // WHEN + const cluster = new ServerlessCluster(stack, 'Database', { + engine: DatabaseClusterEngine.AURORA_MYSQL, + }); + + // THEN + expect(() => { + cluster.addRotationMultiUser('someId', { secret }); + }).toThrow(/Cannot add multi user rotation for a cluster without VPC/); + }); + test('can set deletion protection', () => { // GIVEN const stack = testStack(); @@ -612,15 +615,12 @@ describe('serverless cluster', () => { // THEN expect(stack.resolve(cluster.clusterArn)).toEqual({ - 'Fn::Join': [ - '', - [ - 'arn:', - { Ref: 'AWS::Partition' }, - ':rds:us-test-1:12345:cluster:', - { Ref: 'DatabaseB269D8BB' }, - ], - ], + 'Fn::Join': ['', [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':rds:us-test-1:12345:cluster:', + { Ref: 'DatabaseB269D8BB' }, + ]], }); }); @@ -803,6 +803,65 @@ describe('serverless cluster', () => { DBClusterIdentifier: clusterIdentifier, }); }); + + test('can create a Serverless cluster without VPC', () => { + // GIVEN + const stack = testStack(); + + // WHEN + new ServerlessCluster(stack, 'Database', { + engine: DatabaseClusterEngine.AURORA_MYSQL, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::RDS::DBCluster', { + Engine: 'aurora-mysql', + EngineMode: 'serverless', + DbSubnetGroupName: Match.absent(), + VpcSecurityGroupIds: [], + }); + }); + + test('cannot create a Serverless cluster without VPC but specifying a security group', () => { + // GIVEN + const stack = testStack(); + const sg = ec2.SecurityGroup.fromSecurityGroupId(stack, 'SG', 'SecurityGroupId12345'); + + // THEN + expect(() => new ServerlessCluster(stack, 'Database', { + engine: DatabaseClusterEngine.AURORA_MYSQL, + securityGroups: [sg], + })).toThrow(/A VPC is required to use securityGroups in ServerlessCluster. Please add a VPC or remove securityGroups/); + }); + + test('cannot create a Serverless cluster without VPC but specifying a subnet group', () => { + // GIVEN + const stack = testStack(); + const SubnetGroupName = 'SubnetGroupId12345'; + const subnetGroup = SubnetGroup.fromSubnetGroupName(stack, 'SubnetGroup12345', SubnetGroupName); + + // THEN + expect(() => new ServerlessCluster(stack, 'Database', { + engine: DatabaseClusterEngine.AURORA_MYSQL, + subnetGroup, + })).toThrow(/A VPC is required to use subnetGroup in ServerlessCluster. Please add a VPC or remove subnetGroup/); + }); + + test('cannot create a Serverless cluster without VPC but specifying VPC subnets', () => { + // GIVEN + const stack = testStack(); + + // WHEN + const vpcSubnets = { + subnetName: 'AVpcSubnet', + }; + + // THEN + expect(() => new ServerlessCluster(stack, 'Database', { + engine: DatabaseClusterEngine.AURORA_MYSQL, + vpcSubnets, + })).toThrow(/A VPC is required to use vpcSubnets in ServerlessCluster. Please add a VPC or remove vpcSubnets/); + }); }); function testStack(app?: cdk.App, id?: string): cdk.Stack { diff --git a/packages/@aws-cdk/aws-redshift/package.json b/packages/@aws-cdk/aws-redshift/package.json index 6c214a6a8ab89..d6841a31195d5 100644 --- a/packages/@aws-cdk/aws-redshift/package.json +++ b/packages/@aws-cdk/aws-redshift/package.json @@ -84,7 +84,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "aws-sdk": "^2.848.0", "jest": "^27.5.1" }, diff --git a/packages/@aws-cdk/aws-rekognition/package.json b/packages/@aws-cdk/aws-rekognition/package.json index 9cf5d2e0d407d..1c92e782a9e64 100644 --- a/packages/@aws-cdk/aws-rekognition/package.json +++ b/packages/@aws-cdk/aws-rekognition/package.json @@ -95,7 +95,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-resourcegroups/package.json b/packages/@aws-cdk/aws-resourcegroups/package.json index caf23fb138d50..a17a9aa169e15 100644 --- a/packages/@aws-cdk/aws-resourcegroups/package.json +++ b/packages/@aws-cdk/aws-resourcegroups/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-robomaker/package.json b/packages/@aws-cdk/aws-robomaker/package.json index d40dc417d86d6..b96c0b59e92b4 100644 --- a/packages/@aws-cdk/aws-robomaker/package.json +++ b/packages/@aws-cdk/aws-robomaker/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-route53-patterns/package.json b/packages/@aws-cdk/aws-route53-patterns/package.json index 1ee06cae1d0b8..2d4e248234582 100644 --- a/packages/@aws-cdk/aws-route53-patterns/package.json +++ b/packages/@aws-cdk/aws-route53-patterns/package.json @@ -77,7 +77,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-route53-targets/package.json b/packages/@aws-cdk/aws-route53-targets/package.json index 101ccb2e8c39c..7aca456bffc24 100644 --- a/packages/@aws-cdk/aws-route53-targets/package.json +++ b/packages/@aws-cdk/aws-route53-targets/package.json @@ -79,7 +79,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-route53/lib/record-set.ts b/packages/@aws-cdk/aws-route53/lib/record-set.ts index 823257f6fb576..a10cb05c37e67 100644 --- a/packages/@aws-cdk/aws-route53/lib/record-set.ts +++ b/packages/@aws-cdk/aws-route53/lib/record-set.ts @@ -690,13 +690,13 @@ export class CrossAccountZoneDelegationRecord extends CoreConstruct { const role = iam.Role.fromRoleArn(this, 'cross-account-zone-delegation-handler-role', provider.roleArn); - role.addToPrincipalPolicy(new iam.PolicyStatement({ + const addToPrinciplePolicyResult = role.addToPrincipalPolicy(new iam.PolicyStatement({ effect: iam.Effect.ALLOW, actions: ['sts:AssumeRole'], resources: [props.delegationRole.roleArn], })); - new CustomResource(this, 'CrossAccountZoneDelegationCustomResource', { + const customResource = new CustomResource(this, 'CrossAccountZoneDelegationCustomResource', { resourceType: CROSS_ACCOUNT_ZONE_DELEGATION_RESOURCE_TYPE, serviceToken: provider.serviceToken, removalPolicy: props.removalPolicy, @@ -709,5 +709,9 @@ export class CrossAccountZoneDelegationRecord extends CoreConstruct { TTL: (props.ttl || Duration.days(2)).toSeconds(), }, }); + + if (addToPrinciplePolicyResult.policyDependable) { + customResource.node.addDependency(addToPrinciplePolicyResult.policyDependable); + } } } diff --git a/packages/@aws-cdk/aws-route53/package.json b/packages/@aws-cdk/aws-route53/package.json index 6b85275fe8528..9cb18851a5db3 100644 --- a/packages/@aws-cdk/aws-route53/package.json +++ b/packages/@aws-cdk/aws-route53/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", "@types/aws-lambda": "^8.10.92", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "aws-sdk": "^2.848.0", "jest": "^27.5.1" }, diff --git a/packages/@aws-cdk/aws-route53/test/integ.cross-account-zone-delegation.expected.json b/packages/@aws-cdk/aws-route53/test/integ.cross-account-zone-delegation.expected.json index d5890cda1c955..3ad72296cd685 100644 --- a/packages/@aws-cdk/aws-route53/test/integ.cross-account-zone-delegation.expected.json +++ b/packages/@aws-cdk/aws-route53/test/integ.cross-account-zone-delegation.expected.json @@ -154,6 +154,9 @@ }, "TTL": 172800 }, + "DependsOn": [ + "DelegationWithZoneIdcrossaccountzonedelegationhandlerrolePolicy5170A69B" + ], "UpdateReplacePolicy": "Delete", "DeletionPolicy": "Delete" }, @@ -184,7 +187,7 @@ "Properties": { "Code": { "S3Bucket": { - "Ref": "AssetParametersd17df4f90e07a972e8f7b00dddbae8e3eba45a212226d2b714dcd28dded69602S3Bucket200D9216" + "Ref": "AssetParameters7625bcc3bbd65c490a92d42790a563e31dc02c18006ef272338c8c788849bb8aS3BucketC1366C27" }, "S3Key": { "Fn::Join": [ @@ -197,7 +200,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParametersd17df4f90e07a972e8f7b00dddbae8e3eba45a212226d2b714dcd28dded69602S3VersionKey0E5C26F0" + "Ref": "AssetParameters7625bcc3bbd65c490a92d42790a563e31dc02c18006ef272338c8c788849bb8aS3VersionKeyEE72CEF8" } ] } @@ -210,7 +213,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParametersd17df4f90e07a972e8f7b00dddbae8e3eba45a212226d2b714dcd28dded69602S3VersionKey0E5C26F0" + "Ref": "AssetParameters7625bcc3bbd65c490a92d42790a563e31dc02c18006ef272338c8c788849bb8aS3VersionKeyEE72CEF8" } ] } @@ -315,22 +318,25 @@ }, "TTL": 172800 }, + "DependsOn": [ + "DelegationWithZoneNamecrossaccountzonedelegationhandlerrolePolicy86996882" + ], "UpdateReplacePolicy": "Delete", "DeletionPolicy": "Delete" } }, "Parameters": { - "AssetParametersd17df4f90e07a972e8f7b00dddbae8e3eba45a212226d2b714dcd28dded69602S3Bucket200D9216": { + "AssetParameters7625bcc3bbd65c490a92d42790a563e31dc02c18006ef272338c8c788849bb8aS3BucketC1366C27": { "Type": "String", - "Description": "S3 bucket for asset \"d17df4f90e07a972e8f7b00dddbae8e3eba45a212226d2b714dcd28dded69602\"" + "Description": "S3 bucket for asset \"7625bcc3bbd65c490a92d42790a563e31dc02c18006ef272338c8c788849bb8a\"" }, - "AssetParametersd17df4f90e07a972e8f7b00dddbae8e3eba45a212226d2b714dcd28dded69602S3VersionKey0E5C26F0": { + "AssetParameters7625bcc3bbd65c490a92d42790a563e31dc02c18006ef272338c8c788849bb8aS3VersionKeyEE72CEF8": { "Type": "String", - "Description": "S3 key for asset version \"d17df4f90e07a972e8f7b00dddbae8e3eba45a212226d2b714dcd28dded69602\"" + "Description": "S3 key for asset version \"7625bcc3bbd65c490a92d42790a563e31dc02c18006ef272338c8c788849bb8a\"" }, - "AssetParametersd17df4f90e07a972e8f7b00dddbae8e3eba45a212226d2b714dcd28dded69602ArtifactHash37FB4D0C": { + "AssetParameters7625bcc3bbd65c490a92d42790a563e31dc02c18006ef272338c8c788849bb8aArtifactHashAADF3168": { "Type": "String", - "Description": "Artifact hash for asset \"d17df4f90e07a972e8f7b00dddbae8e3eba45a212226d2b714dcd28dded69602\"" + "Description": "Artifact hash for asset \"7625bcc3bbd65c490a92d42790a563e31dc02c18006ef272338c8c788849bb8a\"" } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-route53/test/record-set.test.ts b/packages/@aws-cdk/aws-route53/test/record-set.test.ts index a48cb07bb5ab0..fbf3d56517d3b 100644 --- a/packages/@aws-cdk/aws-route53/test/record-set.test.ts +++ b/packages/@aws-cdk/aws-route53/test/record-set.test.ts @@ -737,33 +737,38 @@ describe('record set', () => { // THEN const childHostedZones = [ - { name: 'sub.myzone.com', id: 'ChildHostedZone4B14AC71' }, - { name: 'anothersub.myzone.com', id: 'ChildHostedZone2A37198F0' }, + { name: 'sub.myzone.com', id: 'ChildHostedZone4B14AC71', dependsOn: 'DelegationcrossaccountzonedelegationhandlerrolePolicy1E157602' }, + { name: 'anothersub.myzone.com', id: 'ChildHostedZone2A37198F0', dependsOn: 'Delegation2crossaccountzonedelegationhandlerrolePolicy713BEAC3' }, ]; for (var childHostedZone of childHostedZones) { - Template.fromStack(stack).hasResourceProperties('Custom::CrossAccountZoneDelegation', { - ServiceToken: { - 'Fn::GetAtt': [ - 'CustomCrossAccountZoneDelegationCustomResourceProviderHandler44A84265', - 'Arn', - ], - }, - AssumeRoleArn: { - 'Fn::GetAtt': [ - 'ParentHostedZoneCrossAccountZoneDelegationRole95B1C36E', - 'Arn', - ], - }, - ParentZoneName: 'myzone.com', - DelegatedZoneName: childHostedZone.name, - DelegatedZoneNameServers: { - 'Fn::GetAtt': [ - childHostedZone.id, - 'NameServers', - ], + Template.fromStack(stack).hasResource('Custom::CrossAccountZoneDelegation', { + Properties: { + ServiceToken: { + 'Fn::GetAtt': [ + 'CustomCrossAccountZoneDelegationCustomResourceProviderHandler44A84265', + 'Arn', + ], + }, + AssumeRoleArn: { + 'Fn::GetAtt': [ + 'ParentHostedZoneCrossAccountZoneDelegationRole95B1C36E', + 'Arn', + ], + }, + ParentZoneName: 'myzone.com', + DelegatedZoneName: childHostedZone.name, + DelegatedZoneNameServers: { + 'Fn::GetAtt': [ + childHostedZone.id, + 'NameServers', + ], + }, + TTL: 60, }, - TTL: 60, + DependsOn: [ + childHostedZone.dependsOn, + ], }); } }); diff --git a/packages/@aws-cdk/aws-route53recoverycontrol/package.json b/packages/@aws-cdk/aws-route53recoverycontrol/package.json index 0ec2546ada38d..cde17f02ec86e 100644 --- a/packages/@aws-cdk/aws-route53recoverycontrol/package.json +++ b/packages/@aws-cdk/aws-route53recoverycontrol/package.json @@ -87,7 +87,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-route53recoveryreadiness/package.json b/packages/@aws-cdk/aws-route53recoveryreadiness/package.json index 6dcaed6cb8433..8feeeca412adb 100644 --- a/packages/@aws-cdk/aws-route53recoveryreadiness/package.json +++ b/packages/@aws-cdk/aws-route53recoveryreadiness/package.json @@ -87,7 +87,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-route53resolver/package.json b/packages/@aws-cdk/aws-route53resolver/package.json index 851453eb1279c..be0c3e79cea04 100644 --- a/packages/@aws-cdk/aws-route53resolver/package.json +++ b/packages/@aws-cdk/aws-route53resolver/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/aws-ec2": "0.0.0", diff --git a/packages/@aws-cdk/aws-s3-assets/package.json b/packages/@aws-cdk/aws-s3-assets/package.json index 80996d4ebc255..5291ae6cb726e 100644 --- a/packages/@aws-cdk/aws-s3-assets/package.json +++ b/packages/@aws-cdk/aws-s3-assets/package.json @@ -82,7 +82,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cloud-assembly-schema": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/assets": "0.0.0", diff --git a/packages/@aws-cdk/aws-s3-deployment/README.md b/packages/@aws-cdk/aws-s3-deployment/README.md index 62595042f652a..84ccec9e23c55 100644 --- a/packages/@aws-cdk/aws-s3-deployment/README.md +++ b/packages/@aws-cdk/aws-s3-deployment/README.md @@ -42,6 +42,25 @@ This is what happens under the hood: `websiteBucket`). If there is more than one source, the sources will be downloaded and merged pre-deployment at this step. +If you are referencing the filled bucket in another construct that depends on +the files already be there, be sure to use `deployment.deployedBucket`. This +will ensure the bucket deployment has finished before the resource that uses +the bucket is created: + +```ts +declare const websiteBucket: s3.Bucket; + +const deployment = new s3deploy.BucketDeployment(this, 'DeployWebsite', { + sources: [s3deploy.Source.asset(path.join(__dirname, 'my-website'))], + destinationBucket: websiteBucket, +}); + +new ConstructThatReadsFromTheBucket(this, 'Consumer', { + // Use 'deployment.deployedBucket' instead of 'websiteBucket' here + bucket: deployment.deployedBucket, +}); +``` + ## Supported sources The following source types are supported for bucket deployments: @@ -302,7 +321,7 @@ substituting it when its deployed to the destination with the actual value. ## Notes -- This library uses an AWS CloudFormation custom resource which about 10MiB in +- This library uses an AWS CloudFormation custom resource which is about 10MiB in size. The code of this resource is bundled with this library. - AWS Lambda execution time is limited to 15min. This limits the amount of data which can be deployed into the bucket by this timeout. diff --git a/packages/@aws-cdk/aws-s3-deployment/lib/bucket-deployment.ts b/packages/@aws-cdk/aws-s3-deployment/lib/bucket-deployment.ts index b08011866f7ea..31a7ec92e2db5 100644 --- a/packages/@aws-cdk/aws-s3-deployment/lib/bucket-deployment.ts +++ b/packages/@aws-cdk/aws-s3-deployment/lib/bucket-deployment.ts @@ -239,6 +239,10 @@ export interface BucketDeploymentProps { * other S3 buckets or from local disk */ export class BucketDeployment extends CoreConstruct { + private readonly cr: cdk.CustomResource; + private _deployedBucket?: s3.IBucket; + private requestDestinationArn: boolean = false; + constructor(scope: Construct, id: string, props: BucketDeploymentProps) { super(scope, id); @@ -328,7 +332,7 @@ export class BucketDeployment extends CoreConstruct { const hasMarkers = sources.some(source => source.markers); const crUniqueId = `CustomResource${this.renderUniqueId(props.memoryLimit, props.vpc)}`; - const cr = new cdk.CustomResource(this, crUniqueId, { + this.cr = new cdk.CustomResource(this, crUniqueId, { serviceToken: handler.functionArn, resourceType: 'Custom::CDKBucketDeployment', properties: { @@ -345,13 +349,15 @@ export class BucketDeployment extends CoreConstruct { SystemMetadata: mapSystemMetadata(props), DistributionId: props.distribution?.distributionId, DistributionPaths: props.distributionPaths, + // Passing through the ARN sequences dependencees on the deployment + DestinationBucketArn: cdk.Lazy.string({ produce: () => this.requestDestinationArn ? props.destinationBucket.bucketArn : undefined }), }, }); let prefix: string = props.destinationKeyPrefix ? `:${props.destinationKeyPrefix}` : ''; - prefix += `:${cr.node.addr.substr(-8)}`; + prefix += `:${this.cr.node.addr.substr(-8)}`; const tagKey = CUSTOM_RESOURCE_OWNER_TAG + prefix; // destinationKeyPrefix can be 104 characters before we hit @@ -405,6 +411,21 @@ export class BucketDeployment extends CoreConstruct { } + /** + * The bucket after the deployment + * + * If you want to reference the destination bucket in another construct and make sure the + * bucket deployment has happened before the next operation is started, pass the other construct + * a reference to `deployment.deployedBucket`. + * + * Doing this replaces calling `otherResource.node.addDependency(deployment)`. + */ + public get deployedBucket(): s3.IBucket { + this.requestDestinationArn = true; + this._deployedBucket = this._deployedBucket ?? s3.Bucket.fromBucketArn(this, 'DestinationBucket', cdk.Token.asString(this.cr.getAtt('DestinationBucketArn'))); + return this._deployedBucket; + } + private renderUniqueId(memoryLimit?: number, vpc?: ec2.IVpc) { let uuid = ''; diff --git a/packages/@aws-cdk/aws-s3-deployment/lib/lambda/index.py b/packages/@aws-cdk/aws-s3-deployment/lib/lambda/index.py index 14b1cc479e9d8..877b78a8452ee 100644 --- a/packages/@aws-cdk/aws-s3-deployment/lib/lambda/index.py +++ b/packages/@aws-cdk/aws-s3-deployment/lib/lambda/index.py @@ -118,7 +118,10 @@ def cfn_error(message=None): if distribution_id: cloudfront_invalidate(distribution_id, distribution_paths) - cfn_send(event, context, CFN_SUCCESS, physicalResourceId=physical_id) + cfn_send(event, context, CFN_SUCCESS, physicalResourceId=physical_id, responseData={ + # Passing through the ARN sequences dependencees on the deployment + 'DestinationBucketArn': props.get('DestinationBucketArn') + }) except KeyError as e: cfn_error("invalid request. Missing key %s" % str(e)) except Exception as e: diff --git a/packages/@aws-cdk/aws-s3-deployment/package.json b/packages/@aws-cdk/aws-s3-deployment/package.json index 58ea46c3250ed..104ff0bc223d2 100644 --- a/packages/@aws-cdk/aws-s3-deployment/package.json +++ b/packages/@aws-cdk/aws-s3-deployment/package.json @@ -90,7 +90,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cx-api": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-s3-deployment/rosetta/default.ts-fixture b/packages/@aws-cdk/aws-s3-deployment/rosetta/default.ts-fixture index 75a435a142566..8733f436c5e29 100644 --- a/packages/@aws-cdk/aws-s3-deployment/rosetta/default.ts-fixture +++ b/packages/@aws-cdk/aws-s3-deployment/rosetta/default.ts-fixture @@ -13,3 +13,8 @@ class Fixture extends Stack { /// here } } + +class ConstructThatReadsFromTheBucket { + constructor(...args: any[]) { + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3-deployment/test/bucket-deployment.test.ts b/packages/@aws-cdk/aws-s3-deployment/test/bucket-deployment.test.ts index cff1a509c9b5b..9706f9d9d33f1 100644 --- a/packages/@aws-cdk/aws-s3-deployment/test/bucket-deployment.test.ts +++ b/packages/@aws-cdk/aws-s3-deployment/test/bucket-deployment.test.ts @@ -945,6 +945,68 @@ test('deployment allows vpc and subnets to be implicitly supplied to lambda', () }); }); +test('s3 deployment bucket is identical to destination bucket', () => { + // GIVEN + const stack = new cdk.Stack(); + const bucket = new s3.Bucket(stack, 'Dest'); + + // WHEN + const bd = new s3deploy.BucketDeployment(stack, 'Deployment', { + destinationBucket: bucket, + sources: [s3deploy.Source.asset(path.join(__dirname, 'my-website'))], + }); + + // Call this function + void(bd.deployedBucket); + + // THEN + const template = Template.fromStack(stack); + template.hasResourceProperties('Custom::CDKBucketDeployment', { + // Since this utilizes GetAtt, we know CFN will deploy the bucket first + // before deploying other resources that rely call the destination bucket. + DestinationBucketArn: { 'Fn::GetAtt': ['DestC383B82A', 'Arn'] }, + }); +}); + +test('using deployment bucket references the destination bucket by means of the CustomResource', () => { + // GIVEN + const stack = new cdk.Stack(); + const bucket = new s3.Bucket(stack, 'Dest'); + const deployment = new s3deploy.BucketDeployment(stack, 'Deployment', { + destinationBucket: bucket, + sources: [s3deploy.Source.asset(path.join(__dirname, 'my-website'))], + }); + + // WHEN + new cdk.CfnOutput(stack, 'DestinationArn', { + value: deployment.deployedBucket.bucketArn, + }); + new cdk.CfnOutput(stack, 'DestinationName', { + value: deployment.deployedBucket.bucketName, + }); + + // THEN + + const template = Template.fromStack(stack); + expect(template.findOutputs('*')).toEqual({ + DestinationArn: { + Value: { 'Fn::GetAtt': ['DeploymentCustomResource47E8B2E6', 'DestinationBucketArn'] }, + }, + DestinationName: { + Value: { + 'Fn::Select': [0, { + 'Fn::Split': ['/', { + 'Fn::Select': [5, { + 'Fn::Split': [':', + { 'Fn::GetAtt': ['DeploymentCustomResource47E8B2E6', 'DestinationBucketArn'] }], + }], + }], + }], + }, + }, + }); +}); + test('resource id includes memory and vpc', () => { // GIVEN @@ -1139,4 +1201,4 @@ function readDataFile(casm: cxapi.CloudAssembly, assetId: string, filePath: stri const asset = casm.stacks[0].assets.find(a => a.id === assetId); if (!asset) { throw new Error('Asset not found'); } return readFileSync(path.join(casm.directory, asset.path, filePath), 'utf-8'); -} \ No newline at end of file +} diff --git a/packages/@aws-cdk/aws-s3-notifications/README.md b/packages/@aws-cdk/aws-s3-notifications/README.md index 0b57126001cf8..75fba9152e2b8 100644 --- a/packages/@aws-cdk/aws-s3-notifications/README.md +++ b/packages/@aws-cdk/aws-s3-notifications/README.md @@ -26,6 +26,18 @@ const topic = new sns.Topic(this, 'Topic'); bucket.addEventNotification(s3.EventType.OBJECT_CREATED_PUT, new s3n.SnsDestination(topic)); ``` +The following example shows how to send a notification to an SQS queue +when an object is created in an S3 bucket: + +```ts +import * as sqs from '@aws-cdk/aws-sqs'; + +const bucket = new s3.Bucket(this, 'Bucket'); +const queue = new sqs.Queue(this, 'Queue'); + +bucket.addEventNotification(s3.EventType.OBJECT_CREATED_PUT, new s3n.SqsDestination(queue)); +``` + The following example shows how to send a notification to a Lambda function when an object is created in an S3 bucket: ```ts diff --git a/packages/@aws-cdk/aws-s3-notifications/lib/sqs.ts b/packages/@aws-cdk/aws-s3-notifications/lib/sqs.ts index 330a941a9ae86..5562a07c5182a 100644 --- a/packages/@aws-cdk/aws-s3-notifications/lib/sqs.ts +++ b/packages/@aws-cdk/aws-s3-notifications/lib/sqs.ts @@ -1,6 +1,10 @@ import * as iam from '@aws-cdk/aws-iam'; import * as s3 from '@aws-cdk/aws-s3'; import * as sqs from '@aws-cdk/aws-sqs'; +import { Annotations } from '@aws-cdk/core'; + +// 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'; /** @@ -24,11 +28,15 @@ export class SqsDestination implements s3.IBucketNotificationDestination { // if this queue is encrypted, we need to allow S3 to read messages since that's how // it verifies that the notification destination configuration is valid. if (this.queue.encryptionMasterKey) { - this.queue.encryptionMasterKey.addToResourcePolicy(new iam.PolicyStatement({ + const statement = new iam.PolicyStatement({ principals: [new iam.ServicePrincipal('s3.amazonaws.com')], actions: ['kms:GenerateDataKey*', 'kms:Decrypt'], resources: ['*'], - }), /* allowNoOp */ false); + }); + const addResult = this.queue.encryptionMasterKey.addToResourcePolicy(statement, /* allowNoOp */ true); + if (!addResult.statementAdded) { + Annotations.of(this.queue.encryptionMasterKey).addWarning(`Can not change key policy of imported kms key. Ensure that your key policy contains the following permissions: \n${JSON.stringify(statement.toJSON(), null, 2)}`); + } } return { diff --git a/packages/@aws-cdk/aws-s3-notifications/package.json b/packages/@aws-cdk/aws-s3-notifications/package.json index 966572d8350ea..32738cd1b0d93 100644 --- a/packages/@aws-cdk/aws-s3-notifications/package.json +++ b/packages/@aws-cdk/aws-s3-notifications/package.json @@ -75,11 +75,12 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "dependencies": { "@aws-cdk/aws-iam": "0.0.0", + "@aws-cdk/aws-kms": "0.0.0", "@aws-cdk/aws-lambda": "0.0.0", "@aws-cdk/aws-s3": "0.0.0", "@aws-cdk/aws-sns": "0.0.0", @@ -90,6 +91,7 @@ "homepage": "https://github.com/aws/aws-cdk", "peerDependencies": { "@aws-cdk/aws-iam": "0.0.0", + "@aws-cdk/aws-kms": "0.0.0", "@aws-cdk/aws-lambda": "0.0.0", "@aws-cdk/aws-s3": "0.0.0", "@aws-cdk/aws-sns": "0.0.0", diff --git a/packages/@aws-cdk/aws-s3-notifications/test/queue.test.ts b/packages/@aws-cdk/aws-s3-notifications/test/queue.test.ts index b1ae15e895a7c..44404de1b1d79 100644 --- a/packages/@aws-cdk/aws-s3-notifications/test/queue.test.ts +++ b/packages/@aws-cdk/aws-s3-notifications/test/queue.test.ts @@ -1,4 +1,5 @@ -import { Match, Template } from '@aws-cdk/assertions'; +import { Match, Template, Annotations } from '@aws-cdk/assertions'; +import * as kms from '@aws-cdk/aws-kms'; import * as s3 from '@aws-cdk/aws-s3'; import * as sqs from '@aws-cdk/aws-sqs'; import { Stack } from '@aws-cdk/core'; @@ -96,3 +97,27 @@ test('if the queue is encrypted with a custom kms key, the key resource policy i }, }); }); + +test('if the queue is encrypted with a imported kms key, printout warning', () => { + const stack = new Stack(); + const bucket = new s3.Bucket(stack, 'Bucket'); + const key = kms.Key.fromKeyArn(stack, 'ImportedKey', 'arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab'); + const queue = new sqs.Queue(stack, 'Queue', { + encryption: sqs.QueueEncryption.KMS, + encryptionMasterKey: key, + }); + + bucket.addObjectCreatedNotification(new notif.SqsDestination(queue)); + + Annotations.fromStack(stack).hasWarning('/Default/ImportedKey', `Can not change key policy of imported kms key. Ensure that your key policy contains the following permissions: \n${JSON.stringify({ + Action: [ + 'kms:GenerateDataKey*', + 'kms:Decrypt', + ], + Effect: 'Allow', + Principal: { + Service: 's3.amazonaws.com', + }, + Resource: '*', + }, null, 2)}`); +}); diff --git a/packages/@aws-cdk/aws-s3/lib/bucket.ts b/packages/@aws-cdk/aws-s3/lib/bucket.ts index 42d6a84bdc18b..321f65603c14c 100644 --- a/packages/@aws-cdk/aws-s3/lib/bucket.ts +++ b/packages/@aws-cdk/aws-s3/lib/bucket.ts @@ -2297,6 +2297,16 @@ export enum EventType { */ OBJECT_RESTORE_COMPLETED = 's3:ObjectRestore:Completed', + /** + * Using restore object event types you can receive notifications for + * initiation and completion when restoring objects from the S3 Glacier + * storage class. + * + * You use s3:ObjectRestore:Delete to request notification of + * restoration completion. + */ + OBJECT_RESTORE_DELETE = 's3:ObjectRestore:Delete', + /** * You can use this event type to request Amazon S3 to send a notification * message when Amazon S3 detects that an object of the RRS storage class is diff --git a/packages/@aws-cdk/aws-s3/package.json b/packages/@aws-cdk/aws-s3/package.json index 55531e2da34ff..13f96096a7018 100644 --- a/packages/@aws-cdk/aws-s3/package.json +++ b/packages/@aws-cdk/aws-s3/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", "@types/aws-lambda": "^8.10.92", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-s3objectlambda/README.md b/packages/@aws-cdk/aws-s3objectlambda/README.md index 60a5c42835925..35deed15685a9 100644 --- a/packages/@aws-cdk/aws-s3objectlambda/README.md +++ b/packages/@aws-cdk/aws-s3objectlambda/README.md @@ -9,23 +9,92 @@ > > [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. + --- -This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) project. +This construct library allows you to define S3 object lambda access points. -```ts nofixture +```ts +import * as lambda from '@aws-cdk/aws-lambda'; +import * as s3 from '@aws-cdk/aws-s3'; import * as s3objectlambda from '@aws-cdk/aws-s3objectlambda'; +import * as cdk from '@aws-cdk/core'; + +const stack = new cdk.Stack(); +const bucket = new s3.Bucket(stack, 'MyBucket'); +const handler = new lambda.Function(stack, 'MyFunction', { + runtime: lambda.Runtime.NODEJS_14_X, + handler: 'index.handler', + code: lambda.Code.fromAsset('lambda.zip'), +}); +new s3objectlambda.AccessPoint(stack, 'MyObjectLambda', { + bucket, + handler, + accessPointName: 'my-access-point', + payload: { + prop: "value", + }, +}); ``` - +## Handling range and part number requests + +Lambdas are currently limited to only transforming `GetObject` requests. However, they can additionally support `GetObject-Range` and `GetObject-PartNumber` requests, which needs to be specified in the access point configuration: + +```ts +import * as lambda from '@aws-cdk/aws-lambda'; +import * as s3 from '@aws-cdk/aws-s3'; +import * as s3objectlambda from '@aws-cdk/aws-s3objectlambda'; +import * as cdk from '@aws-cdk/core'; -There are no hand-written ([L2](https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_lib)) constructs for this service yet. -However, you can still use the automatically generated [L1](https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_l1_using) constructs, and use this service exactly as you would using CloudFormation directly. +const stack = new cdk.Stack(); +const bucket = new s3.Bucket(stack, 'MyBucket'); +const handler = new lambda.Function(stack, 'MyFunction', { + runtime: lambda.Runtime.NODEJS_14_X, + handler: 'index.handler', + code: lambda.Code.fromAsset('lambda.zip'), +}); +new s3objectlambda.AccessPoint(stack, 'MyObjectLambda', { + bucket, + handler, + accessPointName: 'my-access-point', + supportsGetObjectRange: true, + supportsGetObjectPartNumber: true, +}); +``` -For more information on the resources and properties available for this service, see the [CloudFormation documentation for AWS::S3ObjectLambda](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/AWS_S3ObjectLambda.html). +## Pass additional data to Lambda function -(Read the [CDK Contributing Guide](https://github.com/aws/aws-cdk/blob/master/CONTRIBUTING.md) if you are interested in contributing to this construct library.) +You can specify an additional object that provides supplemental data to the Lambda function used to transform objects. The data is delivered as a JSON payload to the Lambda: - +```ts +import * as lambda from '@aws-cdk/aws-lambda'; +import * as s3 from '@aws-cdk/aws-s3'; +import * as s3objectlambda from '@aws-cdk/aws-s3objectlambda'; +import * as cdk from '@aws-cdk/core'; + +const stack = new cdk.Stack(); +const bucket = new s3.Bucket(stack, 'MyBucket'); +const handler = new lambda.Function(stack, 'MyFunction', { + runtime: lambda.Runtime.NODEJS_14_X, + handler: 'index.handler', + code: lambda.Code.fromAsset('lambda.zip'), +}); +new s3objectlambda.AccessPoint(stack, 'MyObjectLambda', { + bucket, + handler, + accessPointName: 'my-access-point', + payload: { + prop: "value", + }, +}); +``` diff --git a/packages/@aws-cdk/aws-s3objectlambda/lib/access-point.ts b/packages/@aws-cdk/aws-s3objectlambda/lib/access-point.ts new file mode 100644 index 0000000000000..a99fd64669f81 --- /dev/null +++ b/packages/@aws-cdk/aws-s3objectlambda/lib/access-point.ts @@ -0,0 +1,255 @@ +import * as iam from '@aws-cdk/aws-iam'; +import * as lambda from '@aws-cdk/aws-lambda'; +import * as s3 from '@aws-cdk/aws-s3'; +import * as core from '@aws-cdk/core'; +import { Construct } from 'constructs'; +import { CfnAccessPoint } from './s3objectlambda.generated'; + +/** + * The interface that represents the AccessPoint resource. + */ +export interface IAccessPoint extends core.IResource { + /** + * The ARN of the access point. + * @attribute + */ + readonly accessPointArn: string; + + /** + * The creation data of the access point. + * @attribute + */ + readonly accessPointCreationDate: string; + + /** + * The IPv4 DNS name of the access point. + */ + readonly domainName: string; + + /** + * The regional domain name of the access point. + */ + readonly regionalDomainName: string; + + /** + * The virtual hosted-style URL of an S3 object through this access point. + * Specify `regional: false` at the options for non-regional URL. + * @param key The S3 key of the object. If not specified, the URL of the + * bucket is returned. + * @param options Options for generating URL. + * @returns an ObjectS3Url token + */ + virtualHostedUrlForObject(key?: string, options?: s3.VirtualHostedStyleUrlOptions): string; +} + +/** + * The S3 object lambda access point configuration. + */ +export interface AccessPointProps { + /** + * The bucket to which this access point belongs. + */ + readonly bucket: s3.IBucket; + + /** + * The Lambda function used to transform objects. + */ + readonly handler: lambda.IFunction; + + /** + * The name of the S3 object lambda access point. + * + * @default a unique name will be generated + */ + readonly accessPointName?: string; + + /** + * Whether CloudWatch metrics are enabled for the access point. + * + * @default false + */ + readonly cloudWatchMetricsEnabled?: boolean; + + /** + * Whether the Lambda function can process `GetObject-Range` requests. + * + * @default false + */ + readonly supportsGetObjectRange?: boolean; + + /** + * Whether the Lambda function can process `GetObject-PartNumber` requests. + * + * @default false + */ + readonly supportsGetObjectPartNumber?: boolean; + + /** + * Additional JSON that provides supplemental data passed to the + * Lambda function on every request. + * + * @default - No data. + */ + readonly payload?: { [key: string]: any }; +} + +abstract class AccessPointBase extends core.Resource implements IAccessPoint { + public abstract readonly accessPointArn: string; + public abstract readonly accessPointCreationDate: string; + public abstract readonly accessPointName: string; + + /** Implement the {@link IAccessPoint.domainName} field. */ + get domainName(): string { + const urlSuffix = this.stack.urlSuffix; + return `${this.accessPointName}-${this.stack.account}.s3-object-lambda.${urlSuffix}`; + } + + /** Implement the {@link IAccessPoint.regionalDomainName} field. */ + get regionalDomainName(): string { + const urlSuffix = this.stack.urlSuffix; + const region = this.stack.region; + return `${this.accessPointName}-${this.stack.account}.s3-object-lambda.${region}.${urlSuffix}`; + } + + /** Implement the {@link IAccessPoint.virtualHostedUrlForObject} method. */ + public virtualHostedUrlForObject(key?: string, options?: s3.VirtualHostedStyleUrlOptions): string { + const domainName = options?.regional ?? true ? this.regionalDomainName : this.domainName; + const prefix = `https://${domainName}`; + if (!key) { + return prefix; + } + if (key.startsWith('/')) { + key = key.slice(1); + } + if (key.endsWith('/')) { + key = key.slice(0, -1); + } + return `${prefix}/${key}`; + } +} + +/** + * The access point resource attributes. + */ +export interface AccessPointAttributes { + /** + * The ARN of the access point. + */ + readonly accessPointArn: string + + /** + * The creation data of the access point. + */ + readonly accessPointCreationDate: string; +} + +/** + * Checks the access point name against the rules in https://docs.aws.amazon.com/AmazonS3/latest/userguide/creating-access-points.html#access-points-names + * @param name The name of the access point + */ +function validateAccessPointName(name: string): void { + if (name.length < 3 || name.length > 50) { + throw new Error('Access point name must be between 3 and 50 characters long'); + } + if (name.endsWith('-s3alias')) { + throw new Error('Access point name cannot end with the suffix -s3alias'); + } + if (name[0] === '-' || name[name.length - 1] === '-') { + throw new Error('Access point name cannot begin or end with a dash'); + } + if (!/^[0-9a-z](.(?![\.A-Z_]))+[0-9a-z]$/.test(name)) { + throw new Error('Access point name must begin with a number or lowercase letter and not contain underscores, uppercase letters, or periods'); + } +} + +/** + * An S3 object lambda access point for intercepting and + * transforming `GetObject` requests. + */ +export class AccessPoint extends AccessPointBase { + /** + * Reference an existing AccessPoint defined outside of the CDK code. + */ + public static fromAccessPointAttributes(scope: Construct, id: string, attrs: AccessPointAttributes): IAccessPoint { + const arn = core.Arn.split(attrs.accessPointArn, core.ArnFormat.SLASH_RESOURCE_NAME); + if (!arn.resourceName) { + throw new Error('Unable to parse acess point name'); + } + const name = arn.resourceName; + class Import extends AccessPointBase { + public readonly accessPointArn: string = attrs.accessPointArn; + public readonly accessPointCreationDate: string = attrs.accessPointCreationDate; + public readonly accessPointName: string = name; + } + return new Import(scope, id); + } + + /** + * The ARN of the access point. + */ + public readonly accessPointName: string + + /** + * The ARN of the access point. + * @attribute + */ + public readonly accessPointArn: string + + /** + * The creation data of the access point. + * @attribute + */ + public readonly accessPointCreationDate: string + + constructor(scope: Construct, id: string, props: AccessPointProps) { + super(scope, id, { + physicalName: props.accessPointName, + }); + + if (props.accessPointName) { + validateAccessPointName(props.accessPointName); + } + + const supporting = new s3.CfnAccessPoint(this, 'SupportingAccessPoint', { + bucket: props.bucket.bucketName, + }); + + const allowedFeatures = []; + if (props.supportsGetObjectPartNumber) { + allowedFeatures.push('GetObject-PartNumber'); + } + if (props.supportsGetObjectRange) { + allowedFeatures.push('GetObject-Range'); + } + + const accessPoint = new CfnAccessPoint(this, id, { + name: this.physicalName, + objectLambdaConfiguration: { + allowedFeatures, + cloudWatchMetricsEnabled: props.cloudWatchMetricsEnabled, + supportingAccessPoint: supporting.attrArn, + transformationConfigurations: [ + { + actions: ['GetObject'], + contentTransformation: { + AwsLambda: { + FunctionArn: props.handler.functionArn, + FunctionPayload: props.payload ? JSON.stringify(props.payload) : undefined, + }, + }, + }, + ], + }, + }); + this.accessPointName = accessPoint.ref; + this.accessPointArn = accessPoint.attrArn; + this.accessPointCreationDate = accessPoint.attrCreationDate; + + props.handler.addToRolePolicy( + new iam.PolicyStatement({ + actions: ['s3-object-lambda:WriteGetObjectResponse'], + resources: ['*'], + }), + ); + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3objectlambda/lib/index.ts b/packages/@aws-cdk/aws-s3objectlambda/lib/index.ts index 791ddcf126933..e3c96c8d8be85 100644 --- a/packages/@aws-cdk/aws-s3objectlambda/lib/index.ts +++ b/packages/@aws-cdk/aws-s3objectlambda/lib/index.ts @@ -1,2 +1,4 @@ +export * from './access-point'; + // AWS::S3ObjectLambda CloudFormation Resources: export * from './s3objectlambda.generated'; diff --git a/packages/@aws-cdk/aws-s3objectlambda/package.json b/packages/@aws-cdk/aws-s3objectlambda/package.json index 0e1020f5e6dc1..97ccfc93dfff9 100644 --- a/packages/@aws-cdk/aws-s3objectlambda/package.json +++ b/packages/@aws-cdk/aws-s3objectlambda/package.json @@ -85,25 +85,40 @@ "devDependencies": { "@aws-cdk/assertions": "0.0.0", "@aws-cdk/cdk-build-tools": "0.0.0", + "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1", + "jest": "^27.5.1" }, "dependencies": { - "@aws-cdk/core": "0.0.0" + "@aws-cdk/aws-iam": "0.0.0", + "@aws-cdk/aws-lambda": "0.0.0", + "@aws-cdk/aws-s3": "0.0.0", + "@aws-cdk/core": "0.0.0", + "constructs": "^3.3.69" }, "peerDependencies": { - "@aws-cdk/core": "0.0.0" + "@aws-cdk/aws-iam": "0.0.0", + "@aws-cdk/aws-lambda": "0.0.0", + "@aws-cdk/aws-s3": "0.0.0", + "@aws-cdk/core": "0.0.0", + "constructs": "^3.3.69" }, "engines": { "node": ">= 10.13.0 <13 || >=13.7.0" }, "stability": "experimental", - "maturity": "cfn-only", + "maturity": "experimental", "awscdkio": { "announce": false }, "publishConfig": { "tag": "latest" + }, + "awslint": { + "exclude": [ + "attribute-tag:@aws-cdk/aws-s3objectlambda.AccessPoint.accessPointName" + ] } -} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3objectlambda/test/integ.s3objectlambda.expected.json b/packages/@aws-cdk/aws-s3objectlambda/test/integ.s3objectlambda.expected.json new file mode 100644 index 0000000000000..c53bfb57cd719 --- /dev/null +++ b/packages/@aws-cdk/aws-s3objectlambda/test/integ.s3objectlambda.expected.json @@ -0,0 +1,239 @@ +{ + "Resources": { + "MyBucketF68F3FF0": { + "Type": "AWS::S3::Bucket", + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + }, + "MyFunction1ServiceRole9852B06B": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "MyFunction1ServiceRoleDefaultPolicy39556460": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "s3-object-lambda:WriteGetObjectResponse", + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "MyFunction1ServiceRoleDefaultPolicy39556460", + "Roles": [ + { + "Ref": "MyFunction1ServiceRole9852B06B" + } + ] + } + }, + "MyFunction12A744C2E": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "foo" + }, + "Role": { + "Fn::GetAtt": [ + "MyFunction1ServiceRole9852B06B", + "Arn" + ] + }, + "Handler": "index.handler", + "Runtime": "nodejs14.x" + }, + "DependsOn": [ + "MyFunction1ServiceRoleDefaultPolicy39556460", + "MyFunction1ServiceRole9852B06B" + ] + }, + "MyFunction2ServiceRole07E5BE0E": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "MyFunction2ServiceRoleDefaultPolicyA79C693E": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "s3-object-lambda:WriteGetObjectResponse", + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "MyFunction2ServiceRoleDefaultPolicyA79C693E", + "Roles": [ + { + "Ref": "MyFunction2ServiceRole07E5BE0E" + } + ] + } + }, + "MyFunction2F2A964CA": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "foo" + }, + "Role": { + "Fn::GetAtt": [ + "MyFunction2ServiceRole07E5BE0E", + "Arn" + ] + }, + "Handler": "index.handler", + "Runtime": "nodejs14.x" + }, + "DependsOn": [ + "MyFunction2ServiceRoleDefaultPolicyA79C693E", + "MyFunction2ServiceRole07E5BE0E" + ] + }, + "MyObjectLambda1SupportingAccessPoint223B719B": { + "Type": "AWS::S3::AccessPoint", + "Properties": { + "Bucket": { + "Ref": "MyBucketF68F3FF0" + } + } + }, + "MyObjectLambda17554FEF4": { + "Type": "AWS::S3ObjectLambda::AccessPoint", + "Properties": { + "Name": "obj-lambda-1", + "ObjectLambdaConfiguration": { + "AllowedFeatures": [ + "GetObject-PartNumber" + ], + "CloudWatchMetricsEnabled": true, + "SupportingAccessPoint": { + "Fn::GetAtt": [ + "MyObjectLambda1SupportingAccessPoint223B719B", + "Arn" + ] + }, + "TransformationConfigurations": [ + { + "Actions": [ + "GetObject" + ], + "ContentTransformation": { + "AwsLambda": { + "FunctionArn": { + "Fn::GetAtt": [ + "MyFunction12A744C2E", + "Arn" + ] + } + } + } + } + ] + } + } + }, + "MyObjectLambda2SupportingAccessPoint6C54778F": { + "Type": "AWS::S3::AccessPoint", + "Properties": { + "Bucket": { + "Ref": "MyBucketF68F3FF0" + } + } + }, + "MyObjectLambda2CCBCAAF7": { + "Type": "AWS::S3ObjectLambda::AccessPoint", + "Properties": { + "Name": "obj-lambda-1", + "ObjectLambdaConfiguration": { + "AllowedFeatures": [ + "GetObject-Range" + ], + "SupportingAccessPoint": { + "Fn::GetAtt": [ + "MyObjectLambda2SupportingAccessPoint6C54778F", + "Arn" + ] + }, + "TransformationConfigurations": [ + { + "Actions": [ + "GetObject" + ], + "ContentTransformation": { + "AwsLambda": { + "FunctionArn": { + "Fn::GetAtt": [ + "MyFunction2F2A964CA", + "Arn" + ] + }, + "FunctionPayload": "{\"foo\":10}" + } + } + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3objectlambda/test/integ.s3objectlambda.ts b/packages/@aws-cdk/aws-s3objectlambda/test/integ.s3objectlambda.ts new file mode 100644 index 0000000000000..e840de6367479 --- /dev/null +++ b/packages/@aws-cdk/aws-s3objectlambda/test/integ.s3objectlambda.ts @@ -0,0 +1,45 @@ +import * as lambda from '@aws-cdk/aws-lambda'; +import * as s3 from '@aws-cdk/aws-s3'; +import * as cdk from '@aws-cdk/core'; +import { AccessPoint } from '../lib'; + +class TestStack extends cdk.Stack { + constructor(scope: cdk.App, id: string) { + super(scope, id); + + const bucket = new s3.Bucket(this, 'MyBucket'); + const handler1 = new lambda.Function(this, 'MyFunction1', { + runtime: lambda.Runtime.NODEJS_14_X, + handler: 'index.handler', + code: lambda.Code.fromInline('foo'), + }); + + const handler2 = new lambda.Function(this, 'MyFunction2', { + runtime: lambda.Runtime.NODEJS_14_X, + handler: 'index.handler', + code: lambda.Code.fromInline('foo'), + }); + + new AccessPoint(this, 'MyObjectLambda1', { + bucket, + handler: handler1, + accessPointName: 'obj-lambda-1', + cloudWatchMetricsEnabled: true, + supportsGetObjectPartNumber: true, + }); + + new AccessPoint(this, 'MyObjectLambda2', { + bucket, + handler: handler2, + accessPointName: 'obj-lambda-1', + supportsGetObjectRange: true, + payload: { foo: 10 }, + }); + } +} + +const app = new cdk.App(); + +new TestStack(app, 'aws-s3-object-lambda'); + +app.synth(); diff --git a/packages/@aws-cdk/aws-s3objectlambda/test/s3objectlambda.test.ts b/packages/@aws-cdk/aws-s3objectlambda/test/s3objectlambda.test.ts index 465c7bdea0693..3e62fd370f039 100644 --- a/packages/@aws-cdk/aws-s3objectlambda/test/s3objectlambda.test.ts +++ b/packages/@aws-cdk/aws-s3objectlambda/test/s3objectlambda.test.ts @@ -1,6 +1,338 @@ -import '@aws-cdk/assertions'; -import {} from '../lib'; +import { Template } from '@aws-cdk/assertions'; +import * as lambda from '@aws-cdk/aws-lambda'; +import * as s3 from '@aws-cdk/aws-s3'; +import * as cdk from '@aws-cdk/core'; +import { AccessPoint } from '../lib'; -test('No tests are specified for this package', () => { - expect(true).toBe(true); +let stack: cdk.Stack; +let bucket: s3.Bucket; +let handler: lambda.Function; + +beforeEach(() => { + stack = new cdk.Stack(); + bucket = new s3.Bucket(stack, 'MyBucket'); + handler = new lambda.Function(stack, 'MyFunction', { + runtime: lambda.Runtime.NODEJS_14_X, + handler: 'index.hello', + code: new lambda.InlineCode('def hello(): pass'), + }); +}); + +test('Can create a valid access point', () => { + const accessPoint = new AccessPoint(stack, 'MyObjectLambda', { + bucket, + handler, + accessPointName: 'obj-lambda', + supportsGetObjectRange: true, + supportsGetObjectPartNumber: true, + payload: { foo: 10 }, + }); + new cdk.CfnOutput(stack, 'AccessPointName', { + value: accessPoint.accessPointName, + }); + new cdk.CfnOutput(stack, 'DomainName', { + value: accessPoint.domainName, + }); + new cdk.CfnOutput(stack, 'RegionalDomainName', { + value: accessPoint.regionalDomainName, + }); + new cdk.CfnOutput(stack, 'VirtualHostedUrl', { + value: accessPoint.virtualHostedUrlForObject('key', { + regional: true, + }), + }); + new cdk.CfnOutput(stack, 'VirtualHostedRegionalUrl', { + value: accessPoint.virtualHostedUrlForObject('key', { + regional: false, + }), + }); + + expect(Template.fromStack(stack).findOutputs('*')).toEqual( + { + AccessPointName: { + Value: { + Ref: 'MyObjectLambda3F9602DC', + }, + }, + DomainName: { + Value: { + 'Fn::Join': [ + '', + [ + { + Ref: 'MyObjectLambda3F9602DC', + }, + '-', + { + Ref: 'AWS::AccountId', + }, + '.s3-object-lambda.', + { + Ref: 'AWS::URLSuffix', + }, + ], + ], + }, + }, + RegionalDomainName: { + Value: { + 'Fn::Join': [ + '', + [ + { + Ref: 'MyObjectLambda3F9602DC', + }, + '-', + { + Ref: 'AWS::AccountId', + }, + '.s3-object-lambda.', + { + Ref: 'AWS::Region', + }, + '.', + { + Ref: 'AWS::URLSuffix', + }, + ], + ], + }, + }, + VirtualHostedRegionalUrl: { + Value: { + 'Fn::Join': [ + '', + [ + 'https://', + { + Ref: 'MyObjectLambda3F9602DC', + }, + '-', + { + Ref: 'AWS::AccountId', + }, + '.s3-object-lambda.', + { + Ref: 'AWS::URLSuffix', + }, + '/key', + ], + ], + }, + }, + VirtualHostedUrl: { + Value: { + 'Fn::Join': [ + '', + [ + 'https://', + { + Ref: 'MyObjectLambda3F9602DC', + }, + '-', + { + Ref: 'AWS::AccountId', + }, + '.s3-object-lambda.', + { + Ref: 'AWS::Region', + }, + '.', + { + Ref: 'AWS::URLSuffix', + }, + '/key', + ], + ], + }, + }, + }, + ); + + Template.fromStack(stack).hasResourceProperties('AWS::S3ObjectLambda::AccessPoint', { + ObjectLambdaConfiguration: { + AllowedFeatures: [ + 'GetObject-PartNumber', + 'GetObject-Range', + ], + TransformationConfigurations: [ + { + Actions: [ + 'GetObject', + ], + ContentTransformation: { + AwsLambda: { + FunctionArn: { + 'Fn::GetAtt': [ + 'MyFunction3BAA72D1', + 'Arn', + ], + }, + FunctionPayload: '{"foo":10}', + }, + }, + }, + ], + }, + }); +}); + +test('Can create an access point without specifying the name', () => { + new AccessPoint(stack, 'MyObjectLambda', { + bucket, + handler, + }); + Template.fromStack(stack).hasResourceProperties('AWS::S3ObjectLambda::AccessPoint', { + ObjectLambdaConfiguration: { + AllowedFeatures: [], + }, + }); +}); + +test('Slashes are removed from the virtual hosted url', () => { + const accessPoint = new AccessPoint(stack, 'MyObjectLambda', { + bucket, + handler, + }); + new cdk.CfnOutput(stack, 'VirtualHostedUrlNoKey', { + value: accessPoint.virtualHostedUrlForObject(), + }); + new cdk.CfnOutput(stack, 'VirtualHostedUrlKeyBeginsSlash', { + value: accessPoint.virtualHostedUrlForObject('/key1/key2'), + }); + new cdk.CfnOutput(stack, 'VirtualHostedUrlKeyEndsSlash', { + value: accessPoint.virtualHostedUrlForObject('key1/key2/'), + }); + expect(Template.fromStack(stack).findOutputs('*')).toEqual( { + VirtualHostedUrlKeyBeginsSlash: { + Value: { + 'Fn::Join': [ + '', + [ + 'https://', + { + Ref: 'MyObjectLambda3F9602DC', + }, + '-', + { + Ref: 'AWS::AccountId', + }, + '.s3-object-lambda.', + { + Ref: 'AWS::Region', + }, + '.', + { + Ref: 'AWS::URLSuffix', + }, + '/key1/key2', + ], + ], + }, + }, + VirtualHostedUrlKeyEndsSlash: { + Value: { + 'Fn::Join': [ + '', + [ + 'https://', + { + Ref: 'MyObjectLambda3F9602DC', + }, + '-', + { + Ref: 'AWS::AccountId', + }, + '.s3-object-lambda.', + { + Ref: 'AWS::Region', + }, + '.', + { + Ref: 'AWS::URLSuffix', + }, + '/key1/key2', + ], + ], + }, + }, + VirtualHostedUrlNoKey: { + Value: { + 'Fn::Join': [ + '', + [ + 'https://', + { + Ref: 'MyObjectLambda3F9602DC', + }, + '-', + { + Ref: 'AWS::AccountId', + }, + '.s3-object-lambda.', + { + Ref: 'AWS::Region', + }, + '.', + { + Ref: 'AWS::URLSuffix', + }, + ], + ], + }, + }, + }); +}); + +test('Validates the access point name', () => { + expect(() => new AccessPoint(stack, 'MyObjectLambda1', { + bucket, + handler, + accessPointName: 'aa', + })).toThrowError(/name must be between 3 and 50 characters long/); + expect(() => new AccessPoint(stack, 'MyObjectLambda2', { + bucket, + handler, + accessPointName: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + })).toThrowError(/name must be between 3 and 50 characters long/); + expect(() => new AccessPoint(stack, 'MyObjectLambda3', { + bucket, + handler, + accessPointName: 'aaaa-s3alias', + })).toThrowError(/name cannot end with the suffix -s3alias/); + expect(() => new AccessPoint(stack, 'MyObjectLambda4', { + bucket, + handler, + accessPointName: '-aaaaa', + })).toThrowError(/name cannot begin or end with a dash/); + expect(() => new AccessPoint(stack, 'MyObjectLambda5', { + bucket, + handler, + accessPointName: 'aaaaa-', + })).toThrowError(/name cannot begin or end with a dash/); + expect(() => new AccessPoint(stack, 'MyObjectLambda6', { + bucket, + handler, + accessPointName: 'Aaaaa', + })).toThrowError(/name must begin with a number or lowercase letter and not contain underscores, uppercase letters, or periods/); + expect(() => new AccessPoint(stack, 'MyObjectLambda7', { + bucket, + handler, + accessPointName: '$aaaaa', + })).toThrowError(/name must begin with a number or lowercase letter and not contain underscores, uppercase letters, or periods/); + expect(() => new AccessPoint(stack, 'MyObjectLambda8', { + bucket, + handler, + accessPointName: 'aaaAaaa', + })).toThrowError(/name must begin with a number or lowercase letter and not contain underscores, uppercase letters, or periods/); + expect(() => new AccessPoint(stack, 'MyObjectLambda9', { + bucket, + handler, + accessPointName: 'aaa_aaa', + })).toThrowError(/name must begin with a number or lowercase letter and not contain underscores, uppercase letters, or periods/); + expect(() => new AccessPoint(stack, 'MyObjectLambda10', { + bucket, + handler, + accessPointName: 'aaa.aaa', + })).toThrowError(/name must begin with a number or lowercase letter and not contain underscores, uppercase letters, or periods/); }); diff --git a/packages/@aws-cdk/aws-s3outposts/package.json b/packages/@aws-cdk/aws-s3outposts/package.json index 9c1b9dc830771..0ad8877061133 100644 --- a/packages/@aws-cdk/aws-s3outposts/package.json +++ b/packages/@aws-cdk/aws-s3outposts/package.json @@ -87,7 +87,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-sagemaker/package.json b/packages/@aws-cdk/aws-sagemaker/package.json index 9741c8b8d96a3..cb5332a56fc47 100644 --- a/packages/@aws-cdk/aws-sagemaker/package.json +++ b/packages/@aws-cdk/aws-sagemaker/package.json @@ -84,7 +84,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-sam/package.json b/packages/@aws-cdk/aws-sam/package.json index 0b7d7cd0c97a9..bb86f7d0fceca 100644 --- a/packages/@aws-cdk/aws-sam/package.json +++ b/packages/@aws-cdk/aws-sam/package.json @@ -84,7 +84,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1", "ts-jest": "^27.1.3" }, diff --git a/packages/@aws-cdk/aws-sdb/package.json b/packages/@aws-cdk/aws-sdb/package.json index 4636ae5160146..a4072de0aa01c 100644 --- a/packages/@aws-cdk/aws-sdb/package.json +++ b/packages/@aws-cdk/aws-sdb/package.json @@ -83,7 +83,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-secretsmanager/README.md b/packages/@aws-cdk/aws-secretsmanager/README.md index 8ff23ea3ba01d..5b88885e863a5 100644 --- a/packages/@aws-cdk/aws-secretsmanager/README.md +++ b/packages/@aws-cdk/aws-secretsmanager/README.md @@ -63,7 +63,7 @@ A secret can set `RemovalPolicy`. If it set to `RETAIN`, that removing a secret ## Grant permission to use the secret to a role You must grant permission to a resource for that resource to be allowed to -use a secret. This can be achieved with the `Secret.grantRead` and/or `Secret.grantUpdate` +use a secret. This can be achieved with the `Secret.grantRead` and/or `Secret.grantWrite` method, depending on your need: ```ts diff --git a/packages/@aws-cdk/aws-secretsmanager/package.json b/packages/@aws-cdk/aws-secretsmanager/package.json index a289566a2728c..abf808fed6a01 100644 --- a/packages/@aws-cdk/aws-secretsmanager/package.json +++ b/packages/@aws-cdk/aws-secretsmanager/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/aws-ec2": "0.0.0", diff --git a/packages/@aws-cdk/aws-securityhub/package.json b/packages/@aws-cdk/aws-securityhub/package.json index 7c542fa20395b..2be17327b22a1 100644 --- a/packages/@aws-cdk/aws-securityhub/package.json +++ b/packages/@aws-cdk/aws-securityhub/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-servicecatalog/README.md b/packages/@aws-cdk/aws-servicecatalog/README.md index 12e57cbc200ee..54c28a0b46201 100644 --- a/packages/@aws-cdk/aws-servicecatalog/README.md +++ b/packages/@aws-cdk/aws-servicecatalog/README.md @@ -9,13 +9,13 @@ > > [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) +![cdk-constructs: Developer Preview](https://img.shields.io/badge/cdk--constructs-developer--preview-informational.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. +> The APIs of higher level constructs in this module are in **developer preview** before they +> become stable. We will only make breaking changes to address unforeseen API issues. Therefore, +> these APIs are not subject to [Semantic Versioning](https://semver.org/), and breaking changes +> will be announced in 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. --- @@ -37,7 +37,7 @@ enables organizations to create and manage catalogs of products for their end us - [Constraints](#constraints) - [Tag update constraint](#tag-update-constraint) - [Notify on stack events](#notify-on-stack-events) - - [CloudFormation parameters constraint](#cloudformation-parameters-constraint) + - [CloudFormation template parameters constraint](#cloudformation-template-parameters-constraint) - [Set launch role](#set-launch-role) - [Deploy with StackSets](#deploy-with-stacksets) @@ -50,23 +50,23 @@ import * as servicecatalog from '@aws-cdk/aws-servicecatalog'; ## Portfolio -AWS Service Catalog portfolios allow admins to manage products that their end users have access to. +AWS Service Catalog portfolios allow administrators to organize, manage, and distribute cloud resources for their end users. Using the CDK, a new portfolio can be created with the `Portfolio` construct: ```ts -new servicecatalog.Portfolio(this, 'MyFirstPortfolio', { - displayName: 'MyFirstPortfolio', +new servicecatalog.Portfolio(this, 'Portfolio', { + displayName: 'MyPortfolio', providerName: 'MyTeam', }); ``` -You can also specify properties such as `description` and `acceptLanguage` +You can also specify optional metadata properties such as `description` and `messageLanguage` to help better catalog and manage your portfolios. ```ts -new servicecatalog.Portfolio(this, 'MyFirstPortfolio', { +new servicecatalog.Portfolio(this, 'Portfolio', { displayName: 'MyFirstPortfolio', - providerName: 'MyTeam', + providerName: 'SCAdmin', description: 'Portfolio for a project', messageLanguage: servicecatalog.MessageLanguage.EN, }); @@ -74,37 +74,39 @@ new servicecatalog.Portfolio(this, 'MyFirstPortfolio', { Read more at [Creating and Managing Portfolios](https://docs.aws.amazon.com/servicecatalog/latest/adminguide/catalogs_portfolios.html). -A portfolio that has been created outside the stack can be imported into your CDK app. -Portfolios can be imported by their ARN via the `Portfolio.fromPortfolioArn()` API: +To import an existing portfolio into your CDK application, use the `Portfolio.fromPortfolioArn()` factory method: ```ts -const portfolio = servicecatalog.Portfolio.fromPortfolioArn(this, 'MyImportedPortfolio', +const portfolio = servicecatalog.Portfolio.fromPortfolioArn(this, 'ImportedPortfolio', 'arn:aws:catalog:region:account-id:portfolio/port-abcdefghi'); ``` ### Granting access to a portfolio -You can manage end user access to a portfolio by granting permissions to `IAM` entities like a user, group, or role. +You can grant access to and manage the `IAM` users, groups, or roles that have access to the products within a portfolio. +Entities with granted access will be able to utilize the portfolios resources and products via the console or AWS CLI. Once resources are deployed end users will be able to access them via the console or service catalog CLI. ```ts fixture=basic-portfolio import * as iam from '@aws-cdk/aws-iam'; -const user = new iam.User(this, 'MyUser'); +const user = new iam.User(this, 'User'); portfolio.giveAccessToUser(user); -const role = new iam.Role(this, 'MyRole', { +const role = new iam.Role(this, 'Role', { assumedBy: new iam.AccountRootPrincipal(), }); portfolio.giveAccessToRole(role); -const group = new iam.Group(this, 'MyGroup'); +const group = new iam.Group(this, 'Group'); portfolio.giveAccessToGroup(group); ``` ### Sharing a portfolio with another AWS account -A portfolio can be programatically shared with other accounts so that specified users can also access it: +You can use account-to-account sharing to distribute a reference to your portfolio to other AWS accounts by passing the recipient account number. +After the share is initiated, the recipient account can accept the share via CLI or console by importing the portfolio ID. +Changes made to the shared portfolio will automatically propagate to recipients. ```ts fixture=basic-portfolio portfolio.shareWithAccount('012345678901'); @@ -112,10 +114,10 @@ portfolio.shareWithAccount('012345678901'); ## Product -Products are the resources you are allowing end users to provision and utilize. +Products are version friendly infrastructure-as-code templates that admins create and add to portfolios for end users to provision and create AWS resources. The CDK currently only supports adding products of type Cloudformation product. Using the CDK, a new Product can be created with the `CloudFormationProduct` construct. -`CloudFormationTemplate.fromUrl` can be utilized to create a Product using a Cloudformation template directly from an URL: +You can use `CloudFormationTemplate.fromUrl` to create a Product from a CloudFormation template directly from a URL that points to the template in S3, GitHub, or CodeCommit: ```ts const product = new servicecatalog.CloudFormationProduct(this, 'MyFirstProduct', { @@ -133,14 +135,14 @@ const product = new servicecatalog.CloudFormationProduct(this, 'MyFirstProduct', ### Creating a product from a local asset -A `CloudFormationProduct` can also be created using a Cloudformation template from an Asset. +A `CloudFormationProduct` can also be created by using a CloudFormation template held locally on disk using Assets. Assets are files that are uploaded to an S3 Bucket before deployment. `CloudFormationTemplate.fromAsset` can be utilized to create a Product by passing the path to a local template file on your disk: ```ts import * as path from 'path'; -const product = new servicecatalog.CloudFormationProduct(this, 'MyFirstProduct', { +const product = new servicecatalog.CloudFormationProduct(this, 'Product', { productName: "My Product", owner: "Product Owner", productVersions: [ @@ -159,10 +161,10 @@ const product = new servicecatalog.CloudFormationProduct(this, 'MyFirstProduct', ### Creating a product from a stack -You can define a service catalog `CloudFormationProduct` entirely within CDK using a service catalog `ProductStack`. +You can create a Service Catalog `CloudFormationProduct` entirely defined with CDK code using a service catalog `ProductStack`. A separate child stack for your product is created and you can add resources like you would for any other CDK stack, such as an S3 Bucket, IAM roles, and EC2 instances. This stack is passed in as a product version to your -product. This will not create a separate stack during deployment. +product. This will not create a separate CloudFormation stack during deployment. ```ts import * as s3 from '@aws-cdk/aws-s3'; @@ -176,7 +178,7 @@ class S3BucketProduct extends servicecatalog.ProductStack { } } -const product = new servicecatalog.CloudFormationProduct(this, 'MyFirstProduct', { +const product = new servicecatalog.CloudFormationProduct(this, 'Product', { productName: "My Product", owner: "Product Owner", productVersions: [ @@ -190,9 +192,9 @@ const product = new servicecatalog.CloudFormationProduct(this, 'MyFirstProduct', ### Adding a product to a portfolio -You add products to a portfolio to manage your resources at scale. After adding a product to a portfolio, -it creates a portfolio-product association, and will become visible from the portfolio side in both the console and service catalog CLI. -A product can be added to multiple portfolios depending on your resource and organizational needs. +You add products to a portfolio to organize and distribute your catalog at scale. Adding a product to a portfolio creates an association, +and the product will become visible within the portfolio side in both the Service Catalog console and AWS CLI. +You can add a product to multiple portfolios depending on your organizational structure and how you would like to group access to products. ```ts fixture=portfolio-product portfolio.addProduct(product); @@ -200,11 +202,11 @@ portfolio.addProduct(product); ## Tag Options -TagOptions allow administrators to easily manage tags on provisioned products by creating a selection of tags for end users to choose from. -TagOptions are created by specifying a tag key with a selection of allowed values and can be associated with both portfolios and products. +TagOptions allow administrators to easily manage tags on provisioned products by providing a template for a selection of tags that end users choose from. +TagOptions are created by specifying a tag key with a set of allowed values and can be associated with both portfolios and products. When launching a product, both the TagOptions associated with the product and the containing portfolio are made available. -At the moment, TagOptions can only be disabled in the console. +At the moment, TagOptions can only be deactivated in the console. ```ts fixture=portfolio-product const tagOptionsForPortfolio = new servicecatalog.TagOptions(this, 'OrgTagOptions', { @@ -225,12 +227,11 @@ product.associateTagOptions(tagOptionsForProduct); ## Constraints -Constraints define governance mechanisms that allow you to manage permissions, notifications, and options related to actions end users can perform on products, -Constraints are applied on a portfolio-product association. +Constraints are governance gestures that you place on product-portfolio associations that allow you to manage minimal launch permissions, notifications, and other optional actions that end users can perform on products. Using the CDK, if you do not explicitly associate a product to a portfolio and add a constraint, it will automatically add an association for you. -There are rules around plurariliites of constraints for a portfolio and product. -For example, you can only have a single "tag update" constraint applied to a portfolio-product association. +There are rules around how constraints are applied to portfolio-product associations. +For example, you can only have a single "launch role" constraint applied to a portfolio-product association. If a misconfigured constraint is added, `synth` will fail with an error message. Read more at [Service Catalog Constraints](https://docs.aws.amazon.com/servicecatalog/latest/adminguide/constraints.html). @@ -238,7 +239,7 @@ Read more at [Service Catalog Constraints](https://docs.aws.amazon.com/serviceca ### Tag update constraint Tag update constraints allow or disallow end users to update tags on resources associated with an AWS Service Catalog product upon provisioning. -By default, tag updating is not permitted. +By default, if a Tag Update constraint is not configured, tag updating is not permitted. If tag updating is allowed, then new tags associated with the product or portfolio will be applied to provisioned resources during a provisioned product update. ```ts fixture=portfolio-product @@ -258,30 +259,30 @@ portfolio.constrainTagUpdates(product, { ### Notify on stack events -Allows users to subscribe an AWS `SNS` topic to the stack events of the product. -When an end user provisions a product it creates a product stack that notifies the subscribed topic on creation, edit, and delete events. -An individual `SNS` topic may only be subscribed once to a portfolio-product association. +Allows users to subscribe an AWS `SNS` topic to a provisioned product's CloudFormation stack events. +When an end user provisions a product it creates a CloudFormation stack that notifies the subscribed topic on creation, edit, and delete events. +An individual `SNS` topic may only have a single subscription to any given portfolio-product association. ```ts fixture=portfolio-product import * as sns from '@aws-cdk/aws-sns'; -const topic1 = new sns.Topic(this, 'MyTopic1'); +const topic1 = new sns.Topic(this, 'Topic1'); portfolio.notifyOnStackEvents(product, topic1); -const topic2 = new sns.Topic(this, 'MyTopic2'); +const topic2 = new sns.Topic(this, 'Topic2'); portfolio.notifyOnStackEvents(product, topic2, { - description: 'description for this topic2', // description is an optional field. + description: 'description for topic2', // description is an optional field. }); ``` -### CloudFormation parameters constraint +### CloudFormation template parameters constraint -CloudFormation parameters constraints allow you to configure the that are available to end users when they launch a product via defined rules. -A rule consists of one or more assertions that narrow the allowable values for parameters in a product. -You can configure multiple parameter constraints to govern the different parameters and parameter options in your products. -For example, a rule might define the various instance types that users can choose from when launching a stack that includes EC2 instances. -A parameter rule has an optional `condition` field that allows ability to configure when rules are applied. -If a `condition` is specified, all the assertions will be applied if the condition evalutates to true. +CloudFormation template parameter constraints allow you to configure the provisioning parameters that are available to end users when they launch a product. +Template constraint rules consist of one or more assertions that define the default and/or allowable values for a product’s provisioning parameters. +You can configure multiple parameter constraints to govern the different provisioning parameters within your products. +For example, a rule might define the `EC2` instance types that users can choose from when launching a product that includes one or more `EC2` instances. +Parameter rules have an optional `condition` field that allow for rule application to consider conditional evaluations. +If a `condition` is specified, all assertions will be applied if the condition evaluates to true. For information on rule-specific intrinsic functions to define rule conditions and assertions, see [AWS Rule Functions](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-rules.html). @@ -302,10 +303,12 @@ portfolio.constrainCloudFormationParameters(product, { ### Set launch role -Allows you to configure a specific AWS `IAM` role that a user must assume when launching a product. -By setting this launch role, you can control what policies and privileges end users can have. -The launch role must be assumed by the service catalog principal. -You can only have one launch role set for a portfolio-product association, and you cannot set a launch role if a StackSets deployment has been configured. +Allows you to configure a specific `IAM` role that Service Catalog assumes on behalf of the end user when launching a product. +By setting a launch role constraint, you can maintain least permissions for an end user when launching a product. +For example, a launch role can grant permissions for specific resource creation like an `S3` bucket that the user. +The launch role must be assumed by the Service Catalog principal. +You can only have one launch role set for a portfolio-product association, +and you cannot set a launch role on a product that already has a StackSets deployment configured. ```ts fixture=portfolio-product import * as iam from '@aws-cdk/aws-iam'; @@ -346,16 +349,16 @@ const launchRole: iam.IRole = portfolio.setLocalLaunchRoleName(product, roleName ``` See [Launch Constraint](https://docs.aws.amazon.com/servicecatalog/latest/adminguide/constraints-launch.html) documentation -to understand the permissions roles need. +to understand the permissions that launch roles need. ### Deploy with StackSets A StackSets deployment constraint allows you to configure product deployment options using [AWS CloudFormation StackSets](https://docs.aws.amazon.com/servicecatalog/latest/adminguide/using-stacksets.html). -You can specify multiple accounts and regions for the product launch following StackSets conventions. -There is an additional field `allowStackSetInstanceOperations` that configures ability for end users to create, edit, or delete the stacks. +You can specify one or more accounts and regions into which stack instances will launch when the product is provisioned. +There is an additional field `allowStackSetInstanceOperations` that sets ability for end users to create, edit, or delete the stacks created by the StackSet. By default, this field is set to `false`. -End users can manage those accounts and determine where products deploy and the order of deployment. +When launching a StackSets product, end users can select from the list of accounts and regions configured in the constraint to determine where the Stack Instances will deploy and the order of deployment. You can only define one StackSets deployment configuration per portfolio-product association, and you cannot both set a launch role and StackSets deployment configuration for an assocation. diff --git a/packages/@aws-cdk/aws-servicecatalog/package.json b/packages/@aws-cdk/aws-servicecatalog/package.json index d5493a3813974..57c961ef8f68d 100644 --- a/packages/@aws-cdk/aws-servicecatalog/package.json +++ b/packages/@aws-cdk/aws-servicecatalog/package.json @@ -84,7 +84,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/aws-iam": "0.0.0", @@ -121,7 +121,7 @@ "ref-via-interface:@aws-cdk/aws-servicecatalog.PortfolioProps.tagOptions" ] }, - "maturity": "experimental", + "maturity": "developer-preview", "stability": "experimental", "awscdkio": { "announce": false diff --git a/packages/@aws-cdk/aws-servicecatalogappregistry/package.json b/packages/@aws-cdk/aws-servicecatalogappregistry/package.json index 1db1a743a5952..96e9d4dd7967c 100644 --- a/packages/@aws-cdk/aws-servicecatalogappregistry/package.json +++ b/packages/@aws-cdk/aws-servicecatalogappregistry/package.json @@ -88,7 +88,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-servicediscovery/package.json b/packages/@aws-cdk/aws-servicediscovery/package.json index 4a45183391e02..98567a421aa13 100644 --- a/packages/@aws-cdk/aws-servicediscovery/package.json +++ b/packages/@aws-cdk/aws-servicediscovery/package.json @@ -87,7 +87,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-ses-actions/package.json b/packages/@aws-cdk/aws-ses-actions/package.json index e0f76df37ce79..92c00efabcbcb 100644 --- a/packages/@aws-cdk/aws-ses-actions/package.json +++ b/packages/@aws-cdk/aws-ses-actions/package.json @@ -77,7 +77,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-ses/package.json b/packages/@aws-cdk/aws-ses/package.json index e751bf00efd99..45d5852e16554 100644 --- a/packages/@aws-cdk/aws-ses/package.json +++ b/packages/@aws-cdk/aws-ses/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", "@types/aws-lambda": "^8.10.92", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-signer/package.json b/packages/@aws-cdk/aws-signer/package.json index 7f44205727a9b..0bc0f4f9d9522 100644 --- a/packages/@aws-cdk/aws-signer/package.json +++ b/packages/@aws-cdk/aws-signer/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-sns-subscriptions/package.json b/packages/@aws-cdk/aws-sns-subscriptions/package.json index 9e70dd36e2ba3..f295805a8b389 100644 --- a/packages/@aws-cdk/aws-sns-subscriptions/package.json +++ b/packages/@aws-cdk/aws-sns-subscriptions/package.json @@ -76,7 +76,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-sns/package.json b/packages/@aws-cdk/aws-sns/package.json index 9d641f195de5b..b1664ed712223 100644 --- a/packages/@aws-cdk/aws-sns/package.json +++ b/packages/@aws-cdk/aws-sns/package.json @@ -88,7 +88,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-sqs/package.json b/packages/@aws-cdk/aws-sqs/package.json index 973e8275ec4bc..a6b12eaf10285 100644 --- a/packages/@aws-cdk/aws-sqs/package.json +++ b/packages/@aws-cdk/aws-sqs/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "aws-sdk": "^2.848.0", "jest": "^27.5.1" }, diff --git a/packages/@aws-cdk/aws-ssm/package.json b/packages/@aws-cdk/aws-ssm/package.json index 68e346b561e6c..65caf4f4c5873 100644 --- a/packages/@aws-cdk/aws-ssm/package.json +++ b/packages/@aws-cdk/aws-ssm/package.json @@ -84,7 +84,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-ssmcontacts/package.json b/packages/@aws-cdk/aws-ssmcontacts/package.json index ff883b494f4a9..bfce82c5f9d0a 100644 --- a/packages/@aws-cdk/aws-ssmcontacts/package.json +++ b/packages/@aws-cdk/aws-ssmcontacts/package.json @@ -87,7 +87,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-ssmincidents/package.json b/packages/@aws-cdk/aws-ssmincidents/package.json index a0663b40f9cd1..f014c6fc4ef38 100644 --- a/packages/@aws-cdk/aws-ssmincidents/package.json +++ b/packages/@aws-cdk/aws-ssmincidents/package.json @@ -87,7 +87,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-sso/package.json b/packages/@aws-cdk/aws-sso/package.json index 5a3e38bd255d2..349b3f7ef235a 100644 --- a/packages/@aws-cdk/aws-sso/package.json +++ b/packages/@aws-cdk/aws-sso/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/README.md b/packages/@aws-cdk/aws-stepfunctions-tasks/README.md index 17948bc1112f4..ad4c2a365c38b 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/README.md +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/README.md @@ -1167,6 +1167,8 @@ If your training job or model uses resources from AWS Marketplace, [network isolation is required](https://docs.aws.amazon.com/sagemaker/latest/dg/mkt-algo-model-internet-free.html). To do so, set the `enableNetworkIsolation` property to `true` for `SageMakerCreateModel` or `SageMakerCreateTrainingJob`. +To set environment variables for the Docker container use the `environment` property. + ### Create Training Job You can call the [`CreateTrainingJob`](https://docs.aws.amazon.com/sagemaker/latest/dg/API_CreateTrainingJob.html) API from a `Task` state. diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/lib/aws-sdk/call-aws-service.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/lib/aws-sdk/call-aws-service.ts index f3987cc0677ae..34f1bd78fe3c2 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/lib/aws-sdk/call-aws-service.ts +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/lib/aws-sdk/call-aws-service.ts @@ -64,6 +64,10 @@ export class CallAwsService extends sfn.TaskStateBase { constructor(scope: Construct, id: string, private readonly props: CallAwsServiceProps) { super(scope, id, props); + if (this.props.integrationPattern === sfn.IntegrationPattern.RUN_JOB) { + throw new Error('The RUN_JOB integration pattern is not supported for CallAwsService'); + } + this.taskPolicies = [ new iam.PolicyStatement({ resources: props.iamResources, diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/lib/sagemaker/create-training-job.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/lib/sagemaker/create-training-job.ts index 64680dc357747..ba3274579eb37 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/lib/sagemaker/create-training-job.ts +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/lib/sagemaker/create-training-job.ts @@ -5,7 +5,7 @@ import { Duration, Lazy, Size, Stack } from '@aws-cdk/core'; import { Construct } from 'constructs'; import { integrationResourceArn, validatePatternSupported } from '../private/task-utils'; import { AlgorithmSpecification, Channel, InputMode, OutputDataConfig, ResourceConfig, S3DataType, StoppingCondition, VpcConfig } from './base-types'; -import { renderTags } from './private/utils'; +import { renderEnvironment, renderTags } from './private/utils'; /** * Properties for creating an Amazon SageMaker training job @@ -85,6 +85,13 @@ export interface SageMakerCreateTrainingJobProps extends sfn.TaskStateBaseProps * @default - No VPC */ readonly vpcConfig?: VpcConfig; + + /** + * Environment variables to set in the Docker container. + * + * @default - No environment variables + */ + readonly environment?: { [key: string]: string }; } /** @@ -234,6 +241,7 @@ export class SageMakerCreateTrainingJob extends sfn.TaskStateBase implements iam ...this.renderHyperparameters(this.props.hyperparameters), ...renderTags(this.props.tags), ...this.renderVpcConfig(this.props.vpcConfig), + ...renderEnvironment(this.props.environment), }; } diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/lib/sagemaker/create-transform-job.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/lib/sagemaker/create-transform-job.ts index cc108c45e4439..84c08fa22529d 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/lib/sagemaker/create-transform-job.ts +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/lib/sagemaker/create-transform-job.ts @@ -5,7 +5,7 @@ import { Size, Stack, Token } from '@aws-cdk/core'; import { Construct } from 'constructs'; import { integrationResourceArn, validatePatternSupported } from '../private/task-utils'; import { BatchStrategy, ModelClientOptions, S3DataType, TransformInput, TransformOutput, TransformResources } from './base-types'; -import { renderTags } from './private/utils'; +import { renderEnvironment, renderTags } from './private/utils'; /** * Properties for creating an Amazon SageMaker transform job task @@ -166,7 +166,7 @@ export class SageMakerCreateTransformJob extends sfn.TaskStateBase { private renderParameters(): { [key: string]: any } { return { ...(this.props.batchStrategy ? { BatchStrategy: this.props.batchStrategy } : {}), - ...this.renderEnvironment(this.props.environment), + ...renderEnvironment(this.props.environment), ...(this.props.maxConcurrentTransforms ? { MaxConcurrentTransforms: this.props.maxConcurrentTransforms } : {}), ...(this.props.maxPayload ? { MaxPayloadInMB: this.props.maxPayload.toMebibytes() } : {}), ...this.props.modelClientOptions ? this.renderModelClientOptions(this.props.modelClientOptions) : {}, @@ -234,10 +234,6 @@ export class SageMakerCreateTransformJob extends sfn.TaskStateBase { }; } - private renderEnvironment(environment: { [key: string]: any } | undefined): { [key: string]: any } { - return environment ? { Environment: environment } : {}; - } - private makePolicyStatements(): iam.PolicyStatement[] { const stack = Stack.of(this); diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/lib/sagemaker/private/utils.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/lib/sagemaker/private/utils.ts index e308fd890864c..bbcaed118a083 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/lib/sagemaker/private/utils.ts +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/lib/sagemaker/private/utils.ts @@ -1,4 +1,7 @@ - export function renderTags(tags: { [key: string]: any } | undefined): { [key: string]: any } { return tags ? { Tags: Object.keys(tags).map((key) => ({ Key: key, Value: tags[key] })) } : {}; -} \ No newline at end of file +} + +export function renderEnvironment(environment: { [key: string]: any } | undefined): { [key: string]: any } { + return environment ? { Environment: environment } : {}; +} diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/package.json b/packages/@aws-cdk/aws-stepfunctions-tasks/package.json index 58936893a7f08..0bbda5a9263c7 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/package.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/package.json @@ -90,7 +90,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/aws-sdk/call-aws-service.test.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/aws-sdk/call-aws-service.test.ts index d3b9e3e0d42ba..da26dc7d8450e 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/aws-sdk/call-aws-service.test.ts +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/aws-sdk/call-aws-service.test.ts @@ -146,3 +146,16 @@ test('with unresolved tokens', () => { Parameters: {}, }); }); + +test('throws with invalid integration pattern', () => { + expect(() => new tasks.CallAwsService(stack, 'GetObject', { + integrationPattern: sfn.IntegrationPattern.RUN_JOB, + service: 's3', + action: 'getObject', + parameters: { + Bucket: 'my-bucket', + Key: sfn.JsonPath.stringAt('$.key'), + }, + iamResources: ['*'], + })).toThrow(/The RUN_JOB integration pattern is not supported for CallAwsService/); +}); diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/sagemaker/create-training-job.test.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/sagemaker/create-training-job.test.ts index 7e7a5eff26348..9d5ebb1f9711a 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/sagemaker/create-training-job.test.ts +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/sagemaker/create-training-job.test.ts @@ -192,6 +192,9 @@ test('create complex training job', () => { vpcConfig: { vpc, }, + environment: { + SOMEVAR: 'myvalue', + }, }); trainTask.addSecurityGroup(securityGroup); @@ -285,6 +288,9 @@ test('create complex training job', () => { { Ref: 'VPCPrivateSubnet2SubnetCFCDAA7A' }, ], }, + Environment: { + SOMEVAR: 'myvalue', + }, }, }); }); diff --git a/packages/@aws-cdk/aws-stepfunctions/lib/state-machine.ts b/packages/@aws-cdk/aws-stepfunctions/lib/state-machine.ts index 4143e4bba6601..7fe4423b8a310 100644 --- a/packages/@aws-cdk/aws-stepfunctions/lib/state-machine.ts +++ b/packages/@aws-cdk/aws-stepfunctions/lib/state-machine.ts @@ -142,7 +142,9 @@ abstract class StateMachineBase extends Resource implements IStateMachine { public readonly stateMachineArn = stateMachineArn; public readonly grantPrincipal = new iam.UnknownPrincipal({ resource: this }); } - return new Import(scope, id); + return new Import(scope, id, { + environmentFromArn: stateMachineArn, + }); } public abstract readonly stateMachineArn: string; diff --git a/packages/@aws-cdk/aws-stepfunctions/package.json b/packages/@aws-cdk/aws-stepfunctions/package.json index f9018098cd4d6..c901ae4980ad4 100644 --- a/packages/@aws-cdk/aws-stepfunctions/package.json +++ b/packages/@aws-cdk/aws-stepfunctions/package.json @@ -84,7 +84,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/aws-cloudwatch": "0.0.0", diff --git a/packages/@aws-cdk/aws-stepfunctions/test/state-machine.test.ts b/packages/@aws-cdk/aws-stepfunctions/test/state-machine.test.ts index f60c0b756e66a..f99cc479c9975 100644 --- a/packages/@aws-cdk/aws-stepfunctions/test/state-machine.test.ts +++ b/packages/@aws-cdk/aws-stepfunctions/test/state-machine.test.ts @@ -277,4 +277,35 @@ describe('State Machine', () => { ], }); }); + + describe('StateMachine.fromStateMachineArn()', () => { + let stack: cdk.Stack; + + beforeEach(() => { + const app = new cdk.App(); + stack = new cdk.Stack(app, 'Base', { + env: { account: '111111111111', region: 'stack-region' }, + }); + }); + + describe('for a state machine in a different account and region', () => { + let mach: stepfunctions.IStateMachine; + + beforeEach(() => { + mach = stepfunctions.StateMachine.fromStateMachineArn( + stack, + 'iMach', + 'arn:aws:states:machine-region:222222222222:stateMachine:machine-name', + ); + }); + + test("the state machine's region is taken from the ARN", () => { + expect(mach.env.region).toBe('machine-region'); + }); + + test("the state machine's account is taken from the ARN", () => { + expect(mach.env.account).toBe('222222222222'); + }); + }); + }); }); diff --git a/packages/@aws-cdk/aws-synthetics/package.json b/packages/@aws-cdk/aws-synthetics/package.json index 66eb03b85dd8b..ed5b4eb9f4534 100644 --- a/packages/@aws-cdk/aws-synthetics/package.json +++ b/packages/@aws-cdk/aws-synthetics/package.json @@ -86,7 +86,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/aws-cloudwatch": "0.0.0", diff --git a/packages/@aws-cdk/aws-timestream/package.json b/packages/@aws-cdk/aws-timestream/package.json index 35305de3ba407..d630d3f2f818f 100644 --- a/packages/@aws-cdk/aws-timestream/package.json +++ b/packages/@aws-cdk/aws-timestream/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-transfer/package.json b/packages/@aws-cdk/aws-transfer/package.json index 5c6fefa69391a..efeddaba3fff8 100644 --- a/packages/@aws-cdk/aws-transfer/package.json +++ b/packages/@aws-cdk/aws-transfer/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-waf/package.json b/packages/@aws-cdk/aws-waf/package.json index 8aaf46f4b625f..20c6e3c1a8896 100644 --- a/packages/@aws-cdk/aws-waf/package.json +++ b/packages/@aws-cdk/aws-waf/package.json @@ -83,7 +83,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-wafregional/package.json b/packages/@aws-cdk/aws-wafregional/package.json index 485d9962f8424..aa4997b25435f 100644 --- a/packages/@aws-cdk/aws-wafregional/package.json +++ b/packages/@aws-cdk/aws-wafregional/package.json @@ -83,7 +83,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-wafv2/package.json b/packages/@aws-cdk/aws-wafv2/package.json index 331e6229ca89b..3f6fa8ac9d3ff 100644 --- a/packages/@aws-cdk/aws-wafv2/package.json +++ b/packages/@aws-cdk/aws-wafv2/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-wisdom/package.json b/packages/@aws-cdk/aws-wisdom/package.json index 376daf9bdaaa8..f641345d8e7ea 100644 --- a/packages/@aws-cdk/aws-wisdom/package.json +++ b/packages/@aws-cdk/aws-wisdom/package.json @@ -88,7 +88,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-workspaces/package.json b/packages/@aws-cdk/aws-workspaces/package.json index 95758a0601e75..8f0da7bbbfc03 100644 --- a/packages/@aws-cdk/aws-workspaces/package.json +++ b/packages/@aws-cdk/aws-workspaces/package.json @@ -83,7 +83,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-xray/package.json b/packages/@aws-cdk/aws-xray/package.json index b41a6bb35eb27..83f4d9e17dfed 100644 --- a/packages/@aws-cdk/aws-xray/package.json +++ b/packages/@aws-cdk/aws-xray/package.json @@ -87,7 +87,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0" + "@types/jest": "^27.4.1" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/cdk-assets-schema/package.json b/packages/@aws-cdk/cdk-assets-schema/package.json index 9370ac05d5848..abec52ee08000 100644 --- a/packages/@aws-cdk/cdk-assets-schema/package.json +++ b/packages/@aws-cdk/cdk-assets-schema/package.json @@ -61,7 +61,7 @@ "devDependencies": { "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "repository": { diff --git a/packages/@aws-cdk/cfnspec/CHANGELOG.md b/packages/@aws-cdk/cfnspec/CHANGELOG.md index 8ec673916ae30..247a718165fd2 100644 --- a/packages/@aws-cdk/cfnspec/CHANGELOG.md +++ b/packages/@aws-cdk/cfnspec/CHANGELOG.md @@ -1,3 +1,258 @@ +# CloudFormation Resource Specification v59.0.0 + +## New Resource Types + +* AWS::EKS::IdentityProviderConfig +* AWS::MSK::BatchScramSecret +* AWS::MSK::Configuration + +## Attribute Changes + +* AWS::ImageBuilder::Image ImageUri (__added__) +* AWS::MSK::Cluster Arn (__added__) + +## Property Changes + +* AWS::AmplifyUIBuilder::Component SchemaVersion (__added__) +* AWS::ApiGateway::BasePathMapping Id (__added__) +* AWS::EC2::TransitGatewayVpcAttachment SubnetIds.Required (__changed__) + * Old: false + * New: true +* AWS::EC2::TransitGatewayVpcAttachment TransitGatewayId.Required (__changed__) + * Old: false + * New: true +* AWS::EC2::TransitGatewayVpcAttachment VpcId.Required (__changed__) + * Old: false + * New: true +* AWS::ImageBuilder::Image ContainerRecipeArn.UpdateType (__changed__) + * Old: Mutable + * New: Immutable +* AWS::MSK::Cluster CurrentVersion (__added__) +* AWS::MSK::Cluster Tags.PrimitiveType (__deleted__) +* AWS::MSK::Cluster Tags.PrimitiveItemType (__added__) +* AWS::MSK::Cluster Tags.Type (__added__) + +## Property Type Changes + +* AWS::DataBrew::Job.Output MaxOutputFiles (__added__) +* AWS::MSK::Cluster.BrokerNodeGroupInfo ClientSubnets.DuplicatesAllowed (__added__) +* AWS::MSK::Cluster.BrokerNodeGroupInfo SecurityGroups.DuplicatesAllowed (__added__) +* AWS::MSK::Cluster.Tls CertificateAuthorityArnList.DuplicatesAllowed (__added__) + + +# CloudFormation Resource Specification v58.0.0 + +## New Resource Types + +* AWS::AppIntegrations::DataIntegration +* AWS::DataSync::LocationFSxLustre + +## Attribute Changes + +* AWS::AmplifyUIBuilder::Component CreatedAt (__deleted__) +* AWS::AmplifyUIBuilder::Component ModifiedAt (__deleted__) + +## Property Changes + +* AWS::AmplifyUIBuilder::Component Events (__added__) +* AWS::AmplifyUIBuilder::Component BindingProperties.Required (__changed__) + * Old: false + * New: true +* AWS::AmplifyUIBuilder::Component ComponentType.Required (__changed__) + * Old: false + * New: true +* AWS::AmplifyUIBuilder::Component Name.Required (__changed__) + * Old: false + * New: true +* AWS::AmplifyUIBuilder::Component Overrides.Required (__changed__) + * Old: false + * New: true +* AWS::AmplifyUIBuilder::Component Properties.Required (__changed__) + * Old: false + * New: true +* AWS::AmplifyUIBuilder::Component Variants.Required (__changed__) + * Old: false + * New: true +* AWS::Events::Connection AuthParameters.PrimitiveType (__deleted__) +* AWS::Events::Connection AuthParameters.Type (__added__) +* AWS::Transfer::Server PostAuthenticationLoginBanner (__added__) +* AWS::Transfer::Server PreAuthenticationLoginBanner (__added__) + +## Property Type Changes + +* AWS::AmplifyUIBuilder::Component.ActionParameters (__added__) +* AWS::AmplifyUIBuilder::Component.ComponentEvent (__added__) +* AWS::AmplifyUIBuilder::Component.ComponentEvents (__added__) +* AWS::AmplifyUIBuilder::Component.MutationActionSetStateParameter (__added__) +* AWS::AppFlow::Flow.SAPODataDestinationProperties (__added__) +* AWS::AppFlow::Flow.SuccessResponseHandlingConfig (__added__) +* AWS::AppMesh::Mesh.MeshServiceDiscovery (__added__) +* AWS::Events::Connection.ApiKeyAuthParameters (__added__) +* AWS::Events::Connection.AuthParameters (__added__) +* AWS::Events::Connection.BasicAuthParameters (__added__) +* AWS::Events::Connection.ClientParameters (__added__) +* AWS::Events::Connection.ConnectionHttpParameters (__added__) +* AWS::Events::Connection.OAuthParameters (__added__) +* AWS::Events::Connection.Parameter (__added__) +* AWS::AmplifyUIBuilder::Component.ComponentChild Events (__added__) +* AWS::AmplifyUIBuilder::Component.ComponentConditionProperty OperandType (__added__) +* AWS::AmplifyUIBuilder::Component.ComponentProperty ComponentName (__added__) +* AWS::AmplifyUIBuilder::Component.ComponentProperty Property (__added__) +* AWS::AppFlow::Flow.DestinationConnectorProperties SAPOData (__added__) + + +# CloudFormation Resource Specification v57.0.0 + +## New Resource Types + +* AWS::ECR::PullThroughCacheRule + +## Attribute Changes + +* AWS::Batch::ComputeEnvironment ComputeEnvironmentArn (__added__) +* AWS::Batch::JobQueue JobQueueArn (__added__) +* AWS::SES::ConfigurationSetEventDestination Id (__added__) + +## Property Changes + +* AWS::Batch::ComputeEnvironment Tags.PrimitiveType (__deleted__) +* AWS::Batch::ComputeEnvironment Tags.PrimitiveItemType (__added__) +* AWS::Batch::ComputeEnvironment Tags.Type (__added__) +* AWS::Batch::JobQueue ComputeEnvironmentOrder.DuplicatesAllowed (__added__) +* AWS::Batch::JobQueue Tags.PrimitiveType (__deleted__) +* AWS::Batch::JobQueue Tags.PrimitiveItemType (__added__) +* AWS::Batch::JobQueue Tags.Type (__added__) +* AWS::DocDB::DBCluster MasterUserPassword.Required (__changed__) + * Old: true + * New: false +* AWS::DocDB::DBCluster MasterUsername.Required (__changed__) + * Old: true + * New: false +* AWS::EC2::Instance PrivateDnsNameOptions (__added__) +* AWS::IoT::Authorizer EnableCachingForHttp (__added__) +* AWS::Kendra::DataSource CustomDocumentEnrichmentConfiguration (__added__) +* AWS::Lambda::EventSourceMapping FilterCriteria.PrimitiveType (__deleted__) +* AWS::Lambda::EventSourceMapping FilterCriteria.Type (__added__) +* AWS::Lambda::EventSourceMapping StartingPositionTimestamp.UpdateType (__changed__) + * Old: Mutable + * New: Immutable +* AWS::StepFunctions::StateMachine StateMachineType.UpdateType (__changed__) + * Old: Mutable + * New: Immutable + +## Property Type Changes + +* AWS::EC2::Instance.PrivateDnsNameOptions (__added__) +* AWS::Kendra::DataSource.CustomDocumentEnrichmentConfiguration (__added__) +* AWS::Kendra::DataSource.DocumentAttributeCondition (__added__) +* AWS::Kendra::DataSource.DocumentAttributeTarget (__added__) +* AWS::Kendra::DataSource.DocumentAttributeValue (__added__) +* AWS::Kendra::DataSource.HookConfiguration (__added__) +* AWS::Kendra::DataSource.InlineCustomDocumentEnrichmentConfiguration (__added__) +* AWS::Lambda::EventSourceMapping.Filter (__added__) +* AWS::Lambda::EventSourceMapping.FilterCriteria (__added__) +* AWS::WAFv2::WebACL.FieldIdentifier (__added__) +* AWS::WAFv2::WebACL.ManagedRuleGroupConfig (__added__) +* AWS::Batch::ComputeEnvironment.ComputeResources Ec2Configuration.DuplicatesAllowed (__added__) +* AWS::Batch::ComputeEnvironment.ComputeResources InstanceTypes.DuplicatesAllowed (__added__) +* AWS::Batch::ComputeEnvironment.ComputeResources SecurityGroupIds.DuplicatesAllowed (__added__) +* AWS::Batch::ComputeEnvironment.ComputeResources Subnets.DuplicatesAllowed (__added__) +* AWS::Batch::ComputeEnvironment.ComputeResources Tags.PrimitiveType (__deleted__) +* AWS::Batch::ComputeEnvironment.ComputeResources Tags.PrimitiveItemType (__added__) +* AWS::Batch::ComputeEnvironment.ComputeResources Tags.Type (__added__) +* AWS::EC2::SpotFleet.LaunchTemplateOverrides Priority (__added__) +* AWS::IoTAnalytics::Dataset.RetentionPeriod NumberOfDays.Required (__changed__) + * Old: true + * New: false +* AWS::IoTAnalytics::Dataset.RetentionPeriod Unlimited.Required (__changed__) + * Old: true + * New: false +* AWS::NetworkFirewall::FirewallPolicy.FirewallPolicy StatefulDefaultActions.DuplicatesAllowed (__changed__) + * Old: false + * New: true +* AWS::NetworkFirewall::FirewallPolicy.FirewallPolicy StatefulRuleGroupReferences.DuplicatesAllowed (__changed__) + * Old: false + * New: true +* AWS::NetworkFirewall::FirewallPolicy.FirewallPolicy StatelessCustomActions.DuplicatesAllowed (__changed__) + * Old: false + * New: true +* AWS::NetworkFirewall::FirewallPolicy.FirewallPolicy StatelessDefaultActions.DuplicatesAllowed (__changed__) + * Old: false + * New: true +* AWS::NetworkFirewall::FirewallPolicy.FirewallPolicy StatelessFragmentDefaultActions.DuplicatesAllowed (__changed__) + * Old: false + * New: true +* AWS::NetworkFirewall::FirewallPolicy.FirewallPolicy StatelessRuleGroupReferences.DuplicatesAllowed (__changed__) + * Old: false + * New: true +* AWS::NetworkFirewall::FirewallPolicy.PublishMetricAction Dimensions.DuplicatesAllowed (__changed__) + * Old: false + * New: true +* AWS::NetworkFirewall::RuleGroup.IPSet Definition.DuplicatesAllowed (__changed__) + * Old: false + * New: true +* AWS::NetworkFirewall::RuleGroup.MatchAttributes DestinationPorts.DuplicatesAllowed (__changed__) + * Old: false + * New: true +* AWS::NetworkFirewall::RuleGroup.MatchAttributes Destinations.DuplicatesAllowed (__changed__) + * Old: false + * New: true +* AWS::NetworkFirewall::RuleGroup.MatchAttributes Protocols.DuplicatesAllowed (__changed__) + * Old: false + * New: true +* AWS::NetworkFirewall::RuleGroup.MatchAttributes SourcePorts.DuplicatesAllowed (__changed__) + * Old: false + * New: true +* AWS::NetworkFirewall::RuleGroup.MatchAttributes Sources.DuplicatesAllowed (__changed__) + * Old: false + * New: true +* AWS::NetworkFirewall::RuleGroup.MatchAttributes TCPFlags.DuplicatesAllowed (__changed__) + * Old: false + * New: true +* AWS::NetworkFirewall::RuleGroup.PortSet Definition.DuplicatesAllowed (__changed__) + * Old: false + * New: true +* AWS::NetworkFirewall::RuleGroup.PublishMetricAction Dimensions.DuplicatesAllowed (__changed__) + * Old: false + * New: true +* AWS::NetworkFirewall::RuleGroup.RuleDefinition Actions.DuplicatesAllowed (__changed__) + * Old: false + * New: true +* AWS::NetworkFirewall::RuleGroup.RuleOption Settings.DuplicatesAllowed (__changed__) + * Old: false + * New: true +* AWS::NetworkFirewall::RuleGroup.RulesSource StatefulRules.DuplicatesAllowed (__changed__) + * Old: false + * New: true +* AWS::NetworkFirewall::RuleGroup.RulesSourceList TargetTypes.DuplicatesAllowed (__changed__) + * Old: false + * New: true +* AWS::NetworkFirewall::RuleGroup.RulesSourceList Targets.DuplicatesAllowed (__changed__) + * Old: false + * New: true +* AWS::NetworkFirewall::RuleGroup.StatefulRule RuleOptions.DuplicatesAllowed (__changed__) + * Old: false + * New: true +* AWS::NetworkFirewall::RuleGroup.StatelessRulesAndCustomActions CustomActions.DuplicatesAllowed (__changed__) + * Old: false + * New: true +* AWS::NetworkFirewall::RuleGroup.StatelessRulesAndCustomActions StatelessRules.DuplicatesAllowed (__changed__) + * Old: false + * New: true +* AWS::NetworkFirewall::RuleGroup.TCPFlagField Flags.DuplicatesAllowed (__changed__) + * Old: false + * New: true +* AWS::NetworkFirewall::RuleGroup.TCPFlagField Masks.DuplicatesAllowed (__changed__) + * Old: false + * New: true +* AWS::SES::ConfigurationSetEventDestination.CloudWatchDestination DimensionConfigurations.DuplicatesAllowed (__added__) +* AWS::SES::ConfigurationSetEventDestination.EventDestination MatchingEventTypes.DuplicatesAllowed (__added__) +* AWS::WAFv2::WebACL.ManagedRuleGroupStatement ManagedRuleGroupConfigs (__added__) + +## Unapplied changes + +* AWS::AppIntegrations is at 53.1.0 + # CloudFormation Resource Specification v56.0.0 ## New Resource Types diff --git a/packages/@aws-cdk/cfnspec/cfn.version b/packages/@aws-cdk/cfnspec/cfn.version index 293f11fea4bf8..1a985d6cc8839 100644 --- a/packages/@aws-cdk/cfnspec/cfn.version +++ b/packages/@aws-cdk/cfnspec/cfn.version @@ -1 +1 @@ -56.0.0 +59.0.0 diff --git a/packages/@aws-cdk/cfnspec/package.json b/packages/@aws-cdk/cfnspec/package.json index 655a14cb29f43..f299732ab20a0 100644 --- a/packages/@aws-cdk/cfnspec/package.json +++ b/packages/@aws-cdk/cfnspec/package.json @@ -32,7 +32,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0", "@types/fs-extra": "^8.1.2", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "@types/md5": "^2.3.2", "fast-json-patch": "^2.2.1", "jest": "^27.5.1", diff --git a/packages/@aws-cdk/cfnspec/spec-source/cfn-docs/cfn-docs.json b/packages/@aws-cdk/cfnspec/spec-source/cfn-docs/cfn-docs.json index a0ad047d83a2a..ac2b4d0caddc7 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/cfn-docs/cfn-docs.json +++ b/packages/@aws-cdk/cfnspec/spec-source/cfn-docs/cfn-docs.json @@ -639,10 +639,8 @@ "AWS::AmplifyUIBuilder::Component": { "attributes": { "AppId": "The unique ID for the Amplify app.", - "CreatedAt": "The time that the component was created.", "EnvironmentName": "The name of the backend environment that is a part of the Amplify app.", "Id": "The unique ID of the component.", - "ModifiedAt": "The time that the component was modified.", "Ref": "" }, "description": "The AWS::AmplifyUIBuilder::Component resource specifies a component within an Amplify app. A component is a user interface (UI) element that you can customize. Use `ComponentChild` to configure an instance of a `Component` . A `ComponentChild` instance inherits the configuration of the main `Component` .", @@ -651,14 +649,31 @@ "Children": "A list of the component's `ComponentChild` instances.", "CollectionProperties": "The data binding configuration for the component's properties. Use this for a collection component. You can't specify `tags` as a valid property for `collectionProperties` .", "ComponentType": "The type of the component. This can be an Amplify custom UI component or another custom component.", + "Events": "Describes the events that can be raised on the component. Use for the workflow feature in Amplify Studio that allows you to bind events and actions to components.", "Name": "The name of the component.", "Overrides": "Describes the component's properties that can be overriden in a customized instance of the component. You can't specify `tags` as a valid property for `overrides` .", "Properties": "Describes the component's properties. You can't specify `tags` as a valid property for `properties` .", + "SchemaVersion": "The schema version of the component when it was imported.", "SourceId": "The unique ID of the component in its original source system, such as Figma.", "Tags": "One or more key-value pairs to use when tagging the component.", "Variants": "A list of the component's variants. A variant is a unique style configuration of a main component." } }, + "AWS::AmplifyUIBuilder::Component.ActionParameters": { + "attributes": {}, + "description": "The `ActionParameters` property specifies the event action configuration for an element of a `Component` or `ComponentChild` . Use for the workflow feature in Amplify Studio that allows you to bind events and actions to components. `ActionParameters` defines the action that is performed when an event occurs on the component.", + "properties": { + "Anchor": "The HTML anchor link to the location to open. Specify this value for a navigation action.", + "Fields": "A dictionary of key-value pairs mapping Amplify Studio properties to fields in a data model. Use when the action performs an operation on an Amplify DataStore model.", + "Global": "Specifies whether the user should be signed out globally. Specify this value for an auth sign out action.", + "Id": "The unique ID of the component that the `ActionParameters` apply to.", + "Model": "The name of the data model. Use when the action performs an operation on an Amplify DataStore model.", + "State": "A key-value pair that specifies the state property name and its initial value.", + "Target": "The element within the same component to modify when the action occurs.", + "Type": "The type of navigation action. Valid values are `url` and `anchor` . This value is required for a navigation action.", + "Url": "The URL to the location to open. Specify this value for a navigation action." + } + }, "AWS::AmplifyUIBuilder::Component.ComponentBindingPropertiesValue": { "attributes": {}, "description": "The `ComponentBindingPropertiesValue` property specifies the data binding configuration for a component at runtime. You can use `ComponentBindingPropertiesValue` to add exposed properties to a component to allow different values to be entered when a component is reused in different places in an app.", @@ -687,6 +702,7 @@ "properties": { "Children": "The list of `ComponentChild` instances for this component.", "ComponentType": "The type of the child component.", + "Events": "Describes the events that can be raised on the child component. Use for the workflow feature in Amplify Studio that allows you to bind events and actions to components.", "Name": "The name of the child component.", "Properties": "Describes the properties of the child component. You can't specify `tags` as a valid property for `properties` ." } @@ -698,6 +714,7 @@ "Else": "The value to assign to the property if the condition is not met.", "Field": "The name of a field. Specify this when the property is a data model.", "Operand": "The value of the property to evaluate.", + "OperandType": "The type of the property to evaluate.", "Operator": "The operator to use to perform the evaluation, such as `eq` to represent equals.", "Property": "The name of the conditional property.", "Then": "The value to assign to the property if the condition is met." @@ -713,6 +730,19 @@ "Sort": "Describes how to sort the component's properties." } }, + "AWS::AmplifyUIBuilder::Component.ComponentEvent": { + "attributes": {}, + "description": "The `ComponentEvent` property specifies the configuration of an event. You can bind an event and a corresponding action to a `Component` or a `ComponentChild` . A button click is an example of an event.", + "properties": { + "Action": "The action to perform when a specific event is raised.", + "Parameters": "Describes information about the action." + } + }, + "AWS::AmplifyUIBuilder::Component.ComponentEvents": { + "attributes": {}, + "description": "The `ComponentEvents` property specifies the events that can be raised on the component. Use for the workflow feature in Amplify Studio that allows you to bind events and actions to components.", + "properties": {} + }, "AWS::AmplifyUIBuilder::Component.ComponentOverrides": { "attributes": {}, "description": "The `ComponentOverrides` property specifies the component's properties that can be overriden in a customized instance of the component.", @@ -735,6 +765,7 @@ "BindingProperties": "The information to bind the component property to data at runtime.", "Bindings": "The information to bind the component property to form data.", "CollectionBindingProperties": "The information to bind the component property to data at runtime. Use this for collection components.", + "ComponentName": "The name of the component that is affected by an event.", "Concat": "A list of component properties to concatenate to create the value to assign to this component property.", "Condition": "The conditional expression to use to assign a value to the component property.", "Configured": "Specifies whether the user configured the property in Amplify Studio after importing it.", @@ -742,6 +773,7 @@ "Event": "An event that occurs in your app. Use this for workflow data binding.", "ImportedValue": "The default value assigned to the property when the component is imported into an app.", "Model": "The data model to use to assign a value to the component property.", + "Property": "The name of the component's property that is affected by an event.", "Type": "The component type.", "UserAttribute": "An authenticated user attribute to use to assign a value to the component property.", "Value": "The value to assign to the component property." @@ -773,6 +805,15 @@ "description": "The `FormBindings` property specifies how to bind a component's properties to form data.", "properties": {} }, + "AWS::AmplifyUIBuilder::Component.MutationActionSetStateParameter": { + "attributes": {}, + "description": "The `MutationActionSetStateParameter` property specifies the state configuration when an action modifies a property of another element within the same component.", + "properties": { + "ComponentName": "The name of the component that is being modified.", + "Property": "The name of the component property to apply the state configuration to.", + "Set": "The state configuration to assign to the property." + } + }, "AWS::AmplifyUIBuilder::Component.Predicate": { "attributes": {}, "description": "The `Predicate` property specifies information for generating Amplify DataStore queries. Use `Predicate` to retrieve a subset of the data in a collection.", @@ -885,6 +926,7 @@ "properties": { "BasePath": "The base path name that callers of the API must provide in the URL after the domain name.", "DomainName": "The `DomainName` of an [AWS::ApiGateway::DomainName](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-domainname.html) resource.", + "Id": "", "RestApiId": "The ID of the API.", "Stage": "The name of the API's stage." } @@ -2216,6 +2258,7 @@ "LookoutMetrics": "The properties required to query Amazon Lookout for Metrics.", "Redshift": "The properties required to query Amazon Redshift.", "S3": "The properties required to query Amazon S3.", + "SAPOData": "The properties required to query SAPOData.", "Salesforce": "The properties required to query Salesforce.", "Snowflake": "The properties required to query Snowflake.", "Upsolver": "The properties required to query Upsolver.", @@ -2342,6 +2385,17 @@ "S3InputFormatConfig": "" } }, + "AWS::AppFlow::Flow.SAPODataDestinationProperties": { + "attributes": {}, + "description": "The properties that are applied when using SAPOData as a flow destination", + "properties": { + "ErrorHandlingConfig": "", + "IdFieldNames": "", + "ObjectPath": "The object path specified in the SAPOData flow destination.", + "SuccessResponseHandlingConfig": "Determines how Amazon AppFlow handles the success response that it gets from the connector after placing data.\n\nFor example, this setting would determine where to write the response from a destination connector upon a successful insert operation.", + "WriteOperationType": "" + } + }, "AWS::AppFlow::Flow.SAPODataSourceProperties": { "attributes": {}, "description": "", @@ -2442,6 +2496,14 @@ "SourceConnectorProperties": "Specifies the information that is required to query a particular source connector." } }, + "AWS::AppFlow::Flow.SuccessResponseHandlingConfig": { + "attributes": {}, + "description": "Determines how Amazon AppFlow handles the success response that it gets from the connector after placing data.\n\nFor example, this setting would determine where to write the response from the destination connector upon a successful insert operation.", + "properties": { + "BucketName": "The name of the Amazon S3 bucket.", + "BucketPrefix": "The Amazon S3 bucket prefix." + } + }, "AWS::AppFlow::Flow.Task": { "attributes": {}, "description": "The `Task` property type specifies the class for modeling different type of tasks. Task implementation varies based on the `TaskType` .", @@ -2826,6 +2888,11 @@ "Type": "The egress filter type. By default, the type is `DROP_ALL` , which allows egress only from virtual nodes to other defined resources in the service mesh (and any traffic to `*.amazonaws.com` for AWS API calls). You can set the egress filter type to `ALLOW_ALL` to allow egress to any endpoint inside or outside of the service mesh." } }, + "AWS::AppMesh::Mesh.MeshServiceDiscovery": { + "attributes": {}, + "description": "", + "properties": {} + }, "AWS::AppMesh::Mesh.MeshSpec": { "attributes": {}, "description": "An object that represents the specification of a service mesh.", @@ -4866,12 +4933,12 @@ "NamedQueryId": "The unique ID of the query.", "Ref": "`Ref` returns the resource name." }, - "description": "The `AWS::Athena::NamedQuery` resource specifies an Amazon Athena saved query, where `QueryString` is the list of SQL query statements that comprise the query.", + "description": "The `AWS::Athena::NamedQuery` resource specifies an Amazon Athena saved query, where `QueryString` contains the SQL query statements that make up the query.", "properties": { "Database": "The database to which the query belongs.", "Description": "The query description.", "Name": "The query name.", - "QueryString": "The SQL query statements that comprise the query.", + "QueryString": "The SQL statements that make up the query.", "WorkGroup": "The name of the workgroup that contains the named query." } }, @@ -5069,7 +5136,7 @@ "MixedInstancesPolicy": "An embedded object that specifies a mixed instances policy.\n\nThe policy includes properties that not only define the distribution of On-Demand Instances and Spot Instances, the maximum price to pay for Spot Instances (optional), and how the Auto Scaling group allocates instance types to fulfill On-Demand and Spot capacities, but also the properties that specify the instance configuration information\u2014the launch template and instance types. The policy can also include a weight for each instance type and different launch templates for individual instance types.\n\nFor more information, see [Auto Scaling groups with multiple instance types and purchase options](https://docs.aws.amazon.com/autoscaling/ec2/userguide/ec2-auto-scaling-mixed-instances-groups.html) in the *Amazon EC2 Auto Scaling User Guide* .\n\nIf you specify `LaunchTemplate` , `InstanceId` , or `LaunchConfigurationName` , don't specify `MixedInstancesPolicy` .", "NewInstancesProtectedFromScaleIn": "Indicates whether newly launched instances are protected from termination by Amazon EC2 Auto Scaling when scaling in. For more information about preventing instances from terminating on scale in, see [Instance Protection](https://docs.aws.amazon.com/autoscaling/ec2/userguide/as-instance-termination.html#instance-protection) in the *Amazon EC2 Auto Scaling User Guide* .", "NotificationConfigurations": "Configures an Auto Scaling group to send notifications when specified events take place.", - "PlacementGroup": "The name of the placement group into which you want to launch your instances. A placement group is a logical grouping of instances within a single Availability Zone. For more information, see [Placement Groups](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/placement-groups.html) in the *Amazon EC2 User Guide for Linux Instances* .", + "PlacementGroup": "The name of the placement group into which you want to launch your instances. For more information, see [Placement groups](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/placement-groups.html) in the *Amazon EC2 User Guide for Linux Instances* .\n\n> A *cluster* placement group is a logical grouping of instances within a single Availability Zone. You cannot specify multiple Availability Zones and a cluster placement group.", "ServiceLinkedRoleARN": "The Amazon Resource Name (ARN) of the service-linked role that the Auto Scaling group uses to call other AWS services on your behalf. By default, Amazon EC2 Auto Scaling uses a service-linked role named `AWSServiceRoleForAutoScaling` , which it creates if it does not exist. For more information, see [Service-linked roles for Amazon EC2 Auto Scaling](https://docs.aws.amazon.com/autoscaling/ec2/userguide/autoscaling-service-linked-role.html) in the *Amazon EC2 Auto Scaling User Guide* .", "Tags": "One or more tags. You can tag your Auto Scaling group and propagate the tags to the Amazon EC2 instances it launches. For more information, see [Tagging Auto Scaling groups and instances](https://docs.aws.amazon.com/autoscaling/ec2/userguide/autoscaling-tagging.html) in the *Amazon EC2 Auto Scaling User Guide* .", "TargetGroupARNs": "One or more Amazon Resource Names (ARN) of load balancer target groups to associate with the Auto Scaling group. Instances are registered as targets in a target group, and traffic is routed to the target group. For more information, see [Elastic Load Balancing and Amazon EC2 Auto Scaling](https://docs.aws.amazon.com/autoscaling/ec2/userguide/autoscaling-load-balancer.html) in the *Amazon EC2 Auto Scaling User Guide* .", @@ -5154,7 +5221,7 @@ "properties": { "InstanceRequirements": "The instance requirements. When you specify instance requirements, Amazon EC2 Auto Scaling finds instance types that satisfy your requirements, and then uses your On-Demand and Spot allocation strategies to launch instances from these instance types, in the same way as when you specify a list of specific instance types.\n\n> `InstanceRequirements` are incompatible with the `InstanceType` property. If you specify both of these properties, Amazon EC2 Auto Scaling will return a `ValidationException` exception.", "InstanceType": "The instance type, such as `m3.xlarge` . You must use an instance type that is supported in your requested Region and Availability Zones. For more information, see [Available instance types](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-types.html#AvailableInstanceTypes) in the *Amazon EC2 User Guide for Linux Instances.*", - "LaunchTemplateSpecification": "Provides the launch template to be used when launching the instance type specified in `InstanceType` . For example, some instance types might require a launch template with a different AMI. If not provided, Amazon EC2 Auto Scaling uses the launch template that's defined for your mixed instances policy. For more information, see [Specifying a different launch template for an instance type](https://docs.aws.amazon.com/autoscaling/ec2/userguide/ec2-auto-scaling-mixed-instances-groups-launch-template-overrides.html) in the *Amazon EC2 Auto Scaling User Guide* .", + "LaunchTemplateSpecification": "Provides a launch template for the specified instance type or instance requirements. For example, some instance types might require a launch template with a different AMI. If not provided, Amazon EC2 Auto Scaling uses the launch template that's defined for your mixed instances policy. For more information, see [Specifying a different launch template for an instance type](https://docs.aws.amazon.com/autoscaling/ec2/userguide/ec2-auto-scaling-mixed-instances-groups-launch-template-overrides.html) in the *Amazon EC2 Auto Scaling User Guide* .", "WeightedCapacity": "The number of capacity units provided by the instance type specified in `InstanceType` in terms of virtual CPUs, memory, storage, throughput, or other relative performance characteristic. When a Spot or On-Demand Instance is provisioned, the capacity units count toward the desired capacity. Amazon EC2 Auto Scaling provisions instances until the desired capacity is totally fulfilled, even if this results in an overage. For example, if there are 2 units remaining to fulfill capacity, and Amazon EC2 Auto Scaling can only provision an instance with a `WeightedCapacity` of 5 units, the instance is provisioned, and the desired capacity is exceeded by 3 units. For more information, see [Instance weighting for Amazon EC2 Auto Scaling](https://docs.aws.amazon.com/autoscaling/ec2/userguide/ec2-auto-scaling-mixed-instances-groups-instance-weighting.html) in the *Amazon EC2 Auto Scaling User Guide* . Value must be in the range of 1-999.\n\n> Every Auto Scaling group has three size parameters ( `DesiredCapacity` , `MaxSize` , and `MinSize` ). Usually, you set these sizes based on a specific number of instances. However, if you configure a mixed instances policy that defines weights for the instance types, you must specify these sizes with the same units that you use for weighting instances." } }, @@ -5459,7 +5526,7 @@ "description": "The `AWS::AutoScaling::WarmPool` resource creates a pool of pre-initialized EC2 instances that sits alongside the Auto Scaling group. Whenever your application needs to scale out, the Auto Scaling group can draw on the warm pool to meet its new desired capacity.\n\nWhen you create a warm pool, you can define a minimum size. When your Auto Scaling group scales out and the size of the warm pool shrinks, Amazon EC2 Auto Scaling launches new instances into the warm pool to maintain its minimum size.\n\nFor more information, see [Warm pools for Amazon EC2 Auto Scaling](https://docs.aws.amazon.com/autoscaling/ec2/userguide/ec2-auto-scaling-warm-pools.html) in the *Amazon EC2 Auto Scaling User Guide* .\n\n> CloudFormation supports the `UpdatePolicy` attribute for Auto Scaling groups. During an update, if `UpdatePolicy` is set to `AutoScalingRollingUpdate` , CloudFormation replaces `InService` instances only. Instances in the warm pool are not replaced. The difference in which instances are replaced can potentially result in different instance configurations after the stack update completes. If `UpdatePolicy` is set to `AutoScalingReplacingUpdate` , you do not encounter this issue because CloudFormation replaces both the Auto Scaling group and the warm pool.", "properties": { "AutoScalingGroupName": "The name of the Auto Scaling group.", - "InstanceReusePolicy": "", + "InstanceReusePolicy": "Indicates whether instances in the Auto Scaling group can be returned to the warm pool on scale in. The default is to terminate instances in the Auto Scaling group when the group scales in.", "MaxGroupPreparedCapacity": "Specifies the maximum number of instances that are allowed to be in the warm pool or in any state except `Terminated` for the Auto Scaling group. This is an optional property. Specify it only if you do not want the warm pool size to be determined by the difference between the group's maximum capacity and its desired capacity.\n\n> If a value for `MaxGroupPreparedCapacity` is not specified, Amazon EC2 Auto Scaling launches and maintains the difference between the group's maximum capacity and its desired capacity. If you specify a value for `MaxGroupPreparedCapacity` , Amazon EC2 Auto Scaling uses the difference between the `MaxGroupPreparedCapacity` and the desired capacity instead.\n> \n> The size of the warm pool is dynamic. Only when `MaxGroupPreparedCapacity` and `MinSize` are set to the same value does the warm pool have an absolute size. \n\nIf the desired capacity of the Auto Scaling group is higher than the `MaxGroupPreparedCapacity` , the capacity of the warm pool is 0, unless you specify a value for `MinSize` . To remove a value that you previously set, include the property but specify -1 for the value.", "MinSize": "Specifies the minimum number of instances to maintain in the warm pool. This helps you to ensure that there is always a certain number of warmed instances available to handle traffic spikes. Defaults to 0 if not specified.", "PoolState": "Sets the instance state to transition to after the lifecycle actions are complete. Default is `Stopped` ." @@ -5467,9 +5534,9 @@ }, "AWS::AutoScaling::WarmPool.InstanceReusePolicy": { "attributes": {}, - "description": "", + "description": "A structure that specifies an instance reuse policy for the `InstanceReusePolicy` property of the [AWS::AutoScaling::WarmPool](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-autoscaling-warmpool.html) resource type.\n\nFor more information, see [Warm pools for Amazon EC2 Auto Scaling](https://docs.aws.amazon.com/autoscaling/ec2/userguide/ec2-auto-scaling-warm-pools.html) in the *Amazon EC2 Auto Scaling User Guide* .", "properties": { - "ReuseOnScaleIn": "" + "ReuseOnScaleIn": "Specifies whether instances in the Auto Scaling group can be returned to the warm pool on scale in." } }, "AWS::AutoScalingPlans::ScalingPlan": { @@ -5764,21 +5831,21 @@ }, "AWS::Budgets::Budget.BudgetData": { "attributes": {}, - "description": "Represents the output of the `CreateBudget` operation. The content consists of the detailed metadata and data file information, and the current status of the `budget` object.\n\nThis is the ARN pattern for a budget:\n\n`arn:aws:budgets::AccountId:budget/budgetName`", + "description": "Represents the output of the `CreateBudget` operation. The content consists of the detailed metadata and data file information, and the current status of the `budget` object.\n\nThis is the Amazon Resource Name (ARN) pattern for a budget:\n\n`arn:aws:budgets::AccountId:budget/budgetName`", "properties": { - "BudgetLimit": "The total amount of cost, usage, RI utilization, RI coverage, Savings Plans utilization, or Savings Plans coverage that you want to track with your budget.\n\n`BudgetLimit` is required for cost or usage budgets, but optional for RI or Savings Plans utilization or coverage budgets. RI and Savings Plans utilization or coverage budgets default to `100` , which is the only valid value for RI or Savings Plans utilization or coverage budgets. You can't use `BudgetLimit` with `PlannedBudgetLimits` for `CreateBudget` and `UpdateBudget` actions.", + "BudgetLimit": "The total amount of cost, usage, RI utilization, RI coverage, Savings Plans utilization, or Savings Plans coverage that you want to track with your budget.\n\n`BudgetLimit` is required for cost or usage budgets, but optional for RI or Savings Plans utilization or coverage budgets. RI and Savings Plans utilization or coverage budgets default to `100` . This is the only valid value for RI or Savings Plans utilization or coverage budgets. You can't use `BudgetLimit` with `PlannedBudgetLimits` for `CreateBudget` and `UpdateBudget` actions.", "BudgetName": "The name of a budget. The value must be unique within an account. `BudgetName` can't include `:` and `\\` characters. If you don't include value for `BudgetName` in the template, Billing and Cost Management assigns your budget a randomly generated name.", - "BudgetType": "Whether this budget tracks costs, usage, RI utilization, RI coverage, Savings Plans utilization, or Savings Plans coverage.", + "BudgetType": "Specifies whether this budget tracks costs, usage, RI utilization, RI coverage, Savings Plans utilization, or Savings Plans coverage.", "CostFilters": "The cost filters, such as `Region` , `Service` , `member account` , `Tag` , or `Cost Category` , that are applied to a budget.\n\nAWS Budgets supports the following services as a `Service` filter for RI budgets:\n\n- Amazon EC2\n- Amazon Redshift\n- Amazon Relational Database Service\n- Amazon ElastiCache\n- Amazon OpenSearch Service", "CostTypes": "The types of costs that are included in this `COST` budget.\n\n`USAGE` , `RI_UTILIZATION` , `RI_COVERAGE` , `SAVINGS_PLANS_UTILIZATION` , and `SAVINGS_PLANS_COVERAGE` budgets do not have `CostTypes` .", - "PlannedBudgetLimits": "A map containing multiple `BudgetLimit` , including current or future limits.\n\n`PlannedBudgetLimits` is available for cost or usage budget and supports monthly and quarterly `TimeUnit` .\n\nFor monthly budgets, provide 12 months of `PlannedBudgetLimits` values. This must start from the current month and include the next 11 months. The `key` is the start of the month, `UTC` in epoch seconds.\n\nFor quarterly budgets, provide 4 quarters of `PlannedBudgetLimits` value entries in standard calendar quarter increments. This must start from the current quarter and include the next 3 quarters. The `key` is the start of the quarter, `UTC` in epoch seconds.\n\nIf the planned budget expires before 12 months for monthly or 4 quarters for quarterly, provide the `PlannedBudgetLimits` values only for the remaining periods.\n\nIf the budget begins at a date in the future, provide `PlannedBudgetLimits` values from the start date of the budget.\n\nAfter all of the `BudgetLimit` values in `PlannedBudgetLimits` are used, the budget continues to use the last limit as the `BudgetLimit` . At that point, the planned budget provides the same experience as a fixed budget.\n\n`DescribeBudget` and `DescribeBudgets` response along with `PlannedBudgetLimits` will also contain `BudgetLimit` representing the current month or quarter limit present in `PlannedBudgetLimits` . This only applies to budgets created with `PlannedBudgetLimits` . Budgets created without `PlannedBudgetLimits` will only contain `BudgetLimit` , and no `PlannedBudgetLimits` .", + "PlannedBudgetLimits": "A map containing multiple `BudgetLimit` , including current or future limits.\n\n`PlannedBudgetLimits` is available for cost or usage budget and supports both monthly and quarterly `TimeUnit` .\n\nFor monthly budgets, provide 12 months of `PlannedBudgetLimits` values. This must start from the current month and include the next 11 months. The `key` is the start of the month, `UTC` in epoch seconds.\n\nFor quarterly budgets, provide four quarters of `PlannedBudgetLimits` value entries in standard calendar quarter increments. This must start from the current quarter and include the next three quarters. The `key` is the start of the quarter, `UTC` in epoch seconds.\n\nIf the planned budget expires before 12 months for monthly or four quarters for quarterly, provide the `PlannedBudgetLimits` values only for the remaining periods.\n\nIf the budget begins at a date in the future, provide `PlannedBudgetLimits` values from the start date of the budget.\n\nAfter all of the `BudgetLimit` values in `PlannedBudgetLimits` are used, the budget continues to use the last limit as the `BudgetLimit` . At that point, the planned budget provides the same experience as a fixed budget.\n\n`DescribeBudget` and `DescribeBudgets` response along with `PlannedBudgetLimits` also contain `BudgetLimit` representing the current month or quarter limit present in `PlannedBudgetLimits` . This only applies to budgets that are created with `PlannedBudgetLimits` . Budgets that are created without `PlannedBudgetLimits` only contain `BudgetLimit` . They don't contain `PlannedBudgetLimits` .", "TimePeriod": "The period of time that is covered by a budget. The period has a start date and an end date. The start date must come before the end date. There are no restrictions on the end date.\n\nThe start date for a budget. If you created your budget and didn't specify a start date, the start date defaults to the start of the chosen time period (MONTHLY, QUARTERLY, or ANNUALLY). For example, if you create your budget on January 24, 2019, choose `MONTHLY` , and don't set a start date, the start date defaults to `01/01/19 00:00 UTC` . The defaults are the same for the AWS Billing and Cost Management console and the API.\n\nYou can change your start date with the `UpdateBudget` operation.\n\nAfter the end date, AWS deletes the budget and all associated notifications and subscribers.", "TimeUnit": "The length of time until a budget resets the actual and forecasted spend. `DAILY` is available only for `RI_UTILIZATION` and `RI_COVERAGE` budgets." } }, "AWS::Budgets::Budget.CostTypes": { "attributes": {}, - "description": "The types of cost that are included in a `COST` budget, such as tax and subscriptions.\n\n`USAGE` , `RI_UTILIZATION` , `RI_COVERAGE` , `SAVINGS_PLANS_UTILIZATION` , and `SAVINGS_PLANS_COVERAGE` budgets do not have `CostTypes` .", + "description": "The types of cost that are included in a `COST` budget, such as tax and subscriptions.\n\n`USAGE` , `RI_UTILIZATION` , `RI_COVERAGE` , `SAVINGS_PLANS_UTILIZATION` , and `SAVINGS_PLANS_COVERAGE` budgets don't have `CostTypes` .", "properties": { "IncludeCredit": "Specifies whether a budget includes credits.\n\nThe default value is `true` .", "IncludeDiscount": "Specifies whether a budget includes discounts.\n\nThe default value is `true` .", @@ -5795,11 +5862,11 @@ }, "AWS::Budgets::Budget.Notification": { "attributes": {}, - "description": "A notification that is associated with a budget. A budget can have up to ten notifications.\n\nEach notification must have at least one subscriber. A notification can have one SNS subscriber and up to 10 email subscribers, for a total of 11 subscribers.\n\nFor example, if you have a budget for 200 dollars and you want to be notified when you go over 160 dollars, create a notification with the following parameters:\n\n- A notificationType of `ACTUAL`\n- A `thresholdType` of `PERCENTAGE`\n- A `comparisonOperator` of `GREATER_THAN`\n- A notification `threshold` of `80`", + "description": "A notification that's associated with a budget. A budget can have up to ten notifications.\n\nEach notification must have at least one subscriber. A notification can have one SNS subscriber and up to 10 email subscribers, for a total of 11 subscribers.\n\nFor example, if you have a budget for 200 dollars and you want to be notified when you go over 160 dollars, create a notification with the following parameters:\n\n- A notificationType of `ACTUAL`\n- A `thresholdType` of `PERCENTAGE`\n- A `comparisonOperator` of `GREATER_THAN`\n- A notification `threshold` of `80`", "properties": { - "ComparisonOperator": "The comparison that is used for this notification.", - "NotificationType": "Whether the notification is for how much you have spent ( `ACTUAL` ) or for how much you're forecasted to spend ( `FORECASTED` ).", - "Threshold": "The threshold that is associated with a notification. Thresholds are always a percentage, and many customers find value being alerted between 50% - 200% of the budgeted amount. The maximum limit for your threshold is 1,000,000% above the budgeted amount.", + "ComparisonOperator": "The comparison that's used for this notification.", + "NotificationType": "Specifies whether the notification is for how much you have spent ( `ACTUAL` ) or for how much that you're forecasted to spend ( `FORECASTED` ).", + "Threshold": "The threshold that's associated with a notification. Thresholds are always a percentage, and many customers find value being alerted between 50% - 200% of the budgeted amount. The maximum limit for your threshold is 1,000,000% above the budgeted amount.", "ThresholdType": "The type of threshold for a notification. For `ABSOLUTE_VALUE` thresholds, AWS notifies you when you go over or are forecasted to go over your total cost threshold. For `PERCENTAGE` thresholds, AWS notifies you when you go over or are forecasted to go over a certain percentage of your forecasted spend. For example, if you have a budget for 200 dollars and you have a `PERCENTAGE` threshold of 80%, AWS notifies you when you go over 160 dollars." } }, @@ -5807,16 +5874,16 @@ "attributes": {}, "description": "A notification with subscribers. A notification can have one SNS subscriber and up to 10 email subscribers, for a total of 11 subscribers.", "properties": { - "Notification": "The notification that is associated with a budget.", + "Notification": "The notification that's associated with a budget.", "Subscribers": "A list of subscribers who are subscribed to this notification." } }, "AWS::Budgets::Budget.Spend": { "attributes": {}, - "description": "The amount of cost or usage that is measured for a budget.\n\nFor example, a `Spend` for `3 GB` of S3 usage would have the following parameters:\n\n- An `Amount` of `3`\n- A `unit` of `GB`", + "description": "The amount of cost or usage that's measured for a budget.\n\nFor example, a `Spend` for `3 GB` of S3 usage has the following parameters:\n\n- An `Amount` of `3`\n- A `unit` of `GB`", "properties": { - "Amount": "The cost or usage amount that is associated with a budget forecast, actual spend, or budget threshold.", - "Unit": "The unit of measurement that is used for the budget forecast, actual spend, or budget threshold, such as USD or GB." + "Amount": "The cost or usage amount that's associated with a budget forecast, actual spend, or budget threshold.", + "Unit": "The unit of measurement that's used for the budget forecast, actual spend, or budget threshold, such as USD or GBP." } }, "AWS::Budgets::Budget.Subscriber": { @@ -5831,7 +5898,7 @@ "attributes": {}, "description": "The period of time that is covered by a budget. The period has a start date and an end date. The start date must come before the end date. There are no restrictions on the end date.", "properties": { - "End": "The end date for a budget. If you didn't specify an end date, AWS set your end date to `06/15/87 00:00 UTC` . The defaults are the same for the AWS Billing and Cost Management console and the API.\n\nAfter the end date, AWS deletes the budget and all associated notifications and subscribers. You can change your end date with the `UpdateBudget` operation.", + "End": "The end date for a budget. If you didn't specify an end date, AWS set your end date to `06/15/87 00:00 UTC` . The defaults are the same for the AWS Billing and Cost Management console and the API.\n\nAfter the end date, AWS deletes the budget and all the associated notifications and subscribers. You can change your end date with the `UpdateBudget` operation.", "Start": "The start date for a budget. If you created your budget and didn't specify a start date, the start date defaults to the start of the chosen time period (MONTHLY, QUARTERLY, or ANNUALLY). For example, if you create your budget on January 24, 2019, choose `MONTHLY` , and don't set a start date, the start date defaults to `01/01/19 00:00 UTC` . The defaults are the same for the AWS Billing and Cost Management console and the API.\n\nYou can change your start date with the `UpdateBudget` operation.\n\nValid values depend on the value of `BudgetType` :\n\n- If `BudgetType` is `COST` or `USAGE` : Valid values are `MONTHLY` , `QUARTERLY` , and `ANNUALLY` .\n- If `BudgetType` is `RI_UTILIZATION` or `RI_COVERAGE` : Valid values are `DAILY` , `MONTHLY` , `QUARTERLY` , and `ANNUALLY` ." } }, @@ -5897,7 +5964,7 @@ }, "AWS::Budgets::BudgetsAction.Subscriber": { "attributes": {}, - "description": "The subscriber to a budget notification. The subscriber consists of a subscription type and either an Amazon SNS topic or an email address.\n\nFor example, an email subscriber would have the following parameters:\n\n- A `subscriptionType` of `EMAIL`\n- An `address` of `example@example.com`", + "description": "The subscriber to a budget notification. The subscriber consists of a subscription type and either an Amazon SNS topic or an email address.\n\nFor example, an email subscriber has the following parameters:\n\n- A `subscriptionType` of `EMAIL`\n- An `address` of `example@example.com`", "properties": { "Address": "The address that AWS sends budget notifications to, either an SNS topic or an email.\n\nWhen you create a subscriber, the value of `Address` can't contain line breaks.", "Type": "The type of notification that AWS sends to a subscriber." @@ -8140,7 +8207,7 @@ "properties": { "Category": "A category defines what kind of action can be taken in the stage, and constrains the provider type for the action. Valid categories are limited to one of the values below.\n\n- `Source`\n- `Build`\n- `Test`\n- `Deploy`\n- `Invoke`\n- `Approval`", "Owner": "The creator of the action being called. There are three valid values for the `Owner` field in the action category section within your pipeline structure: `AWS` , `ThirdParty` , and `Custom` . For more information, see [Valid Action Types and Providers in CodePipeline](https://docs.aws.amazon.com/codepipeline/latest/userguide/reference-pipeline-structure.html#actions-valid-providers) .", - "Provider": "The provider of the service being called by the action. Valid providers are determined by the action category. For example, an action in the Deploy category type might have a provider of CodeDeploy, which would be specified as CodeDeploy. For more information, see [Valid Action Types and Providers in CodePipeline](https://docs.aws.amazon.com/codepipeline/latest/userguide/reference-pipeline-structure.html#actions-valid-providers) .", + "Provider": "The provider of the service being called by the action. Valid providers are determined by the action category. For example, an action in the Deploy category type might have a provider of CodeDeploy, which would be specified as `CodeDeploy` . For more information, see [Valid Action Types and Providers in CodePipeline](https://docs.aws.amazon.com/codepipeline/latest/userguide/reference-pipeline-structure.html#actions-valid-providers) .", "Version": "A string that describes the action version." } }, @@ -8612,7 +8679,7 @@ "AllowedOAuthFlows": "The allowed OAuth flows.\n\nSet to `code` to initiate a code grant flow, which provides an authorization code as the response. This code can be exchanged for access tokens with the token endpoint.\n\nSet to `implicit` to specify that the client should get the access token (and, optionally, ID token, based on scopes) directly.\n\nSet to `client_credentials` to specify that the client should get the access token (and, optionally, ID token, based on scopes) from the token endpoint using a combination of client and client_secret.", "AllowedOAuthFlowsUserPoolClient": "Set to true if the client is allowed to follow the OAuth protocol when interacting with Amazon Cognito user pools.", "AllowedOAuthScopes": "The allowed OAuth scopes. Possible values provided by OAuth are: `phone` , `email` , `openid` , and `profile` . Possible values provided by AWS are: `aws.cognito.signin.user.admin` . Custom scopes created in Resource Servers are also supported.", - "AnalyticsConfiguration": "The Amazon Pinpoint analytics configuration for collecting metrics for this user pool.\n\n> In AWS Regions where isn't available, User Pools only supports sending events to Amazon Pinpoint projects in AWS Region us-east-1. In Regions where is available, User Pools will support sending events to Amazon Pinpoint projects within that same Region.", + "AnalyticsConfiguration": "The Amazon Pinpoint analytics configuration for collecting metrics for this user pool.\n\n> In AWS Regions where Amazon Pinpoint isn't available, User Pools only supports sending events to Amazon Pinpoint projects in AWS Region us-east-1. In Regions where is available, User Pools will support sending events to Amazon Pinpoint projects within that same Region.", "CallbackURLs": "A list of allowed redirect (callback) URLs for the identity providers.\n\nA redirect URI must:\n\n- Be an absolute URI.\n- Be registered with the authorization server.\n- Not include a fragment component.\n\nSee [OAuth 2.0 - Redirection Endpoint](https://docs.aws.amazon.com/https://tools.ietf.org/html/rfc6749#section-3.1.2) .\n\nAmazon Cognito requires HTTPS over HTTP except for http://localhost for testing purposes only.\n\nApp callback URLs such as myapp://example are also supported.", "ClientName": "The client name for the user pool client you would like to create.", "DefaultRedirectURI": "The default redirect URI. Must be in the `CallbackURLs` list.\n\nA redirect URI must:\n\n- Be an absolute URI.\n- Be registered with the authorization server.\n- Not include a fragment component.\n\nSee [OAuth 2.0 - Redirection Endpoint](https://docs.aws.amazon.com/https://tools.ietf.org/html/rfc6749#section-3.1.2) .\n\nAmazon Cognito requires HTTPS over HTTP except for http://localhost for testing purposes only.\n\nApp callback URLs such as myapp://example are also supported.", @@ -10213,10 +10280,24 @@ "SubnetArn": "The Amazon Resource Name (ARN) of the subnet that DataSync uses to access the target EFS file system." } }, + "AWS::DataSync::LocationFSxLustre": { + "attributes": { + "LocationArn": "The ARN of the specified FSx for Lustre file system location.", + "LocationUri": "The URI of the specified FSx for Lustre file system location.", + "Ref": "`Ref` returns the location resource ARN. For example:\n\n`arn:aws:datasync:us-east-2:111222333444:location/loc-07db7abfc326c50s3`" + }, + "description": "The `AWS::DataSync::LocationFSxLustre` resource specifies an endpoint for an Amazon FSx for Lustre file system.", + "properties": { + "FsxFilesystemArn": "The Amazon Resource Name (ARN) for the FSx for Lustre file system.", + "SecurityGroupArns": "The ARNs of the security groups that are used to configure the FSx for Lustre file system.\n\n*Pattern* : `^arn:(aws|aws-cn|aws-us-gov|aws-iso|aws-iso-b):ec2:[a-z\\-0-9]*:[0-9]{12}:security-group/.*$`\n\n*Length constraints* : Maximum length of 128.", + "Subdirectory": "A subdirectory in the location's path. This subdirectory in the FSx for Lustre file system is used to read data from the FSx for Lustre source location or write data to the FSx for Lustre destination.", + "Tags": "The key-value pair that represents a tag that you want to add to the resource. The value can be an empty string. This value helps you manage, filter, and search for your resources. We recommend that you create a name tag for your location." + } + }, "AWS::DataSync::LocationFSxWindows": { "attributes": { - "LocationArn": "The Amazon Resource Name (ARN) of the specified Amazon FSx for Windows Server file system location.", - "LocationUri": "The URI of the specified Amazon FSx for Windows Server file system.", + "LocationArn": "The ARN of the specified FSx for Windows Server file system location.", + "LocationUri": "The URI of the specified FSx for Windows Server file system location.", "Ref": "When you pass the logical ID of this resource to the intrinsic `Ref` function, `Ref` returns the location resource ARN. For example:\n\n`arn:aws:datasync:us-east-2:111222333444:location/loc-07db7abfc326c50s3`\n\nFor more information about using the `Ref` function, see [Ref](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-ref.html) ." }, "description": "The `AWS::DataSync::LocationFSxWindows` resource specifies an endpoint for an Amazon FSx for Windows Server file system.", @@ -10224,7 +10305,7 @@ "Domain": "The name of the Windows domain that the FSx for Windows File Server belongs to.", "FsxFilesystemArn": "The Amazon Resource Name (ARN) for the FSx for Windows File Server file system.", "Password": "The password of the user who has the permissions to access files and folders in the FSx for Windows File Server file system.", - "SecurityGroupArns": "The Amazon Resource Names (ARNs) of the security groups that are used to configure the FSx for Windows File Server file system.\n\n*Pattern* : `^arn:(aws|aws-cn|aws-us-gov|aws-iso|aws-iso-b):ec2:[a-z\\-0-9]*:[0-9]{12}:security-group/.*$`\n\n*Length Constraints* : Maximum length of 128.", + "SecurityGroupArns": "The Amazon Resource Names (ARNs) of the security groups that are used to configure the FSx for Windows File Server file system.\n\n*Pattern* : `^arn:(aws|aws-cn|aws-us-gov|aws-iso|aws-iso-b):ec2:[a-z\\-0-9]*:[0-9]{12}:security-group/.*$`\n\n*Length constraints* : Maximum length of 128.", "Subdirectory": "A subdirectory in the location's path. This subdirectory in the Amazon FSx for Windows File Server file system is used to read data from the Amazon FSx for Windows File Server source location or write data to the FSx for Windows File Server destination.", "Tags": "The key-value pair that represents a tag that you want to add to the resource. The value can be an empty string. This value helps you manage, filter, and search for your resources. We recommend that you create a name tag for your location.", "User": "The user who has the permissions to access files and folders in the FSx for Windows File Server file system.\n\nFor information about choosing a user name that ensures sufficient permissions to files, folders, and metadata, see [user](https://docs.aws.amazon.com/datasync/latest/userguide/create-fsx-location.html#FSxWuser) ." @@ -10236,10 +10317,10 @@ "LocationUri": "The URI of the HDFS cluster location.", "Ref": "When you pass the logical ID of this resource to the intrinsic `Ref` function, `Ref` returns the location resource ARN. For example:\n\n`arn:aws:datasync:us-east-2:111222333444:location/loc-07db7abfc326c50s3`\n\nFor more information about using the `Ref` function, see [Ref](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-ref.html) ." }, - "description": "Creates an endpoint for a Hadoop Distributed File System (HDFS).", + "description": "The `AWS::DataSync::LocationHDFS` resource specifies an endpoint for a Hadoop Distributed File System (HDFS).", "properties": { "AgentArns": "The Amazon Resource Names (ARNs) of the agents that are used to connect to the HDFS cluster.", - "AuthenticationType": "The type of authentication used to determine the identity of the user.", + "AuthenticationType": "", "BlockSize": "The size of data blocks to write into the HDFS cluster. The block size must be a multiple of 512 bytes. The default block size is 128 mebibytes (MiB).", "KerberosKeytab": "The Kerberos key table (keytab) that contains mappings between the defined Kerberos principal and the encrypted keys. Provide the base64-encoded file text. If `KERBEROS` is specified for `AuthType` , this value is required.", "KerberosKrb5Conf": "The `krb5.conf` file that contains the Kerberos configuration information. You can load the `krb5.conf` by providing a string of the file's contents or an Amazon S3 presigned URL of the file. If `KERBEROS` is specified for `AuthType` , this value is required.", @@ -10334,9 +10415,9 @@ }, "AWS::DataSync::LocationS3.S3Config": { "attributes": {}, - "description": "The Amazon Resource Name (ARN) of the AWS Identity and Access Management (IAM) role that is used to access an Amazon S3 bucket.\n\nFor detailed information about using such a role, see [Creating a Location for Amazon S3](https://docs.aws.amazon.com/datasync/latest/userguide/working-with-locations.html#create-s3-location) in the *AWS DataSync User Guide* .", + "description": "The Amazon Resource Name (ARN) of the AWS Identity and Access Management (IAM) role used to access an Amazon S3 bucket.\n\nFor detailed information about using such a role, see [Creating a Location for Amazon S3](https://docs.aws.amazon.com/datasync/latest/userguide/working-with-locations.html#create-s3-location) in the *AWS DataSync User Guide* .", "properties": { - "BucketAccessRoleArn": "The Amazon S3 bucket to access. This bucket is used as a parameter in the [CreateLocationS3](https://docs.aws.amazon.com/datasync/latest/userguide/API_CreateLocationS3.html) operation." + "BucketAccessRoleArn": "The ARN of the IAM role for accessing the S3 bucket." } }, "AWS::DataSync::LocationSMB": { @@ -10366,12 +10447,13 @@ }, "AWS::DataSync::Task": { "attributes": { - "DestinationNetworkInterfaceArns": "", - "ErrorCode": "Errors that AWS DataSync encountered during execution of the task. You can use this error code to help troubleshoot issues.", + "DestinationNetworkInterfaceArns": "The ARNs of the destination elastic network interfaces (ENIs) that were created for your subnet.", + "ErrorCode": "Errors encountered during task execution. Troubleshoot issues with this error code.", "ErrorDetail": "Detailed description of an error that was encountered during the task execution. You can use this information to help troubleshoot issues.", - "Ref": "When you pass the logical ID of this resource to the intrinsic `Ref` function, `Ref` returns the location resource ARN. For example:\n\n`arn:aws:datasync:us-east-2:111222333444:location/loc-07db7abfc326c50s3`\n\nFor more information about using the `Ref` function, see [Ref](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-ref.html) .", + "Ref": "When you pass the logical ID of this resource to the intrinsic `Ref` function, `Ref` returns the location resource ARN. For example:\n\n`arn:aws:datasync:us-east-2:111222333444:task/task-07db7abfc326c50s3`\n\nFor more information about using the `Ref` function, see [Ref](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-ref.html) .", + "SourceNetworkInterfaceArns": "The ARNs of the source ENIs that were created for your subnet.", "Status": "The status of the task that was described.", - "TaskArn": "The Amazon Resource Name (ARN) of the task." + "TaskArn": "The ARN of the task." }, "description": "The `AWS::DataSync::Task` resource specifies a task. A task is a set of two locations (source and destination) and a set of `Options` that you use to control the behavior of a task. If you don't specify `Options` when you create a task, AWS DataSync populates them with service defaults.", "properties": { @@ -10738,7 +10820,7 @@ "GlobalSecondaryIndexes": "Global secondary indexes to be created on the global table. You can create up to 20 global secondary indexes. Each replica in your global table will have the same global secondary index settings. You can only create or delete one global secondary index in a single stack operation.\n\nSince the backfilling of an index could take a long time, CloudFormation does not wait for the index to become active. If a stack operation rolls back, CloudFormation might not delete an index that has been added. In that case, you will need to delete the index manually.", "KeySchema": "Specifies the attributes that make up the primary key for the table. The attributes in the `KeySchema` property must also be defined in the `AttributeDefinitions` property.", "LocalSecondaryIndexes": "Local secondary indexes to be created on the table. You can create up to five local secondary indexes. Each index is scoped to a given hash key value. The size of each hash key can be up to 10 gigabytes. Each replica in your global table will have the same local secondary index settings.", - "Replicas": "Specifies the list of replicas for your global table. The list must contain at least one element, the region where the stack defining the global table is deployed. For example, if you define your table in a stack deployed to us-east-1, you must have an entry in `Replicas` with the region us-east-1. You cannot remove the replica in the stack region.\n\n> Adding a replica might take a few minutes for an empty table, or up to several hours for large tables. If you want to add or remove a replica, we recommend submitting an `UpdateStack` operation containing only that change.\n> \n> If you add or delete a replica during an update, we recommend that you don't update any other resources. If your stack fails to update and is rolled back while adding a new replica, you might need to manually delete the replica. \n\nYou can create a new global table with up to two replicas. You can add or remove replicas after table creation, but you can only add or remove a single replica in each update.", + "Replicas": "Specifies the list of replicas for your global table. The list must contain at least one element, the region where the stack defining the global table is deployed. For example, if you define your table in a stack deployed to us-east-1, you must have an entry in `Replicas` with the region us-east-1. You cannot remove the replica in the stack region.\n\n> Adding a replica might take a few minutes for an empty table, or up to several hours for large tables. If you want to add or remove a replica, we recommend submitting an `UpdateStack` operation containing only that change.\n> \n> If you add or delete a replica during an update, we recommend that you don't update any other resources. If your stack fails to update and is rolled back while adding a new replica, you might need to manually delete the replica. \n\nYou can create a new global table with as many replicas as needed. You can add or remove replicas after table creation, but you can only add or remove a single replica in each update.", "SSESpecification": "Specifies the settings to enable server-side encryption. These settings will be applied to all replicas. If you plan to use customer-managed KMS keys, you must provide a key for each replica using the `ReplicaSpecification.ReplicaSSESpecification` property.", "StreamSpecification": "Specifies the streams settings on your global table. You must provide a value for this property if your global table contains more than one replica. You can only change the streams settings if your global table has only one replica.", "TableName": "A name for the global table. If you don't specify a name, AWS CloudFormation generates a unique ID and uses that ID as the table name. For more information, see [Name type](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-name.html) .\n\n> If you specify a name, you cannot perform updates that require replacement of this resource. You can perform updates that require no or some interruption. If you must replace the resource, specify a new name.", @@ -10847,7 +10929,7 @@ "ReadProvisionedThroughputSettings": "Defines read capacity settings for the replica table.", "Region": "The region in which this replica exists.", "SSESpecification": "Allows you to specify a customer-managed key for the replica. When using customer-managed keys for server-side encryption, this property must have a value in all replicas.", - "TableClass": "", + "TableClass": "The table class of the specified table. Valid values are `STANDARD` and `STANDARD_INFREQUENT_ACCESS` .", "Tags": "An array of key-value pairs to apply to this replica.\n\nFor more information, see [Tag](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-resource-tags.html) ." } }, @@ -11357,9 +11439,9 @@ "MemoryGiBPerVCpu": "The minimum and maximum amount of memory per vCPU, in GiB.\n\nDefault: No minimum or maximum limits", "MemoryMiB": "The minimum and maximum amount of memory, in MiB.", "NetworkInterfaceCount": "The minimum and maximum number of network interfaces.\n\nDefault: No minimum or maximum limits", - "OnDemandMaxPricePercentageOverLowestPrice": "The price protection threshold for On-Demand Instances. This is the maximum you\u2019ll pay for an On-Demand Instance, expressed as a percentage above the cheapest M, C, or R instance type with your specified attributes. When Amazon EC2 selects instance types with your attributes, it excludes instance types priced above your threshold.\n\nThe parameter accepts an integer, which Amazon EC2 interprets as a percentage.\n\nTo turn off price protection, specify a high value, such as `999999` .\n\nThis parameter is not supported for [GetSpotPlacementScores](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_GetSpotPlacementScores.html) and [GetInstanceTypesFromInstanceRequirements](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_GetInstanceTypesFromInstanceRequirements.html) .\n\nDefault: `20`", + "OnDemandMaxPricePercentageOverLowestPrice": "The price protection threshold for On-Demand Instances. This is the maximum you\u2019ll pay for an On-Demand Instance, expressed as a percentage above the cheapest M, C, or R instance type with your specified attributes. When Amazon EC2 selects instance types with your attributes, it excludes instance types priced above your threshold.\n\nThe parameter accepts an integer, which Amazon EC2 interprets as a percentage.\n\nTo turn off price protection, specify a high value, such as `999999` .\n\nThis parameter is not supported for [GetSpotPlacementScores](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_GetSpotPlacementScores.html) and [GetInstanceTypesFromInstanceRequirements](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_GetInstanceTypesFromInstanceRequirements.html) .\n\n> If you set `TargetCapacityUnitType` to `vcpu` or `memory-mib` , the price protection threshold is applied based on the per-vCPU or per-memory price instead of the per-instance price. \n\nDefault: `20`", "RequireHibernateSupport": "Indicates whether instance types must support hibernation for On-Demand Instances.\n\nThis parameter is not supported for [GetSpotPlacementScores](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_GetSpotPlacementScores.html) .\n\nDefault: `false`", - "SpotMaxPricePercentageOverLowestPrice": "The price protection threshold for Spot Instance. This is the maximum you\u2019ll pay for an Spot Instance, expressed as a percentage above the cheapest M, C, or R instance type with your specified attributes. When Amazon EC2 selects instance types with your attributes, it excludes instance types priced above your threshold.\n\nThe parameter accepts an integer, which Amazon EC2 interprets as a percentage.\n\nTo turn off price protection, specify a high value, such as `999999` .\n\nThis parameter is not supported for [GetSpotPlacementScores](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_GetSpotPlacementScores.html) and [GetInstanceTypesFromInstanceRequirements](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_GetInstanceTypesFromInstanceRequirements.html) .\n\nDefault: `100`", + "SpotMaxPricePercentageOverLowestPrice": "The price protection threshold for Spot Instance. This is the maximum you\u2019ll pay for an Spot Instance, expressed as a percentage above the cheapest M, C, or R instance type with your specified attributes. When Amazon EC2 selects instance types with your attributes, it excludes instance types priced above your threshold.\n\nThe parameter accepts an integer, which Amazon EC2 interprets as a percentage.\n\nTo turn off price protection, specify a high value, such as `999999` .\n\nThis parameter is not supported for [GetSpotPlacementScores](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_GetSpotPlacementScores.html) and [GetInstanceTypesFromInstanceRequirements](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_GetInstanceTypesFromInstanceRequirements.html) .\n\n> If you set `TargetCapacityUnitType` to `vcpu` or `memory-mib` , the price protection threshold is applied based on the per-vCPU or per-memory price instead of the per-instance price. \n\nDefault: `100`", "TotalLocalStorageGB": "The minimum and maximum amount of total local storage, in GB.\n\nDefault: No minimum or maximum limits", "VCpuCount": "The minimum and maximum number of vCPUs." } @@ -11527,7 +11609,7 @@ "description": "Specifies a VPC flow log that captures IP traffic for a specified network interface, subnet, or VPC. To view the log data, use Amazon CloudWatch Logs (CloudWatch Logs) to help troubleshoot connection issues. For example, you can use a flow log to investigate why certain traffic isn't reaching an instance, which can help you diagnose overly restrictive security group rules. For more information, see [VPC Flow Logs](https://docs.aws.amazon.com/vpc/latest/userguide/flow-logs.html) in the *Amazon VPC User Guide* .", "properties": { "DeliverLogsPermissionArn": "The ARN for the IAM role that permits Amazon EC2 to publish flow logs to a CloudWatch Logs log group in your account.\n\nIf you specify `LogDestinationType` as `s3` , do not specify `DeliverLogsPermissionArn` or `LogGroupName` .", - "DestinationOptions": "The destination options.", + "DestinationOptions": "The destination options. The following options are supported:\n\n- `FileFormat` - The format for the flow log ( `plain-text` | `parquet` ). The default is `plain-text` .\n- `HiveCompatiblePartitions` - Indicates whether to use Hive-compatible prefixes for flow logs stored in Amazon S3 ( `true` | `false` ). The default is `false` .\n- `PerHourPartition` - Indicates whether to partition the flow log per hour ( `true` | `false` ). The default is `false` .", "LogDestination": "The destination to which the flow log data is to be published. Flow log data can be published to a CloudWatch Logs log group or an Amazon S3 bucket. The value specified for this parameter depends on the value specified for `LogDestinationType` .\n\nIf `LogDestinationType` is not specified or `cloud-watch-logs` , specify the Amazon Resource Name (ARN) of the CloudWatch Logs log group. For example, to publish to a log group called `my-logs` , specify `arn:aws:logs:us-east-1:123456789012:log-group:my-logs` . Alternatively, use `LogGroupName` instead.\n\nIf LogDestinationType is `s3` , specify the ARN of the Amazon S3 bucket. You can also specify a subfolder in the bucket. To specify a subfolder in the bucket, use the following ARN format: `bucket_ARN/subfolder_name/` . For example, to specify a subfolder named `my-logs` in a bucket named `my-bucket` , use the following ARN: `arn:aws:s3:::my-bucket/my-logs/` . You cannot use `AWSLogs` as a subfolder name. This is a reserved term.", "LogDestinationType": "The type of destination to which the flow log data is to be published. Flow log data can be published to CloudWatch Logs or Amazon S3. To publish flow log data to CloudWatch Logs, specify `cloud-watch-logs` . To publish flow log data to Amazon S3, specify `s3` .\n\nIf you specify `LogDestinationType` as `s3` , do not specify `DeliverLogsPermissionArn` or `LogGroupName` .\n\nDefault: `cloud-watch-logs`", "LogFormat": "The fields to include in the flow log record, in the order in which they should appear. For a list of available fields, see [Flow Log Records](https://docs.aws.amazon.com/vpc/latest/userguide/flow-logs.html#flow-log-records) . If you omit this parameter, the flow log is created using the default format. If you specify this parameter, you must specify at least one field.\n\nSpecify the fields using the `${field-id}` format, separated by spaces.", @@ -11645,7 +11727,7 @@ "PoolCount": "The number of pools in a scope.", "Ref": "`Ref` returns the IPAM scope ID." }, - "description": "In IPAM, a scope is the highest-level container within IPAM. An IPAM contains two default scopes. Each scope represents the IP space for a single network. The private scope is intended for all private IP address space. The public scope is intended for all public IP address space. Scopes enable you to reuse IP addresses across multiple unconnected networks without causing IP address overlap or conflict.\n\nFor more information, see [How IPAM works](https://docs.aws.amazon.com//vpc/latest/ipam/how-it-works-ipam.html) in the *Amazon VPC IPAM User Guide* .", + "description": "In IPAM, a scope is the highest-level container within IPAM. An IPAM contains two default scopes. Each scope represents the IP space for a single network. The private scope is intended for all private IP address space. The public scope is intended for all public IP address space. Scopes enable you to reuse IP addresses across multiple unconnected networks without causing IP address overlap or conflict.\n\nFor more information, see [How IPAM works](https://docs.aws.amazon.com//vpc/latest/ipam/how-it-works-ipam.html) in the *Amazon VPC IPAM User Guide*", "properties": { "Description": "The description of the scope.", "IpamId": "The ID of the IPAM for which you're creating this scope.", @@ -11690,8 +11772,9 @@ "Monitoring": "Specifies whether detailed monitoring is enabled for the instance.", "NetworkInterfaces": "The network interfaces to associate with the instance.\n\n> If you use this property to point to a network interface, you must terminate the original interface before attaching a new one to allow the update of the instance to succeed.\n> \n> If this resource has a public IP address and is also in a VPC that is defined in the same template, you must use the [DependsOn Attribute](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-dependson.html) to declare a dependency on the VPC-gateway attachment.", "PlacementGroupName": "The name of an existing placement group that you want to launch the instance into (cluster | partition | spread).", + "PrivateDnsNameOptions": "The options for the instance hostname.", "PrivateIpAddress": "[EC2-VPC] The primary IPv4 address. You must specify a value from the IPv4 address range of the subnet.\n\nOnly one private IP address can be designated as primary. You can't specify this option if you've specified the option to designate a private IP address as the primary IP address in a network interface specification. You cannot specify this option if you're launching more than one instance in the request.\n\nYou cannot specify this option and the network interfaces option in the same request.\n\nIf you make an update to an instance that requires replacement, you must assign a new private IP address. During a replacement, AWS CloudFormation creates a new instance but doesn't delete the old instance until the stack has successfully updated. If the stack update fails, AWS CloudFormation uses the old instance to roll back the stack to the previous working state. The old and new instances cannot have the same private IP address.", - "PropagateTagsToVolumeOnCreation": "", + "PropagateTagsToVolumeOnCreation": "Indicates whether to assign the tags from the instance to all of the volumes attached to the instance at launch. If you specify `true` and you assign tags to the instance, those tags are automatically assigned to all of the volumes that you attach to the instance at launch. If you specify `false` , those tags are not assigned to the attached volumes.", "RamdiskId": "The ID of the RAM disk to select. Some kernels require additional drivers at launch. Check the kernel requirements for information about whether you need to specify a RAM disk. To find kernel requirements, go to the AWS Resource Center and search for the kernel ID.\n\n> We recommend that you use PV-GRUB instead of kernels and RAM disks. For more information, see [PV-GRUB](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/UserProvidedkernels.html) in the *Amazon EC2 User Guide* .", "SecurityGroupIds": "The IDs of the security groups. You can create a security group using [CreateSecurityGroup](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_CreateSecurityGroup.html) .\n\nIf you specify a network interface, you must specify any security groups as part of the network interface.", "SecurityGroups": "[EC2-Classic, default VPC] The names of the security groups. For a nondefault VPC, you must use security group IDs instead.\n\nYou cannot specify this option and the network interfaces option in the same request. The list can contain both the name of existing Amazon EC2 security groups or references to AWS::EC2::SecurityGroup resources created in the template.\n\nDefault: Amazon EC2 uses the default security group.", @@ -11806,6 +11889,7 @@ "attributes": {}, "description": "Specifies a network interface that is to be attached to an instance.\n\nYou can create a network interface when launching an instance. For an example, see the [AWS::EC2::Instance examples](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html#aws-properties-ec2-instance--examples--Automatically_assign_a_public_IP_address) .\n\nAlternatively, you can attach an existing network interface when launching an instance. For an example, see the [AWS::EC2:NetworkInterface examples](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-network-interface.html#aws-resource-ec2-network-interface--examples--Basic_network_interface) .", "properties": { + "AssociateCarrierIpAddress": "", "AssociatePublicIpAddress": "Indicates whether to assign a public IPv4 address to an instance. Applies only if creating a network interface when launching an instance. The network interface must be the primary network interface. If launching into a default subnet, the default value is `true` .", "DeleteOnTermination": "Indicates whether the network interface is deleted when the instance is terminated. Applies only if creating a network interface when launching an instance.", "Description": "The description of the network interface. Applies only if creating a network interface when launching an instance.", @@ -11825,6 +11909,15 @@ "description": "Suppresses the specified device included in the block device mapping of the AMI. To suppress a device, specify an empty string.\n\n`NoDevice` is a property of the [Amazon EC2 BlockDeviceMapping](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-blockdev-mapping.html) property.", "properties": {} }, + "AWS::EC2::Instance.PrivateDnsNameOptions": { + "attributes": {}, + "description": "The type of hostnames to assign to instances in the subnet at launch. For IPv4 only subnets, an instance DNS name must be based on the instance IPv4 address. For IPv6 only subnets, an instance DNS name must be based on the instance ID. For dual-stack subnets, you can specify whether DNS names use the instance IPv4 address or the instance ID. For more information, see [Amazon EC2 instance hostname types](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-naming.html) in the *Amazon Elastic Compute Cloud User Guide* .", + "properties": { + "EnableResourceNameDnsAAAARecord": "Indicates whether to respond to DNS queries for instance hostnames with DNS AAAA records. For more information, see [Amazon EC2 instance hostname types](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-naming.html) in the *Amazon Elastic Compute Cloud User Guide* .", + "EnableResourceNameDnsARecord": "Indicates whether to respond to DNS queries for instance hostnames with DNS A records. For more information, see [Amazon EC2 instance hostname types](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-naming.html) in the *Amazon Elastic Compute Cloud User Guide* .", + "HostnameType": "The type of hostnames to assign to instances in the subnet at launch. For IPv4 only subnets, an instance DNS name must be based on the instance IPv4 address. For IPv6 only subnets, an instance DNS name must be based on the instance ID. For dual-stack subnets, you can specify whether DNS names use the instance IPv4 address or the instance ID. For more information, see [Amazon EC2 instance hostname types](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-naming.html) in the *Amazon Elastic Compute Cloud User Guide* ." + } + }, "AWS::EC2::Instance.PrivateIpAddressSpecification": { "attributes": {}, "description": "Specifies a secondary private IPv4 address for a network interface.\n\n`PrivateIpAddressSpecification` is a property of the [AWS::EC2::NetworkInterface](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-network-interface.html) resource.", @@ -12008,9 +12101,9 @@ "MemoryGiBPerVCpu": "The minimum and maximum amount of memory per vCPU, in GiB.\n\nDefault: No minimum or maximum limits", "MemoryMiB": "The minimum and maximum amount of memory, in MiB.", "NetworkInterfaceCount": "The minimum and maximum number of network interfaces.\n\nDefault: No minimum or maximum limits", - "OnDemandMaxPricePercentageOverLowestPrice": "The price protection threshold for On-Demand Instances. This is the maximum you\u2019ll pay for an On-Demand Instance, expressed as a percentage above the cheapest M, C, or R instance type with your specified attributes. When Amazon EC2 selects instance types with your attributes, it excludes instance types priced above your threshold.\n\nThe parameter accepts an integer, which Amazon EC2 interprets as a percentage.\n\nTo turn off price protection, specify a high value, such as `999999` .\n\nThis parameter is not supported for [GetSpotPlacementScores](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_GetSpotPlacementScores.html) and [GetInstanceTypesFromInstanceRequirements](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_GetInstanceTypesFromInstanceRequirements.html) .\n\nDefault: `20`", + "OnDemandMaxPricePercentageOverLowestPrice": "The price protection threshold for On-Demand Instances. This is the maximum you\u2019ll pay for an On-Demand Instance, expressed as a percentage above the cheapest M, C, or R instance type with your specified attributes. When Amazon EC2 selects instance types with your attributes, it excludes instance types priced above your threshold.\n\nThe parameter accepts an integer, which Amazon EC2 interprets as a percentage.\n\nTo turn off price protection, specify a high value, such as `999999` .\n\nThis parameter is not supported for [GetSpotPlacementScores](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_GetSpotPlacementScores.html) and [GetInstanceTypesFromInstanceRequirements](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_GetInstanceTypesFromInstanceRequirements.html) .\n\n> If you set `TargetCapacityUnitType` to `vcpu` or `memory-mib` , the price protection threshold is applied based on the per-vCPU or per-memory price instead of the per-instance price. \n\nDefault: `20`", "RequireHibernateSupport": "Indicates whether instance types must support hibernation for On-Demand Instances.\n\nThis parameter is not supported for [GetSpotPlacementScores](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_GetSpotPlacementScores.html) .\n\nDefault: `false`", - "SpotMaxPricePercentageOverLowestPrice": "The price protection threshold for Spot Instances. This is the maximum you\u2019ll pay for a Spot Instance, expressed as a percentage above the cheapest M, C, or R instance type with your specified attributes. When Amazon EC2 selects instance types with your attributes, it excludes instance types priced above your threshold.\n\nThe parameter accepts an integer, which Amazon EC2 interprets as a percentage.\n\nTo turn off price protection, specify a high value, such as `999999` .\n\nThis parameter is not supported for [GetSpotPlacementScores](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_GetSpotPlacementScores.html) and [GetInstanceTypesFromInstanceRequirements](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_GetInstanceTypesFromInstanceRequirements.html) .\n\nDefault: `100`", + "SpotMaxPricePercentageOverLowestPrice": "The price protection threshold for Spot Instances. This is the maximum you\u2019ll pay for a Spot Instance, expressed as a percentage above the cheapest M, C, or R instance type with your specified attributes. When Amazon EC2 selects instance types with your attributes, it excludes instance types priced above your threshold.\n\nThe parameter accepts an integer, which Amazon EC2 interprets as a percentage.\n\nTo turn off price protection, specify a high value, such as `999999` .\n\nThis parameter is not supported for [GetSpotPlacementScores](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_GetSpotPlacementScores.html) and [GetInstanceTypesFromInstanceRequirements](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_GetInstanceTypesFromInstanceRequirements.html) .\n\n> If you set `TargetCapacityUnitType` to `vcpu` or `memory-mib` , the price protection threshold is applied based on the per-vCPU or per-memory price instead of the per-instance price. \n\nDefault: `100`", "TotalLocalStorageGB": "The minimum and maximum amount of total local storage, in GB.\n\nDefault: No minimum or maximum limits", "VCpuCount": "The minimum and maximum number of vCPUs." } @@ -12163,7 +12256,7 @@ "properties": { "EnableResourceNameDnsAAAARecord": "Indicates whether to respond to DNS queries for instance hostnames with DNS AAAA records.", "EnableResourceNameDnsARecord": "Indicates whether to respond to DNS queries for instance hostnames with DNS A records.", - "HostnameType": "The type of hostname for Amazon EC2 instances. For IPv4 only subnets, an instance DNS name must be based on the instance IPv4 address. For IPv6 native subnets, an instance DNS name must be based on the instance ID. For dual-stack subnets, you can specify whether DNS names use the instance IPv4 address or the instance ID." + "HostnameType": "The type of hostname for EC2 instances. For IPv4 only subnets, an instance DNS name must be based on the instance IPv4 address. For IPv6 only subnets, an instance DNS name must be based on the instance ID. For dual-stack subnets, you can specify whether DNS names use the instance IPv4 address or the instance ID. For more information, see [Amazon EC2 instance hostname types](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-naming.html) in the *Amazon Elastic Compute Cloud User Guide* ." } }, "AWS::EC2::LaunchTemplate.PrivateIpAdd": { @@ -12301,7 +12394,7 @@ "Ref": "`Ref` returns the ID of the network insights scope.", "UpdatedDate": "The last updated date." }, - "description": "Describes a Network Access Scope.", + "description": "Describes a Network Access Scope. A Network Access Scope defines outbound (egress) and inbound (ingress) traffic patterns, including sources, destinations, paths, and traffic types.\n\nNetwork Access Analyzer identifies unintended network access to your resources on AWS . When you start an analysis on a Network Access Scope, Network Access Analyzer produces findings. For more information, see the [Network Access Analyzer User Guide](https://docs.aws.amazon.com/vpc/latest/network-access-analyzer/) .", "properties": { "ExcludePaths": "The paths to exclude.", "MatchPaths": "The paths to match.", @@ -12915,9 +13008,9 @@ "MemoryGiBPerVCpu": "The minimum and maximum amount of memory per vCPU, in GiB.\n\nDefault: No minimum or maximum limits", "MemoryMiB": "The minimum and maximum amount of memory, in MiB.", "NetworkInterfaceCount": "The minimum and maximum number of network interfaces.\n\nDefault: No minimum or maximum limits", - "OnDemandMaxPricePercentageOverLowestPrice": "The price protection threshold for On-Demand Instances. This is the maximum you\u2019ll pay for an On-Demand Instance, expressed as a percentage above the cheapest M, C, or R instance type with your specified attributes. When Amazon EC2 selects instance types with your attributes, it excludes instance types priced above your threshold.\n\nThe parameter accepts an integer, which Amazon EC2 interprets as a percentage.\n\nTo turn off price protection, specify a high value, such as `999999` .\n\nThis parameter is not supported for [GetSpotPlacementScores](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_GetSpotPlacementScores.html) and [GetInstanceTypesFromInstanceRequirements](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_GetInstanceTypesFromInstanceRequirements.html) .\n\nDefault: `20`", + "OnDemandMaxPricePercentageOverLowestPrice": "The price protection threshold for On-Demand Instances. This is the maximum you\u2019ll pay for an On-Demand Instance, expressed as a percentage above the cheapest M, C, or R instance type with your specified attributes. When Amazon EC2 selects instance types with your attributes, it excludes instance types priced above your threshold.\n\nThe parameter accepts an integer, which Amazon EC2 interprets as a percentage.\n\nTo turn off price protection, specify a high value, such as `999999` .\n\nThis parameter is not supported for [GetSpotPlacementScores](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_GetSpotPlacementScores.html) and [GetInstanceTypesFromInstanceRequirements](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_GetInstanceTypesFromInstanceRequirements.html) .\n\n> If you set `TargetCapacityUnitType` to `vcpu` or `memory-mib` , the price protection threshold is applied based on the per-vCPU or per-memory price instead of the per-instance price. \n\nDefault: `20`", "RequireHibernateSupport": "Indicates whether instance types must support hibernation for On-Demand Instances.\n\nThis parameter is not supported for [GetSpotPlacementScores](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_GetSpotPlacementScores.html) .\n\nDefault: `false`", - "SpotMaxPricePercentageOverLowestPrice": "The price protection threshold for Spot Instance. This is the maximum you\u2019ll pay for an Spot Instance, expressed as a percentage above the cheapest M, C, or R instance type with your specified attributes. When Amazon EC2 selects instance types with your attributes, it excludes instance types priced above your threshold.\n\nThe parameter accepts an integer, which Amazon EC2 interprets as a percentage.\n\nTo turn off price protection, specify a high value, such as `999999` .\n\nThis parameter is not supported for [GetSpotPlacementScores](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_GetSpotPlacementScores.html) and [GetInstanceTypesFromInstanceRequirements](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_GetInstanceTypesFromInstanceRequirements.html) .\n\nDefault: `100`", + "SpotMaxPricePercentageOverLowestPrice": "The price protection threshold for Spot Instance. This is the maximum you\u2019ll pay for an Spot Instance, expressed as a percentage above the cheapest M, C, or R instance type with your specified attributes. When Amazon EC2 selects instance types with your attributes, it excludes instance types priced above your threshold.\n\nThe parameter accepts an integer, which Amazon EC2 interprets as a percentage.\n\nTo turn off price protection, specify a high value, such as `999999` .\n\nThis parameter is not supported for [GetSpotPlacementScores](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_GetSpotPlacementScores.html) and [GetInstanceTypesFromInstanceRequirements](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_GetInstanceTypesFromInstanceRequirements.html) .\n\n> If you set `TargetCapacityUnitType` to `vcpu` or `memory-mib` , the price protection threshold is applied based on the per-vCPU or per-memory price instead of the per-instance price. \n\nDefault: `100`", "TotalLocalStorageGB": "The minimum and maximum amount of total local storage, in GB.\n\nDefault: No minimum or maximum limits", "VCpuCount": "The minimum and maximum number of vCPUs." } @@ -12937,6 +13030,7 @@ "AvailabilityZone": "The Availability Zone in which to launch the instances.", "InstanceRequirements": "The instance requirements. When you specify instance requirements, Amazon EC2 will identify instance types with the provided requirements, and then use your On-Demand and Spot allocation strategies to launch instances from these instance types, in the same way as when you specify a list of instance types.\n\n> If you specify `InstanceRequirements` , you can't specify `InstanceTypes` .", "InstanceType": "The instance type.", + "Priority": "The priority for the launch template override. The highest priority is launched first.\n\nIf `OnDemandAllocationStrategy` is set to `prioritized` , Spot Fleet uses priority to determine which launch template override to use first in fulfilling On-Demand capacity.\n\nIf the Spot `AllocationStrategy` is set to `capacityOptimizedPrioritized` , Spot Fleet uses priority on a best-effort basis to determine which launch template override to use in fulfilling Spot capacity, but optimizes for capacity first.\n\nValid values are whole numbers starting at `0` . The lower the number, the higher the priority. If no number is set, the launch template override has the lowest priority. You can set the same priority for different launch template overrides.", "SpotPrice": "The maximum price per unit hour that you are willing to pay for a Spot Instance.", "SubnetId": "The ID of the subnet in which to launch the instances.", "WeightedCapacity": "The number of units provided by the specified instance type." @@ -13522,7 +13616,7 @@ "attributes": { "Ref": "`Ref` returns the ID of the VPC endpoint service configuration." }, - "description": "Creates a VPC endpoint service configuration to which service consumers ( AWS accounts, IAM users, and IAM roles) can connect.\n\nTo create an endpoint service configuration, you must first create one of the following for your service:\n\n- A [Network Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/introduction.html) . Service consumers connect to your service using an interface endpoint.\n- A [Gateway Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/gateway/introduction.html) . Service consumers connect to your service using a Gateway Load Balancer endpoint.\n\nFor more information, see [VPC Endpoint Services](https://docs.aws.amazon.com/vpc/latest/userguide/endpoint-service.html) in the *Amazon Virtual Private Cloud User Guide* .", + "description": "Creates a VPC endpoint service configuration to which service consumers ( AWS accounts, IAM users, and IAM roles) can connect.\n\nTo create an endpoint service configuration, you must first create one of the following for your service:\n\n- A [Network Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/introduction.html) . Service consumers connect to your service using an interface endpoint.\n- A [Gateway Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/gateway/introduction.html) . Service consumers connect to your service using a Gateway Load Balancer endpoint.\n\nFor more information, see the [AWS PrivateLink User Guide](https://docs.aws.amazon.com/vpc/latest/privatelink/) .", "properties": { "AcceptanceRequired": "Indicates whether requests from service consumers to create an endpoint to your service must be accepted.", "GatewayLoadBalancerArns": "The Amazon Resource Names (ARNs) of one or more Gateway Load Balancers.", @@ -13662,6 +13756,16 @@ "Tags": "An array of key-value pairs to apply to this resource." } }, + "AWS::ECR::PullThroughCacheRule": { + "attributes": { + "RegistryId": "The account ID of the private registry." + }, + "description": "Creates a pull through cache rule. A pull through cache rule provides a way to cache images from an external public registry in your Amazon ECR private registry.", + "properties": { + "EcrRepositoryPrefix": "The Amazon ECR repository prefix associated with the pull through cache rule.", + "UpstreamRegistryUrl": "The upstream registry URL associated with the pull through cache rule." + } + }, "AWS::ECR::RegistryPolicy": { "attributes": { "RegistryId": "The account ID of the private registry the policy is associated with." @@ -13778,7 +13882,7 @@ "InstanceWarmupPeriod": "The period of time, in seconds, after a newly launched Amazon EC2 instance can contribute to CloudWatch metrics for Auto Scaling group. If this parameter is omitted, the default value of `300` seconds is used.", "MaximumScalingStepSize": "The maximum number of container instances that Amazon ECS scales in or scales out at one time. If this parameter is omitted, the default value of `10000` is used.", "MinimumScalingStepSize": "The minimum number of container instances that Amazon ECS scales in or scales out at one time. If this parameter is omitted, the default value of `1` is used.", - "Status": "Determines whether to enable managed scaling for the capacity provider.", + "Status": "Determines whether to use managed scaling for the capacity provider.", "TargetCapacity": "The target capacity value for the capacity provider. The specified value must be greater than `0` and less than or equal to `100` . A value of `100` results in the Amazon EC2 instances in your Auto Scaling group being completely used." } }, @@ -13815,7 +13919,7 @@ }, "AWS::ECS::Cluster.ClusterSettings": { "attributes": {}, - "description": "The settings to use when creating a cluster. This parameter is used to enable CloudWatch Container Insights for a cluster.", + "description": "The settings to use when creating a cluster. This parameter is used to turn on CloudWatch Container Insights for a cluster.", "properties": { "Name": "The name of the cluster setting. The only supported value is `containerInsights` .", "Value": "The value to set for the cluster setting. The supported values are `enabled` and `disabled` . If `enabled` is specified, CloudWatch Container Insights will be enabled for the cluster, otherwise it will be disabled unless the `containerInsights` account setting is enabled. If a cluster value is specified, it will override the `containerInsights` value set with [PutAccountSetting](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_PutAccountSetting.html) or [PutAccountSettingDefault](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_PutAccountSettingDefault.html) ." @@ -13834,7 +13938,7 @@ "attributes": {}, "description": "The log configuration for the results of the execute command actions. The logs can be sent to CloudWatch Logs or an Amazon S3 bucket.", "properties": { - "CloudWatchEncryptionEnabled": "Determines whether to enable encryption on the CloudWatch logs. If not specified, encryption will be disabled.", + "CloudWatchEncryptionEnabled": "Determines whether to use encryption on the CloudWatch logs. If not specified, encryption will be disabled.", "CloudWatchLogGroupName": "The name of the CloudWatch log group to send logs to.\n\n> The CloudWatch log group must already be created.", "S3BucketName": "The name of the S3 bucket to send logs to.\n\n> The S3 bucket must already be created.", "S3EncryptionEnabled": "Determines whether to use encryption on the S3 logs. If not specified, encryption is not used.", @@ -13885,7 +13989,7 @@ "DeploymentConfiguration": "Optional deployment parameters that control how many tasks run during the deployment and the ordering of stopping and starting tasks.", "DeploymentController": "The deployment controller to use for the service. If no deployment controller is specified, the default value of `ECS` is used.", "DesiredCount": "The number of instantiations of the specified task definition to place and keep running on your cluster.\n\nFor new services, if a desired count is not specified, a default value of `1` is used. When using the `DAEMON` scheduling strategy, the desired count is not required.\n\nFor existing services, if a desired count is not specified, it is omitted from the operation.", - "EnableECSManagedTags": "Specifies whether to enable Amazon ECS managed tags for the tasks within the service. For more information, see [Tagging Your Amazon ECS Resources](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-using-tags.html) in the *Amazon Elastic Container Service Developer Guide* .", + "EnableECSManagedTags": "Specifies whether to turn on Amazon ECS managed tags for the tasks within the service. For more information, see [Tagging Your Amazon ECS Resources](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-using-tags.html) in the *Amazon Elastic Container Service Developer Guide* .", "EnableExecuteCommand": "Determines whether the execute command functionality is enabled for the service. If `true` , the execute command functionality is enabled for all containers in tasks as part of the service.", "HealthCheckGracePeriodSeconds": "The period of time, in seconds, that the Amazon ECS service scheduler ignores unhealthy Elastic Load Balancing target health checks after a task has first started. This is only used when your service is configured to use a load balancer. If your service has a load balancer defined and you don't specify a health check grace period value, the default value of `0` is used.\n\nIf you do not use an Elastic Load Balancing, we recomend that you use the `startPeriod` in the task definition healtch check parameters. For more information, see [Health check](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_HealthCheck.html) .\n\nIf your service's tasks take a while to start and respond to Elastic Load Balancing health checks, you can specify a health check grace period of up to 2,147,483,647 seconds (about 69 years). During that time, the Amazon ECS service scheduler ignores health check status. This grace period can prevent the service scheduler from marking tasks as unhealthy and stopping them before they have time to come up.", "LaunchType": "The launch type on which to run your service. For more information, see [Amazon ECS Launch Types](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/launch_types.html) in the *Amazon Elastic Container Service Developer Guide* .", @@ -13925,8 +14029,8 @@ "attributes": {}, "description": "> The deployment circuit breaker can only be used for services using the rolling update ( `ECS` ) deployment type. \n\nThe `DeploymentCircuitBreaker` property determines whether a service deployment will fail if the service can't reach a steady state. If deployment circuit breaker is enabled, a service deployment will transition to a failed state and stop launching new tasks. If rollback is enabled, when a service deployment fails, the service is rolled back to the last deployment that completed successfully.", "properties": { - "Enable": "Determines whether to enable the deployment circuit breaker logic for the service.", - "Rollback": "Determines whether to enable Amazon ECS to roll back the service if a service deployment fails. If rollback is enabled, when a service deployment fails, the service is rolled back to the last deployment that completed successfully." + "Enable": "Determines whether to use the deployment circuit breaker logic for the service.", + "Rollback": "Determines whether to configure Amazon ECS to roll back the service if a service deployment fails. If rollback is enabled, when a service deployment fails, the service is rolled back to the last deployment that completed successfully." } }, "AWS::ECS::Service.DeploymentConfiguration": { @@ -14027,7 +14131,7 @@ "properties": { "Command": "The command that's passed to the container. This parameter maps to `Cmd` in the [Create a container](https://docs.aws.amazon.com/https://docs.docker.com/engine/api/v1.35/#operation/ContainerCreate) section of the [Docker Remote API](https://docs.aws.amazon.com/https://docs.docker.com/engine/api/v1.35/) and the `COMMAND` parameter to [docker run](https://docs.aws.amazon.com/https://docs.docker.com/engine/reference/run/#security-configuration) . For more information, see [https://docs.docker.com/engine/reference/builder/#cmd](https://docs.aws.amazon.com/https://docs.docker.com/engine/reference/builder/#cmd) . If there are multiple arguments, each argument is a separated string in the array.", "Cpu": "The number of `cpu` units reserved for the container. This parameter maps to `CpuShares` in the [Create a container](https://docs.aws.amazon.com/https://docs.docker.com/engine/api/v1.35/#operation/ContainerCreate) section of the [Docker Remote API](https://docs.aws.amazon.com/https://docs.docker.com/engine/api/v1.35/) and the `--cpu-shares` option to [docker run](https://docs.aws.amazon.com/https://docs.docker.com/engine/reference/run/#security-configuration) .\n\nThis field is optional for tasks using the Fargate launch type, and the only requirement is that the total amount of CPU reserved for all containers within a task be lower than the task-level `cpu` value.\n\n> You can determine the number of CPU units that are available per EC2 instance type by multiplying the vCPUs listed for that instance type on the [Amazon EC2 Instances](https://docs.aws.amazon.com/ec2/instance-types/) detail page by 1,024. \n\nLinux containers share unallocated CPU units with other containers on the container instance with the same ratio as their allocated amount. For example, if you run a single-container task on a single-core instance type with 512 CPU units specified for that container, and that's the only task running on the container instance, that container could use the full 1,024 CPU unit share at any given time. However, if you launched another copy of the same task on that container instance, each task is guaranteed a minimum of 512 CPU units when needed. Moreover, each container could float to higher CPU usage if the other container was not using it. If both tasks were 100% active all of the time, they would be limited to 512 CPU units.\n\nOn Linux container instances, the Docker daemon on the container instance uses the CPU value to calculate the relative CPU share ratios for running containers. For more information, see [CPU share constraint](https://docs.aws.amazon.com/https://docs.docker.com/engine/reference/run/#cpu-share-constraint) in the Docker documentation. The minimum valid CPU share value that the Linux kernel allows is 2. However, the CPU parameter isn't required, and you can use CPU values below 2 in your container definitions. For CPU values below 2 (including null), the behavior varies based on your Amazon ECS container agent version:\n\n- *Agent versions less than or equal to 1.1.0:* Null and zero CPU values are passed to Docker as 0, which Docker then converts to 1,024 CPU shares. CPU values of 1 are passed to Docker as 1, which the Linux kernel converts to two CPU shares.\n- *Agent versions greater than or equal to 1.2.0:* Null, zero, and CPU values of 1 are passed to Docker as 2.\n\nOn Windows container instances, the CPU limit is enforced as an absolute limit, or a quota. Windows containers only have access to the specified amount of CPU that's described in the task definition. A null or zero CPU value is passed to Docker as `0` , which Windows interprets as 1% of one CPU.", - "DependsOn": "The dependencies defined for container startup and shutdown. A container can contain multiple dependencies. When a dependency is defined for container startup, for container shutdown it is reversed.\n\nFor tasks using the EC2 launch type, the container instances require at least version 1.26.0 of the container agent to enable container dependencies. However, we recommend using the latest container agent version. For information about checking your agent version and updating to the latest version, see [Updating the Amazon ECS Container Agent](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-agent-update.html) in the *Amazon Elastic Container Service Developer Guide* . If you're using an Amazon ECS-optimized Linux AMI, your instance needs at least version 1.26.0-1 of the `ecs-init` package. If your container instances are launched from version `20190301` or later, then they contain the required versions of the container agent and `ecs-init` . For more information, see [Amazon ECS-optimized Linux AMI](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-optimized_AMI.html) in the *Amazon Elastic Container Service Developer Guide* .\n\nFor tasks using the Fargate launch type, the task or service requires the following platforms:\n\n- Linux platform version `1.3.0` or later.\n- Windows platform version `1.0.0` or later.", + "DependsOn": "The dependencies defined for container startup and shutdown. A container can contain multiple dependencies. When a dependency is defined for container startup, for container shutdown it is reversed.\n\nFor tasks using the EC2 launch type, the container instances require at least version 1.26.0 of the container agent to turn on container dependencies. However, we recommend using the latest container agent version. For information about checking your agent version and updating to the latest version, see [Updating the Amazon ECS Container Agent](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-agent-update.html) in the *Amazon Elastic Container Service Developer Guide* . If you're using an Amazon ECS-optimized Linux AMI, your instance needs at least version 1.26.0-1 of the `ecs-init` package. If your container instances are launched from version `20190301` or later, then they contain the required versions of the container agent and `ecs-init` . For more information, see [Amazon ECS-optimized Linux AMI](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-optimized_AMI.html) in the *Amazon Elastic Container Service Developer Guide* .\n\nFor tasks using the Fargate launch type, the task or service requires the following platforms:\n\n- Linux platform version `1.3.0` or later.\n- Windows platform version `1.0.0` or later.", "DisableNetworking": "When this parameter is true, networking is disabled within the container. This parameter maps to `NetworkDisabled` in the [Create a container](https://docs.aws.amazon.com/https://docs.docker.com/engine/api/v1.35/#operation/ContainerCreate) section of the [Docker Remote API](https://docs.aws.amazon.com/https://docs.docker.com/engine/api/v1.35/) .\n\n> This parameter is not supported for Windows containers.", "DnsSearchDomains": "A list of DNS search domains that are presented to the container. This parameter maps to `DnsSearch` in the [Create a container](https://docs.aws.amazon.com/https://docs.docker.com/engine/api/v1.35/#operation/ContainerCreate) section of the [Docker Remote API](https://docs.aws.amazon.com/https://docs.docker.com/engine/api/v1.35/) and the `--dns-search` option to [docker run](https://docs.aws.amazon.com/https://docs.docker.com/engine/reference/run/#security-configuration) .\n\n> This parameter is not supported for Windows containers.", "DnsServers": "A list of DNS servers that are presented to the container. This parameter maps to `Dns` in the [Create a container](https://docs.aws.amazon.com/https://docs.docker.com/engine/api/v1.35/#operation/ContainerCreate) section of the [Docker Remote API](https://docs.aws.amazon.com/https://docs.docker.com/engine/api/v1.35/) and the `--dns` option to [docker run](https://docs.aws.amazon.com/https://docs.docker.com/engine/reference/run/#security-configuration) .\n\n> This parameter is not supported for Windows containers.", @@ -14057,8 +14161,8 @@ "RepositoryCredentials": "The private repository authentication credentials to use.", "ResourceRequirements": "The type and amount of a resource to assign to a container. The only supported resource is a GPU.", "Secrets": "The secrets to pass to the container. For more information, see [Specifying Sensitive Data](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/specifying-sensitive-data.html) in the *Amazon Elastic Container Service Developer Guide* .", - "StartTimeout": "Time duration (in seconds) to wait before giving up on resolving dependencies for a container. For example, you specify two containers in a task definition with containerA having a dependency on containerB reaching a `COMPLETE` , `SUCCESS` , or `HEALTHY` status. If a `startTimeout` value is specified for containerB and it doesn't reach the desired status within that time then containerA gives up and not start. This results in the task transitioning to a `STOPPED` state.\n\n> When the `ECS_CONTAINER_START_TIMEOUT` container agent configuration variable is used, it's enforced independently from this start timeout value. \n\nFor tasks using the Fargate launch type, the task or service requires the following platforms:\n\n- Linux platform version `1.3.0` or later.\n- Windows platform version `1.0.0` or later.\n\nFor tasks using the EC2 launch type, your container instances require at least version `1.26.0` of the container agent to enable a container start timeout value. However, we recommend using the latest container agent version. For information about checking your agent version and updating to the latest version, see [Updating the Amazon ECS Container Agent](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-agent-update.html) in the *Amazon Elastic Container Service Developer Guide* . If you're using an Amazon ECS-optimized Linux AMI, your instance needs at least version `1.26.0-1` of the `ecs-init` package. If your container instances are launched from version `20190301` or later, then they contain the required versions of the container agent and `ecs-init` . For more information, see [Amazon ECS-optimized Linux AMI](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-optimized_AMI.html) in the *Amazon Elastic Container Service Developer Guide* .", - "StopTimeout": "Time duration (in seconds) to wait before the container is forcefully killed if it doesn't exit normally on its own.\n\nFor tasks using the Fargate launch type, the task or service requires the following platforms:\n\n- Linux platform version `1.3.0` or later.\n- Windows platform version `1.0.0` or later.\n\nThe max stop timeout value is 120 seconds and if the parameter is not specified, the default value of 30 seconds is used.\n\nFor tasks that use the EC2 launch type, if the `stopTimeout` parameter isn't specified, the value set for the Amazon ECS container agent configuration variable `ECS_CONTAINER_STOP_TIMEOUT` is used. If neither the `stopTimeout` parameter or the `ECS_CONTAINER_STOP_TIMEOUT` agent configuration variable are set, then the default values of 30 seconds for Linux containers and 30 seconds on Windows containers are used. Your container instances require at least version 1.26.0 of the container agent to enable a container stop timeout value. However, we recommend using the latest container agent version. For information about checking your agent version and updating to the latest version, see [Updating the Amazon ECS Container Agent](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-agent-update.html) in the *Amazon Elastic Container Service Developer Guide* . If you're using an Amazon ECS-optimized Linux AMI, your instance needs at least version 1.26.0-1 of the `ecs-init` package. If your container instances are launched from version `20190301` or later, then they contain the required versions of the container agent and `ecs-init` . For more information, see [Amazon ECS-optimized Linux AMI](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-optimized_AMI.html) in the *Amazon Elastic Container Service Developer Guide* .", + "StartTimeout": "Time duration (in seconds) to wait before giving up on resolving dependencies for a container. For example, you specify two containers in a task definition with containerA having a dependency on containerB reaching a `COMPLETE` , `SUCCESS` , or `HEALTHY` status. If a `startTimeout` value is specified for containerB and it doesn't reach the desired status within that time then containerA gives up and not start. This results in the task transitioning to a `STOPPED` state.\n\n> When the `ECS_CONTAINER_START_TIMEOUT` container agent configuration variable is used, it's enforced independently from this start timeout value. \n\nFor tasks using the Fargate launch type, the task or service requires the following platforms:\n\n- Linux platform version `1.3.0` or later.\n- Windows platform version `1.0.0` or later.\n\nFor tasks using the EC2 launch type, your container instances require at least version `1.26.0` of the container agent to use a container start timeout value. However, we recommend using the latest container agent version. For information about checking your agent version and updating to the latest version, see [Updating the Amazon ECS Container Agent](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-agent-update.html) in the *Amazon Elastic Container Service Developer Guide* . If you're using an Amazon ECS-optimized Linux AMI, your instance needs at least version `1.26.0-1` of the `ecs-init` package. If your container instances are launched from version `20190301` or later, then they contain the required versions of the container agent and `ecs-init` . For more information, see [Amazon ECS-optimized Linux AMI](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-optimized_AMI.html) in the *Amazon Elastic Container Service Developer Guide* .", + "StopTimeout": "Time duration (in seconds) to wait before the container is forcefully killed if it doesn't exit normally on its own.\n\nFor tasks using the Fargate launch type, the task or service requires the following platforms:\n\n- Linux platform version `1.3.0` or later.\n- Windows platform version `1.0.0` or later.\n\nThe max stop timeout value is 120 seconds and if the parameter is not specified, the default value of 30 seconds is used.\n\nFor tasks that use the EC2 launch type, if the `stopTimeout` parameter isn't specified, the value set for the Amazon ECS container agent configuration variable `ECS_CONTAINER_STOP_TIMEOUT` is used. If neither the `stopTimeout` parameter or the `ECS_CONTAINER_STOP_TIMEOUT` agent configuration variable are set, then the default values of 30 seconds for Linux containers and 30 seconds on Windows containers are used. Your container instances require at least version 1.26.0 of the container agent to use a container stop timeout value. However, we recommend using the latest container agent version. For information about checking your agent version and updating to the latest version, see [Updating the Amazon ECS Container Agent](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-agent-update.html) in the *Amazon Elastic Container Service Developer Guide* . If you're using an Amazon ECS-optimized Linux AMI, your instance needs at least version 1.26.0-1 of the `ecs-init` package. If your container instances are launched from version `20190301` or later, then they contain the required versions of the container agent and `ecs-init` . For more information, see [Amazon ECS-optimized Linux AMI](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-optimized_AMI.html) in the *Amazon Elastic Container Service Developer Guide* .", "SystemControls": "A list of namespaced kernel parameters to set in the container. This parameter maps to `Sysctls` in the [Create a container](https://docs.aws.amazon.com/https://docs.docker.com/engine/api/v1.35/#operation/ContainerCreate) section of the [Docker Remote API](https://docs.aws.amazon.com/https://docs.docker.com/engine/api/v1.35/) and the `--sysctl` option to [docker run](https://docs.aws.amazon.com/https://docs.docker.com/engine/reference/run/#security-configuration) .\n\n> We don't recommended that you specify network-related `systemControls` parameters for multiple containers in a single task that also uses either the `awsvpc` or `host` network modes. For tasks that use the `awsvpc` network mode, the container that's started last determines which `systemControls` parameters take effect. For tasks that use the `host` network mode, it changes the container instance's namespaced kernel parameters as well as the containers.", "Ulimits": "A list of `ulimits` to set in the container. This parameter maps to `Ulimits` in the [Create a container](https://docs.aws.amazon.com/https://docs.docker.com/engine/api/v1.35/#operation/ContainerCreate) section of the [Docker Remote API](https://docs.aws.amazon.com/https://docs.docker.com/engine/api/v1.35/) and the `--ulimit` option to [docker run](https://docs.aws.amazon.com/https://docs.docker.com/engine/reference/run/) . Valid naming values are displayed in the [Ulimit](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_Ulimit.html) data type. This parameter requires version 1.18 of the Docker Remote API or greater on your container instance. To check the Docker Remote API version on your container instance, log in to your container instance and run the following command: `sudo docker version --format '{{.Server.APIVersion}}'`\n\n> This parameter is not supported for Windows containers.", "User": "The user to use inside the container. This parameter maps to `User` in the [Create a container](https://docs.aws.amazon.com/https://docs.docker.com/engine/api/v1.35/#operation/ContainerCreate) section of the [Docker Remote API](https://docs.aws.amazon.com/https://docs.docker.com/engine/api/v1.35/) and the `--user` option to [docker run](https://docs.aws.amazon.com/https://docs.docker.com/engine/reference/run/#security-configuration) .\n\n> When running tasks using the `host` network mode, don't run containers using the root user (UID 0). We recommend using a non-root user for better security. \n\nYou can specify the `user` using the following formats. If specifying a UID or GID, you must specify it as a positive integer.\n\n- `user`\n- `user:group`\n- `uid`\n- `uid:gid`\n- `user:gid`\n- `uid:group`\n\n> This parameter is not supported for Windows containers.", @@ -14101,7 +14205,7 @@ "AuthorizationConfig": "The authorization configuration details for the Amazon EFS file system.", "FilesystemId": "The Amazon EFS file system ID to use.", "RootDirectory": "The directory within the Amazon EFS file system to mount as the root directory inside the host. If this parameter is omitted, the root of the Amazon EFS volume will be used. Specifying `/` will have the same effect as omitting this parameter.\n\n> If an EFS access point is specified in the `authorizationConfig` , the root directory parameter must either be omitted or set to `/` which will enforce the path set on the EFS access point.", - "TransitEncryption": "Determines whether to enable encryption for Amazon EFS data in transit between the Amazon ECS host and the Amazon EFS server. Transit encryption must be enabled if Amazon EFS IAM authorization is used. If this parameter is omitted, the default value of `DISABLED` is used. For more information, see [Encrypting Data in Transit](https://docs.aws.amazon.com/efs/latest/ug/encryption-in-transit.html) in the *Amazon Elastic File System User Guide* .", + "TransitEncryption": "Determines whether to use encryption for Amazon EFS data in transit between the Amazon ECS host and the Amazon EFS server. Transit encryption must be enabled if Amazon EFS IAM authorization is used. If this parameter is omitted, the default value of `DISABLED` is used. For more information, see [Encrypting Data in Transit](https://docs.aws.amazon.com/efs/latest/ug/encryption-in-transit.html) in the *Amazon Elastic File System User Guide* .", "TransitEncryptionPort": "The port to use when sending encrypted data between the Amazon ECS host and the Amazon EFS server. If you do not specify a transit encryption port, it will use the port selection strategy that the Amazon EFS mount helper uses. For more information, see [EFS Mount Helper](https://docs.aws.amazon.com/efs/latest/ug/efs-mount-helper.html) in the *Amazon Elastic File System User Guide* ." } }, @@ -14365,7 +14469,7 @@ }, "AWS::ECS::TaskSet.ServiceRegistry": { "attributes": {}, - "description": "The details for the service registry.", + "description": "The details for the service registry.\n\nEach service may be associated with one service registry. Multiple service registries for each service are not supported.\n\nWhen you add, update, or remove the service registries configuration, Amazon ECS starts a new deployment. New tasks are registered and deregistered to the updated service registry configuration.", "properties": { "ContainerName": "The container name value to be used for your service discovery service. It's already specified in the task definition. If the task definition that your service task specifies uses the `bridge` or `host` network mode, you must specify a `containerName` and `containerPort` combination from the task definition. If the task definition that your service task specifies uses the `awsvpc` network mode and a type SRV DNS record is used, you must specify either a `containerName` and `containerPort` combination or a `port` value. However, you can't specify both.", "ContainerPort": "The port value to be used for your service discovery service. It's already specified in the task definition. If the task definition your service task specifies uses the `bridge` or `host` network mode, you must specify a `containerName` and `containerPort` combination from the task definition. If the task definition your service task specifies uses the `awsvpc` network mode and a type SRV DNS record is used, you must specify either a `containerName` and `containerPort` combination or a `port` value. However, you can't specify both.", @@ -14483,7 +14587,7 @@ "AWS::EKS::Addon": { "attributes": { "Arn": "The ARN of the add-on, such as `arn:aws:eks:us-west-2:111122223333:addon/1-19/vpc-cni/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx` .", - "Ref": "`Ref` returns the resource name. For example:\n\n`{ \"Ref\": \"vpc-cni\" }`\n\nFor the add-on `vpc-cni` , `Ref` returns the name of the add-on. For example, `|` ." + "Ref": "`Ref` returns the resource name. For example:\n\n`{ \"Ref\": \"vpc-cni\" }`\n\nFor the add-on `vpc-cni` , `Ref` returns the name of the add-on. For example, `cluster-name|vpc-cni` ." }, "description": "Creates an Amazon EKS add-on.\n\nAmazon EKS add-ons help to automate the provisioning and lifecycle management of common operational software for Amazon EKS clusters. Amazon EKS add-ons require clusters running version 1.18 or later because Amazon EKS add-ons rely on the Server-side Apply Kubernetes feature, which is only available in Kubernetes 1.18 and later. For more information, see [Amazon EKS add-ons](https://docs.aws.amazon.com/eks/latest/userguide/eks-add-ons.html) in the *Amazon EKS User Guide* .", "properties": { @@ -14503,7 +14607,7 @@ "EncryptionConfigKeyArn": "Amazon Resource Name (ARN) or alias of the customer master key (CMK).", "Endpoint": "The endpoint for your Kubernetes API server, such as `https://5E1D0CEXAMPLEA591B746AFC5AB30262.yl4.us-west-2.eks.amazonaws.com` .", "KubernetesNetworkConfig.ServiceIpv6Cidr": "The CIDR block that Kubernetes Service IP addresses are assigned from if you created a 1.21 or later cluster with version 1.10.1 or later of the Amazon VPC CNI add-on and specified `ipv6` for *ipFamily* when you created the cluster. Kubernetes assigns Service addresses from the unique local address range ( `fc00::/7` ) because you can't specify a custom IPv6 CIDR block when you create the cluster.", - "OpenIdConnectIssuerUrl": "The issuer URL for the OIDC identity provider of the cluster, such as `https://oidc.eks.us-west-2.amazonaws.com/id/EXAMPLED539D4633E53DE1B716D3041E` . If you need to remove `https://` from this output value, you can include the following code in your template.\n\n`!Select [1, !Split [\"//\", !GetAtt EKSCluster.OpenIdConnectIssuerUrl]]`", + "OpenIdConnectIssuerUrl": "", "Ref": "`Ref` returns the resource name. For example:\n\n`{ \"Ref\": \"myCluster\" }`\n\nFor the Amazon EKS cluster `myCluster` , `Ref` returns the name of the cluster." }, "description": "Creates an Amazon EKS control plane.\n\nThe Amazon EKS control plane consists of control plane instances that run the Kubernetes software, such as `etcd` and the API server. The control plane runs in an account managed by AWS , and the Kubernetes API is exposed by the Amazon EKS API server endpoint. Each Amazon EKS cluster control plane is single tenant and unique. It runs on its own set of Amazon EC2 instances.\n\nThe cluster control plane is provisioned across multiple Availability Zones and fronted by an Elastic Load Balancing Network Load Balancer. Amazon EKS also provisions elastic network interfaces in your VPC subnets to provide connectivity from the control plane instances to the nodes (for example, to support `kubectl exec` , `logs` , and `proxy` data flows).\n\nAmazon EKS nodes run in your AWS account and connect to your cluster's control plane over the Kubernetes API server endpoint and a certificate file that is created for your cluster.\n\nIn most cases, it takes several minutes to create a cluster. After you create an Amazon EKS cluster, you must configure your Kubernetes tooling to communicate with the API server and launch nodes into your cluster. For more information, see [Managing Cluster Authentication](https://docs.aws.amazon.com/eks/latest/userguide/managing-auth.html) and [Launching Amazon EKS nodes](https://docs.aws.amazon.com/eks/latest/userguide/launch-workers.html) in the *Amazon EKS User Guide* .", @@ -14570,7 +14674,7 @@ "AWS::EKS::FargateProfile": { "attributes": { "Arn": "The ARN of the cluster, such as `arn:aws:eks:us-west-2:666666666666:fargateprofile/myCluster/myFargateProfile/1cb1a11a-1dc1-1d11-cf11-1111f11fa111` .", - "Ref": "`Ref` returns the resource name. For example:\n\n`{ \"Ref\": \"myFargateProfile\" }`\n\nFor the Fargate profile `myFargateProfile` , Ref returns the physical resource ID of the Fargate profile. For example, `/` ." + "Ref": "`Ref` returns the resource name. For example:\n\n`{ \"Ref\": \"myFargateProfile\" }`\n\nFor the Fargate profile `myFargateProfile` , Ref returns the physical resource ID of the Fargate profile. For example, `/` ." }, "description": "Creates an AWS Fargate profile for your Amazon EKS cluster. You must have at least one Fargate profile in a cluster to be able to run pods on Fargate.\n\nThe Fargate profile allows an administrator to declare which pods run on Fargate and specify which pods run on which Fargate profile. This declaration is done through the profile\u2019s selectors. Each profile can have up to five selectors that contain a namespace and labels. A namespace is required for every selector. The label field consists of multiple optional key-value pairs. Pods that match the selectors are scheduled on Fargate. If a to-be-scheduled pod matches any of the selectors in the Fargate profile, then that pod is run on Fargate.\n\nWhen you create a Fargate profile, you must specify a pod execution role to use with the pods that are scheduled with the profile. This role is added to the cluster's Kubernetes [Role Based Access Control](https://docs.aws.amazon.com/https://kubernetes.io/docs/admin/authorization/rbac/) (RBAC) for authorization so that the `kubelet` that is running on the Fargate infrastructure can register with your Amazon EKS cluster so that it can appear in your cluster as a node. The pod execution role also provides IAM permissions to the Fargate infrastructure to allow read access to Amazon ECR image repositories. For more information, see [Pod Execution Role](https://docs.aws.amazon.com/eks/latest/userguide/pod-execution-role.html) in the *Amazon EKS User Guide* .\n\nFargate profiles are immutable. However, you can create a new updated profile to replace an existing profile and then delete the original after the updated profile has finished creating.\n\nIf any Fargate profiles in a cluster are in the `DELETING` status, you must wait for that Fargate profile to finish deleting before you can create any other profiles in that cluster.\n\nFor more information, see [AWS Fargate Profile](https://docs.aws.amazon.com/eks/latest/userguide/fargate-profile.html) in the *Amazon EKS User Guide* .", "properties": { @@ -14598,13 +14702,48 @@ "Namespace": "The Kubernetes namespace that the selector should match." } }, + "AWS::EKS::IdentityProviderConfig": { + "attributes": { + "IdentityProviderConfigArn": "The Amazon Resource Name (ARN) associated with the identity provider config.", + "Ref": "`Ref` returns the resource name. For example:\n\n`{ \"Ref\": \"myIdentityProviderConfig\" }`\n\nFor the IdentityProviderConfig, Ref returns the physical resource ID of the config. For example, `cluster-name/oidc/identity-provider-config-name` ." + }, + "description": "Associate an identity provider configuration to a cluster.\n\nIf you want to authenticate identities using an identity provider, you can create an identity provider configuration and associate it to your cluster. After configuring authentication to your cluster you can create Kubernetes `roles` and `clusterroles` to assign permissions to the roles, and then bind the roles to the identities using Kubernetes `rolebindings` and `clusterrolebindings` . For more information see [Using RBAC Authorization](https://docs.aws.amazon.com/https://kubernetes.io/docs/reference/access-authn-authz/rbac/) in the Kubernetes documentation.\n\nThis resource isn't available in all AWS Regions .", + "properties": { + "ClusterName": "The cluster that the configuration is associated to.", + "IdentityProviderConfigName": "The name of the configuration.", + "Oidc": "An object that represents an OpenID Connect (OIDC) identity provider configuration.", + "Tags": "The metadata to apply to the provider configuration to assist with categorization and organization. Each tag consists of a key and an optional value. You define both.", + "Type": "The type of the identity provider configuration. The only type available is `oidc` ." + } + }, + "AWS::EKS::IdentityProviderConfig.OidcIdentityProviderConfig": { + "attributes": {}, + "description": "An object that represents the configuration for an OpenID Connect (OIDC) identity provider.\n\nThis resource isn't available in all AWS Regions .", + "properties": { + "ClientId": "This is also known as *audience* . The ID of the client application that makes authentication requests to the OIDC identity provider.", + "GroupsClaim": "The JSON web token (JWT) claim that the provider uses to return your groups.", + "GroupsPrefix": "The prefix that is prepended to group claims to prevent clashes with existing names (such as `system:` groups). For example, the value `oidc:` creates group names like `oidc:engineering` and `oidc:infra` . The prefix can't contain `system:`", + "IssuerUrl": "The URL of the OIDC identity provider that allows the API server to discover public signing keys for verifying tokens.", + "RequiredClaims": "The key-value pairs that describe required claims in the identity token. If set, each claim is verified to be present in the token with a matching value.", + "UsernameClaim": "The JSON Web token (JWT) claim that is used as the username.", + "UsernamePrefix": "The prefix that is prepended to username claims to prevent clashes with existing names. The prefix can't contain `system:`" + } + }, + "AWS::EKS::IdentityProviderConfig.RequiredClaim": { + "attributes": {}, + "description": "A key-value pair that describes a required claim in the identity token. If set, each claim is verified to be present in the token with a matching value.\n\nThis resource isn't available in all AWS Regions .", + "properties": { + "Key": "The key to match from the token.", + "Value": "The value for the key from the token." + } + }, "AWS::EKS::Nodegroup": { "attributes": { "Arn": "The Amazon Resource Name (ARN) associated with the managed node group.", "ClusterName": "The name of the cluster that the managed node group resides in.", "Id": "", "NodegroupName": "The name associated with an Amazon EKS managed node group.", - "Ref": "`Ref` returns the resource name. For example:\n\n`{ \"Ref\": \"myNodegroup\" }`\n\nFor the Amazon EKS node group `myNodegroup` , Ref returns the physical resource ID of the node group. For example, `/` ." + "Ref": "`Ref` returns the resource name. For example:\n\n`{ \"Ref\": \"myNodegroup\" }`\n\nFor the Amazon EKS node group `myNodegroup` , Ref returns the physical resource ID of the node group. For example, `cluster-name/nodegroup_name` ." }, "description": "Creates a managed node group for an Amazon EKS cluster. You can only create a node group for your cluster that is equal to the current Kubernetes version for the cluster. All node groups are created with the latest AMI release version for the respective minor Kubernetes version of the cluster, unless you deploy a custom AMI using a launch template. For more information about using launch templates, see [Launch template support](https://docs.aws.amazon.com/eks/latest/userguide/launch-templates.html) .\n\nAn Amazon EKS managed node group is an Amazon EC2 Auto Scaling group and associated Amazon EC2 instances that are managed by AWS for an Amazon EKS cluster. Each node group uses a version of the Amazon EKS optimized Amazon Linux 2 AMI. For more information, see [Managed Node Groups](https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html) in the *Amazon EKS User Guide* .", "properties": { @@ -15321,7 +15460,7 @@ "properties": { "AZMode": "Specifies whether the nodes in this Memcached cluster are created in a single Availability Zone or created across multiple Availability Zones in the cluster's region.\n\nThis parameter is only supported for Memcached clusters.\n\nIf the `AZMode` and `PreferredAvailabilityZones` are not specified, ElastiCache assumes `single-az` mode.", "AutoMinorVersionUpgrade": "If you are running Redis engine version 6.0 or later, set this parameter to yes if you want to opt-in to the next minor version upgrade campaign. This parameter is disabled for previous versions.", - "CacheNodeType": "The compute and memory capacity of the nodes in the node group (shard).\n\nThe following node types are supported by ElastiCache. Generally speaking, the current generation types provide more memory and computational power at lower cost when compared to their equivalent previous generation counterparts. Changing the CacheNodeType of a Memcached instance is currently not supported. If you need to scale using Memcached, we recommend forcing a replacement update by changing the `LogicalResourceId` of the resource.\n\n- General purpose:\n\n- Current generation:\n\n*M6g node types:* `cache.m6g.large` , `cache.m6g.xlarge` , `cache.m6g.2xlarge` , `cache.m6g.4xlarge` , `cache.m6g.12xlarge` , `cache.m6g.24xlarge`\n\n*M5 node types:* `cache.m5.large` , `cache.m5.xlarge` , `cache.m5.2xlarge` , `cache.m5.4xlarge` , `cache.m5.12xlarge` , `cache.m5.24xlarge`\n\n*M4 node types:* `cache.m4.large` , `cache.m4.xlarge` , `cache.m4.2xlarge` , `cache.m4.4xlarge` , `cache.m4.10xlarge`\n\n*T4g node types:* `cache.t4g.micro` , `cache.t4g.small` , `cache.t4g.medium`\n\n*T3 node types:* `cache.t3.micro` , `cache.t3.small` , `cache.t3.medium`\n\n*T2 node types:* `cache.t2.micro` , `cache.t2.small` , `cache.t2.medium`\n- Previous generation: (not recommended)\n\n*T1 node types:* `cache.t1.micro`\n\n*M1 node types:* `cache.m1.small` , `cache.m1.medium` , `cache.m1.large` , `cache.m1.xlarge`\n\n*M3 node types:* `cache.m3.medium` , `cache.m3.large` , `cache.m3.xlarge` , `cache.m3.2xlarge`\n- Compute optimized:\n\n- Previous generation: (not recommended)\n\n*C1 node types:* `cache.c1.xlarge`\n- Memory optimized:\n\n- Current generation:\n\n*R6gd node types:* `cache.r6gd.xlarge` , `cache.r6gd.2xlarge` , `cache.r6gd.4xlarge` , `cache.r6gd.8xlarge` , `cache.r6gd.12xlarge` , `cache.r6gd.16xlarge`\n\n> The `r6gd` family is available in the following regions: `us-east-2` , `us-east-1` , `us-west-2` , `us-west-1` , `eu-west-1` , `eu-central-1` , `ap-northeast-1` , `ap-southeast-1` , `ap-southeast-2` . \n\n*R6g node types:* `cache.r6g.large` , `cache.r6g.xlarge` , `cache.r6g.2xlarge` , `cache.r6g.4xlarge` , `cache.r6g.12xlarge` , `cache.r6g.24xlarge`\n\n*R5 node types:* `cache.r5.large` , `cache.r5.xlarge` , `cache.r5.2xlarge` , `cache.r5.4xlarge` , `cache.r5.12xlarge` , `cache.r5.24xlarge`\n\n*R4 node types:* `cache.r4.large` , `cache.r4.xlarge` , `cache.r4.2xlarge` , `cache.r4.4xlarge` , `cache.r4.8xlarge` , `cache.r4.16xlarge`\n- Previous generation: (not recommended)\n\n*M2 node types:* `cache.m2.xlarge` , `cache.m2.2xlarge` , `cache.m2.4xlarge`\n\n*R3 node types:* `cache.r3.large` , `cache.r3.xlarge` , `cache.r3.2xlarge` , `cache.r3.4xlarge` , `cache.r3.8xlarge`\n\nFor region availability, see [Supported Node Types by Amazon Region](https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/CacheNodes.SupportedTypes.html#CacheNodes.SupportedTypesByRegion)\n\n*Additional node type info*\n\n- All current generation instance types are created in Amazon VPC by default.\n- Redis append-only files (AOF) are not supported for T1 or T2 instances.\n- Redis Multi-AZ with automatic failover is not supported on T1 instances.\n- Redis configuration variables `appendonly` and `appendfsync` are not supported on Redis version 2.8.22 and later.", + "CacheNodeType": "The compute and memory capacity of the nodes in the node group (shard).\n\nThe following node types are supported by ElastiCache. Generally speaking, the current generation types provide more memory and computational power at lower cost when compared to their equivalent previous generation counterparts. Changing the CacheNodeType of a Memcached instance is currently not supported. If you need to scale using Memcached, we recommend forcing a replacement update by changing the `LogicalResourceId` of the resource.\n\n- General purpose:\n\n- Current generation:\n\n*M6g node types:* `cache.m6g.large` , `cache.m6g.xlarge` , `cache.m6g.2xlarge` , `cache.m6g.4xlarge` , `cache.m6g.8xlarge` , `cache.m6g.12xlarge` , `cache.m6g.16xlarge` , `cache.m6g.24xlarge`\n\n*M5 node types:* `cache.m5.large` , `cache.m5.xlarge` , `cache.m5.2xlarge` , `cache.m5.4xlarge` , `cache.m5.12xlarge` , `cache.m5.24xlarge`\n\n*M4 node types:* `cache.m4.large` , `cache.m4.xlarge` , `cache.m4.2xlarge` , `cache.m4.4xlarge` , `cache.m4.10xlarge`\n\n*T4g node types:* `cache.t4g.micro` , `cache.t4g.small` , `cache.t4g.medium`\n\n*T3 node types:* `cache.t3.micro` , `cache.t3.small` , `cache.t3.medium`\n\n*T2 node types:* `cache.t2.micro` , `cache.t2.small` , `cache.t2.medium`\n- Previous generation: (not recommended)\n\n*T1 node types:* `cache.t1.micro`\n\n*M1 node types:* `cache.m1.small` , `cache.m1.medium` , `cache.m1.large` , `cache.m1.xlarge`\n\n*M3 node types:* `cache.m3.medium` , `cache.m3.large` , `cache.m3.xlarge` , `cache.m3.2xlarge`\n- Compute optimized:\n\n- Previous generation: (not recommended)\n\n*C1 node types:* `cache.c1.xlarge`\n- Memory optimized:\n\n- Current generation:\n\n*R6gd node types:* `cache.r6gd.xlarge` , `cache.r6gd.2xlarge` , `cache.r6gd.4xlarge` , `cache.r6gd.8xlarge` , `cache.r6gd.12xlarge` , `cache.r6gd.16xlarge`\n\n> The `r6gd` family is available in the following regions: `us-east-2` , `us-east-1` , `us-west-2` , `us-west-1` , `eu-west-1` , `eu-central-1` , `ap-northeast-1` , `ap-southeast-1` , `ap-southeast-2` . \n\n*R6g node types:* `cache.r6g.large` , `cache.r6g.xlarge` , `cache.r6g.2xlarge` , `cache.r6g.4xlarge` , `cache.r6g.8xlarge` , `cache.r6g.12xlarge` , `cache.r6g.16xlarge` , `cache.r6g.24xlarge`\n\n*R5 node types:* `cache.r5.large` , `cache.r5.xlarge` , `cache.r5.2xlarge` , `cache.r5.4xlarge` , `cache.r5.12xlarge` , `cache.r5.24xlarge`\n\n*R4 node types:* `cache.r4.large` , `cache.r4.xlarge` , `cache.r4.2xlarge` , `cache.r4.4xlarge` , `cache.r4.8xlarge` , `cache.r4.16xlarge`\n- Previous generation: (not recommended)\n\n*M2 node types:* `cache.m2.xlarge` , `cache.m2.2xlarge` , `cache.m2.4xlarge`\n\n*R3 node types:* `cache.r3.large` , `cache.r3.xlarge` , `cache.r3.2xlarge` , `cache.r3.4xlarge` , `cache.r3.8xlarge`\n\nFor region availability, see [Supported Node Types by Amazon Region](https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/CacheNodes.SupportedTypes.html#CacheNodes.SupportedTypesByRegion)\n\n*Additional node type info*\n\n- All current generation instance types are created in Amazon VPC by default.\n- Redis append-only files (AOF) are not supported for T1 or T2 instances.\n- Redis Multi-AZ with automatic failover is not supported on T1 instances.\n- Redis configuration variables `appendonly` and `appendfsync` are not supported on Redis version 2.8.22 and later.", "CacheParameterGroupName": "The name of the parameter group to associate with this cluster. If this argument is omitted, the default parameter group for the specified engine is used. You cannot use any parameter group which has `cluster-enabled='yes'` when creating a cluster.", "CacheSecurityGroupNames": "A list of security group names to associate with this cluster.\n\nUse this parameter only when you are creating a cluster outside of an Amazon Virtual Private Cloud (Amazon VPC).", "CacheSubnetGroupName": "The name of the subnet group to be used for the cluster.\n\nUse this parameter only when you are creating a cluster in an Amazon Virtual Private Cloud (Amazon VPC).\n\n> If you're going to launch your cluster in an Amazon VPC, you need to create a subnet group before you start creating a cluster. For more information, see [AWS::ElastiCache::SubnetGroup](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticache-subnetgroup.html) .", @@ -15449,7 +15588,7 @@ "description": "The `AWS::ElastiCache::ReplicationGroup` resource creates an Amazon ElastiCache Redis replication group. A Redis (cluster mode disabled) replication group is a collection of cache clusters, where one of the clusters is a primary read-write cluster and the others are read-only replicas.\n\nA Redis (cluster mode enabled) cluster is comprised of from 1 to 90 shards (API/CLI: node groups). Each shard has a primary node and up to 5 read-only replica nodes. The configuration can range from 90 shards and 0 replicas to 15 shards and 5 replicas, which is the maximum number or replicas allowed.\n\nThe node or shard limit can be increased to a maximum of 500 per cluster if the Redis engine version is 5.0.6 or higher. For example, you can choose to configure a 500 node cluster that ranges between 83 shards (one primary and 5 replicas per shard) and 500 shards (single primary and no replicas). Make sure there are enough available IP addresses to accommodate the increase. Common pitfalls include the subnets in the subnet group have too small a CIDR range or the subnets are shared and heavily used by other clusters. For more information, see [Creating a Subnet Group](https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/SubnetGroups.Creating.html) . For versions below 5.0.6, the limit is 250 per cluster.\n\nTo request a limit increase, see [Amazon Service Limits](https://docs.aws.amazon.com/general/latest/gr/aws_service_limits.html) and choose the limit type *Nodes per cluster per instance type* .", "properties": { "AtRestEncryptionEnabled": "A flag that enables encryption at rest when set to `true` .\n\nYou cannot modify the value of `AtRestEncryptionEnabled` after the replication group is created. To enable encryption at rest on a replication group you must set `AtRestEncryptionEnabled` to `true` when you create the replication group.\n\n*Required:* Only available when creating a replication group in an Amazon VPC using redis version `3.2.6` or `4.x` onward.\n\nDefault: `false`", - "AuthToken": "*Reserved parameter.* The password used to access a password protected server.\n\n`AuthToken` can be specified only on replication groups where `TransitEncryptionEnabled` is `true` . For more information, see [Authenticating Users with the Redis AUTH Command](https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/auth.html) .\n\n> For HIPAA compliance, you must specify `TransitEncryptionEnabled` as `true` , an `AuthToken` , and a `CacheSubnetGroup` . \n\nPassword constraints:\n\n- Must be only printable ASCII characters.\n- Must be at least 16 characters and no more than 128 characters in length.\n- Cannot contain any of the following characters: '/', '\"', or '@'.\n\nFor more information, see [AUTH password](https://docs.aws.amazon.com/http://redis.io/commands/AUTH) at http://redis.io/commands/AUTH.", + "AuthToken": "*Reserved parameter.* The password used to access a password protected server.\n\n`AuthToken` can be specified only on replication groups where `TransitEncryptionEnabled` is `true` . For more information, see [Authenticating Users with the Redis AUTH Command](https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/auth.html) .\n\n> For HIPAA compliance, you must specify `TransitEncryptionEnabled` as `true` , an `AuthToken` , and a `CacheSubnetGroup` . \n\nPassword constraints:\n\n- Must be only printable ASCII characters.\n- Must be at least 16 characters and no more than 128 characters in length.\n- Nonalphanumeric characters are restricted to (!, &, #, $, ^, <, >, -, ).\n\nFor more information, see [AUTH password](https://docs.aws.amazon.com/http://redis.io/commands/AUTH) at http://redis.io/commands/AUTH.", "AutoMinorVersionUpgrade": "If you are running Redis engine version 6.0 or later, set this parameter to yes if you want to opt-in to the next minor version upgrade campaign. This parameter is disabled for previous versions.", "AutomaticFailoverEnabled": "Specifies whether a read-only replica is automatically promoted to read/write primary if the existing primary fails.\n\n`AutomaticFailoverEnabled` must be enabled for Redis (cluster mode enabled) replication groups.\n\nDefault: false", "CacheNodeType": "The compute and memory capacity of the nodes in the node group (shard).\n\nThe following node types are supported by ElastiCache. Generally speaking, the current generation types provide more memory and computational power at lower cost when compared to their equivalent previous generation counterparts.\n\n- General purpose:\n\n- Current generation:\n\n*M6g node types:* `cache.m6g.large` , `cache.m6g.xlarge` , `cache.m6g.2xlarge` , `cache.m6g.4xlarge` , `cache.m6g.12xlarge` , `cache.m6g.24xlarge`\n\n*M5 node types:* `cache.m5.large` , `cache.m5.xlarge` , `cache.m5.2xlarge` , `cache.m5.4xlarge` , `cache.m5.12xlarge` , `cache.m5.24xlarge`\n\n*M4 node types:* `cache.m4.large` , `cache.m4.xlarge` , `cache.m4.2xlarge` , `cache.m4.4xlarge` , `cache.m4.10xlarge`\n\n*T4g node types:* `cache.t4g.micro` , `cache.t4g.small` , `cache.t4g.medium`\n\n*T3 node types:* `cache.t3.micro` , `cache.t3.small` , `cache.t3.medium`\n\n*T2 node types:* `cache.t2.micro` , `cache.t2.small` , `cache.t2.medium`\n- Previous generation: (not recommended)\n\n*T1 node types:* `cache.t1.micro`\n\n*M1 node types:* `cache.m1.small` , `cache.m1.medium` , `cache.m1.large` , `cache.m1.xlarge`\n\n*M3 node types:* `cache.m3.medium` , `cache.m3.large` , `cache.m3.xlarge` , `cache.m3.2xlarge`\n- Compute optimized:\n\n- Previous generation: (not recommended)\n\n*C1 node types:* `cache.c1.xlarge`\n- Memory optimized:\n\n- Current generation:\n\n*R6gd node types:* `cache.r6gd.xlarge` , `cache.r6gd.2xlarge` , `cache.r6gd.4xlarge` , `cache.r6gd.8xlarge` , `cache.r6gd.12xlarge` , `cache.r6gd.16xlarge`\n\n> The `r6gd` family is available in the following regions: `us-east-2` , `us-east-1` , `us-west-2` , `us-west-1` , `eu-west-1` , `eu-central-1` , `ap-northeast-1` , `ap-southeast-1` , `ap-southeast-2` . \n\n*R6g node types:* `cache.r6g.large` , `cache.r6g.xlarge` , `cache.r6g.2xlarge` , `cache.r6g.4xlarge` , `cache.r6g.12xlarge` , `cache.r6g.24xlarge`\n\n*R5 node types:* `cache.r5.large` , `cache.r5.xlarge` , `cache.r5.2xlarge` , `cache.r5.4xlarge` , `cache.r5.12xlarge` , `cache.r5.24xlarge`\n\n*R4 node types:* `cache.r4.large` , `cache.r4.xlarge` , `cache.r4.2xlarge` , `cache.r4.4xlarge` , `cache.r4.8xlarge` , `cache.r4.16xlarge`\n- Previous generation: (not recommended)\n\n*M2 node types:* `cache.m2.xlarge` , `cache.m2.2xlarge` , `cache.m2.4xlarge`\n\n*R3 node types:* `cache.r3.large` , `cache.r3.xlarge` , `cache.r3.2xlarge` , `cache.r3.4xlarge` , `cache.r3.8xlarge`\n\nFor region availability, see [Supported Node Types by Amazon Region](https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/CacheNodes.SupportedTypes.html#CacheNodes.SupportedTypesByRegion)", @@ -16493,6 +16632,68 @@ "Name": "The name for the connection to create." } }, + "AWS::Events::Connection.ApiKeyAuthParameters": { + "attributes": {}, + "description": "", + "properties": { + "ApiKeyName": "", + "ApiKeyValue": "" + } + }, + "AWS::Events::Connection.AuthParameters": { + "attributes": {}, + "description": "", + "properties": { + "ApiKeyAuthParameters": "", + "BasicAuthParameters": "", + "InvocationHttpParameters": "", + "OAuthParameters": "" + } + }, + "AWS::Events::Connection.BasicAuthParameters": { + "attributes": {}, + "description": "", + "properties": { + "Password": "", + "Username": "" + } + }, + "AWS::Events::Connection.ClientParameters": { + "attributes": {}, + "description": "", + "properties": { + "ClientID": "", + "ClientSecret": "" + } + }, + "AWS::Events::Connection.ConnectionHttpParameters": { + "attributes": {}, + "description": "Contains additional parameters for the connection.", + "properties": { + "BodyParameters": "Contains additional body string parameters for the connection.", + "HeaderParameters": "Contains additional header parameters for the connection.", + "QueryStringParameters": "Contains additional query string parameters for the connection." + } + }, + "AWS::Events::Connection.OAuthParameters": { + "attributes": {}, + "description": "", + "properties": { + "AuthorizationEndpoint": "", + "ClientParameters": "", + "HttpMethod": "", + "OAuthHttpParameters": "" + } + }, + "AWS::Events::Connection.Parameter": { + "attributes": {}, + "description": "", + "properties": { + "IsValueSecret": "", + "Key": "", + "Value": "" + } + }, "AWS::Events::EventBus": { "attributes": { "Arn": "The ARN of the event bus, such as `arn:aws:events:us-east-2:123456789012:event-bus/aws.partner/PartnerName/acct1/repo1` .", @@ -17057,7 +17258,7 @@ "KmsKeyId": "The ID of the AWS Key Management Service ( AWS KMS ) key used to encrypt the file system's data for Amazon FSx for Windows File Server file systems, Amazon FSx for NetApp ONTAP file systems, and `PERSISTENT` Amazon FSx for Lustre file systems at rest. If this ID isn't specified, the Amazon FSx-managed key for your account is used. The scratch Amazon FSx for Lustre file systems are always encrypted at rest using the Amazon FSx-managed key for your account. For more information, see [Encrypt](https://docs.aws.amazon.com//kms/latest/APIReference/API_Encrypt.html) in the *AWS Key Management Service API Reference* .", "LustreConfiguration": "The Lustre configuration for the file system being created.\n\n> The following parameters are not supported for file systems with the `Persistent_2` deployment type. Instead, use `CreateDataRepositoryAssociation` to create a data repository association to link your Lustre file system to a data repository.\n> \n> - `AutoImportPolicy`\n> - `ExportPath`\n> - `ImportedChunkSize`\n> - `ImportPath`", "OntapConfiguration": "The ONTAP configuration properties of the FSx for ONTAP file system that you are creating.", - "OpenZFSConfiguration": "The OpenZFS configuration properties for the file system that you are creating.", + "OpenZFSConfiguration": "The Amazon FSx for OpenZFS configuration properties for the file system that you are creating.", "SecurityGroupIds": "A list of IDs specifying the security groups to apply to all network interfaces created for file system access. This list isn't returned in later requests to describe the file system.", "StorageCapacity": "Sets the storage capacity of the file system that you're creating. `StorageCapacity` is required if you are creating a new file system. Do not include `StorageCapacity` if you are creating a file system from a backup.\n\nFor Lustre file systems:", "StorageType": "Sets the storage type for the file system that you're creating. Valid values are `SSD` and `HDD` .\n\n- Set to `SSD` to use solid state drive storage. SSD is supported on all Windows, Lustre, ONTAP, and OpenZFS deployment types.\n- Set to `HDD` to use hard disk drive storage. HDD is supported on `SINGLE_AZ_2` and `MULTI_AZ_1` Windows file system deployment types, and on `PERSISTENT` Lustre file system deployment types.\n\nDefault value is `SSD` . For more information, see [Storage type options](https://docs.aws.amazon.com/fsx/latest/WindowsGuide/optimize-fsx-costs.html#storage-type-options) in the *FSx for Windows File Server User Guide* and [Multiple storage options](https://docs.aws.amazon.com/fsx/latest/LustreGuide/what-is.html#storage-options) in the *FSx for Lustre User Guide* .", @@ -17079,8 +17280,8 @@ "attributes": {}, "description": "Specifies who can mount the file system and the options that can be used while mounting the file system.", "properties": { - "Clients": "A value that specifies who can mount the file system. You can provide a wildcard character ( `*` ), an IP address ( `0.0.0.0` ), or a CIDR address ( `192.0.2.0/24` . By default, Amazon FSx uses the wildcard character when specifying the client.", - "Options": "The options to use when mounting the file system. For a list of options that you can use with Network File System (NFS), see the [exports(5) - Linux man page](https://docs.aws.amazon.com/https://linux.die.net/man/5/exports) . When choosing your options, consider the following:\n\n- `crossmount` is used by default. If you don't specify `crossmount` when changing the client configuration, you won't be able to see or access snapshots in your file system's snapshot directory.\n- `sync` is used by default. If you instead specify `async` , the system acknowledges writes before writing to disk. If the system crashes before the writes are finished, you lose the unwritten data." + "Clients": "A value that specifies who can mount the file system. You can provide a wildcard character ( `*` ), an IP address ( `0.0.0.0` ), or a CIDR address ( `192.0.2.0/24` ). By default, Amazon FSx uses the wildcard character when specifying the client.", + "Options": "The options to use when mounting the file system. For a list of options that you can use with Network File System (NFS), see the [exports(5) - Linux man page](https://docs.aws.amazon.com/https://linux.die.net/man/5/exports) . When choosing your options, consider the following:\n\n- `crossmnt` is used by default. If you don't specify `crossmnt` when changing the client configuration, you won't be able to see or access snapshots in your file system's snapshot directory.\n- `sync` is used by default. If you instead specify `async` , the system acknowledges writes before writing to disk. If the system crashes before the writes are finished, you lose the unwritten data." } }, "AWS::FSx::FileSystem.DiskIopsConfiguration": { @@ -17124,7 +17325,7 @@ "DailyAutomaticBackupStartTime": "A recurring daily time, in the format `HH:MM` . `HH` is the zero-padded hour of the day (0-23), and `MM` is the zero-padded minute of the hour. For example, `05:00` specifies 5 AM daily.", "DeploymentType": "Specifies the FSx for ONTAP file system deployment type to use in creating the file system. `MULTI_AZ_1` is the supported ONTAP deployment type.", "DiskIopsConfiguration": "The SSD IOPS configuration for the FSx for ONTAP file system.", - "EndpointIpAddressRange": "Specifies the IP address range in which the endpoints to access your file system will be created. By default, Amazon FSx selects an unused IP address range for you from the 198.19.* range.", + "EndpointIpAddressRange": "Specifies the IP address range in which the endpoints to access your file system will be created. By default, Amazon FSx selects an unused IP address range for you from the 198.19.* range.\n\n> The Endpoint IP address range you select for your file system must exist outside the VPC's CIDR range and must be at least /30 or larger.", "FsxAdminPassword": "The ONTAP administrative password for the `fsxadmin` user with which you administer your file system using the NetApp ONTAP CLI and REST API.", "PreferredSubnetId": "Required when `DeploymentType` is set to `MULTI_AZ_1` . This specifies the subnet in which you want the preferred file server to be located.", "RouteTableIds": "Specifies the virtual private cloud (VPC) route tables in which your file system's endpoints will be created. You should specify all VPC route tables associated with the subnets in which your clients are located. By default, Amazon FSx selects your VPC's default route table.", @@ -17140,7 +17341,7 @@ "CopyTagsToBackups": "A Boolean value indicating whether tags for the file system should be copied to backups. This value defaults to `false` . If it's set to `true` , all tags for the file system are copied to all automatic and user-initiated backups where the user doesn't specify tags. If this value is `true` , and you specify one or more tags, only the specified tags are copied to backups. If you specify one or more tags when creating a user-initiated backup, no tags are copied from the file system, regardless of this value.", "CopyTagsToVolumes": "A Boolean value indicating whether tags for the volume should be copied to snapshots. This value defaults to `false` . If it's set to `true` , all tags for the volume are copied to snapshots where the user doesn't specify tags. If this value is `true` , and you specify one or more tags, only the specified tags are copied to snapshots. If you specify one or more tags when creating the snapshot, no tags are copied from the volume, regardless of this value.", "DailyAutomaticBackupStartTime": "A recurring daily time, in the format `HH:MM` . `HH` is the zero-padded hour of the day (0-23), and `MM` is the zero-padded minute of the hour. For example, `05:00` specifies 5 AM daily.", - "DeploymentType": "Specifies the file system deployment type. Amazon FSx for OpenZFS supports `SINGLE_AZ_1` . `SINGLE_AZ_1` is a file system configured for a single Availability Zone (AZ) of redundancy.", + "DeploymentType": "Specifies the file system deployment type. Amazon FSx for OpenZFS supports `SINGLE_AZ_1` . `SINGLE_AZ_1` deployment type is configured for redundancy within a single Availability Zone.", "DiskIopsConfiguration": "The SSD IOPS (input/output operations per second) configuration for an Amazon FSx for NetApp ONTAP or Amazon FSx for OpenZFS file system. The default is 3 IOPS per GB of storage capacity, but you can provision additional IOPS per GB of storage. The configuration consists of the total number of provisioned SSD IOPS and how the amount was provisioned (by the customer or by the system).", "RootVolumeConfiguration": "The configuration Amazon FSx uses when creating the root value of the Amazon FSx for OpenZFS file system. All volumes are children of the root volume.", "ThroughputCapacity": "Specifies the throughput of an Amazon FSx for OpenZFS file system, measured in megabytes per second (MB/s). Valid values are 64, 128, 256, 512, 1024, 2048, 3072, or 4096 MB/s. You pay for additional throughput capacity that you provision.", @@ -17151,8 +17352,8 @@ "attributes": {}, "description": "The configuration of an Amazon FSx for OpenZFS root volume.", "properties": { - "CopyTagsToSnapshots": "A Boolean value indicating whether tags for the volume should be copied to snapshots. This value defaults to `false` . If it's set to `true` , all tags for the volume are copied to snapshots where the user doesn't specify tags. If this value is `true` and you specify one or more tags, only the specified tags are copied to snapshots. If you specify one or more tags when creating the snapshot, no tags are copied from the volume, regardless of this value.", - "DataCompressionType": "Specifies the method used to compress the data on the volume. Unless the compression type is specified, volumes inherit the `DataCompressionType` value of their parent volume.\n\n- `NONE` - Doesn't compress the data on the volume.\n- `ZSTD` - Compresses the data in the volume using the ZStandard (ZSTD) compression algorithm. This algorithm reduces the amount of space used on your volume and has very little impact on compute resources.", + "CopyTagsToSnapshots": "A Boolean value indicating whether tags for the volume should be copied to snapshots of the volume. This value defaults to `false` . If it's set to `true` , all tags for the volume are copied to snapshots where the user doesn't specify tags. If this value is `true` and you specify one or more tags, only the specified tags are copied to snapshots. If you specify one or more tags when creating the snapshot, no tags are copied from the volume, regardless of this value.", + "DataCompressionType": "Specifies the method used to compress the data on the volume. The compression type is `NONE` by default.\n\n- `NONE` - Doesn't compress the data on the volume. `NONE` is the default.\n- `ZSTD` - Compresses the data in the volume using the Zstandard (ZSTD) compression algorithm. Compared to LZ4, Z-Standard provides a better compression ratio to minimize on-disk storage utilization.\n- `LZ4` - Compresses the data in the volume using the LZ4 compression algorithm. Compared to Z-Standard, LZ4 is less compute-intensive and delivers higher write throughput speeds.", "NfsExports": "The configuration object for mounting a file system.", "ReadOnly": "A Boolean value indicating whether the volume is read-only. Setting this value to `true` can be useful after you have completed changes to a volume and no longer want changes to occur.", "UserAndGroupQuotas": "An object specifying how much storage users or groups can use on the volume." @@ -17252,12 +17453,12 @@ "UUID": "Returns the volume's universally unique identifier (UUID).\n\nExample: `abcd0123-cd45-ef67-11aa-1111aaaa23bc`", "VolumeId": "Returns the volume's ID.\n\nExample: `fsvol-0123456789abcdefa`" }, - "description": "Creates an Amazon FSx for NetApp ONTAP or Amazon FSx for OpenZFS storage volume.", + "description": "Creates an FSx for ONTAP or Amazon FSx for OpenZFS storage volume.", "properties": { "BackupId": "The ID of the source backup. Specifies the backup that you are copying.", "Name": "The name of the volume.", "OntapConfiguration": "The configuration of an Amazon FSx for NetApp ONTAP volume.", - "OpenZFSConfiguration": "Specifies the configuration of the OpenZFS volume that you are creating.", + "OpenZFSConfiguration": "Specifies the configuration of the Amazon FSx for OpenZFS volume that you are creating.", "Options": "To delete the volume's child volumes, snapshots, and clones, use the string `DELETE_CHILD_VOLUMES_AND_SNAPSHOTS` .", "SnapshotId": "A unique ID that represents the snapshot.", "Tags": "An array of key-value pairs to apply to this resource.\n\nFor more information, see [Tag](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-resource-tags.html) .", @@ -17268,8 +17469,8 @@ "attributes": {}, "description": "Specifies who can mount the file system and the options that can be used while mounting the file system.", "properties": { - "Clients": "A value that specifies who can mount the file system. You can provide a wildcard character ( `*` ), an IP address ( `0.0.0.0` ), or a CIDR address ( `192.0.2.0/24` . By default, Amazon FSx uses the wildcard character when specifying the client.", - "Options": "The options to use when mounting the file system. For a list of options that you can use with Network File System (NFS), see the [exports(5) - Linux man page](https://docs.aws.amazon.com/https://linux.die.net/man/5/exports) . When choosing your options, consider the following:\n\n- `crossmount` is used by default. If you don't specify `crossmount` when changing the client configuration, you won't be able to see or access snapshots in your file system's snapshot directory.\n- `sync` is used by default. If you instead specify `async` , the system acknowledges writes before writing to disk. If the system crashes before the writes are finished, you lose the unwritten data." + "Clients": "A value that specifies who can mount the file system. You can provide a wildcard character ( `*` ), an IP address ( `0.0.0.0` ), or a CIDR address ( `192.0.2.0/24` ). By default, Amazon FSx uses the wildcard character when specifying the client.", + "Options": "The options to use when mounting the file system. For a list of options that you can use with Network File System (NFS), see the [exports(5) - Linux man page](https://docs.aws.amazon.com/https://linux.die.net/man/5/exports) . When choosing your options, consider the following:\n\n- `crossmnt` is used by default. If you don't specify `crossmnt` when changing the client configuration, you won't be able to see or access snapshots in your file system's snapshot directory.\n- `sync` is used by default. If you instead specify `async` , the system acknowledges writes before writing to disk. If the system crashes before the writes are finished, you lose the unwritten data." } }, "AWS::FSx::Volume.NfsExports": { @@ -17293,16 +17494,16 @@ }, "AWS::FSx::Volume.OpenZFSConfiguration": { "attributes": {}, - "description": "Specifies the configuration of the OpenZFS volume that you are creating.", + "description": "Specifies the configuration of the Amazon FSx for OpenZFS volume that you are creating.", "properties": { "CopyTagsToSnapshots": "A Boolean value indicating whether tags for the volume should be copied to snapshots. This value defaults to `false` . If it's set to `true` , all tags for the volume are copied to snapshots where the user doesn't specify tags. If this value is `true` , and you specify one or more tags, only the specified tags are copied to snapshots. If you specify one or more tags when creating the snapshot, no tags are copied from the volume, regardless of this value.", - "DataCompressionType": "The method used to compress the data on the volume. Unless a compression type is specified, volumes inherit the `DataCompressionType` value of their parent volume.\n\n- `NONE` - Doesn't compress the data on the volume.\n- `ZSTD` - Compresses the data in the volume using the Zstandard (ZSTD) compression algorithm. This algorithm reduces the amount of space used on your volume and has very little impact on compute resources.", + "DataCompressionType": "Specifies the method used to compress the data on the volume. The compression type is `NONE` by default.\n\n- `NONE` - Doesn't compress the data on the volume. `NONE` is the default.\n- `ZSTD` - Compresses the data in the volume using the Zstandard (ZSTD) compression algorithm. Compared to LZ4, Z-Standard provides a better compression ratio to minimize on-disk storage utilization.\n- `LZ4` - Compresses the data in the volume using the LZ4 compression algorithm. Compared to Z-Standard, LZ4 is less compute-intensive and delivers higher write throughput speeds.", "NfsExports": "The configuration object for mounting a Network File System (NFS) file system.", "OriginSnapshot": "The configuration object that specifies the snapshot to use as the origin of the data for the volume.", - "ParentVolumeId": "The ID of the volume to use as the parent volume.", + "ParentVolumeId": "The ID of the volume to use as the parent volume of the volume that you are creating.", "ReadOnly": "A Boolean value indicating whether the volume is read-only.", - "StorageCapacityQuotaGiB": "The maximum amount of storage in gibibytes (GiB) that the volume can use from its parent. You can specify a quota larger than the storage on the parent volume.", - "StorageCapacityReservationGiB": "The amount of storage in gibibytes (GiB) to reserve from the parent volume. You can't reserve more storage than the parent volume has reserved.", + "StorageCapacityQuotaGiB": "Sets the maximum storage size in gibibytes (GiB) for the volume. You can specify a quota that is larger than the storage on the parent volume. A volume quota limits the amount of storage that the volume can consume to the configured amount, but does not guarantee the space will be available on the parent volume. To guarantee quota space, you must also set `StorageCapacityReservationGiB` . To *not* specify a storage capacity quota, set this to `-1` .\n\nFor more information, see [Volume properties](https://docs.aws.amazon.com/fsx/latest/OpenZFSGuide/managing-volumes.html#volume-properties) in the *Amazon FSx for OpenZFS User Guide* .", + "StorageCapacityReservationGiB": "Specifies the amount of storage in gibibytes (GiB) to reserve from the parent volume. Setting `StorageCapacityReservationGiB` guarantees that the specified amount of storage space on the parent volume will always be available for the volume. You can't reserve more storage than the parent volume has. To *not* specify a storage capacity reservation, set this to `0` or `-1` . For more information, see [Volume properties](https://docs.aws.amazon.com/fsx/latest/OpenZFSGuide/managing-volumes.html#volume-properties) in the *Amazon FSx for OpenZFS User Guide* .", "UserAndGroupQuotas": "An object specifying how much storage users or groups can use on the volume." } }, @@ -17615,14 +17816,14 @@ }, "AWS::GameLift::Alias": { "attributes": { - "AliasId": "", + "AliasId": "A unique identifier for the alias. For example, `arn:aws:gamelift:us-west-1::alias/alias-a1234567-b8c9-0d1e-2fa3-b45c6d7e8912`\n\nAlias IDs are unique within a Region.", "Ref": "`Ref` returns the alias ID, such as `alias-1111aaaa-22bb-33cc-44dd-5555eeee66ff` ." }, "description": "The `AWS::GameLift::Alias` resource creates an alias for an Amazon GameLift (GameLift) fleet destination. There are two types of routing strategies for aliases: simple and terminal. A simple alias points to an active fleet. A terminal alias displays a message instead of routing players to an active fleet. For example, a terminal alias might display a URL link that directs players to an upgrade site. You can use aliases to define destinations in a game session queue or when requesting new game sessions.", "properties": { "Description": "A human-readable description of the alias.", "Name": "A descriptive label that is associated with an alias. Alias names do not need to be unique.", - "RoutingStrategy": "A routing configuration that specifies where traffic is directed for this alias, such as to a fleet or to a message." + "RoutingStrategy": "The routing configuration, including routing type and fleet target, for the alias." } }, "AWS::GameLift::Alias.RoutingStrategy": { @@ -17658,47 +17859,47 @@ }, "AWS::GameLift::Fleet": { "attributes": { - "FleetId": "", + "FleetId": "A unique identifier for the fleet.", "Ref": "`Ref` returns the fleet ID, such as `fleet-1111aaaa-22bb-33cc-44dd-5555eeee66ff` ." }, "description": "The `AWS::GameLift::Fleet` resource creates an Amazon GameLift (GameLift) fleet to host game servers. A fleet is a set of EC2 instances, each of which can host multiple game sessions.", "properties": { "BuildId": "A unique identifier for a build to be deployed on the new fleet. If you are deploying the fleet with a custom game build, you must specify this property. The build must have been successfully uploaded to Amazon GameLift and be in a `READY` status. This fleet setting cannot be changed once the fleet is created.", - "CertificateConfiguration": "Indicates whether to generate a TLS/SSL certificate for the new fleet. TLS certificates are used for encrypting traffic between game clients and game servers running on GameLift. If this parameter is not set, certificate generation is disabled. This fleet setting cannot be changed once the fleet is created. Learn more at [Securing Client/Server Communication](https://docs.aws.amazon.com/gamelift/latest/developerguide/gamelift-howitworks.html#gamelift-howitworks-security) .\n\nNote: This feature requires the AWS Certificate Manager service, which is available in the AWS global partition but not in all other partitions. When working in a partition that does not support this feature, a request for a new fleet with certificate generation results fails with a 4xx unsupported region error.", + "CertificateConfiguration": "Prompts GameLift to generate a TLS/SSL certificate for the fleet. TLS certificates are used for encrypting traffic between game clients and the game servers that are running on GameLift. By default, the `CertificateConfiguration` is set to `DISABLED` . This property cannot be changed after the fleet is created.\n\nNote: This feature requires the AWS Certificate Manager (ACM) service, which is not available in all AWS regions. When working in a region that does not support this feature, a fleet creation request with certificate generation fails with a 4xx error.", "Description": "A human-readable description of the fleet.", "DesiredEC2Instances": "The number of EC2 instances that you want this fleet to host. When creating a new fleet, GameLift automatically sets this value to \"1\" and initiates a single instance. Once the fleet is active, update this value to trigger GameLift to add or remove instances from the fleet.", - "EC2InboundPermissions": "A range of IP addresses and port settings that allow inbound traffic to connect to server processes on an Amazon GameLift server.", + "EC2InboundPermissions": "The allowed IP address ranges and port settings that allow inbound traffic to access game sessions on this fleet. If the fleet is hosting a custom game build, this property must be set before players can connect to game sessions. For Realtime Servers fleets, GameLift automatically sets TCP and UDP ranges.", "EC2InstanceType": "The GameLift-supported Amazon EC2 instance type to use for all fleet instances. Instance type determines the computing resources that will be used to host your game servers, including CPU, memory, storage, and networking capacity. See [Amazon Elastic Compute Cloud Instance Types](https://docs.aws.amazon.com/ec2/instance-types/) for detailed descriptions of Amazon EC2 instance types.", "FleetType": "Indicates whether to use On-Demand or Spot instances for this fleet. By default, this property is set to `ON_DEMAND` . Learn more about when to use [On-Demand versus Spot Instances](https://docs.aws.amazon.com/gamelift/latest/developerguide/gamelift-ec2-instances.html#gamelift-ec2-instances-spot) . This property cannot be changed after the fleet is created.", "InstanceRoleARN": "A unique identifier for an IAM role that manages access to your AWS services. With an instance role ARN set, any application that runs on an instance in this fleet can assume the role, including install scripts, server processes, and daemons (background processes). Create a role or look up a role's ARN by using the [IAM dashboard](https://docs.aws.amazon.com/iam/) in the AWS Management Console . Learn more about using on-box credentials for your game servers at [Access external resources from a game server](https://docs.aws.amazon.com/gamelift/latest/developerguide/gamelift-sdk-server-resources.html) . This property cannot be changed after the fleet is created.", "Locations": "A set of remote locations to deploy additional instances to and manage as part of the fleet. This parameter can only be used when creating fleets in AWS Regions that support multiple locations. You can add any GameLift-supported AWS Region as a remote location, in the form of an AWS Region code such as `us-west-2` . To create a fleet with instances in the home Region only, omit this parameter.", - "MaxSize": "The maximum value that is allowed for the fleet's instance count. When creating a new fleet, GameLift automatically sets this value to \"1\". Once the fleet is active, you can change this value.", - "MetricGroups": "The name of an Amazon CloudWatch metric group. A metric group aggregates the metrics for all fleets in the group. Specify a string containing the metric group name. You can use an existing name or use a new name to create a new metric group. Currently, this parameter can have only one string.", - "MinSize": "The minimum value allowed for the fleet's instance count. When creating a new fleet, GameLift automatically sets this value to \"0\". After the fleet is active, you can change this value.", + "MaxSize": "The maximum number of instances that are allowed in the specified fleet location. If this parameter is not set, the default is 1.", + "MetricGroups": "The name of an AWS CloudWatch metric group to add this fleet to. A metric group is used to aggregate the metrics for multiple fleets. You can specify an existing metric group name or set a new name to create a new metric group. A fleet can be included in only one metric group at a time.", + "MinSize": "The minimum number of instances that are allowed in the specified fleet location. If this parameter is not set, the default is 0.", "Name": "A descriptive label that is associated with a fleet. Fleet names do not need to be unique.", - "NewGameSessionProtectionPolicy": "A game session protection policy to apply to all game sessions hosted on instances in this fleet. When protected, active game sessions cannot be terminated during a scale-down event. If this parameter is not set, instances in this fleet default to no protection. You can change a fleet's protection policy to affect future game sessions on the fleet. You can also set protection for individual game sessions.", + "NewGameSessionProtectionPolicy": "The status of termination protection for active game sessions on the fleet. By default, this property is set to `NoProtection` .\n\n- *NoProtection* - Game sessions can be terminated during active gameplay as a result of a scale-down event.\n- *FullProtection* - Game sessions in `ACTIVE` status cannot be terminated during a scale-down event.", "PeerVpcAwsAccountId": "Used when peering your GameLift fleet with a VPC, the unique identifier for the AWS account that owns the VPC. You can find your account ID in the AWS Management Console under account settings.", "PeerVpcId": "A unique identifier for a VPC with resources to be accessed by your GameLift fleet. The VPC must be in the same Region as your fleet. To look up a VPC ID, use the [VPC Dashboard](https://docs.aws.amazon.com/vpc/) in the AWS Management Console . Learn more about VPC peering in [VPC Peering with GameLift Fleets](https://docs.aws.amazon.com/gamelift/latest/developerguide/vpc-peering.html) .", "ResourceCreationLimitPolicy": "A policy that limits the number of game sessions that an individual player can create on instances in this fleet within a specified span of time.", - "RuntimeConfiguration": "Instructions for launching server processes on each instance in the fleet. Server processes run either a custom game build executable or a Realtime script. The runtime configuration defines the server executables or launch script file, launch parameters, and the number of processes to run concurrently on each instance. When creating a fleet, the runtime configuration must have at least one server process configuration; otherwise the request fails with an invalid request exception.\n\nThis parameter is required unless the parameters `ServerLaunchPath` and `ServerLaunchParameters` are defined. Runtime configuration has replaced these parameters, but fleets that use them will continue to work.", - "ScriptId": "A unique identifier for a Realtime script to be deployed on a new Realtime Servers fleet. The script must have been successfully uploaded to Amazon GameLift. This fleet setting cannot be changed once the fleet is created.\n\nNote: It is not currently possible to use the `!Ref` command to reference a script created with a CloudFormation template for the fleet property `ScriptId` . Instead, use `Fn::GetAtt Script.Arn` or `Fn::GetAtt Script.Id` to retrieve either of these properties as input for `ScriptId` . Alternatively, enter a `ScriptId` string manually." + "RuntimeConfiguration": "Instructions for how to launch and maintain server processes on instances in the fleet. The runtime configuration defines one or more server process configurations, each identifying a build executable or Realtime script file and the number of processes of that type to run concurrently.\n\n> The `RuntimeConfiguration` parameter is required unless the fleet is being configured using the older parameters `ServerLaunchPath` and `ServerLaunchParameters` , which are still supported for backward compatibility.", + "ScriptId": "The unique identifier for a Realtime configuration script to be deployed on fleet instances. You can use either the script ID or ARN. Scripts must be uploaded to GameLift prior to creating the fleet. This fleet property cannot be changed later.\n\n> You can't use the `!Ref` command to reference a script created with a CloudFormation template for the fleet property `ScriptId` . Instead, use `Fn::GetAtt Script.Arn` or `Fn::GetAtt Script.Id` to retrieve either of these properties as input for `ScriptId` . Alternatively, enter a `ScriptId` string manually." } }, "AWS::GameLift::Fleet.CertificateConfiguration": { "attributes": {}, - "description": "Information about the use of a TLS/SSL certificate for a fleet. TLS certificate generation is enabled at the fleet level, with one certificate generated for the fleet. When this feature is enabled, the certificate can be retrieved using the GameLift Server SDK call `GetInstanceCertificate` . All instances in a fleet share the same certificate.", + "description": "Determines whether a TLS/SSL certificate is generated for a fleet. This feature must be enabled when creating the fleet. All instances in a fleet share the same certificate. The certificate can be retrieved by calling the [GameLift Server SDK](https://docs.aws.amazon.com/gamelift/latest/developerguide/reference-serversdk.html) operation `GetInstanceCertificate` .", "properties": { - "CertificateType": "Indicates whether a TLS/SSL certificate is generated for the fleet." + "CertificateType": "Indicates whether a TLS/SSL certificate is generated for a fleet.\n\nValid values include:\n\n- *GENERATED* - Generate a TLS/SSL certificate for this fleet.\n- *DISABLED* - (default) Do not generate a TLS/SSL certificate for this fleet." } }, "AWS::GameLift::Fleet.IpPermission": { "attributes": {}, - "description": "A range of IP addresses and port settings that allow inbound traffic to connect to server processes on an Amazon GameLift hosting resource. New game sessions that are started on the fleet are assigned an IP address/port number combination, which must fall into the fleet's allowed ranges. For fleets created with a custom game server, the ranges reflect the server's game session assignments. For Realtime Servers fleets, Amazon GameLift automatically opens two port ranges, one for TCP messaging and one for UDP, for use by the Realtime servers.", + "description": "A range of IP addresses and port settings that allow inbound traffic to connect to server processes on an instance in a fleet. New game sessions are assigned an IP address/port number combination, which must fall into the fleet's allowed ranges. Fleets with custom game builds must have permissions explicitly set. For Realtime Servers fleets, GameLift automatically opens two port ranges, one for TCP messaging and one for UDP.", "properties": { - "FromPort": "A starting value for a range of allowed port numbers.\n\nFor fleets using Linux builds, only port 22, 443, 1026-60000 are valid. For fleets using Windows builds, only port 443, 1026-60000 are valid.", + "FromPort": "A starting value for a range of allowed port numbers.\n\nFor fleets using Windows and Linux builds, only ports 1026-60000 are valid.", "IpRange": "A range of allowed IP addresses. This value must be expressed in CIDR notation. Example: \" `000.000.000.000/[subnet mask]` \" or optionally the shortened version \" `0.0.0.0/[subnet mask]` \".", "Protocol": "The network communication protocol used by the fleet.", - "ToPort": "An ending value for a range of allowed port numbers. Port numbers are end-inclusive. This value must be higher than `FromPort` .\n\nFor fleets using Linux builds, only port 22, 443, 1026-60000 are valid. For fleets using Windows builds, only port 443, 1026-60000 are valid." + "ToPort": "An ending value for a range of allowed port numbers. Port numbers are end-inclusive. This value must be higher than `FromPort` .\n\nFor fleets using Windows and Linux builds, only ports 1026-60000 are valid." } }, "AWS::GameLift::Fleet.LocationCapacity": { @@ -17728,7 +17929,7 @@ }, "AWS::GameLift::Fleet.RuntimeConfiguration": { "attributes": {}, - "description": "A collection of server process configurations that describe the processes to run on each instance in a fleet. All fleets must have a runtime configuration. Each instance in the fleet maintains server processes as specified in the runtime configuration, launching new ones as existing processes end. Each instance regularly checks for an updated runtime configuration makes adjustments as called for.\n\nThe runtime configuration enables the instances in a fleet to run multiple processes simultaneously. Potential scenarios are as follows: (1) Run multiple processes of a single game server executable to maximize usage of your hosting resources. (2) Run one or more processes of different executables, such as your game server and a metrics tracking program. (3) Run multiple processes of a single game server but with different launch parameters, for example to run one process on each instance in debug mode.\n\nAn Amazon GameLift instance is limited to 50 processes running simultaneously. A runtime configuration must specify fewer than this limit. To calculate the total number of processes specified in a runtime configuration, add the values of the `ConcurrentExecutions` parameter for each `ServerProcess` object in the runtime configuration.", + "description": "A collection of server process configurations that describe the set of processes to run on each instance in a fleet. Server processes run either an executable in a custom game build or a Realtime Servers script. GameLift launches the configured processes, manages their life cycle, and replaces them as needed. Each instance checks regularly for an updated runtime configuration.\n\nA GameLift instance is limited to 50 processes running concurrently. To calculate the total number of processes in a runtime configuration, add the values of the `ConcurrentExecutions` parameter for each ServerProcess. Learn more about [Running Multiple Processes on a Fleet](https://docs.aws.amazon.com/gamelift/latest/developerguide/fleets-multiprocess.html) .", "properties": { "GameSessionActivationTimeoutSeconds": "The maximum amount of time (in seconds) allowed to launch a new game session and have it report ready to host players. During this time, the game session is in status `ACTIVATING` . If the game session does not become active before the timeout, it is ended and the game session status is changed to `TERMINATED` .", "MaxConcurrentGameSessionActivations": "The number of game sessions in status `ACTIVATING` to allow on an instance. This setting limits the instance resources that can be used for new game activations at any one time.", @@ -17737,7 +17938,7 @@ }, "AWS::GameLift::Fleet.ServerProcess": { "attributes": {}, - "description": "A set of instructions for launching server processes on each instance in a fleet. Each instruction set identifies the location of the server executable, optional launch parameters, and the number of server processes with this configuration to maintain concurrently on the instance. Server process configurations make up a fleet's `RuntimeConfiguration` .", + "description": "A set of instructions for launching server processes on each instance in a fleet. Server processes run either an executable in a custom game build or a Realtime Servers script.", "properties": { "ConcurrentExecutions": "The number of server processes using this configuration that run concurrently on each instance.", "LaunchPath": "The location of a game build executable or the Realtime script file that contains the `Init()` function. Game builds and Realtime scripts are installed on instances at the root:\n\n- Windows (custom game builds only): `C:\\game` . Example: \" `C:\\game\\MyGame\\server.exe` \"\n- Linux: `/local/game` . Examples: \" `/local/game/MyGame/server.exe` \" or \" `/local/game/MyRealtimeScript.js` \"", @@ -17746,32 +17947,32 @@ }, "AWS::GameLift::GameServerGroup": { "attributes": { - "AutoScalingGroupArn": "", - "GameServerGroupArn": "", + "AutoScalingGroupArn": "A unique identifier for the auto scaling group.", + "GameServerGroupArn": "A unique identifier for the game server group.", "Ref": "" }, "description": "*This operation is used with the Amazon GameLift FleetIQ solution and game server groups.*\n\nCreates a GameLift FleetIQ game server group for managing game hosting on a collection of Amazon EC2 instances for game hosting. This operation creates the game server group, creates an Auto Scaling group in your AWS account , and establishes a link between the two groups. You can view the status of your game server groups in the GameLift console. Game server group metrics and events are emitted to Amazon CloudWatch.\n\nBefore creating a new game server group, you must have the following:\n\n- An Amazon EC2 launch template that specifies how to launch Amazon EC2 instances with your game server build. For more information, see [Launching an Instance from a Launch Template](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-launch-templates.html) in the *Amazon EC2 User Guide* .\n- An IAM role that extends limited access to your AWS account to allow GameLift FleetIQ to create and interact with the Auto Scaling group. For more information, see [Create IAM roles for cross-service interaction](https://docs.aws.amazon.com/gamelift/latest/fleetiqguide/gsg-iam-permissions-roles.html) in the *GameLift FleetIQ Developer Guide* .\n\nTo create a new game server group, specify a unique group name, IAM role and Amazon EC2 launch template, and provide a list of instance types that can be used in the group. You must also set initial maximum and minimum limits on the group's instance count. You can optionally set an Auto Scaling policy with target tracking based on a GameLift FleetIQ metric.\n\nOnce the game server group and corresponding Auto Scaling group are created, you have full access to change the Auto Scaling group's configuration as needed. Several properties that are set when creating a game server group, including maximum/minimum size and auto-scaling policy settings, must be updated directly in the Auto Scaling group. Keep in mind that some Auto Scaling group properties are periodically updated by GameLift FleetIQ as part of its balancing activities to optimize for availability and cost.\n\n*Learn more*\n\n[GameLift FleetIQ Guide](https://docs.aws.amazon.com/gamelift/latest/fleetiqguide/gsg-intro.html)", "properties": { - "AutoScalingPolicy": "", + "AutoScalingPolicy": "Configuration settings to define a scaling policy for the Auto Scaling group that is optimized for game hosting. The scaling policy uses the metric `\"PercentUtilizedGameServers\"` to maintain a buffer of idle game servers that can immediately accommodate new games and players. After the Auto Scaling group is created, update this value directly in the Auto Scaling group using the AWS console or APIs.", "BalancingStrategy": "Indicates how GameLift FleetIQ balances the use of Spot Instances and On-Demand Instances in the game server group. Method options include the following:\n\n- `SPOT_ONLY` - Only Spot Instances are used in the game server group. If Spot Instances are unavailable or not viable for game hosting, the game server group provides no hosting capacity until Spot Instances can again be used. Until then, no new instances are started, and the existing nonviable Spot Instances are terminated (after current gameplay ends) and are not replaced.\n- `SPOT_PREFERRED` - (default value) Spot Instances are used whenever available in the game server group. If Spot Instances are unavailable, the game server group continues to provide hosting capacity by falling back to On-Demand Instances. Existing nonviable Spot Instances are terminated (after current gameplay ends) and are replaced with new On-Demand Instances.\n- `ON_DEMAND_ONLY` - Only On-Demand Instances are used in the game server group. No Spot Instances are used, even when available, while this balancing strategy is in force.", - "DeleteOption": "", + "DeleteOption": "The type of delete to perform. To delete a game server group, specify the `DeleteOption` . Options include the following:\n\n- `SAFE_DELETE` \u2013 (default) Terminates the game server group and Amazon EC2 Auto Scaling group only when it has no game servers that are in `UTILIZED` status.\n- `FORCE_DELETE` \u2013 Terminates the game server group, including all active game servers regardless of their utilization status, and the Amazon EC2 Auto Scaling group.\n- `RETAIN` \u2013 Does a safe delete of the game server group but retains the Amazon EC2 Auto Scaling group as is.", "GameServerGroupName": "A developer-defined identifier for the game server group. The name is unique for each Region in each AWS account.", "GameServerProtectionPolicy": "A flag that indicates whether instances in the game server group are protected from early termination. Unprotected instances that have active game servers running might be terminated during a scale-down event, causing players to be dropped from the game. Protected instances cannot be terminated while there are active game servers running except in the event of a forced game server group deletion (see ). An exception to this is with Spot Instances, which can be terminated by AWS regardless of protection status.", "InstanceDefinitions": "The set of Amazon EC2 instance types that GameLift FleetIQ can use when balancing and automatically scaling instances in the corresponding Auto Scaling group.", - "LaunchTemplate": "", - "MaxSize": "", - "MinSize": "", + "LaunchTemplate": "The Amazon EC2 launch template that contains configuration settings and game server code to be deployed to all instances in the game server group. You can specify the template using either the template name or ID. For help with creating a launch template, see [Creating a Launch Template for an Auto Scaling Group](https://docs.aws.amazon.com/autoscaling/ec2/userguide/create-launch-template.html) in the *Amazon Elastic Compute Cloud Auto Scaling User Guide* . After the Auto Scaling group is created, update this value directly in the Auto Scaling group using the AWS console or APIs.\n\n> If you specify network interfaces in your launch template, you must explicitly set the property `AssociatePublicIpAddress` to \"true\". If no network interface is specified in the launch template, GameLift FleetIQ uses your account's default VPC.", + "MaxSize": "The maximum number of instances allowed in the Amazon EC2 Auto Scaling group. During automatic scaling events, GameLift FleetIQ and EC2 do not scale up the group above this maximum. After the Auto Scaling group is created, update this value directly in the Auto Scaling group using the AWS console or APIs.", + "MinSize": "The minimum number of instances allowed in the Amazon EC2 Auto Scaling group. During automatic scaling events, GameLift FleetIQ and Amazon EC2 do not scale down the group below this minimum. In production, this value should be set to at least 1. After the Auto Scaling group is created, update this value directly in the Auto Scaling group using the AWS console or APIs.", "RoleArn": "The Amazon Resource Name ( [ARN](https://docs.aws.amazon.com/AmazonS3/latest/dev/s3-arn-format.html) ) for an IAM role that allows Amazon Web Services to access your Amazon EC2 Auto Scaling groups.", - "Tags": "", - "VpcSubnets": "" + "Tags": "A list of labels to assign to the new game server group resource. Tags are developer-defined key-value pairs. Tagging AWS resources is useful for resource management, access management, and cost allocation. For more information, see [Tagging AWS Resources](https://docs.aws.amazon.com/general/latest/gr/aws_tagging.html) in the *AWS General Reference* . Once the resource is created, you can use TagResource, UntagResource, and ListTagsForResource to add, remove, and view tags, respectively. The maximum tag limit may be lower than stated. See the AWS General Reference for actual tagging limits.", + "VpcSubnets": "A list of virtual private cloud (VPC) subnets to use with instances in the game server group. By default, all GameLift FleetIQ-supported Availability Zones are used. You can use this parameter to specify VPCs that you've set up. This property cannot be updated after the game server group is created, and the corresponding Auto Scaling group will always use the property value that is set with this request, even if the Auto Scaling group is updated directly." } }, "AWS::GameLift::GameServerGroup.AutoScalingPolicy": { "attributes": {}, - "description": "", + "description": "*This data type is used with the GameLift FleetIQ and game server groups.*\n\nConfiguration settings for intelligent automatic scaling that uses target tracking. After the Auto Scaling group is created, all updates to Auto Scaling policies, including changing this policy and adding or removing other policies, is done directly on the Auto Scaling group.", "properties": { - "EstimatedInstanceWarmup": "", - "TargetTrackingConfiguration": "" + "EstimatedInstanceWarmup": "Length of time, in seconds, it takes for a new instance to start new game server processes and register with GameLift FleetIQ. Specifying a warm-up time can be useful, particularly with game servers that take a long time to start up, because it avoids prematurely starting new instances.", + "TargetTrackingConfiguration": "Settings for a target-based scaling policy applied to Auto Scaling group. These settings are used to create a target-based policy that tracks the GameLift FleetIQ metric `PercentUtilizedGameServers` and specifies a target value for the metric. As player usage changes, the policy triggers to adjust the game server group capacity so that the metric returns to the target value." } }, "AWS::GameLift::GameServerGroup.InstanceDefinition": { @@ -17784,11 +17985,11 @@ }, "AWS::GameLift::GameServerGroup.LaunchTemplate": { "attributes": {}, - "description": "", + "description": "*This data type is used with the GameLift FleetIQ and game server groups.*\n\nAn Amazon EC2 launch template that contains configuration settings and game server code to be deployed to all instances in a game server group. The launch template is specified when creating a new game server group with `GameServerGroup` .", "properties": { - "LaunchTemplateId": "", - "LaunchTemplateName": "", - "Version": "" + "LaunchTemplateId": "A unique identifier for an existing Amazon EC2 launch template.", + "LaunchTemplateName": "A readable identifier for an existing Amazon EC2 launch template.", + "Version": "The version of the Amazon EC2 launch template to use. If no version is specified, the default version will be used. With Amazon EC2, you can specify a default version for a launch template. If none is set, the default is the first version created." } }, "AWS::GameLift::GameServerGroup.TargetTrackingConfiguration": { @@ -17813,20 +18014,20 @@ "NotificationTarget": "An SNS topic ARN that is set up to receive game session placement notifications. See [Setting up notifications for game session placement](https://docs.aws.amazon.com/gamelift/latest/developerguide/queue-notification.html) .", "PlayerLatencyPolicies": "A set of policies that act as a sliding cap on player latency. FleetIQ works to deliver low latency for most players in a game session. These policies ensure that no individual player can be placed into a game with unreasonably high latency. Use multiple policies to gradually relax latency requirements a step at a time. Multiple policies are applied based on their maximum allowed latency, starting with the lowest value.", "PriorityConfiguration": "Custom settings to use when prioritizing destinations and locations for game session placements. This configuration replaces the FleetIQ default prioritization process. Priority types that are not explicitly named will be automatically applied at the end of the prioritization process.", - "Tags": "A list of labels to assign to the new game session queue resource. Tags are developer-defined key-value pairs. Tagging AWS resources are useful for resource management, access management and cost allocation. For more information, see [Tagging AWS Resources](https://docs.aws.amazon.com/general/latest/gr/aws_tagging.html) in the *AWS General Reference* . Once the resource is created, you can use `TagResource` , `UntagResource` , and `ListTagsForResource` to add, remove, and view tags. The maximum tag limit may be lower than stated. See the AWS General Reference for actual tagging limits.", + "Tags": "A list of labels to assign to the new game session queue resource. Tags are developer-defined key-value pairs. Tagging AWS resources are useful for resource management, access management and cost allocation. For more information, see [Tagging AWS Resources](https://docs.aws.amazon.com/general/latest/gr/aws_tagging.html) in the *AWS General Reference* . Once the resource is created, you can use TagResource, UntagResource, and ListTagsForResource to add, remove, and view tags. The maximum tag limit may be lower than stated. See the AWS General Reference for actual tagging limits.", "TimeoutInSeconds": "The maximum time, in seconds, that a new game session placement request remains in the queue. When a request exceeds this time, the game session placement changes to a `TIMED_OUT` status." } }, "AWS::GameLift::GameSessionQueue.Destination": { "attributes": {}, - "description": "The fleet designated in a game session queue. Requests for new game sessions in the queue are fulfilled by starting a new game session on any destination that is configured for a queue.", + "description": "A fleet or alias designated in a game session queue. Queues fulfill requests for new game sessions by placing a new game session on any of the queue's destinations.", "properties": { "DestinationArn": "The Amazon Resource Name (ARN) that is assigned to fleet or fleet alias. ARNs, which include a fleet ID or alias ID and a Region name, provide a unique identifier across all Regions." } }, "AWS::GameLift::GameSessionQueue.FilterConfiguration": { "attributes": {}, - "description": "A list of fleet locations where a game session queue can place new game sessions. You can use a filter to temporarily turn off placements for specific locations. For queues that have multi-location fleets, you can use a filter configuration allow placement with some, but not all of these locations.\n\nFilter configurations are part of a `GameSessionQueue` .", + "description": "A list of fleet locations where a game session queue can place new game sessions. You can use a filter to temporarily turn off placements for specific locations. For queues that have multi-location fleets, you can use a filter configuration allow placement with some, but not all of these locations.", "properties": { "AllowedLocations": "A list of locations to allow game session placement in, in the form of AWS Region codes such as `us-west-2` ." } @@ -17841,7 +18042,7 @@ }, "AWS::GameLift::GameSessionQueue.PriorityConfiguration": { "attributes": {}, - "description": "Custom prioritization settings for use by a game session queue when placing new game sessions with available game servers. When defined, this configuration replaces the default FleetIQ prioritization process, which is as follows:\n\n- If player latency data is included in a game session request, destinations and locations are prioritized first based on lowest average latency (1), then on lowest hosting cost (2), then on destination list order (3), and finally on location (alphabetical) (4). This approach ensures that the queue's top priority is to place game sessions where average player latency is lowest, and--if latency is the same--where the hosting cost is less, etc.\n- If player latency data is not included, destinations and locations are prioritized first on destination list order (1), and then on location (alphabetical) (2). This approach ensures that the queue's top priority is to place game sessions on the first destination fleet listed. If that fleet has multiple locations, the game session is placed on the first location (when listed alphabetically).\n\nChanging the priority order will affect how game sessions are placed.\n\nPriority configurations are part of a `GameSessionQueue` .", + "description": "Custom prioritization settings for use by a game session queue when placing new game sessions with available game servers. When defined, this configuration replaces the default FleetIQ prioritization process, which is as follows:\n\n- If player latency data is included in a game session request, destinations and locations are prioritized first based on lowest average latency (1), then on lowest hosting cost (2), then on destination list order (3), and finally on location (alphabetical) (4). This approach ensures that the queue's top priority is to place game sessions where average player latency is lowest, and--if latency is the same--where the hosting cost is less, etc.\n- If player latency data is not included, destinations and locations are prioritized first on destination list order (1), and then on location (alphabetical) (2). This approach ensures that the queue's top priority is to place game sessions on the first destination fleet listed. If that fleet has multiple locations, the game session is placed on the first location (when listed alphabetically).\n\nChanging the priority order will affect how game sessions are placed.", "properties": { "LocationOrder": "The prioritization order to use for fleet locations, when the `PriorityOrder` property includes `LOCATION` . Locations are identified by AWS Region codes such as `us-west-2` . Each location can only be listed once.", "PriorityOrder": "The recommended sequence to use when prioritizing where to place new game sessions. Each type can only be listed once.\n\n- `LATENCY` -- FleetIQ prioritizes locations where the average player latency (provided in each game session request) is lowest.\n- `COST` -- FleetIQ prioritizes destinations with the lowest current hosting costs. Cost is evaluated based on the location, instance type, and fleet type (Spot or On-Demand) for each destination in the queue.\n- `DESTINATION` -- FleetIQ prioritizes based on the order that destinations are listed in the queue configuration.\n- `LOCATION` -- FleetIQ prioritizes based on the provided order of locations, as defined in `LocationOrder` ." @@ -17859,22 +18060,22 @@ "AcceptanceTimeoutSeconds": "The length of time (in seconds) to wait for players to accept a proposed match, if acceptance is required.", "AdditionalPlayerCount": "The number of player slots in a match to keep open for future players. For example, if the configuration's rule set specifies a match for a single 12-person team, and the additional player count is set to 2, only 10 players are selected for the match. This parameter is not used if `FlexMatchMode` is set to `STANDALONE` .", "BackfillMode": "The method used to backfill game sessions that are created with this matchmaking configuration. Specify `MANUAL` when your game manages backfill requests manually or does not use the match backfill feature. Specify `AUTOMATIC` to have GameLift create a `StartMatchBackfill` request whenever a game session has one or more open slots. Learn more about manual and automatic backfill in [Backfill Existing Games with FlexMatch](https://docs.aws.amazon.com/gamelift/latest/flexmatchguide/match-backfill.html) . Automatic backfill is not available when `FlexMatchMode` is set to `STANDALONE` .", - "CustomEventData": "Information that is attached to all events related to the matchmaking configuration.", + "CustomEventData": "Information to add to all events related to the matchmaking configuration.", "Description": "A descriptive label that is associated with matchmaking configuration.", - "FlexMatchMode": "Indicates whether this matchmaking configuration is being used with GameLift managed hosting or as a standalone matchmaking solution.\n\n- *STANDALONE* - FlexMatch forms matches and returns match information, including players and team assignments, in a [MatchmakingSucceeded](https://docs.aws.amazon.com/gamelift/latest/flexmatchguide/match-events.html#match-events-matchmakingsucceeded) event.\n- *WITH_QUEUE* - FlexMatch forms matches and uses the specified GameLift queue to start a game session for the match.", + "FlexMatchMode": "Indicates whether this matchmaking configuration is being used with GameLift hosting or as a standalone matchmaking solution.\n\n- *STANDALONE* - FlexMatch forms matches and returns match information, including players and team assignments, in a [MatchmakingSucceeded](https://docs.aws.amazon.com/gamelift/latest/flexmatchguide/match-events.html#match-events-matchmakingsucceeded) event.\n- *WITH_QUEUE* - FlexMatch forms matches and uses the specified GameLift queue to start a game session for the match.", "GameProperties": "A set of custom properties for a game session, formatted as key-value pairs. These properties are passed to a game server process with a request to start a new game session. See [Start a Game Session](https://docs.aws.amazon.com/gamelift/latest/developerguide/gamelift-sdk-server-api.html#gamelift-sdk-server-startsession) . This parameter is not used if `FlexMatchMode` is set to `STANDALONE` .", "GameSessionData": "A set of custom game session properties, formatted as a single string value. This data is passed to a game server process with a request to start a new game session. See [Start a Game Session](https://docs.aws.amazon.com/gamelift/latest/developerguide/gamelift-sdk-server-api.html#gamelift-sdk-server-startsession) . This parameter is not used if `FlexMatchMode` is set to `STANDALONE` .", "GameSessionQueueArns": "The Amazon Resource Name ( [ARN](https://docs.aws.amazon.com/AmazonS3/latest/dev/s3-arn-format.html) ) that is assigned to a GameLift game session queue resource and uniquely identifies it. ARNs are unique across all Regions. Format is `arn:aws:gamelift:::gamesessionqueue/` . Queues can be located in any Region. Queues are used to start new GameLift-hosted game sessions for matches that are created with this matchmaking configuration. If `FlexMatchMode` is set to `STANDALONE` , do not set this parameter.", - "Name": "A unique identifier for a matchmaking configuration. Matchmaking requests use this name to identify which matchmaking configuration to use.", + "Name": "A unique identifier for the matchmaking configuration. This name is used to identify the configuration associated with a matchmaking request or ticket.", "NotificationTarget": "An SNS topic ARN that is set up to receive matchmaking notifications. See [Setting up notifications for matchmaking](https://docs.aws.amazon.com/gamelift/latest/flexmatchguide/match-notification.html) for more information.", "RequestTimeoutSeconds": "The maximum duration, in seconds, that a matchmaking ticket can remain in process before timing out. Requests that fail due to timing out can be resubmitted as needed.", "RuleSetName": "A unique identifier for the matchmaking rule set to use with this configuration. You can use either the rule set name or ARN value. A matchmaking configuration can only use rule sets that are defined in the same Region.", - "Tags": "A list of labels to assign to the new matchmaking configuration resource. Tags are developer-defined key-value pairs. Tagging AWS resources are useful for resource management, access management and cost allocation. For more information, see [Tagging AWS Resources](https://docs.aws.amazon.com/general/latest/gr/aws_tagging.html) in the *AWS General Reference* . Once the resource is created, you can use `TagResource` , `UntagResource` , and `ListTagsForResource` to add, remove, and view tags. The maximum tag limit may be lower than stated. See the AWS General Reference for actual tagging limits." + "Tags": "A list of labels to assign to the new matchmaking configuration resource. Tags are developer-defined key-value pairs. Tagging AWS resources are useful for resource management, access management and cost allocation. For more information, see [Tagging AWS Resources](https://docs.aws.amazon.com/general/latest/gr/aws_tagging.html) in the *AWS General Reference* . Once the resource is created, you can use TagResource, UntagResource, and ListTagsForResource to add, remove, and view tags. The maximum tag limit may be lower than stated. See the AWS General Reference for actual tagging limits." } }, "AWS::GameLift::MatchmakingConfiguration.GameProperty": { "attributes": {}, - "description": "A set of key-value pairs that contain information about a game session. When included in a game session request, these properties communicate details to be used when setting up the new game session. For example, a property might specify a game mode, level, or map. Game properties are passed to the game server process when initiating a new game session.", + "description": "Set of key-value pairs that contain information about a game session. When included in a game session request, these properties communicate details to be used when setting up the new game session. For example, a game property might specify a game mode, level, or map. Game properties are passed to the game server process when initiating a new game session. For more information, see the [GameLift Developer Guide](https://docs.aws.amazon.com/gamelift/latest/developerguide/gamelift-sdk-client-api.html#gamelift-sdk-client-api-create) .", "properties": { "Key": "The game property identifier.", "Value": "The game property value." @@ -17886,11 +18087,11 @@ "Name": "The unique name of the rule set.", "Ref": "`Ref` returns the rule set name, which is unique within each Region." }, - "description": "The `AWS::GameLift::MatchmakingRuleSet` resource creates a new rule set for FlexMatch matchmaking. A rule set describes the type of match to create, such as the number and size of teams. It also sets the parameters for acceptable player matches, such as minimum skill level or character type. A rule set is used by a matchmaking configuration.", + "description": "Creates a new rule set for FlexMatch matchmaking. A rule set describes the type of match to create, such as the number and size of teams. It also sets the parameters for acceptable player matches, such as minimum skill level or character type.\n\nTo create a matchmaking rule set, provide unique rule set name and the rule set body in JSON format. Rule sets must be defined in the same Region as the matchmaking configuration they are used with.\n\nSince matchmaking rule sets cannot be edited, it is a good idea to check the rule set syntax.\n\n*Learn more*\n\n- [Build a rule set](https://docs.aws.amazon.com/gamelift/latest/flexmatchguide/match-rulesets.html)\n- [Design a matchmaker](https://docs.aws.amazon.com/gamelift/latest/flexmatchguide/match-configuration.html)\n- [Matchmaking with FlexMatch](https://docs.aws.amazon.com/gamelift/latest/flexmatchguide/match-intro.html)", "properties": { "Name": "A unique identifier for the matchmaking rule set. A matchmaking configuration identifies the rule set it uses by this name value. Note that the rule set name is different from the optional `name` field in the rule set body.", "RuleSetBody": "A collection of matchmaking rules, formatted as a JSON string. Comments are not allowed in JSON, but most elements support a description field.", - "Tags": "A list of labels to assign to the new matchmaking rule set resource. Tags are developer-defined key-value pairs. Tagging AWS resources are useful for resource management, access management and cost allocation. For more information, see [Tagging AWS Resources](https://docs.aws.amazon.com/general/latest/gr/aws_tagging.html) in the *AWS General Reference* . Once the resource is created, you can use `TagResource` , `UntagResource` , and `ListTagsForResource` to add, remove, and view tags. The maximum tag limit may be lower than stated. See the AWS General Reference for actual tagging limits." + "Tags": "A list of labels to assign to the new matchmaking rule set resource. Tags are developer-defined key-value pairs. Tagging AWS resources are useful for resource management, access management and cost allocation. For more information, see [Tagging AWS Resources](https://docs.aws.amazon.com/general/latest/gr/aws_tagging.html) in the *AWS General Reference* . Once the resource is created, you can use TagResource, UntagResource, and ListTagsForResource to add, remove, and view tags. The maximum tag limit may be lower than stated. See the AWS General Reference for actual tagging limits." } }, "AWS::GameLift::Script": { @@ -17902,8 +18103,8 @@ "description": "The `AWS::GameLift::Script` resource creates a new script record for your Realtime Servers script. Realtime scripts are JavaScript that provide configuration settings and optional custom game logic for your game. The script is deployed when you create a Realtime Servers fleet to host your game sessions. Script logic is executed during an active game session.", "properties": { "Name": "A descriptive label that is associated with a script. Script names do not need to be unique.", - "StorageLocation": "The location in Amazon S3 where build or script files are stored for access by Amazon GameLift.", - "Tags": "", + "StorageLocation": "The location of the Amazon S3 bucket where a zipped file containing your Realtime scripts is stored. The storage location must specify the Amazon S3 bucket name, the zip file name (the \"key\"), and a role ARN that allows Amazon Web Services to access the Amazon S3 storage location. The S3 bucket must be in the same Region where you want to create a new script. By default, Amazon Web Services uploads the latest version of the zip file; if you have S3 object versioning turned on, you can use the `ObjectVersion` parameter to specify an earlier version.", + "Tags": "A list of labels to assign to the new script resource. Tags are developer-defined key-value pairs. Tagging AWS resources are useful for resource management, access management and cost allocation. For more information, see [Tagging AWS Resources](https://docs.aws.amazon.com/general/latest/gr/aws_tagging.html) in the *AWS General Reference* . Once the resource is created, you can use TagResource, UntagResource, and ListTagsForResource to add, remove, and view tags. The maximum tag limit may be lower than stated. See the AWS General Reference for actual tagging limits.", "Version": "The version that is associated with a build or script. Version strings do not need to be unique." } }, @@ -20230,7 +20431,7 @@ "Platform": "The platform of the component. For example, `Windows` .", "SupportedOsVersions": "The operating system (OS) version supported by the component. If the OS information is available, a prefix match is performed against the base image OS version during image recipe creation.", "Tags": "The tags associated with the component.", - "Uri": "The uri of the component. Must be an Amazon S3 URL and the requester must have permission to access the Amazon S3 bucket. If you use Amazon S3, you can specify component content up to your service quota. Either `data` or `uri` can be used to specify the data within the component.", + "Uri": "The `uri` of a YAML component document file. This must be an S3 URL ( `s3://bucket/key` ), and the requester must have permission to access the S3 bucket it points to. If you use Amazon S3, you can specify component content up to your service quota.\n\nAlternatively, you can specify the YAML document inline, using the component `data` property. You cannot specify both properties.", "Version": "The component version. For example, `1.0.0` ." } }, @@ -20344,6 +20545,7 @@ "attributes": { "Arn": "Returns the Amazon Resource Name (ARN) of the image. For example, `arn:aws:imagebuilder:us-west-2:123456789012:image/mybasicrecipe/2019.12.03/1` .", "ImageId": "Returns the AMI ID of the Amazon EC2 AMI in the Region in which you are using Image Builder.", + "ImageUri": "", "Name": "Returns the name of the image.", "Ref": "`Ref` returns the resource ARN, such as `arn:aws:imagebuilder:us-west-2:123456789012:image/my-example-image` ." }, @@ -20427,7 +20629,7 @@ "description": "In addition to your infrastruction configuration, these settings provide an extra layer of control over your build instances. For instances where Image Builder installs the Systems Manager agent, you can choose whether to keep it for the AMI that you create. You can also specify commands to run on launch for all of your build instances.", "properties": { "SystemsManagerAgent": "Contains settings for the Systems Manager agent on your build instance.", - "UserDataOverride": "Use this property to provide commands or a command script to run when you launch your build instance.\n\n> The userDataOverride property replaces any commands that Image Builder might have added to ensure that Systems Manager is installed on your Linux build instance. If you override the user data, make sure that you add commands to install Systems Manager, if it is not pre-installed on your base image." + "UserDataOverride": "Use this property to provide commands or a command script to run when you launch your build instance.\n\nThe userDataOverride property replaces any commands that Image Builder might have added to ensure that Systems Manager is installed on your Linux build instance. If you override the user data, make sure that you add commands to install Systems Manager, if it is not pre-installed on your base image.\n\n> The user data is always base 64 encoded. For example, the following commands are encoded as `IyEvYmluL2Jhc2gKbWtkaXIgLXAgL3Zhci9iYi8KdG91Y2ggL3Zhci$` :\n> \n> *#!/bin/bash*\n> \n> mkdir -p /var/bb/\n> \n> touch /var" } }, "AWS::ImageBuilder::ImageRecipe.ComponentConfiguration": { @@ -20678,6 +20880,7 @@ "properties": { "AuthorizerFunctionArn": "The authorizer's Lambda function ARN.", "AuthorizerName": "The authorizer name.", + "EnableCachingForHttp": "", "SigningDisabled": "Specifies whether AWS IoT validates the token signature in an authorization request.", "Status": "The status of the authorizer.\n\nValid values: `ACTIVE` | `INACTIVE`", "Tags": "Metadata which can be used to manage the custom authorizer.\n\n> For URI Request parameters use format: ...key1=value1&key2=value2...\n> \n> For the CLI command-line parameter use format: &&tags \"key1=value1&key2=value2...\"\n> \n> For the cli-input-json file use format: \"tags\": \"key1=value1&key2=value2...\"", @@ -20707,9 +20910,9 @@ }, "description": "Use the `AWS::IoT::CustomMetric` resource to define a custom metric published by your devices to Device Defender. For API reference, see [CreateCustomMetric](https://docs.aws.amazon.com/iot/latest/apireference/API_CreateCustomMetric.html) and for general information, see [Custom metrics](https://docs.aws.amazon.com/iot/latest/developerguide/dd-detect-custom-metrics.html) .", "properties": { - "DisplayName": "Field that represents a friendly name in the console for the custom metric; it doesn't have to be unique. Don't use this name as the metric identifier in the device metric report. Can be updated.", - "MetricName": "The name of the custom metric. This will be used in the metric report submitted from the device/thing. It shouldn't begin with `aws:` . Cannot be updated once it's defined.", - "MetricType": "The type of the custom metric. Types include `string-list` , `ip-address-list` , and `number-list` .", + "DisplayName": "The friendly name in the console for the custom metric. This name doesn't have to be unique. Don't use this name as the metric identifier in the device metric report. You can update the friendly name after you define it.", + "MetricName": "The name of the custom metric. This will be used in the metric report submitted from the device/thing. The name can't begin with `aws:` . You can\u2019t change the name after you define it.", + "MetricType": "The type of the custom metric. Types include `string-list` , `ip-address-list` , `number-list` , and `number` .\n\n> The type `number` only takes a single metric value as an input, but when you submit the metrics value in the DeviceMetrics report, you must pass it as an array with a single value.", "Tags": "Metadata that can be used to manage the custom metric." } }, @@ -22295,8 +22498,9 @@ }, "AWS::IoTSiteWise::Asset": { "attributes": { - "AssetId": "", - "Ref": "`Ref` returns the `AssetId` ." + "AssetArn": "The ARN of the asset.", + "AssetId": "The ID of the asset.", + "Ref": "`Ref` returns `AssetId` and `AssetArn` ." }, "description": "Creates an asset from an existing asset model. For more information, see [Creating assets](https://docs.aws.amazon.com/iot-sitewise/latest/userguide/create-assets.html) in the *AWS IoT SiteWise User Guide* .", "properties": { @@ -22424,7 +22628,7 @@ "description": "Contains a tumbling window, which is a repeating fixed-sized, non-overlapping, and contiguous time window. You can use this window in metrics to aggregate data from properties and other assets.\n\nYou can use `m` , `h` , `d` , and `w` when you specify an interval or offset. Note that `m` represents minutes, `h` represents hours, `d` represents days, and `w` represents weeks. You can also use `s` to represent seconds in `offset` .\n\nThe `interval` and `offset` parameters support the [ISO 8601 format](https://docs.aws.amazon.com/https://en.wikipedia.org/wiki/ISO_8601) . For example, `PT5S` represents 5 seconds, `PT5M` represents 5 minutes, and `PT5H` represents 5 hours.", "properties": { "Interval": "The time interval for the tumbling window. The interval time must be between 1 minute and 1 week.\n\nAWS IoT SiteWise computes the `1w` interval the end of Sunday at midnight each week (UTC), the `1d` interval at the end of each day at midnight (UTC), the `1h` interval at the end of each hour, and so on.\n\nWhen AWS IoT SiteWise aggregates data points for metric computations, the start of each interval is exclusive and the end of each interval is inclusive. AWS IoT SiteWise places the computed data point at the end of the interval.", - "Offset": "" + "Offset": "The offset for the tumbling window. The `offset` parameter accepts the following:\n\n- The offset time.\n\nFor example, if you specify `18h` for `offset` and `1d` for `interval` , AWS IoT SiteWise aggregates data in one of the following ways:\n\n- If you create the metric before or at 6 PM (UTC), you get the first aggregation result at 6 PM (UTC) on the day when you create the metric.\n- If you create the metric after 6 PM (UTC), you get the first aggregation result at 6 PM (UTC) the next day.\n- The ISO 8601 format.\n\nFor example, if you specify `PT18H` for `offset` and `1d` for `interval` , AWS IoT SiteWise aggregates data in one of the following ways:\n\n- If you create the metric before or at 6 PM (UTC), you get the first aggregation result at 6 PM (UTC) on the day when you create the metric.\n- If you create the metric after 6 PM (UTC), you get the first aggregation result at 6 PM (UTC) the next day.\n- The 24-hour clock.\n\nFor example, if you specify `00:03:00` for `offset` , `5m` for `interval` , and you create the metric at 2 PM (UTC), you get the first aggregation result at 2:03 PM (UTC). You get the second aggregation result at 2:08 PM (UTC).\n- The offset time zone.\n\nFor example, if you specify `2021-07-23T18:00-08` for `offset` and `1d` for `interval` , AWS IoT SiteWise aggregates data in one of the following ways:\n\n- If you create the metric before or at 6 PM (PST), you get the first aggregation result at 6 PM (PST) on the day when you create the metric.\n- If you create the metric after 6 PM (PST), you get the first aggregation result at 6 PM (PST) the next day." } }, "AWS::IoTSiteWise::AssetModel.VariableValue": { @@ -22476,7 +22680,7 @@ "description": "Contains a gateway's platform information.", "properties": { "Greengrass": "A gateway that runs on AWS IoT Greengrass .", - "GreengrassV2": "" + "GreengrassV2": "A gateway that runs on AWS IoT Greengrass V2." } }, "AWS::IoTSiteWise::Gateway.Greengrass": { @@ -22488,9 +22692,9 @@ }, "AWS::IoTSiteWise::Gateway.GreengrassV2": { "attributes": {}, - "description": "", + "description": "Contains details for a gateway that runs on AWS IoT Greengrass V2. To create a gateway that runs on AWS IoT Greengrass V2, you must deploy the IoT SiteWise Edge component to your gateway device. Your [Greengrass device role](https://docs.aws.amazon.com/greengrass/v2/developerguide/device-service-role.html) must use the `AWSIoTSiteWiseEdgeAccess` policy. For more information, see [Using AWS IoT SiteWise at the edge](https://docs.aws.amazon.com/iot-sitewise/latest/userguide/sw-gateways.html) in the *AWS IoT SiteWise User Guide* .", "properties": { - "CoreDeviceThingName": "" + "CoreDeviceThingName": "The name of the AWS IoT thing for your AWS IoT Greengrass V2 core device." } }, "AWS::IoTSiteWise::Portal": { @@ -22521,7 +22725,7 @@ }, "description": "Creates a project in the specified portal.\n\n> Make sure that the project name and description don't contain confidential information.", "properties": { - "AssetIds": "", + "AssetIds": "A list that contains the IDs of each asset associated with the project.", "PortalId": "The ID of the portal in which to create the project.", "ProjectDescription": "A description for the project.", "ProjectName": "A friendly name for the project.", @@ -22947,6 +23151,7 @@ }, "description": "Specifies a data source that you use to with an Amazon Kendra index.\n\nYou specify a name, connector type and description for your data source.", "properties": { + "CustomDocumentEnrichmentConfiguration": "", "DataSourceConfiguration": "Configuration information for an Amazon Kendra data source. The contents of the configuration depend on the type of data source. You can only specify one type of data source in the configuration. Choose from one of the following data sources.\n\n- Amazon S3\n- Confluence\n- Custom\n- Database\n- Microsoft OneDrive\n- Microsoft SharePoint\n- Salesforce\n- ServiceNow\n\nYou can't specify the `Configuration` parameter when the `Type` parameter is set to `CUSTOM` .\n\nThe `Configuration` parameter is required for all other data sources.", "Description": "A description of the data source.", "IndexId": "The identifier of the index that should be associated with this data source.", @@ -23078,6 +23283,16 @@ "TableName": "The name of the table that contains the document data." } }, + "AWS::Kendra::DataSource.CustomDocumentEnrichmentConfiguration": { + "attributes": {}, + "description": "Provides the configuration information for altering document metadata and content during the document ingestion process.\n\nFor more information, see [Customizing document metadata during the ingestion process](https://docs.aws.amazon.com/kendra/latest/dg/custom-document-enrichment.html) .", + "properties": { + "InlineConfigurations": "Configuration information to alter document attributes or metadata fields and content when ingesting documents into Amazon Kendra.", + "PostExtractionHookConfiguration": "Configuration information for invoking a Lambda function in AWS Lambda on the structured documents with their metadata and text extracted. You can use a Lambda function to apply advanced logic for creating, modifying, or deleting document metadata and content. For more information, see [Advanced data manipulation](https://docs.aws.amazon.com/kendra/latest/dg/custom-document-enrichment.html#advanced-data-manipulation) .", + "PreExtractionHookConfiguration": "Configuration information for invoking a Lambda function in AWS Lambda on the original or raw documents before extracting their metadata and text. You can use a Lambda function to apply advanced logic for creating, modifying, or deleting document metadata and content. For more information, see [Advanced data manipulation](https://docs.aws.amazon.com/kendra/latest/dg/custom-document-enrichment.html#advanced-data-manipulation) .", + "RoleArn": "The Amazon Resource Name (ARN) of a role with permission to run `PreExtractionHookConfiguration` and `PostExtractionHookConfiguration` for altering document metadata and content during the document ingestion process. For more information, see [IAM roles for Amazon Kendra](https://docs.aws.amazon.com/kendra/latest/dg/iam-roles.html) ." + } + }, "AWS::Kendra::DataSource.DataSourceConfiguration": { "attributes": {}, "description": "Provides the configuration information for an Amazon Kendra data source.", @@ -23123,6 +23338,34 @@ "VpcConfiguration": "Provides information for connecting to an Amazon VPC." } }, + "AWS::Kendra::DataSource.DocumentAttributeCondition": { + "attributes": {}, + "description": "The condition used for the target document attribute or metadata field when ingesting documents into Amazon Kendra. You use this with [DocumentAttributeTarget to apply the condition](https://docs.aws.amazon.com/kendra/latest/dg/API_DocumentAttributeTarget.html) .\n\nFor example, you can create the 'Department' target field and have it prefill department names associated with the documents based on information in the 'Source_URI' field. Set the condition that if the 'Source_URI' field contains 'financial' in its URI value, then prefill the target field 'Department' with the target value 'Finance' for the document.\n\nAmazon Kendra cannot create a target field if it has not already been created as an index field. After you create your index field, you can create a document metadata field using `DocumentAttributeTarget` . Amazon Kendra then will map your newly created metadata field to your index field.", + "properties": { + "ConditionDocumentAttributeKey": "The identifier of the document attribute used for the condition.\n\nFor example, 'Source_URI' could be an identifier for the attribute or metadata field that contains source URIs associated with the documents.\n\nAmazon Kendra currently does not support `_document_body` as an attribute key used for the condition.", + "ConditionOnValue": "The value used by the operator.\n\nFor example, you can specify the value 'financial' for strings in the 'Source_URI' field that partially match or contain this value.", + "Operator": "The condition operator.\n\nFor example, you can use 'Contains' to partially match a string." + } + }, + "AWS::Kendra::DataSource.DocumentAttributeTarget": { + "attributes": {}, + "description": "The target document attribute or metadata field you want to alter when ingesting documents into Amazon Kendra.\n\nFor example, you can delete customer identification numbers associated with the documents, stored in the document metadata field called 'Customer_ID'. You set the target key as 'Customer_ID' and the deletion flag to `TRUE` . This removes all customer ID values in the field 'Customer_ID'. This would scrub personally identifiable information from each document's metadata.\n\nAmazon Kendra cannot create a target field if it has not already been created as an index field. After you create your index field, you can create a document metadata field using `DocumentAttributeTarget` . Amazon Kendra then will map your newly created metadata field to your index field.\n\nYou can also use this with [DocumentAttributeCondition](https://docs.aws.amazon.com/kendra/latest/dg/API_DocumentAttributeCondition.html) .", + "properties": { + "TargetDocumentAttributeKey": "The identifier of the target document attribute or metadata field.\n\nFor example, 'Department' could be an identifier for the target attribute or metadata field that includes the department names associated with the documents.", + "TargetDocumentAttributeValue": "The target value you want to create for the target attribute.\n\nFor example, 'Finance' could be the target value for the target attribute key 'Department'.", + "TargetDocumentAttributeValueDeletion": "`TRUE` to delete the existing target value for your specified target attribute key. You cannot create a target value and set this to `TRUE` . To create a target value ( `TargetDocumentAttributeValue` ), set this to `FALSE` ." + } + }, + "AWS::Kendra::DataSource.DocumentAttributeValue": { + "attributes": {}, + "description": "The value of a custom document attribute. You can only provide one value for a custom attribute.", + "properties": { + "DateValue": "A date expressed as an ISO 8601 string.\n\nIt is important for the time zone to be included in the ISO 8601 date-time format. For example, 2012-03-25T12:30:10+01:00 is the ISO 8601 date-time format for March 25th 2012 at 12:30PM (plus 10 seconds) in Central European Time.", + "LongValue": "A long integer value.", + "StringListValue": "A list of strings.", + "StringValue": "A string, such as \"department\"." + } + }, "AWS::Kendra::DataSource.DocumentsMetadataConfiguration": { "attributes": {}, "description": "Document metadata files that contain information such as the document access control information, source URI, document author, and custom attributes. Each metadata file contains metadata about a single document.", @@ -23143,6 +23386,24 @@ "SecretArn": "The Amazon Resource Name (ARN) of a AWS Secrets Manager secret that contains the credentials required to connect to Google Drive. For more information, see [Using a Google Workspace Drive data source](https://docs.aws.amazon.com/kendra/latest/dg/data-source-google-drive.html) ." } }, + "AWS::Kendra::DataSource.HookConfiguration": { + "attributes": {}, + "description": "Provides the configuration information for invoking a Lambda function in AWS Lambda to alter document metadata and content when ingesting documents into Amazon Kendra. You can configure your Lambda function using [PreExtractionHookConfiguration](https://docs.aws.amazon.com/kendra/latest/dg/API_CustomDocumentEnrichmentConfiguration.html) if you want to apply advanced alterations on the original or raw documents. If you want to apply advanced alterations on the Amazon Kendra structured documents, you must configure your Lambda function using [PostExtractionHookConfiguration](https://docs.aws.amazon.com/kendra/latest/dg/API_CustomDocumentEnrichmentConfiguration.html) . You can only invoke one Lambda function. However, this function can invoke other functions it requires.\n\nFor more information, see [Customizing document metadata during the ingestion process](https://docs.aws.amazon.com/kendra/latest/dg/custom-document-enrichment.html) .", + "properties": { + "InvocationCondition": "The condition used for when a Lambda function should be invoked.\n\nFor example, you can specify a condition that if there are empty date-time values, then Amazon Kendra should invoke a function that inserts the current date-time.", + "LambdaArn": "The Amazon Resource Name (ARN) of a role with permission to run a Lambda function during ingestion. For more information, see [IAM roles for Amazon Kendra](https://docs.aws.amazon.com/kendra/latest/dg/iam-roles.html) .", + "S3Bucket": "Stores the original, raw documents or the structured, parsed documents before and after altering them. For more information, see [Data contracts for Lambda functions](https://docs.aws.amazon.com/kendra/latest/dg/custom-document-enrichment.html#cde-data-contracts-lambda) ." + } + }, + "AWS::Kendra::DataSource.InlineCustomDocumentEnrichmentConfiguration": { + "attributes": {}, + "description": "Provides the configuration information for applying basic logic to alter document metadata and content when ingesting documents into Amazon Kendra. To apply advanced logic, to go beyond what you can do with basic logic, see [HookConfiguration](https://docs.aws.amazon.com/kendra/latest/dg/API_HookConfiguration.html) .\n\nFor more information, see [Customizing document metadata during the ingestion process](https://docs.aws.amazon.com/kendra/latest/dg/custom-document-enrichment.html) .", + "properties": { + "Condition": "Configuration of the condition used for the target document attribute or metadata field when ingesting documents into Amazon Kendra.", + "DocumentContentDeletion": "`TRUE` to delete content if the condition used for the target attribute is met.", + "Target": "Configuration of the target document attribute or metadata field when ingesting documents into Amazon Kendra. You can also include a value." + } + }, "AWS::Kendra::DataSource.OneDriveConfiguration": { "attributes": {}, "description": "Provides the configuration information to connect to OneDrive as your data source.", @@ -24867,6 +25128,20 @@ "KafkaBootstrapServers": "The list of bootstrap servers for your Kafka brokers in the following format: `\"KafkaBootstrapServers\": [\"abc.xyz.com:xxxx\",\"abc2.xyz.com:xxxx\"]` ." } }, + "AWS::Lambda::EventSourceMapping.Filter": { + "attributes": {}, + "description": "A structure within a `FilterCriteria` object that defines an event filtering pattern.", + "properties": { + "Pattern": "A filter pattern. For more information on the syntax of a filter pattern, see [Filter rule syntax](https://docs.aws.amazon.com/lambda/latest/dg/invocation-eventfiltering.html#filtering-syntax) ." + } + }, + "AWS::Lambda::EventSourceMapping.FilterCriteria": { + "attributes": {}, + "description": "An object that contains the filters for an event source.", + "properties": { + "Filters": "A list of filters." + } + }, "AWS::Lambda::EventSourceMapping.OnFailure": { "attributes": {}, "description": "A destination for events that failed processing.", @@ -26549,8 +26824,19 @@ "SubnetIdList": "An array of strings containing the Amazon VPC subnet IDs (e.g., `subnet-0bb1c79de3EXAMPLE` ." } }, + "AWS::MSK::BatchScramSecret": { + "attributes": { + "Ref": "The ARN of the cluster." + }, + "description": "Represents a secret stored in the Amazon Secrets Manager that can be used to authenticate with a cluster using a user name and a password.", + "properties": { + "ClusterArn": "The Amazon Resource Name (ARN) of the MSK cluster.", + "SecretArnList": "A list of Amazon Secrets Manager secret ARNs." + } + }, "AWS::MSK::Cluster": { "attributes": { + "Arn": "", "Ref": "`Ref` returns the Amazon MSK cluster ARN. For example:\n\n`REF MyTestCluster`\n\nFor the Amazon MSK cluster `MyTestCluster` , Ref returns the ARN of the cluster." }, "description": "The `AWS::MSK::Cluster` resource creates an Amazon MSK cluster . For more information, see [What Is Amazon MSK?](https://docs.aws.amazon.com/msk/latest/developerguide/what-is-msk.html) in the *Amazon MSK Developer Guide* .", @@ -26559,6 +26845,7 @@ "ClientAuthentication": "Includes information related to client authentication.", "ClusterName": "The name of the cluster.", "ConfigurationInfo": "The Amazon MSK configuration to use for the cluster.", + "CurrentVersion": "The version of the cluster that you want to update.", "EncryptionInfo": "Includes all encryption-related information.", "EnhancedMonitoring": "Specifies the level of monitoring for the MSK cluster. The possible values are `DEFAULT` , `PER_BROKER` , and `PER_TOPIC_PER_BROKER` .", "KafkaVersion": "The version of Apache Kafka. For more information, see [Supported Apache Kafka versions](https://docs.aws.amazon.com/msk/latest/developerguide/supported-kafka-versions.html) in the Amazon MSK Developer Guide.", @@ -26625,7 +26912,7 @@ "attributes": {}, "description": "Contains information about the EBS storage volumes attached to brokers.", "properties": { - "ProvisionedThroughput": "", + "ProvisionedThroughput": "Specifies whether provisioned throughput is turned on and the volume throughput target.", "VolumeSize": "The size in GiB of the EBS volume for the data drive on each broker node." } }, @@ -26705,10 +26992,10 @@ }, "AWS::MSK::Cluster.ProvisionedThroughput": { "attributes": {}, - "description": "", + "description": "Specifies whether provisioned throughput is turned on and the volume throughput target.", "properties": { - "Enabled": "", - "VolumeThroughput": "" + "Enabled": "Specifies whether provisioned throughput is turned on for the cluster.", + "VolumeThroughput": "The provisioned throughput rate in MiB per second." } }, "AWS::MSK::Cluster.PublicAccess": { @@ -26764,6 +27051,19 @@ "Enabled": "Unauthenticated is enabled or not." } }, + "AWS::MSK::Configuration": { + "attributes": { + "Arn": "The ARN of the configuration.", + "Ref": "The ARN of the configuration." + }, + "description": "Creates a new MSK configuration.", + "properties": { + "Description": "The description of the configuration.", + "KafkaVersionsList": "A list of the versions of Apache Kafka with which you can use this MSK configuration. You can use this configuration for an MSK cluster only if the Apache Kafka version specified for the cluster appears in this list.", + "Name": "The name of the configuration. Configuration names are strings that match the regex \"^[0-9A-Za-z][0-9A-Za-z-]{0,}$\".", + "ServerProperties": "Contents of the server.properties file. When using the API, you must ensure that the contents of the file are base64 encoded. When using the console, the SDK, or the CLI, the contents of server.properties can be in plaintext." + } + }, "AWS::MWAA::Environment": { "attributes": { "Arn": "The ARN for the Amazon MWAA environment.", @@ -30121,12 +30421,12 @@ "description": "The AWS::OpenSearchService::Domain resource creates an Amazon OpenSearch Service (successor to Amazon Elasticsearch Service) domain.\n\n> The `AWS::OpenSearchService::Domain` resource replaces the legacy [AWS::Elasticsearch::Domain](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticsearch-domain.html) resource. While the Elasticsearch resource and options are still supported, we recommend modifying your existing Cloudformation templates to use the new OpenSearch Service resource, which supports both OpenSearch and legacy Elasticsearch engines. For instructions to upgrade domains defined within CloudFormation from Elasticsearch to OpenSearch, see [Remarks](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-opensearchservice-domain.html#aws-resource-opensearchservice-domain--remarks) .", "properties": { "AccessPolicies": "An AWS Identity and Access Management ( IAM ) policy document that specifies who can access the OpenSearch Service domain and their permissions. For more information, see [Configuring access policies](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/ac.html#ac-creating) in the *Amazon OpenSearch Service Developer Guide* .", - "AdvancedOptions": "Additional options to specify for the OpenSearch Service domain. For more information, see [Advanced cluster parameters](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/createupdatedomains.html#createdomain-configure-advanced-options) in the *Amazon OpenSearch Service Developer Guide* .", + "AdvancedOptions": "Additional options to specify for the OpenSearch Service domain. For more information, see [AdvancedOptions](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/configuration-api.html#configuration-api-datatypes-advancedoptions) in the OpenSearch Service configuration API reference.", "AdvancedSecurityOptions": "Specifies options for fine-grained access control.", "ClusterConfig": "`ClusterConfig` is a property of the AWS::OpenSearchService::Domain resource that configures an Amazon OpenSearch Service cluster.", "CognitoOptions": "Configures OpenSearch Service to use Amazon Cognito authentication for OpenSearch Dashboards.", "DomainEndpointOptions": "Specifies additional options for the domain endpoint, such as whether to require HTTPS for all traffic or whether to use a custom endpoint rather than the default endpoint.", - "DomainName": "A name for the OpenSearch Service domain. For valid values, see the [DomainName](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/configuration-api.html#configuration-api-datatypes-domainname) data type in the *Amazon OpenSearch Service Developer Guide* . If you don't specify a name, AWS CloudFormation generates a unique physical ID and uses that ID for the domain name. For more information, see [Name Type](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-name.html) .\n\n> If you specify a name, you can't perform updates that require replacement of this resource. You can perform updates that require no or some interruption. If you must replace the resource, specify a new name.", + "DomainName": "A name for the OpenSearch Service domain. For valid values, see the [DomainName](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/configuration-api.html#configuration-api-datatypes-domainname) data type in the *Amazon OpenSearch Service Developer Guide* . If you don't specify a name, AWS CloudFormation generates a unique physical ID and uses that ID for the domain name. For more information, see [Name Type](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-name.html) .\n\nRequired when creating a new domain.\n\n> If you specify a name, you can't perform updates that require replacement of this resource. You can perform updates that require no or some interruption. If you must replace the resource, specify a new name.", "EBSOptions": "The configurations of Amazon Elastic Block Store (Amazon EBS) volumes that are attached to data nodes in the OpenSearch Service domain. For more information, see [EBS volume size limits](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/limits.html#ebsresource) in the *Amazon OpenSearch Service Developer Guide* .", "EncryptionAtRestOptions": "Whether the domain should encrypt data at rest, and if so, the AWS KMS key to use. See [Encryption of data at rest for Amazon OpenSearch Service](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/encryption-at-rest.html) .", "EngineVersion": "The version of OpenSearch to use. The value must be in the format `OpenSearch_X.Y` or `Elasticsearch_X.Y` . If not specified, the latest version of OpenSearch is used. For information about the versions that OpenSearch Service supports, see [Supported versions of OpenSearch and Elasticsearch](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/what-is.html#choosing-version) in the *Amazon OpenSearch Service Developer Guide* .\n\nIf you set the [EnableVersionUpgrade](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-updatepolicy.html#cfn-attributes-updatepolicy-upgradeopensearchdomain) update policy to `true` , you can update `EngineVersion` without interruption. When `EnableVersionUpgrade` is set to `false` , or is not specified, updating `EngineVersion` results in [replacement](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-replacement) .", @@ -30167,17 +30467,17 @@ "description": "Configures OpenSearch Service to use Amazon Cognito authentication for OpenSearch Dashboards.", "properties": { "Enabled": "Whether to enable or disable Amazon Cognito authentication for OpenSearch Dashboards. See [Amazon Cognito authentication for OpenSearch Dashboards](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/cognito-auth.html) .", - "IdentityPoolId": "The Amazon Cognito identity pool ID that you want OpenSearch Service to use for OpenSearch Dashboards authentication.", - "RoleArn": "The `AmazonESCognitoAccess` role that allows OpenSearch Service to configure your user pool and identity pool.", - "UserPoolId": "The Amazon Cognito user pool ID that you want OpenSearch Service to use for OpenSearch Dashboards authentication." + "IdentityPoolId": "The Amazon Cognito identity pool ID that you want OpenSearch Service to use for OpenSearch Dashboards authentication.\n\nRequired if you enabled Cognito Authentication for OpenSearch Dashboards.", + "RoleArn": "The `AmazonOpenSearchServiceCognitoAccess` role that allows OpenSearch Service to configure your user pool and identity pool.\n\nRequired if you enabled Cognito Authentication for OpenSearch Dashboards.", + "UserPoolId": "The Amazon Cognito user pool ID that you want OpenSearch Service to use for OpenSearch Dashboards authentication.\n\nRequired if you enabled Cognito Authentication for OpenSearch Dashboards." } }, "AWS::OpenSearchService::Domain.DomainEndpointOptions": { "attributes": {}, "description": "Specifies additional options for the domain endpoint, such as whether to require HTTPS for all traffic or whether to use a custom endpoint rather than the default endpoint.", "properties": { - "CustomEndpoint": "The fully qualified URL for your custom endpoint.", - "CustomEndpointCertificateArn": "The AWS Certificate Manager ARN for your domain's SSL/TLS certificate.", + "CustomEndpoint": "The fully qualified URL for your custom endpoint. Required if you enabled a custom endpoint for the domain.", + "CustomEndpointCertificateArn": "The AWS Certificate Manager ARN for your domain's SSL/TLS certificate. Required if you enabled a custom endpoint for the domain.", "CustomEndpointEnabled": "True to enable a custom endpoint for the domain. If enabled, you must also provide values for `CustomEndpoint` and `CustomEndpointCertificateArn` .", "EnforceHTTPS": "True to require that all traffic to the domain arrive over HTTPS.", "TLSSecurityPolicy": "The minimum TLS version required for traffic to the domain. Valid values are TLS 1.0 (default) or 1.2:\n\n- `Policy-Min-TLS-1-0-2019-07`\n- `Policy-Min-TLS-1-2-2019-07`" @@ -30198,24 +30498,24 @@ "description": "Whether the domain should encrypt data at rest, and if so, the AWS Key Management Service key to use.", "properties": { "Enabled": "Specify `true` to enable encryption at rest.", - "KmsKeyId": "The KMS key ID. Takes the form `1a2a3a4-1a2a-3a4a-5a6a-1a2a3a4a5a6a` ." + "KmsKeyId": "The KMS key ID. Takes the form `1a2a3a4-1a2a-3a4a-5a6a-1a2a3a4a5a6a` . Required if you enable encryption at rest." } }, "AWS::OpenSearchService::Domain.LogPublishingOption": { "attributes": {}, "description": "Specifies whether the OpenSearch Service domain publishes application, search slow logs, or index slow logs to Amazon CloudWatch. Each option must be an object of name `SEARCH_SLOW_LOGS` , `ES_APPLICATION_LOGS` , `INDEX_SLOW_LOGS` , or `AUDIT_LOGS` depending on the type of logs you want to publish. For the full syntax, see the [examples](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-opensearchservice-domain.html#aws-resource-opensearchservice-domain--examples) .\n\nBefore you enable log publishing, you need to create a CloudWatch log group and provide OpenSearch Service the correct permissions to write to it. To learn more, see [Enabling log publishing ( AWS CloudFormation)](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/createdomain-configure-slow-logs.html#createdomain-configure-slow-logs-cfn) .", "properties": { - "CloudWatchLogsLogGroupArn": "Specifies the CloudWatch log group to publish to.", + "CloudWatchLogsLogGroupArn": "Specifies the CloudWatch log group to publish to. Required if you enable log publishing.", "Enabled": "If `true` , enables the publishing of logs to CloudWatch.\n\nDefault: `false` ." } }, "AWS::OpenSearchService::Domain.MasterUserOptions": { "attributes": {}, - "description": "Specifies information about the master user.", + "description": "Specifies information about the master user.\n\nRequired if if `InternalUserDatabaseEnabled` is true in `AdvancedSecurityOptions` .", "properties": { "MasterUserARN": "ARN for the master user. Only specify if `InternalUserDatabaseEnabled` is false in `AdvancedSecurityOptions` .", - "MasterUserName": "Username for the master user. Only specify if `InternalUserDatabaseEnabled` is true in `AdvancedSecurityOptions` .", - "MasterUserPassword": "Password for the master user. Only specify if `InternalUserDatabaseEnabled` is true in `AdvancedSecurityOptions` ." + "MasterUserName": "Username for the master user. Only specify if `InternalUserDatabaseEnabled` is true in `AdvancedSecurityOptions` . If you don't want to specify this value directly within the template, you can use a [dynamic reference](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/dynamic-references.html) instead.", + "MasterUserPassword": "Password for the master user. Only specify if `InternalUserDatabaseEnabled` is true in `AdvancedSecurityOptions` . If you don't want to specify this value directly within the template, you can use a [dynamic reference](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/dynamic-references.html) instead." } }, "AWS::OpenSearchService::Domain.NodeToNodeEncryptionOptions": { @@ -32569,7 +32869,7 @@ "DBClusterIdentifier": "The DB cluster identifier. This parameter is stored as a lowercase string.\n\nConstraints:\n\n- Must contain from 1 to 63 letters, numbers, or hyphens.\n- First character must be a letter.\n- Can't end with a hyphen or contain two consecutive hyphens.\n\nExample: `my-cluster1`", "DBClusterParameterGroupName": "The name of the DB cluster parameter group to associate with this DB cluster.\n\n> If you apply a parameter group to an existing DB cluster, then its DB instances might need to reboot. This can result in an outage while the DB instances are rebooting.\n> \n> If you apply a change to parameter group associated with a stopped DB cluster, then the update stack waits until the DB cluster is started. \n\nTo list all of the available DB cluster parameter group names, use the following command:\n\n`aws rds describe-db-cluster-parameter-groups --query \"DBClusterParameterGroups[].DBClusterParameterGroupName\" --output text`", "DBSubnetGroupName": "A DB subnet group that you want to associate with this DB cluster.\n\nIf you are restoring a DB cluster to a point in time with `RestoreType` set to `copy-on-write` , and don't specify a DB subnet group name, then the DB cluster is restored with a default DB subnet group.", - "DatabaseName": "The name of your database. If you don't provide a name, then Amazon RDS won't create a database in this DB cluster. For naming constraints, see [Naming Constraints](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_Limits.html#RDS_Limits.Constraints) in the *Amazon RDS User Guide* .", + "DatabaseName": "The name of your database. If you don't provide a name, then Amazon RDS won't create a database in this DB cluster. For naming constraints, see [Naming Constraints](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/CHAP_Limits.html#RDS_Limits.Constraints) in the *Amazon Aurora User Guide* .", "DeletionProtection": "A value that indicates whether the DB cluster has deletion protection enabled. The database can't be deleted when deletion protection is enabled. By default, deletion protection is disabled.", "EnableCloudwatchLogsExports": "The list of log types that need to be enabled for exporting to CloudWatch Logs. The values in the list depend on the DB engine being used. For more information, see [Publishing Database Logs to Amazon CloudWatch Logs](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/USER_LogAccess.html#USER_LogAccess.Procedural.UploadtoCloudWatch) in the *Amazon Aurora User Guide* .\n\n*Aurora MySQL*\n\nValid values: `audit` , `error` , `general` , `slowquery`\n\n*Aurora PostgreSQL*\n\nValid values: `postgresql`", "EnableHttpEndpoint": "A value that indicates whether to enable the HTTP endpoint for an Aurora Serverless DB cluster. By default, the HTTP endpoint is disabled.\n\nWhen enabled, the HTTP endpoint provides a connectionless web service API for running SQL queries on the Aurora Serverless DB cluster. You can also query your database from inside the RDS console with the query editor.\n\nFor more information, see [Using the Data API for Aurora Serverless](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/data-api.html) in the *Amazon Aurora User Guide* .", @@ -32645,12 +32945,12 @@ "CopyTagsToSnapshot": "A value that indicates whether to copy tags from the DB instance to snapshots of the DB instance. By default, tags are not copied.\n\n*Amazon Aurora*\n\nNot applicable. Copying tags to snapshots is managed by the DB cluster. Setting this value for an Aurora DB instance has no effect on the DB cluster setting.", "DBClusterIdentifier": "The identifier of the DB cluster that the instance will belong to.", "DBInstanceClass": "The compute and memory capacity of the DB instance, for example, `db.m4.large` . Not all DB instance classes are available in all AWS Regions, or for all database engines.\n\nFor the full list of DB instance classes, and availability for your engine, see [DB Instance Class](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.DBInstanceClass.html) in the *Amazon RDS User Guide.* For more information about DB instance class pricing and AWS Region support for DB instance classes, see [Amazon RDS Pricing](https://docs.aws.amazon.com/rds/pricing/) .", - "DBInstanceIdentifier": "A name for the DB instance. If you specify a name, AWS CloudFormation converts it to lowercase. If you don't specify a name, AWS CloudFormation generates a unique physical ID and uses that ID for the DB instance. For more information, see [Name Type](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-name.html) .\n\n> If you specify a name, you cannot perform updates that require replacement of this resource. You can perform updates that require no or some interruption. If you must replace the resource, specify a new name.", + "DBInstanceIdentifier": "A name for the DB instance. If you specify a name, AWS CloudFormation converts it to lowercase. If you don't specify a name, AWS CloudFormation generates a unique physical ID and uses that ID for the DB instance. For more information, see [Name Type](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-name.html) .\n\nFor information about constraints that apply to DB instance identifiers, see [Naming constraints in Amazon RDS](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_Limits.html#RDS_Limits.Constraints) in the *Amazon RDS User Guide* .\n\n> If you specify a name, you can't perform updates that require replacement of this resource. You can perform updates that require no or some interruption. If you must replace the resource, specify a new name.", "DBName": "The meaning of this parameter differs according to the database engine you use.\n\n> If you specify the `[DBSnapshotIdentifier](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-database-instance.html#cfn-rds-dbinstance-dbsnapshotidentifier)` property, AWS CloudFormation ignores this property.\n> \n> If you restore DB instances from snapshots, this property doesn't apply to the MySQL, PostgreSQL, or MariaDB engines. \n\n*MySQL*\n\nThe name of the database to create when the DB instance is created. If this parameter is not specified, no database is created in the DB instance.\n\nConstraints:\n\n- Must contain 1 to 64 letters or numbers.\n- Can't be a word reserved by the specified database engine\n\n*MariaDB*\n\nThe name of the database to create when the DB instance is created. If this parameter is not specified, no database is created in the DB instance.\n\nConstraints:\n\n- Must contain 1 to 64 letters or numbers.\n- Can't be a word reserved by the specified database engine\n\n*PostgreSQL*\n\nThe name of the database to create when the DB instance is created. If this parameter is not specified, the default `postgres` database is created in the DB instance.\n\nConstraints:\n\n- Must contain 1 to 63 letters, numbers, or underscores.\n- Must begin with a letter or an underscore. Subsequent characters can be letters, underscores, or digits (0-9).\n- Can't be a word reserved by the specified database engine\n\n*Oracle*\n\nThe Oracle System ID (SID) of the created DB instance. If you specify `null` , the default value `ORCL` is used. You can't specify the string NULL, or any other reserved word, for `DBName` .\n\nDefault: `ORCL`\n\nConstraints:\n\n- Can't be longer than 8 characters\n\n*SQL Server*\n\nNot applicable. Must be null.\n\n*Amazon Aurora MySQL*\n\nThe name of the database to create when the primary DB instance of the Aurora MySQL DB cluster is created. If this parameter isn't specified for an Aurora MySQL DB cluster, no database is created in the DB cluster.\n\nConstraints:\n\n- It must contain 1 to 64 alphanumeric characters.\n- It can't be a word reserved by the database engine.\n\n*Amazon Aurora PostgreSQL*\n\nThe name of the database to create when the primary DB instance of the Aurora PostgreSQL DB cluster is created. If this parameter isn't specified for an Aurora PostgreSQL DB cluster, a database named `postgres` is created in the DB cluster.\n\nConstraints:\n\n- It must contain 1 to 63 alphanumeric characters.\n- It must begin with a letter or an underscore. Subsequent characters can be letters, underscores, or digits (0 to 9).\n- It can't be a word reserved by the database engine.", "DBParameterGroupName": "The name of an existing DB parameter group or a reference to an [AWS::RDS::DBParameterGroup](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-dbparametergroup.html) resource created in the template.\n\nTo list all of the available DB parameter group names, use the following command:\n\n`aws rds describe-db-parameter-groups --query \"DBParameterGroups[].DBParameterGroupName\" --output text`\n\n> If any of the data members of the referenced parameter group are changed during an update, the DB instance might need to be restarted, which causes some interruption. If the parameter group contains static parameters, whether they were changed or not, an update triggers a reboot. \n\nIf you don't specify a value for the `DBParameterGroupName` property, the default DB parameter group for the specified engine and engine version is used.", "DBSecurityGroups": "A list of the DB security groups to assign to the DB instance. The list can include both the name of existing DB security groups or references to AWS::RDS::DBSecurityGroup resources created in the template.\n\nIf you set DBSecurityGroups, you must not set VPCSecurityGroups, and vice versa. Also, note that the DBSecurityGroups property exists only for backwards compatibility with older regions and is no longer recommended for providing security information to an RDS DB instance. Instead, use VPCSecurityGroups.\n\n> If you specify this property, AWS CloudFormation sends only the following properties (if specified) to Amazon RDS during create operations:\n> \n> - `AllocatedStorage`\n> - `AutoMinorVersionUpgrade`\n> - `AvailabilityZone`\n> - `BackupRetentionPeriod`\n> - `CharacterSetName`\n> - `DBInstanceClass`\n> - `DBName`\n> - `DBParameterGroupName`\n> - `DBSecurityGroups`\n> - `DBSubnetGroupName`\n> - `Engine`\n> - `EngineVersion`\n> - `Iops`\n> - `LicenseModel`\n> - `MasterUsername`\n> - `MasterUserPassword`\n> - `MultiAZ`\n> - `OptionGroupName`\n> - `PreferredBackupWindow`\n> - `PreferredMaintenanceWindow`\n> \n> All other properties are ignored. Specify a virtual private cloud (VPC) security group if you want to submit other properties, such as `StorageType` , `StorageEncrypted` , or `KmsKeyId` . If you're already using the `DBSecurityGroups` property, you can't use these other properties by updating your DB instance to use a VPC security group. You must recreate the DB instance.", "DBSnapshotIdentifier": "The name or Amazon Resource Name (ARN) of the DB snapshot that's used to restore the DB instance. If you're restoring from a shared manual DB snapshot, you must specify the ARN of the snapshot.\n\nBy specifying this property, you can create a DB instance from the specified DB snapshot. If the `DBSnapshotIdentifier` property is an empty string or the `AWS::RDS::DBInstance` declaration has no `DBSnapshotIdentifier` property, AWS CloudFormation creates a new database. If the property contains a value (other than an empty string), AWS CloudFormation creates a database from the specified snapshot. If a snapshot with the specified name doesn't exist, AWS CloudFormation can't create the database and it rolls back the stack.\n\nSome DB instance properties aren't valid when you restore from a snapshot, such as the `MasterUsername` and `MasterUserPassword` properties. For information about the properties that you can specify, see the `RestoreDBInstanceFromDBSnapshot` action in the *Amazon RDS API Reference* .\n\nAfter you restore a DB instance with a `DBSnapshotIdentifier` property, you must specify the same `DBSnapshotIdentifier` property for any future updates to the DB instance. When you specify this property for an update, the DB instance is not restored from the DB snapshot again, and the data in the database is not changed. However, if you don't specify the `DBSnapshotIdentifier` property, an empty DB instance is created, and the original DB instance is deleted. If you specify a property that is different from the previous snapshot restore property, a new DB instance is restored from the specified `DBSnapshotIdentifier` property, and the original DB instance is deleted.\n\nIf you specify the `DBSnapshotIdentifier` property to restore a DB instance (as opposed to specifying it for DB instance updates), then don't specify the following properties:\n\n- `CharacterSetName`\n- `DBClusterIdentifier`\n- `DBName`\n- `DeleteAutomatedBackups`\n- `EnablePerformanceInsights`\n- `KmsKeyId`\n- `MasterUsername`\n- `MonitoringInterval`\n- `MonitoringRoleArn`\n- `PerformanceInsightsKMSKeyId`\n- `PerformanceInsightsRetentionPeriod`\n- `PromotionTier`\n- `SourceDBInstanceIdentifier`\n- `SourceRegion`\n- `StorageEncrypted`\n- `Timezone`", - "DBSubnetGroupName": "A DB subnet group to associate with the DB instance. If you update this value, the new subnet group must be a subnet group in a new VPC.\n\nIf there's no DB subnet group, then the DB instance isn't a VPC DB instance.\n\nFor more information about using Amazon RDS in a VPC, see [Using Amazon RDS with Amazon Virtual Private Cloud (VPC)](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_VPC.html) in the *Amazon Relational Database Service Developer Guide* .\n\n*Amazon Aurora*\n\nNot applicable. The DB subnet group is managed by the DB cluster. If specified, the setting must match the DB cluster setting.", + "DBSubnetGroupName": "A DB subnet group to associate with the DB instance. If you update this value, the new subnet group must be a subnet group in a new VPC.\n\nIf there's no DB subnet group, then the DB instance isn't a VPC DB instance.\n\nFor more information about using Amazon RDS in a VPC, see [Using Amazon RDS with Amazon Virtual Private Cloud (VPC)](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_VPC.html) in the *Amazon RDS User Guide* .\n\n*Amazon Aurora*\n\nNot applicable. The DB subnet group is managed by the DB cluster. If specified, the setting must match the DB cluster setting.", "DeleteAutomatedBackups": "A value that indicates whether to remove automated backups immediately after the DB instance is deleted. This parameter isn't case-sensitive. The default is to remove automated backups immediately after the DB instance is deleted.", "DeletionProtection": "A value that indicates whether the DB instance has deletion protection enabled. The database can't be deleted when deletion protection is enabled. By default, deletion protection is disabled. For more information, see [Deleting a DB Instance](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_DeleteInstance.html) .\n\n*Amazon Aurora*\n\nNot applicable. You can enable or disable deletion protection for the DB cluster. For more information, see `CreateDBCluster` . DB instances in a DB cluster can be deleted even when deletion protection is enabled for the DB cluster.", "Domain": "The Active Directory directory ID to create the DB instance in. Currently, only Microsoft SQL Server, Oracle, and PostgreSQL DB instances can be created in an Active Directory Domain.\n\nFor more information, see [Kerberos Authentication](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/kerberos-authentication.html) in the *Amazon RDS User Guide* .", @@ -32678,7 +32978,7 @@ "ProcessorFeatures": "The number of CPU cores and the number of threads per core for the DB instance class of the DB instance.\n\nThis setting doesn't apply to RDS Custom.", "PromotionTier": "A value that specifies the order in which an Aurora Replica is promoted to the primary instance after a failure of the existing primary instance. For more information, see [Fault Tolerance for an Aurora DB Cluster](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/Aurora.Managing.Backups.html#Aurora.Managing.FaultTolerance) in the *Amazon Aurora User Guide* .\n\nThis setting doesn't apply to RDS Custom.\n\nDefault: 1\n\nValid Values: 0 - 15", "PubliclyAccessible": "Indicates whether the DB instance is an internet-facing instance. If you specify `true` , AWS CloudFormation creates an instance with a publicly resolvable DNS name, which resolves to a public IP address. If you specify false, AWS CloudFormation creates an internal instance with a DNS name that resolves to a private IP address.\n\nThe default behavior value depends on your VPC setup and the database subnet group. For more information, see the `PubliclyAccessible` parameter in [`CreateDBInstance`](https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_CreateDBInstance.html) in the *Amazon RDS API Reference* .\n\nIf this resource has a public IP address and is also in a VPC that is defined in the same template, you must use the *DependsOn* attribute to declare a dependency on the VPC-gateway attachment. For more information, see [DependsOn Attribute](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-dependson.html) .\n\n> If you specify DBSecurityGroups, AWS CloudFormation ignores this property. To specify a security group and this property, you must use a VPC security group. For more information about Amazon RDS and VPC, see [Using Amazon RDS with Amazon VPC](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_VPC.html) in the *Amazon RDS User Guide* .", - "SourceDBInstanceIdentifier": "If you want to create a read replica DB instance, specify the ID of the source DB instance. Each DB instance can have a limited number of read replicas. For more information, see [Working with Read Replicas](https://docs.aws.amazon.com/AmazonRDS/latest/DeveloperGuide/USER_ReadRepl.html) in the *Amazon Relational Database Service Developer Guide* .\n\nThe `SourceDBInstanceIdentifier` property determines whether a DB instance is a read replica. If you remove the `SourceDBInstanceIdentifier` property from your template and then update your stack, AWS CloudFormation deletes the Read Replica and creates a new DB instance (not a read replica).\n\n> - If you specify a source DB instance that uses VPC security groups, we recommend that you specify the `VPCSecurityGroups` property. If you don't specify the property, the read replica inherits the value of the `VPCSecurityGroups` property from the source DB when you create the replica. However, if you update the stack, AWS CloudFormation reverts the replica's `VPCSecurityGroups` property to the default value because it's not defined in the stack's template. This change might cause unexpected issues.\n> - Read replicas don't support deletion policies. AWS CloudFormation ignores any deletion policy that's associated with a read replica.\n> - If you specify `SourceDBInstanceIdentifier` , don't specify the `DBSnapshotIdentifier` property. You can't create a read replica from a snapshot.\n> - Don't set the `BackupRetentionPeriod` , `DBName` , `MasterUsername` , `MasterUserPassword` , and `PreferredBackupWindow` properties. The database attributes are inherited from the source DB instance, and backups are disabled for read replicas.\n> - If the source DB instance is in a different region than the read replica, specify the source region in `SourceRegion` , and specify an ARN for a valid DB instance in `SourceDBInstanceIdentifier` . For more information, see [Constructing a Amazon RDS Amazon Resource Name (ARN)](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_Tagging.html#USER_Tagging.ARN) in the *Amazon RDS User Guide* .\n> - For DB instances in Amazon Aurora clusters, don't specify this property. Amazon RDS automatically assigns writer and reader DB instances.", + "SourceDBInstanceIdentifier": "If you want to create a read replica DB instance, specify the ID of the source DB instance. Each DB instance can have a limited number of read replicas. For more information, see [Working with Read Replicas](https://docs.aws.amazon.com/AmazonRDS/latest/DeveloperGuide/USER_ReadRepl.html) in the *Amazon RDS User Guide* .\n\nFor information about constraints that apply to DB instance identifiers, see [Naming constraints in Amazon RDS](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_Limits.html#RDS_Limits.Constraints) in the *Amazon RDS User Guide* .\n\nThe `SourceDBInstanceIdentifier` property determines whether a DB instance is a read replica. If you remove the `SourceDBInstanceIdentifier` property from your template and then update your stack, AWS CloudFormation deletes the Read Replica and creates a new DB instance (not a read replica).\n\n> - If you specify a source DB instance that uses VPC security groups, we recommend that you specify the `VPCSecurityGroups` property. If you don't specify the property, the read replica inherits the value of the `VPCSecurityGroups` property from the source DB when you create the replica. However, if you update the stack, AWS CloudFormation reverts the replica's `VPCSecurityGroups` property to the default value because it's not defined in the stack's template. This change might cause unexpected issues.\n> - Read replicas don't support deletion policies. AWS CloudFormation ignores any deletion policy that's associated with a read replica.\n> - If you specify `SourceDBInstanceIdentifier` , don't specify the `DBSnapshotIdentifier` property. You can't create a read replica from a snapshot.\n> - Don't set the `BackupRetentionPeriod` , `DBName` , `MasterUsername` , `MasterUserPassword` , and `PreferredBackupWindow` properties. The database attributes are inherited from the source DB instance, and backups are disabled for read replicas.\n> - If the source DB instance is in a different region than the read replica, specify the source region in `SourceRegion` , and specify an ARN for a valid DB instance in `SourceDBInstanceIdentifier` . For more information, see [Constructing a Amazon RDS Amazon Resource Name (ARN)](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_Tagging.html#USER_Tagging.ARN) in the *Amazon RDS User Guide* .\n> - For DB instances in Amazon Aurora clusters, don't specify this property. Amazon RDS automatically assigns writer and reader DB instances.", "SourceRegion": "The ID of the region that contains the source DB instance for the read replica.", "StorageEncrypted": "A value that indicates whether the DB instance is encrypted. By default, it isn't encrypted.\n\nIf you specify the `KmsKeyId` property, then you must enable encryption.\n\nIf you specify the `SnapshotIdentifier` or `SourceDBInstanceIdentifier` property, don't specify this property. The value is inherited from the snapshot or source DB instance, and if the DB instance is encrypted, the specified `KmsKeyId` property is used.\n\n*Amazon Aurora*\n\nNot applicable. The encryption for DB instances is managed by the DB cluster.", "StorageType": "Specifies the storage type to be associated with the DB instance.\n\nValid values: `standard | gp2 | io1`\n\nThe `standard` value is also known as magnetic.\n\nIf you specify `io1` , you must also include a value for the `Iops` parameter.\n\nDefault: `io1` if the `Iops` parameter is specified, otherwise `standard`\n\nFor more information, see [Amazon RDS DB Instance Storage](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_Storage.html) in the *Amazon RDS User Guide* .\n\n*Amazon Aurora*\n\nNot applicable. Aurora data is stored in the cluster volume, which is a single, virtual volume that uses solid state drives (SSDs).", @@ -32975,12 +33275,12 @@ "EnhancedVpcRouting": "An option that specifies whether to create the cluster with enhanced VPC routing enabled. To create a cluster that uses enhanced VPC routing, the cluster must be in a VPC. For more information, see [Enhanced VPC Routing](https://docs.aws.amazon.com/redshift/latest/mgmt/enhanced-vpc-routing.html) in the Amazon Redshift Cluster Management Guide.\n\nIf this option is `true` , enhanced VPC routing is enabled.\n\nDefault: false", "HsmClientCertificateIdentifier": "Specifies the name of the HSM client certificate the Amazon Redshift cluster uses to retrieve the data encryption keys stored in an HSM.", "HsmConfigurationIdentifier": "Specifies the name of the HSM configuration that contains the information the Amazon Redshift cluster can use to retrieve and store keys in an HSM.", - "IamRoles": "A list of AWS Identity and Access Management (IAM) roles that can be used by the cluster to access other AWS services. You must supply the IAM roles in their Amazon Resource Name (ARN) format. You can supply up to 10 IAM roles in a single request.\n\nA cluster can have up to 10 IAM roles associated with it at any time.", + "IamRoles": "A list of AWS Identity and Access Management (IAM) roles that can be used by the cluster to access other AWS services. You must supply the IAM roles in their Amazon Resource Name (ARN) format.\n\nThe maximum number of IAM roles that you can associate is subject to a quota. For more information, go to [Quotas and limits](https://docs.aws.amazon.com/redshift/latest/mgmt/amazon-redshift-limits.html) in the *Amazon Redshift Cluster Management Guide* .", "KmsKeyId": "The AWS Key Management Service (KMS) key ID of the encryption key that you want to use to encrypt data in the cluster.", "LoggingProperties": "Specifies logging information, such as queries and connection attempts, for the specified Amazon Redshift cluster.", "MaintenanceTrackName": "An optional parameter for the name of the maintenance track for the cluster. If you don't provide a maintenance track name, the cluster is assigned to the `current` track.", "ManualSnapshotRetentionPeriod": "The default number of days to retain a manual snapshot. If the value is -1, the snapshot is retained indefinitely. This setting doesn't change the retention period of existing snapshots.\n\nThe value must be either -1 or an integer between 1 and 3,653.", - "MasterUserPassword": "The password associated with the admin user account for the cluster that is being created.\n\nConstraints:\n\n- Must be between 8 and 64 characters in length.\n- Must contain at least one uppercase letter.\n- Must contain at least one lowercase letter.\n- Must contain one number.\n- Can be any printable ASCII character (ASCII code 33 to 126) except ' (single quote), \" (double quote), \\, /, @, or space.", + "MasterUserPassword": "The password associated with the admin user account for the cluster that is being created.\n\nConstraints:\n\n- Must be between 8 and 64 characters in length.\n- Must contain at least one uppercase letter.\n- Must contain at least one lowercase letter.\n- Must contain one number.\n- Can be any printable ASCII character (ASCII code 33-126) except ' (single quote), \" (double quote), \\, /, or @.", "MasterUsername": "The user name associated with the admin user account for the cluster that is being created.\n\nConstraints:\n\n- Must be 1 - 128 alphanumeric characters. The user name can't be `PUBLIC` .\n- First character must be a letter.\n- Cannot be a reserved word. A list of reserved words can be found in [Reserved Words](https://docs.aws.amazon.com/redshift/latest/dg/r_pg_keywords.html) in the Amazon Redshift Database Developer Guide.", "NodeType": "The node type to be provisioned for the cluster. For information about node types, go to [Working with Clusters](https://docs.aws.amazon.com/redshift/latest/mgmt/working-with-clusters.html#how-many-nodes) in the *Amazon Redshift Cluster Management Guide* .\n\nValid Values: `ds2.xlarge` | `ds2.8xlarge` | `dc1.large` | `dc1.8xlarge` | `dc2.large` | `dc2.8xlarge` | `ra3.xlplus` | `ra3.4xlarge` | `ra3.16xlarge`", "NumberOfNodes": "The number of compute nodes in the cluster. This parameter is required when the *ClusterType* parameter is specified as `multi-node` .\n\nFor information about determining how many nodes you need, go to [Working with Clusters](https://docs.aws.amazon.com/redshift/latest/mgmt/working-with-clusters.html#how-many-nodes) in the *Amazon Redshift Cluster Management Guide* .\n\nIf you don't specify this parameter, you get a single-node cluster. When requesting a multi-node cluster, you must specify the number of nodes that you want in the cluster.\n\nDefault: `1`\n\nConstraints: Value must be at least 1 and no more than 100.", @@ -34147,7 +34447,7 @@ "attributes": {}, "description": "The PublicAccessBlock configuration that you want to apply to this Amazon S3 bucket. You can enable the configuration options in any combination. For more information about when Amazon S3 considers a bucket or object public, see [The Meaning of \"Public\"](https://docs.aws.amazon.com/AmazonS3/latest/dev/access-control-block-public-access.html#access-control-block-public-access-policy-status) in the *Amazon S3 User Guide* .", "properties": { - "BlockPublicAcls": "Specifies whether Amazon S3 should block public access control lists (ACLs) for this bucket and objects in this bucket. Setting this element to `TRUE` causes the following behavior:\n\n- PUT Bucket acl and PUT Object acl calls fail if the specified ACL is public.\n- PUT Object calls fail if the request includes a public ACL.\n- PUT Bucket calls fail if the request includes a public ACL.\n\nEnabling this setting doesn't affect existing policies or ACLs.", + "BlockPublicAcls": "Specifies whether Amazon S3 should block public access control lists (ACLs) for this bucket and objects in this bucket. Setting this element to `TRUE` causes the following behavior:\n\n- PUT Bucket ACL and PUT Object ACL calls fail if the specified ACL is public.\n- PUT Object calls fail if the request includes a public ACL.\n- PUT Bucket calls fail if the request includes a public ACL.\n\nEnabling this setting doesn't affect existing policies or ACLs.", "BlockPublicPolicy": "Specifies whether Amazon S3 should block public bucket policies for this bucket. Setting this element to `TRUE` causes Amazon S3 to reject calls to PUT Bucket policy if the specified bucket policy allows public access.\n\nEnabling this setting doesn't affect existing bucket policies.", "IgnorePublicAcls": "Specifies whether Amazon S3 should ignore public ACLs for this bucket and objects in this bucket. Setting this element to `TRUE` causes Amazon S3 to ignore all public ACLs on this bucket and objects in this bucket.\n\nEnabling this setting doesn't affect the persistence of any existing ACLs and doesn't prevent new public ACLs from being set.", "RestrictPublicBuckets": "Specifies whether Amazon S3 should restrict public bucket policies for this bucket. Setting this element to `TRUE` restricts access to this bucket to only AWS service principals and authorized users within this account if the bucket has a public policy.\n\nEnabling this setting doesn't affect previously stored bucket policies, except that public and cross-account access within any public bucket policy, including non-public delegation to specific accounts, is blocked." @@ -34437,7 +34737,7 @@ "attributes": {}, "description": "The PublicAccessBlock configuration that you want to apply to this Amazon S3 bucket. You can enable the configuration options in any combination. For more information about when Amazon S3 considers a bucket or object public, see [The Meaning of \"Public\"](https://docs.aws.amazon.com/AmazonS3/latest/dev/access-control-block-public-access.html#access-control-block-public-access-policy-status) in the *Amazon S3 User Guide* .", "properties": { - "BlockPublicAcls": "Specifies whether Amazon S3 should block public access control lists (ACLs) for this bucket and objects in this bucket. Setting this element to `TRUE` causes the following behavior:\n\n- PUT Bucket acl and PUT Object acl calls fail if the specified ACL is public.\n- PUT Object calls fail if the request includes a public ACL.\n- PUT Bucket calls fail if the request includes a public ACL.\n\nEnabling this setting doesn't affect existing policies or ACLs.", + "BlockPublicAcls": "Specifies whether Amazon S3 should block public access control lists (ACLs) for this bucket and objects in this bucket. Setting this element to `TRUE` causes the following behavior:\n\n- PUT Bucket ACL and PUT Object ACL calls fail if the specified ACL is public.\n- PUT Object calls fail if the request includes a public ACL.\n- PUT Bucket calls fail if the request includes a public ACL.\n\nEnabling this setting doesn't affect existing policies or ACLs.", "BlockPublicPolicy": "Specifies whether Amazon S3 should block public bucket policies for this bucket. Setting this element to `TRUE` causes Amazon S3 to reject calls to PUT Bucket policy if the specified bucket policy allows public access.\n\nEnabling this setting doesn't affect existing bucket policies.", "IgnorePublicAcls": "Specifies whether Amazon S3 should ignore public ACLs for this bucket and objects in this bucket. Setting this element to `TRUE` causes Amazon S3 to ignore all public ACLs on this bucket and objects in this bucket.\n\nEnabling this setting doesn't affect the persistence of any existing ACLs and doesn't prevent new public ACLs from being set.", "RestrictPublicBuckets": "Specifies whether Amazon S3 should restrict public bucket policies for this bucket. Setting this element to `TRUE` restricts access to this bucket to only AWS service principals and authorized users within this account if the bucket has a public policy.\n\nEnabling this setting doesn't affect previously stored bucket policies, except that public and cross-account access within any public bucket policy, including non-public delegation to specific accounts, is blocked." @@ -34699,7 +34999,7 @@ "attributes": {}, "description": "The PublicAccessBlock configuration that you want to apply to this Amazon S3 Multi-Region Access Point. You can enable the configuration options in any combination. For more information about when Amazon S3 considers an object public, see [The Meaning of \"Public\"](https://docs.aws.amazon.com/AmazonS3/latest/dev/access-control-block-public-access.html#access-control-block-public-access-policy-status) in the *Amazon S3 User Guide* .", "properties": { - "BlockPublicAcls": "Specifies whether Amazon S3 should block public access control lists (ACLs) for this bucket and objects in this bucket. Setting this element to `TRUE` causes the following behavior:\n\n- PUT Bucket acl and PUT Object acl calls fail if the specified ACL is public.\n- PUT Object calls fail if the request includes a public ACL.\n- PUT Bucket calls fail if the request includes a public ACL.\n\nEnabling this setting doesn't affect existing policies or ACLs.", + "BlockPublicAcls": "Specifies whether Amazon S3 should block public access control lists (ACLs) for this bucket and objects in this bucket. Setting this element to `TRUE` causes the following behavior:\n\n- PUT Bucket ACL and PUT Object ACL calls fail if the specified ACL is public.\n- PUT Object calls fail if the request includes a public ACL.\n- PUT Bucket calls fail if the request includes a public ACL.\n\nEnabling this setting doesn't affect existing policies or ACLs.", "BlockPublicPolicy": "Specifies whether Amazon S3 should block public bucket policies for this bucket. Setting this element to `TRUE` causes Amazon S3 to reject calls to PUT Bucket policy if the specified bucket policy allows public access.\n\nEnabling this setting doesn't affect existing bucket policies.", "IgnorePublicAcls": "Specifies whether Amazon S3 should ignore public ACLs for this bucket and objects in this bucket. Setting this element to `TRUE` causes Amazon S3 to ignore all public ACLs on this bucket and objects in this bucket.\n\nEnabling this setting doesn't affect the persistence of any existing ACLs and doesn't prevent new public ACLs from being set.", "RestrictPublicBuckets": "Specifies whether Amazon S3 should restrict public bucket policies for this bucket. Setting this element to `TRUE` restricts access to this bucket to only AWS service principals and authorized users within this account if the bucket has a public policy.\n\nEnabling this setting doesn't affect previously stored bucket policies, except that public and cross-account access within any public bucket policy, including non-public delegation to specific accounts, is blocked." @@ -34991,11 +35291,13 @@ }, "description": "The name of the configuration set.\n\nConfiguration sets let you create groups of rules that you can apply to the emails you send using Amazon SES. For more information about using configuration sets, see [Using Amazon SES Configuration Sets](https://docs.aws.amazon.com/ses/latest/dg/using-configuration-sets.html) in the [Amazon SES Developer Guide](https://docs.aws.amazon.com/ses/latest/dg/) .", "properties": { - "Name": "" + "Name": "The name of the configuration set. The name must meet the following requirements:\n\n- Contain only letters (a-z, A-Z), numbers (0-9), underscores (_), or dashes (-).\n- Contain 64 characters or fewer." } }, "AWS::SES::ConfigurationSetEventDestination": { - "attributes": {}, + "attributes": { + "Id": "" + }, "description": "Specifies a configuration set event destination. An event destination is an AWS service that Amazon SES publishes email sending events to. When you specify an event destination, you provide one, and only one, destination. You can send event data to Amazon CloudWatch or Amazon Kinesis Data Firehose.\n\n> You can't specify Amazon SNS event destinations in CloudFormation templates.", "properties": { "ConfigurationSetName": "The name of the configuration set that contains the event destination.", @@ -35924,7 +36226,7 @@ "CodeRepositoryName": "The name of the code repository, such as `myCodeRepo` .", "Ref": "`Ref` returns the Amazon Resource Name (ARN) of the code repository." }, - "description": "Creates a Git repository as a resource in your Amazon SageMaker account. You can associate the repository with notebook instances so that you can use Git source control for the notebooks you create. The Git repository is a resource in your Amazon SageMaker account, so it can be associated with more than one notebook instance, and it persists independently from the lifecycle of any notebook instances it is associated with.\n\nThe repository can be hosted either in [AWS CodeCommit](https://docs.aws.amazon.com/codecommit/latest/userguide/welcome.html) or in any other Git repository.", + "description": "Creates a Git repository as a resource in your SageMaker account. You can associate the repository with notebook instances so that you can use Git source control for the notebooks you create. The Git repository is a resource in your SageMaker account, so it can be associated with more than one notebook instance, and it persists independently from the lifecycle of any notebook instances it is associated with.\n\nThe repository can be hosted either in [AWS CodeCommit](https://docs.aws.amazon.com/codecommit/latest/userguide/welcome.html) or in any other Git repository.", "properties": { "CodeRepositoryName": "The name of the Git repository.", "GitConfig": "Configuration details for the Git repository, including the URL where it is located and the ARN of the AWS Secrets Manager secret that contains the credentials used to access the repository.", @@ -36064,9 +36366,9 @@ }, "AWS::SageMaker::DataQualityJobDefinition.StoppingCondition": { "attributes": {}, - "description": "Specifies a limit to how long a model training job or model compilation job can run. It also specifies how long a managed spot training job has to complete. When the job reaches the time limit, Amazon SageMaker ends the training or compilation job. Use this API to cap model training costs.\n\nTo stop a training job, Amazon SageMaker sends the algorithm the `SIGTERM` signal, which delays job termination for 120 seconds. Algorithms can use this 120-second window to save the model artifacts, so the results of training are not lost.\n\nThe training algorithms provided by Amazon SageMaker automatically save the intermediate results of a model training job when possible. This attempt to save artifacts is only a best effort case as model might not be in a state from which it can be saved. For example, if training has just started, the model might not be ready to save. When saved, this intermediate data is a valid model artifact. You can use it to create a model with `CreateModel` .\n\n> The Neural Topic Model (NTM) currently does not support saving intermediate model artifacts. When training NTMs, make sure that the maximum runtime is sufficient for the training job to complete.", + "description": "Specifies a limit to how long a model training job or model compilation job can run. It also specifies how long a managed spot training job has to complete. When the job reaches the time limit, SageMaker ends the training or compilation job. Use this API to cap model training costs.\n\nTo stop a training job, SageMaker sends the algorithm the `SIGTERM` signal, which delays job termination for 120 seconds. Algorithms can use this 120-second window to save the model artifacts, so the results of training are not lost.\n\nThe training algorithms provided by SageMaker automatically save the intermediate results of a model training job when possible. This attempt to save artifacts is only a best effort case as model might not be in a state from which it can be saved. For example, if training has just started, the model might not be ready to save. When saved, this intermediate data is a valid model artifact. You can use it to create a model with `CreateModel` .\n\n> The Neural Topic Model (NTM) currently does not support saving intermediate model artifacts. When training NTMs, make sure that the maximum runtime is sufficient for the training job to complete.", "properties": { - "MaxRuntimeInSeconds": "The maximum length of time, in seconds, that a training or compilation job can run.\n\nFor compilation jobs, if the job does not complete during this time, you will receive a `TimeOut` error. We recommend starting with 900 seconds and increase as necessary based on your model.\n\nFor all other jobs, if the job does not complete during this time, Amazon SageMaker ends the job. When `RetryStrategy` is specified in the job request, `MaxRuntimeInSeconds` specifies the maximum time for all of the attempts in total, not each individual attempt. The default value is 1 day. The maximum value is 28 days." + "MaxRuntimeInSeconds": "The maximum length of time, in seconds, that a training or compilation job can run.\n\nFor compilation jobs, if the job does not complete during this time, a `TimeOut` error is generated. We recommend starting with 900 seconds and increasing as necessary based on your model.\n\nFor all other jobs, if the job does not complete during this time, SageMaker ends the job. When `RetryStrategy` is specified in the job request, `MaxRuntimeInSeconds` specifies the maximum time for all of the attempts in total, not each individual attempt. The default value is 1 day. The maximum value is 28 days." } }, "AWS::SageMaker::DataQualityJobDefinition.VpcConfig": { @@ -36421,7 +36723,7 @@ "properties": { "Containers": "Specifies the containers in the inference pipeline.", "EnableNetworkIsolation": "Isolates the model container. No inbound or outbound network calls can be made to or from the model container.", - "ExecutionRoleArn": "The Amazon Resource Name (ARN) of the IAM role that Amazon SageMaker can assume to access model artifacts and docker image for deployment on ML compute instances or for batch transform jobs. Deploying on ML compute instances is part of model hosting. For more information, see [Amazon SageMaker Roles](https://docs.aws.amazon.com/sagemaker/latest/dg/sagemaker-roles.html) .\n\n> To be able to pass this role to Amazon SageMaker, the caller of this API must have the `iam:PassRole` permission.", + "ExecutionRoleArn": "The Amazon Resource Name (ARN) of the IAM role that SageMaker can assume to access model artifacts and docker image for deployment on ML compute instances or for batch transform jobs. Deploying on ML compute instances is part of model hosting. For more information, see [SageMaker Roles](https://docs.aws.amazon.com/sagemaker/latest/dg/sagemaker-roles.html) .\n\n> To be able to pass this role to SageMaker, the caller of this API must have the `iam:PassRole` permission.", "InferenceExecutionConfig": "Specifies details of how containers in a multi-container endpoint are called.", "ModelName": "The name of the new model.", "PrimaryContainer": "The location of the primary docker image containing inference code, associated artifacts, and custom environment map that the inference code uses when the model is deployed for predictions.", @@ -36435,11 +36737,11 @@ "properties": { "ContainerHostname": "This parameter is ignored for models that contain only a `PrimaryContainer` .\n\nWhen a `ContainerDefinition` is part of an inference pipeline, the value of the parameter uniquely identifies the container for the purposes of logging and metrics. For information, see [Use Logs and Metrics to Monitor an Inference Pipeline](https://docs.aws.amazon.com/sagemaker/latest/dg/inference-pipeline-logs-metrics.html) . If you don't specify a value for this parameter for a `ContainerDefinition` that is part of an inference pipeline, a unique name is automatically assigned based on the position of the `ContainerDefinition` in the pipeline. If you specify a value for the `ContainerHostName` for any `ContainerDefinition` that is part of an inference pipeline, you must specify a value for the `ContainerHostName` parameter of every `ContainerDefinition` in that pipeline.", "Environment": "The environment variables to set in the Docker container. Each key and value in the `Environment` string to string map can have length of up to 1024. We support up to 16 entries in the map.", - "Image": "The path where inference code is stored. This can be either in Amazon EC2 Container Registry or in a Docker registry that is accessible from the same VPC that you configure for your endpoint. If you are using your own custom algorithm instead of an algorithm provided by Amazon SageMaker, the inference code must meet Amazon SageMaker requirements. Amazon SageMaker supports both `registry/repository[:tag]` and `registry/repository[@digest]` image path formats. For more information, see [Using Your Own Algorithms with Amazon SageMaker](https://docs.aws.amazon.com/sagemaker/latest/dg/your-algorithms.html)", + "Image": "The path where inference code is stored. This can be either in Amazon EC2 Container Registry or in a Docker registry that is accessible from the same VPC that you configure for your endpoint. If you are using your own custom algorithm instead of an algorithm provided by SageMaker, the inference code must meet SageMaker requirements. SageMaker supports both `registry/repository[:tag]` and `registry/repository[@digest]` image path formats. For more information, see [Using Your Own Algorithms with Amazon SageMaker](https://docs.aws.amazon.com/sagemaker/latest/dg/your-algorithms.html)", "ImageConfig": "Specifies whether the model container is in Amazon ECR or a private Docker registry accessible from your Amazon Virtual Private Cloud (VPC). For information about storing containers in a private Docker registry, see [Use a Private Docker Registry for Real-Time Inference Containers](https://docs.aws.amazon.com/sagemaker/latest/dg/your-algorithms-containers-inference-private.html)", "InferenceSpecificationName": "The inference specification name in the model package version.", "Mode": "Whether the container hosts a single model or multiple models.", - "ModelDataUrl": "The S3 path where the model artifacts, which result from model training, are stored. This path must point to a single gzip compressed tar archive (.tar.gz suffix). The S3 path is required for Amazon SageMaker built-in algorithms, but not if you use your own algorithms. For more information on built-in algorithms, see [Common Parameters](https://docs.aws.amazon.com/sagemaker/latest/dg/sagemaker-algo-docker-registry-paths.html) .\n\n> The model artifacts must be in an S3 bucket that is in the same region as the model or endpoint you are creating. \n\nIf you provide a value for this parameter, Amazon SageMaker uses AWS Security Token Service to download model artifacts from the S3 path you provide. AWS STS is activated in your IAM user account by default. If you previously deactivated AWS STS for a region, you need to reactivate AWS STS for that region. For more information, see [Activating and Deactivating AWS STS in an AWS Region](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html) in the *AWS Identity and Access Management User Guide* .\n\n> If you use a built-in algorithm to create a model, Amazon SageMaker requires that you provide a S3 path to the model artifacts in `ModelDataUrl` .", + "ModelDataUrl": "The S3 path where the model artifacts, which result from model training, are stored. This path must point to a single gzip compressed tar archive (.tar.gz suffix). The S3 path is required for SageMaker built-in algorithms, but not if you use your own algorithms. For more information on built-in algorithms, see [Common Parameters](https://docs.aws.amazon.com/sagemaker/latest/dg/sagemaker-algo-docker-registry-paths.html) .\n\n> The model artifacts must be in an S3 bucket that is in the same region as the model or endpoint you are creating. \n\nIf you provide a value for this parameter, SageMaker uses AWS Security Token Service to download model artifacts from the S3 path you provide. AWS STS is activated in your IAM user account by default. If you previously deactivated AWS STS for a region, you need to reactivate AWS STS for that region. For more information, see [Activating and Deactivating AWS STS in an AWS Region](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html) in the *AWS Identity and Access Management User Guide* .\n\n> If you use a built-in algorithm to create a model, SageMaker requires that you provide a S3 path to the model artifacts in `ModelDataUrl` .", "ModelPackageName": "The name or Amazon Resource Name (ARN) of the model package to use to create the model.", "MultiModelConfig": "Specifies additional configuration for multi-model endpoints." } @@ -36608,9 +36910,9 @@ }, "AWS::SageMaker::ModelBiasJobDefinition.StoppingCondition": { "attributes": {}, - "description": "Specifies a limit to how long a model training job or model compilation job can run. It also specifies how long a managed spot training job has to complete. When the job reaches the time limit, Amazon SageMaker ends the training or compilation job. Use this API to cap model training costs.\n\nTo stop a training job, Amazon SageMaker sends the algorithm the `SIGTERM` signal, which delays job termination for 120 seconds. Algorithms can use this 120-second window to save the model artifacts, so the results of training are not lost.\n\nThe training algorithms provided by Amazon SageMaker automatically save the intermediate results of a model training job when possible. This attempt to save artifacts is only a best effort case as model might not be in a state from which it can be saved. For example, if training has just started, the model might not be ready to save. When saved, this intermediate data is a valid model artifact. You can use it to create a model with `CreateModel` .\n\n> The Neural Topic Model (NTM) currently does not support saving intermediate model artifacts. When training NTMs, make sure that the maximum runtime is sufficient for the training job to complete.", + "description": "Specifies a limit to how long a model training job or model compilation job can run. It also specifies how long a managed spot training job has to complete. When the job reaches the time limit, SageMaker ends the training or compilation job. Use this API to cap model training costs.\n\nTo stop a training job, SageMaker sends the algorithm the `SIGTERM` signal, which delays job termination for 120 seconds. Algorithms can use this 120-second window to save the model artifacts, so the results of training are not lost.\n\nThe training algorithms provided by SageMaker automatically save the intermediate results of a model training job when possible. This attempt to save artifacts is only a best effort case as model might not be in a state from which it can be saved. For example, if training has just started, the model might not be ready to save. When saved, this intermediate data is a valid model artifact. You can use it to create a model with `CreateModel` .\n\n> The Neural Topic Model (NTM) currently does not support saving intermediate model artifacts. When training NTMs, make sure that the maximum runtime is sufficient for the training job to complete.", "properties": { - "MaxRuntimeInSeconds": "The maximum length of time, in seconds, that a training or compilation job can run.\n\nFor compilation jobs, if the job does not complete during this time, you will receive a `TimeOut` error. We recommend starting with 900 seconds and increase as necessary based on your model.\n\nFor all other jobs, if the job does not complete during this time, Amazon SageMaker ends the job. When `RetryStrategy` is specified in the job request, `MaxRuntimeInSeconds` specifies the maximum time for all of the attempts in total, not each individual attempt. The default value is 1 day. The maximum value is 28 days." + "MaxRuntimeInSeconds": "The maximum length of time, in seconds, that a training or compilation job can run.\n\nFor compilation jobs, if the job does not complete during this time, a `TimeOut` error is generated. We recommend starting with 900 seconds and increasing as necessary based on your model.\n\nFor all other jobs, if the job does not complete during this time, SageMaker ends the job. When `RetryStrategy` is specified in the job request, `MaxRuntimeInSeconds` specifies the maximum time for all of the attempts in total, not each individual attempt. The default value is 1 day. The maximum value is 28 days." } }, "AWS::SageMaker::ModelBiasJobDefinition.VpcConfig": { @@ -36737,9 +37039,9 @@ }, "AWS::SageMaker::ModelExplainabilityJobDefinition.StoppingCondition": { "attributes": {}, - "description": "Specifies a limit to how long a model training job or model compilation job can run. It also specifies how long a managed spot training job has to complete. When the job reaches the time limit, Amazon SageMaker ends the training or compilation job. Use this API to cap model training costs.\n\nTo stop a training job, Amazon SageMaker sends the algorithm the `SIGTERM` signal, which delays job termination for 120 seconds. Algorithms can use this 120-second window to save the model artifacts, so the results of training are not lost.\n\nThe training algorithms provided by Amazon SageMaker automatically save the intermediate results of a model training job when possible. This attempt to save artifacts is only a best effort case as model might not be in a state from which it can be saved. For example, if training has just started, the model might not be ready to save. When saved, this intermediate data is a valid model artifact. You can use it to create a model with `CreateModel` .\n\n> The Neural Topic Model (NTM) currently does not support saving intermediate model artifacts. When training NTMs, make sure that the maximum runtime is sufficient for the training job to complete.", + "description": "Specifies a limit to how long a model training job or model compilation job can run. It also specifies how long a managed spot training job has to complete. When the job reaches the time limit, SageMaker ends the training or compilation job. Use this API to cap model training costs.\n\nTo stop a training job, SageMaker sends the algorithm the `SIGTERM` signal, which delays job termination for 120 seconds. Algorithms can use this 120-second window to save the model artifacts, so the results of training are not lost.\n\nThe training algorithms provided by SageMaker automatically save the intermediate results of a model training job when possible. This attempt to save artifacts is only a best effort case as model might not be in a state from which it can be saved. For example, if training has just started, the model might not be ready to save. When saved, this intermediate data is a valid model artifact. You can use it to create a model with `CreateModel` .\n\n> The Neural Topic Model (NTM) currently does not support saving intermediate model artifacts. When training NTMs, make sure that the maximum runtime is sufficient for the training job to complete.", "properties": { - "MaxRuntimeInSeconds": "The maximum length of time, in seconds, that a training or compilation job can run.\n\nFor compilation jobs, if the job does not complete during this time, you will receive a `TimeOut` error. We recommend starting with 900 seconds and increase as necessary based on your model.\n\nFor all other jobs, if the job does not complete during this time, Amazon SageMaker ends the job. When `RetryStrategy` is specified in the job request, `MaxRuntimeInSeconds` specifies the maximum time for all of the attempts in total, not each individual attempt. The default value is 1 day. The maximum value is 28 days." + "MaxRuntimeInSeconds": "The maximum length of time, in seconds, that a training or compilation job can run.\n\nFor compilation jobs, if the job does not complete during this time, a `TimeOut` error is generated. We recommend starting with 900 seconds and increasing as necessary based on your model.\n\nFor all other jobs, if the job does not complete during this time, SageMaker ends the job. When `RetryStrategy` is specified in the job request, `MaxRuntimeInSeconds` specifies the maximum time for all of the attempts in total, not each individual attempt. The default value is 1 day. The maximum value is 28 days." } }, "AWS::SageMaker::ModelExplainabilityJobDefinition.VpcConfig": { @@ -36895,9 +37197,9 @@ }, "AWS::SageMaker::ModelQualityJobDefinition.StoppingCondition": { "attributes": {}, - "description": "Specifies a limit to how long a model training job or model compilation job can run. It also specifies how long a managed spot training job has to complete. When the job reaches the time limit, Amazon SageMaker ends the training or compilation job. Use this API to cap model training costs.\n\nTo stop a training job, Amazon SageMaker sends the algorithm the `SIGTERM` signal, which delays job termination for 120 seconds. Algorithms can use this 120-second window to save the model artifacts, so the results of training are not lost.\n\nThe training algorithms provided by Amazon SageMaker automatically save the intermediate results of a model training job when possible. This attempt to save artifacts is only a best effort case as model might not be in a state from which it can be saved. For example, if training has just started, the model might not be ready to save. When saved, this intermediate data is a valid model artifact. You can use it to create a model with `CreateModel` .\n\n> The Neural Topic Model (NTM) currently does not support saving intermediate model artifacts. When training NTMs, make sure that the maximum runtime is sufficient for the training job to complete.", + "description": "Specifies a limit to how long a model training job or model compilation job can run. It also specifies how long a managed spot training job has to complete. When the job reaches the time limit, SageMaker ends the training or compilation job. Use this API to cap model training costs.\n\nTo stop a training job, SageMaker sends the algorithm the `SIGTERM` signal, which delays job termination for 120 seconds. Algorithms can use this 120-second window to save the model artifacts, so the results of training are not lost.\n\nThe training algorithms provided by SageMaker automatically save the intermediate results of a model training job when possible. This attempt to save artifacts is only a best effort case as model might not be in a state from which it can be saved. For example, if training has just started, the model might not be ready to save. When saved, this intermediate data is a valid model artifact. You can use it to create a model with `CreateModel` .\n\n> The Neural Topic Model (NTM) currently does not support saving intermediate model artifacts. When training NTMs, make sure that the maximum runtime is sufficient for the training job to complete.", "properties": { - "MaxRuntimeInSeconds": "The maximum length of time, in seconds, that a training or compilation job can run.\n\nFor compilation jobs, if the job does not complete during this time, you will receive a `TimeOut` error. We recommend starting with 900 seconds and increase as necessary based on your model.\n\nFor all other jobs, if the job does not complete during this time, Amazon SageMaker ends the job. When `RetryStrategy` is specified in the job request, `MaxRuntimeInSeconds` specifies the maximum time for all of the attempts in total, not each individual attempt. The default value is 1 day. The maximum value is 28 days." + "MaxRuntimeInSeconds": "The maximum length of time, in seconds, that a training or compilation job can run.\n\nFor compilation jobs, if the job does not complete during this time, a `TimeOut` error is generated. We recommend starting with 900 seconds and increasing as necessary based on your model.\n\nFor all other jobs, if the job does not complete during this time, SageMaker ends the job. When `RetryStrategy` is specified in the job request, `MaxRuntimeInSeconds` specifies the maximum time for all of the attempts in total, not each individual attempt. The default value is 1 day. The maximum value is 28 days." } }, "AWS::SageMaker::ModelQualityJobDefinition.VpcConfig": { @@ -37074,9 +37376,9 @@ }, "AWS::SageMaker::MonitoringSchedule.StoppingCondition": { "attributes": {}, - "description": "Specifies a limit to how long a model training job or model compilation job can run. It also specifies how long a managed spot training job has to complete. When the job reaches the time limit, Amazon SageMaker ends the training or compilation job. Use this API to cap model training costs.\n\nTo stop a training job, Amazon SageMaker sends the algorithm the `SIGTERM` signal, which delays job termination for 120 seconds. Algorithms can use this 120-second window to save the model artifacts, so the results of training are not lost.\n\nThe training algorithms provided by Amazon SageMaker automatically save the intermediate results of a model training job when possible. This attempt to save artifacts is only a best effort case as model might not be in a state from which it can be saved. For example, if training has just started, the model might not be ready to save. When saved, this intermediate data is a valid model artifact. You can use it to create a model with `CreateModel` .\n\n> The Neural Topic Model (NTM) currently does not support saving intermediate model artifacts. When training NTMs, make sure that the maximum runtime is sufficient for the training job to complete.", + "description": "Specifies a limit to how long a model training job or model compilation job can run. It also specifies how long a managed spot training job has to complete. When the job reaches the time limit, SageMaker ends the training or compilation job. Use this API to cap model training costs.\n\nTo stop a training job, SageMaker sends the algorithm the `SIGTERM` signal, which delays job termination for 120 seconds. Algorithms can use this 120-second window to save the model artifacts, so the results of training are not lost.\n\nThe training algorithms provided by SageMaker automatically save the intermediate results of a model training job when possible. This attempt to save artifacts is only a best effort case as model might not be in a state from which it can be saved. For example, if training has just started, the model might not be ready to save. When saved, this intermediate data is a valid model artifact. You can use it to create a model with `CreateModel` .\n\n> The Neural Topic Model (NTM) currently does not support saving intermediate model artifacts. When training NTMs, make sure that the maximum runtime is sufficient for the training job to complete.", "properties": { - "MaxRuntimeInSeconds": "The maximum length of time, in seconds, that a training or compilation job can run.\n\nFor compilation jobs, if the job does not complete during this time, you will receive a `TimeOut` error. We recommend starting with 900 seconds and increase as necessary based on your model.\n\nFor all other jobs, if the job does not complete during this time, Amazon SageMaker ends the job. When `RetryStrategy` is specified in the job request, `MaxRuntimeInSeconds` specifies the maximum time for all of the attempts in total, not each individual attempt. The default value is 1 day. The maximum value is 28 days." + "MaxRuntimeInSeconds": "The maximum length of time, in seconds, that a training or compilation job can run.\n\nFor compilation jobs, if the job does not complete during this time, a `TimeOut` error is generated. We recommend starting with 900 seconds and increasing as necessary based on your model.\n\nFor all other jobs, if the job does not complete during this time, SageMaker ends the job. When `RetryStrategy` is specified in the job request, `MaxRuntimeInSeconds` specifies the maximum time for all of the attempts in total, not each individual attempt. The default value is 1 day. The maximum value is 28 days." } }, "AWS::SageMaker::MonitoringSchedule.VpcConfig": { @@ -37095,15 +37397,15 @@ "description": "The `AWS::SageMaker::NotebookInstance` resource creates an Amazon SageMaker notebook instance. A notebook instance is a machine learning (ML) compute instance running on a Jupyter notebook. For more information, see [Use Notebook Instances](https://docs.aws.amazon.com/sagemaker/latest/dg/nbi.html) .", "properties": { "AcceleratorTypes": "A list of Amazon Elastic Inference (EI) instance types to associate with the notebook instance. Currently, only one instance type can be associated with a notebook instance. For more information, see [Using Elastic Inference in Amazon SageMaker](https://docs.aws.amazon.com/sagemaker/latest/dg/ei.html) .\n\n*Valid Values:* `ml.eia1.medium | ml.eia1.large | ml.eia1.xlarge | ml.eia2.medium | ml.eia2.large | ml.eia2.xlarge` .", - "AdditionalCodeRepositories": "An array of up to three Git repositories associated with the notebook instance. These can be either the names of Git repositories stored as resources in your account, or the URL of Git repositories in [AWS CodeCommit](https://docs.aws.amazon.com/codecommit/latest/userguide/welcome.html) or in any other Git repository. These repositories are cloned at the same level as the default repository of your notebook instance. For more information, see [Associating Git Repositories with Amazon SageMaker Notebook Instances](https://docs.aws.amazon.com/sagemaker/latest/dg/nbi-git-repo.html) .", - "DefaultCodeRepository": "The Git repository associated with the notebook instance as its default code repository. This can be either the name of a Git repository stored as a resource in your account, or the URL of a Git repository in [AWS CodeCommit](https://docs.aws.amazon.com/codecommit/latest/userguide/welcome.html) or in any other Git repository. When you open a notebook instance, it opens in the directory that contains this repository. For more information, see [Associating Git Repositories with Amazon SageMaker Notebook Instances](https://docs.aws.amazon.com/sagemaker/latest/dg/nbi-git-repo.html) .", - "DirectInternetAccess": "Sets whether Amazon SageMaker provides internet access to the notebook instance. If you set this to `Disabled` this notebook instance is able to access resources only in your VPC, and is not be able to connect to Amazon SageMaker training and endpoint services unless you configure a NAT Gateway in your VPC.\n\nFor more information, see [Notebook Instances Are Internet-Enabled by Default](https://docs.aws.amazon.com/sagemaker/latest/dg/appendix-additional-considerations.html#appendix-notebook-and-internet-access) . You can set the value of this parameter to `Disabled` only if you set a value for the `SubnetId` parameter.", + "AdditionalCodeRepositories": "An array of up to three Git repositories associated with the notebook instance. These can be either the names of Git repositories stored as resources in your account, or the URL of Git repositories in [AWS CodeCommit](https://docs.aws.amazon.com/codecommit/latest/userguide/welcome.html) or in any other Git repository. These repositories are cloned at the same level as the default repository of your notebook instance. For more information, see [Associating Git Repositories with SageMaker Notebook Instances](https://docs.aws.amazon.com/sagemaker/latest/dg/nbi-git-repo.html) .", + "DefaultCodeRepository": "The Git repository associated with the notebook instance as its default code repository. This can be either the name of a Git repository stored as a resource in your account, or the URL of a Git repository in [AWS CodeCommit](https://docs.aws.amazon.com/codecommit/latest/userguide/welcome.html) or in any other Git repository. When you open a notebook instance, it opens in the directory that contains this repository. For more information, see [Associating Git Repositories with SageMaker Notebook Instances](https://docs.aws.amazon.com/sagemaker/latest/dg/nbi-git-repo.html) .", + "DirectInternetAccess": "Sets whether SageMaker provides internet access to the notebook instance. If you set this to `Disabled` this notebook instance is able to access resources only in your VPC, and is not be able to connect to SageMaker training and endpoint services unless you configure a NAT Gateway in your VPC.\n\nFor more information, see [Notebook Instances Are Internet-Enabled by Default](https://docs.aws.amazon.com/sagemaker/latest/dg/appendix-additional-considerations.html#appendix-notebook-and-internet-access) . You can set the value of this parameter to `Disabled` only if you set a value for the `SubnetId` parameter.", "InstanceType": "The type of ML compute instance to launch for the notebook instance.\n\n> Expect some interruption of service if this parameter is changed as CloudFormation stops a notebook instance and starts it up again to update it.", - "KmsKeyId": "The Amazon Resource Name (ARN) of a AWS Key Management Service key that Amazon SageMaker uses to encrypt data on the storage volume attached to your notebook instance. The KMS key you provide must be enabled. For information, see [Enabling and Disabling Keys](https://docs.aws.amazon.com/kms/latest/developerguide/enabling-keys.html) in the *AWS Key Management Service Developer Guide* .", + "KmsKeyId": "The Amazon Resource Name (ARN) of a AWS Key Management Service key that SageMaker uses to encrypt data on the storage volume attached to your notebook instance. The KMS key you provide must be enabled. For information, see [Enabling and Disabling Keys](https://docs.aws.amazon.com/kms/latest/developerguide/enabling-keys.html) in the *AWS Key Management Service Developer Guide* .", "LifecycleConfigName": "The name of a lifecycle configuration to associate with the notebook instance. For information about lifecycle configurations, see [Customize a Notebook Instance](https://docs.aws.amazon.com/sagemaker/latest/dg/notebook-lifecycle-config.html) in the *Amazon SageMaker Developer Guide* .", "NotebookInstanceName": "The name of the new notebook instance.", "PlatformIdentifier": "The platform identifier of the notebook instance runtime environment.", - "RoleArn": "When you send any requests to AWS resources from the notebook instance, Amazon SageMaker assumes this role to perform tasks on your behalf. You must grant this role necessary permissions so Amazon SageMaker can perform these tasks. The policy must allow the Amazon SageMaker service principal (sagemaker.amazonaws.com) permissions to assume this role. For more information, see [Amazon SageMaker Roles](https://docs.aws.amazon.com/sagemaker/latest/dg/sagemaker-roles.html) .\n\n> To be able to pass this role to Amazon SageMaker, the caller of this API must have the `iam:PassRole` permission.", + "RoleArn": "When you send any requests to AWS resources from the notebook instance, SageMaker assumes this role to perform tasks on your behalf. You must grant this role necessary permissions so SageMaker can perform these tasks. The policy must allow the SageMaker service principal (sagemaker.amazonaws.com) permissions to assume this role. For more information, see [SageMaker Roles](https://docs.aws.amazon.com/sagemaker/latest/dg/sagemaker-roles.html) .\n\n> To be able to pass this role to SageMaker, the caller of this API must have the `iam:PassRole` permission.", "RootAccess": "Whether root access is enabled or disabled for users of the notebook instance. The default value is `Enabled` .\n\n> Lifecycle configurations need root access to be able to set up a notebook instance. Because of this, lifecycle configurations associated with a notebook instance always run with root access even if you disable root access for users.", "SecurityGroupIds": "The VPC security group IDs, in the form sg-xxxxxxxx. The security groups must be for the same VPC as specified in the subnet.", "SubnetId": "The ID of the subnet in a VPC to which you would like to have a connectivity from your ML compute instance.", @@ -37281,10 +37583,10 @@ "attributes": { "Ref": "When you pass the logical ID of an `AWS::SecretsManager::RotationSchedule` resource to the intrinsic `Ref` function, the function returns the ARN of the secret being configured, such as:\n\n*arn:aws:secretsmanager: us-west-2* : *123456789012* :secret: *my-path/my-secret-name* - *1a2b3c*\n\nYou can use the ARN to reference a secret you create in one part of the stack template from within the definition of another resource later, in the same template. You typically do this when you define the [AWS::SecretsManager::SecretTargetAttachment](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-secretsmanager-secrettargetattachment.html) resource type.\n\nFor more information about using the `Ref` function, see [Ref](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-ref.html) ." }, - "description": "Configures rotation for a secret. You must already configure the secret with the details of the database or service. If you define both the secret and the database or service in an AWS CloudFormation template, then define the [AWS::SecretsManager::SecretTargetAttachment](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-secretsmanager-secrettargetattachment.html) resource to populate the secret with the connection details of the database or service before you attempt to configure rotation.\n\n> When you configure rotation for a secret, AWS CloudFormation automatically rotates the secret one time.", + "description": "Configures rotation for a secret. You must already configure the secret with the details of the database or service. If you define both the secret and the database or service in an AWS CloudFormation template, then define the [AWS::SecretsManager::SecretTargetAttachment](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-secretsmanager-secrettargetattachment.html) resource to populate the secret with the connection details of the database or service before you attempt to configure rotation.", "properties": { "HostedRotationLambda": "To use these values, you must specify `Transform: AWS::SecretsManager-2020-07-23` at the beginning of the CloudFormation template.\n\nWhen you enter valid values for `RotationSchedule.HostedRotationLambda` , Secrets Manager launches a Lambda that performs rotation on the secret specified in the `secret-id` property. The template creates a Lambda as part of a nested stack within the current stack.", - "RotateImmediatelyOnUpdate": "", + "RotateImmediatelyOnUpdate": "Specifies whether to rotate the secret immediately or wait until the next scheduled rotation window. The rotation schedule is defined in `RotationRules` .\n\nIf you don't immediately rotate the secret, Secrets Manager tests the rotation configuration by running the [`testSecret` step](https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotate-secrets_how.html) of the Lambda rotation function. The test creates an `AWSPENDING` version of the secret and then removes it.\n\nIf you don't specify this value, then by default, Secrets Manager rotates the secret immediately.", "RotationLambdaARN": "The ARN of the Lambda function that can rotate the secret. If you don't specify this parameter, then the secret must already have the ARN of a Lambda function configured.\n\nTo reference a Lambda function also created in this template, use the [Ref](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-ref.html) function with the function's logical ID.", "RotationRules": "A structure that defines the rotation configuration for this secret.", "SecretId": "The ARN or name of the secret to rotate.\n\nTo reference a secret also created in this template, use the [Ref](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-ref.html) function with the secret's logical ID." @@ -37295,11 +37597,11 @@ "description": "Specifies that you want to create a hosted Lambda rotation function.\n\nTo use these values, you must specify `Transform: AWS::SecretsManager-2020-07-23` at the beginning of the CloudFormation template.", "properties": { "KmsKeyArn": "The ARN of the KMS key that Secrets Manager uses to encrypt the secret. If you don't specify this value, then Secrets Manager uses the key `aws/secretsmanager` . If `aws/secretsmanager` doesn't yet exist, then Secrets Manager creates it for you automatically the first time it encrypts the secret value.", - "MasterSecretArn": "The ARN of the secret that contains elevated credentials. The Lambda rotation function uses this secret for the [Alternating users rotation strategy](https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotating-secrets_strategies.html#rotating-secrets-two-users) .", + "MasterSecretArn": "The ARN of the secret that contains elevated credentials. You must create the elevated secret before you can set this property. The Lambda rotation function uses this secret for the [Alternating users rotation strategy](https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotating-secrets_strategies.html#rotating-secrets-two-users) .", "MasterSecretKmsKeyArn": "The ARN of the KMS key that Secrets Manager uses to encrypt the elevated secret if you use the [alternating users strategy](https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotating-secrets_strategies.html#rotating-secrets-two-users) . If you don't specify this value and you use the alternating users strategy, then Secrets Manager uses the key `aws/secretsmanager` . If `aws/secretsmanager` doesn't yet exist, then Secrets Manager creates it for you automatically the first time it encrypts the secret value.", "RotationLambdaName": "The name of the Lambda rotation function.", "RotationType": "The type of rotation template to use. For more information, see [Secrets Manager rotation function templates](https://docs.aws.amazon.com/secretsmanager/latest/userguide/reference_available-rotation-templates.html) .\n\nYou can specify one of the following `RotationTypes` :\n\n- MySQLSingleUser\n- MySQLMultiUser\n- PostgreSQLSingleUser\n- PostgreSQLMultiUser\n- OracleSingleUser\n- OracleMultiUser\n- MariaDBSingleUser\n- MariaDBMultiUser\n- SQLServerSingleUser\n- SQLServerMultiUser\n- RedshiftSingleUser\n- RedshiftMultiUser\n- MongoDBSingleUser\n- MongoDBMultiUser", - "SuperuserSecretArn": "The ARN of the secret that contains elevated credentials. The Lambda rotation function uses this secret for the [Alternating users rotation strategy](https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotating-secrets_strategies.html#rotating-secrets-two-users) .", + "SuperuserSecretArn": "The ARN of the secret that contains elevated credentials. You must create the superuser secret before you can set this property. The Lambda rotation function uses this secret for the [Alternating users rotation strategy](https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotating-secrets_strategies.html#rotating-secrets-two-users) .", "SuperuserSecretKmsKeyArn": "The ARN of the KMS key that Secrets Manager uses to encrypt the elevated secret if you use the [alternating users strategy](https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotating-secrets_strategies.html#rotating-secrets-two-users) . If you don't specify this value and you use the alternating users strategy, then Secrets Manager uses the key `aws/secretsmanager` . If `aws/secretsmanager` doesn't yet exist, then Secrets Manager creates it for you automatically the first time it encrypts the secret value.", "VpcSecurityGroupIds": "A comma-separated list of security group IDs applied to the target database.\n\nThe templates applies the same security groups as on the Lambda rotation function that is created as part of this stack.", "VpcSubnetIds": "A comma separated list of VPC subnet IDs of the target database network. The Lambda rotation function is in the same subnet group." @@ -37310,8 +37612,8 @@ "description": "A structure that defines the rotation configuration for the secret.", "properties": { "AutomaticallyAfterDays": "The number of days between automatic scheduled rotations of the secret. You can use this value to check that your secret meets your compliance guidelines for how often secrets must be rotated.\n\nIn `DescribeSecret` and `ListSecrets` , this value is calculated from the rotation schedule after every successful rotation. In `RotateSecret` , you can set the rotation schedule in `RotationRules` with `AutomaticallyAfterDays` or `ScheduleExpression` , but not both.", - "Duration": "", - "ScheduleExpression": "" + "Duration": "The length of the rotation window in hours, for example `3h` for a three hour window. Secrets Manager rotates your secret at any time during this window. The window must not go into the next UTC day. If you don't specify this value, the window automatically ends at the end of the UTC day. The window begins according to the `ScheduleExpression` . For more information, including examples, see [Schedule expressions in Secrets Manager rotation](https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotate-secrets_schedule.html) .", + "ScheduleExpression": "A `cron()` or `rate()` expression that defines the schedule for rotating your secret. Secrets Manager rotation schedules use UTC time zone.\n\nSecrets Manager `rate()` expressions represent the interval in days that you want to rotate your secret, for example `rate(10 days)` . If you use a `rate()` expression, the rotation window opens at midnight, and Secrets Manager rotates your secret any time that day after midnight. You can set a `Duration` to shorten the rotation window.\n\nYou can use a `cron()` expression to create rotation schedules that are more detailed than a rotation interval. For more information, including examples, see [Schedule expressions in Secrets Manager rotation](https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotate-secrets_schedule.html) . If you use a `cron()` expression, Secrets Manager rotates your secret any time during that day after the window opens. For example, `cron(0 8 1 * ? *)` represents a rotation window that occurs on the first day of every month beginning at 8:00 AM UTC. Secrets Manager rotates the secret any time that day after 8:00 AM. You can set a `Duration` to shorten the rotation window." } }, "AWS::SecretsManager::Secret": { @@ -37714,7 +38016,7 @@ "AWS::ServiceDiscovery::PrivateDnsNamespace": { "attributes": { "Arn": "The Amazon Resource Name (ARN) of the private namespace.", - "HostedZoneId": "", + "HostedZoneId": "The ID for the Route 53 hosted zone that AWS Cloud Map creates when you create a namespace.", "Id": "The ID of the private namespace.", "Ref": "`Ref` returns the value of `Id` for the namespace, such as `ns-e4anhexample0004` ." }, @@ -37751,7 +38053,7 @@ "AWS::ServiceDiscovery::PublicDnsNamespace": { "attributes": { "Arn": "The Amazon Resource Name (ARN) of the public namespace.", - "HostedZoneId": "", + "HostedZoneId": "The ID for the Route 53 hosted zone that AWS Cloud Map creates when you create a namespace.", "Id": "The ID of the public namespace.", "Ref": "`Ref` returns the value of `Id` for the namespace, such as `ns-e4anhexample0004` ." }, @@ -37999,7 +38301,7 @@ "attributes": {}, "description": "Use this structure to input your script code for the canary. This structure contains the Lambda handler with the location where the canary should start running the script. If the script is stored in an S3 bucket, the bucket name, key, and version are also included. If the script is passed into the canary directly, the script code is contained in the value of `Script` .", "properties": { - "Handler": "The entry point to use for the source code when running the canary. This value must end with the string `.handler` . The string is limited to 29 characters or fewer.", + "Handler": "The entry point to use for the source code when running the canary. For canaries that use the `syn-python-selenium-1.0` runtime or a `syn-nodejs.puppeteer` runtime earlier than `syn-nodejs.puppeteer-3.4` , the handler must be specified as `*fileName* .handler` . For `syn-python-selenium-1.1` , `syn-nodejs.puppeteer-3.4` , and later runtimes, the handler can be specified as `*fileName* . *functionName*` , or you can specify a folder where canary scripts reside as `*folder* / *fileName* . *functionName*` .", "S3Bucket": "If your canary script is located in S3, specify the bucket name here. The bucket must already exist.", "S3Key": "The S3 key of your script. For more information, see [Working with Amazon S3 Objects](https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingObjects.html) .", "S3ObjectVersion": "The S3 version ID of your script.", @@ -38206,13 +38508,15 @@ "properties": { "Certificate": "The Amazon Resource Name (ARN) of the AWS Certificate Manager (ACM) certificate. Required when `Protocols` is set to `FTPS` .\n\nTo request a new public certificate, see [Request a public certificate](https://docs.aws.amazon.com/acm/latest/userguide/gs-acm-request-public.html) in the *AWS Certificate Manager User Guide* .\n\nTo import an existing certificate into ACM, see [Importing certificates into ACM](https://docs.aws.amazon.com/acm/latest/userguide/import-certificate.html) in the *AWS Certificate Manager User Guide* .\n\nTo request a private certificate to use FTPS through private IP addresses, see [Request a private certificate](https://docs.aws.amazon.com/acm/latest/userguide/gs-acm-request-private.html) in the *AWS Certificate Manager User Guide* .\n\nCertificates with the following cryptographic algorithms and key sizes are supported:\n\n- 2048-bit RSA (RSA_2048)\n- 4096-bit RSA (RSA_4096)\n- Elliptic Prime Curve 256 bit (EC_prime256v1)\n- Elliptic Prime Curve 384 bit (EC_secp384r1)\n- Elliptic Prime Curve 521 bit (EC_secp521r1)\n\n> The certificate must be a valid SSL/TLS X.509 version 3 certificate with FQDN or IP address specified and information about the issuer.", "Domain": "Specifies the domain of the storage system that is used for file transfers.", - "EndpointDetails": "The virtual private cloud (VPC) endpoint settings that are configured for your server. When you host your endpoint within your VPC, you can make it accessible only to resources within your VPC, or you can attach Elastic IPs and make it accessible to clients over the internet. You VPC's default security groups are automatically assigned to your endpoint.", - "EndpointType": "The type of VPC endpoint that you want your server to connect to. You can choose to connect to the public internet or a virtual private cloud (VPC) endpoint. With a VPC endpoint, you can restrict access to your server and resources only within your VPC.\n\n> It is recommended that you use `VPC` as the `EndpointType` . With this endpoint type, you have the option to directly associate up to three Elastic IPv4 addresses (BYO IP included) with your server's endpoint and use VPC security groups to restrict traffic by the client's public IP address. This is not possible with `EndpointType` set to `VPC_ENDPOINT` .", + "EndpointDetails": "The virtual private cloud (VPC) endpoint settings that are configured for your server. When you host your endpoint within your VPC, you can make it accessible only to resources within your VPC, or you can attach Elastic IP addresses and make it accessible to clients over the internet. Your VPC's default security groups are automatically assigned to your endpoint.", + "EndpointType": "The type of endpoint that you want your server to use. You can choose to make your server's endpoint publicly accessible (PUBLIC) or host it inside your VPC. With an endpoint that is hosted in a VPC, you can restrict access to your server and resources only within your VPC or choose to make it internet facing by attaching Elastic IP addresses directly to it.", "IdentityProviderDetails": "Required when `IdentityProviderType` is set to `AWS_DIRECTORY_SERVICE` or `API_GATEWAY` . Accepts an array containing all of the information required to use a directory in `AWS_DIRECTORY_SERVICE` or invoke a customer-supplied authentication API, including the API Gateway URL. Not required when `IdentityProviderType` is set to `SERVICE_MANAGED` .", "IdentityProviderType": "Specifies the mode of authentication for a server. The default value is `SERVICE_MANAGED` , which allows you to store and access user credentials within the AWS Transfer Family service.\n\nUse `AWS_DIRECTORY_SERVICE` to provide access to Active Directory groups in AWS Managed Active Directory or Microsoft Active Directory in your on-premises environment or in AWS using AD Connectors. This option also requires you to provide a Directory ID using the `IdentityProviderDetails` parameter.\n\nUse the `API_GATEWAY` value to integrate with an identity provider of your choosing. The `API_GATEWAY` setting requires you to provide an API Gateway endpoint URL to call for authentication using the `IdentityProviderDetails` parameter.\n\nUse the `AWS_LAMBDA` value to directly use a Lambda function as your identity provider. If you choose this value, you must specify the ARN for the lambda function in the `Function` parameter for the `IdentityProviderDetails` data type.", "LoggingRole": "Specifies the Amazon Resource Name (ARN) of the AWS Identity and Access Management (IAM) role that allows a server to turn on Amazon CloudWatch logging for Amazon S3 or Amazon EFS events. When set, user activity can be viewed in your CloudWatch logs.", - "ProtocolDetails": "Protocol settings that are configured for your server.\n\n> Only valid in the `UpdateServer` API.", - "Protocols": "Specifies the file transfer protocol or protocols over which your file transfer protocol client can connect to your server's endpoint.", + "PostAuthenticationLoginBanner": "Specify a string to display when users connect to a server. This string is displayed after the user authenticates.\n\n> The SFTP protocol does not support post-authentication display banners.", + "PreAuthenticationLoginBanner": "Specify a string to display when users connect to a server. This string is displayed before the user authenticates. For example, the following banner displays details about using the system.\n\n`This system is for the use of authorized users only. Individuals using this computer system without authority, or in excess of their authority, are subject to having all of their activities on this system monitored and recorded by system personnel.`", + "ProtocolDetails": "The protocol settings that are configured for your server.\n\nUse the `PassiveIp` parameter to indicate passive mode (for FTP and FTPS protocols). Enter a single dotted-quad IPv4 address, such as the external IP address of a firewall, router, or load balancer.\n\nUse the `TlsSessionResumptionMode` parameter to determine whether or not your Transfer server resumes recent, negotiated sessions through a unique session ID.", + "Protocols": "Specifies the file transfer protocol or protocols over which your file transfer protocol client can connect to your server's endpoint. The available protocols are:\n\n- `SFTP` (Secure Shell (SSH) File Transfer Protocol): File transfer over SSH\n- `FTPS` (File Transfer Protocol Secure): File transfer with TLS encryption\n- `FTP` (File Transfer Protocol): Unencrypted file transfer\n\n> If you select `FTPS` , you must choose a certificate stored in AWS Certificate Manager (ACM) which is used to identify your server when clients connect to it over FTPS.\n> \n> If `Protocol` includes either `FTP` or `FTPS` , then the `EndpointType` must be `VPC` and the `IdentityProviderType` must be `AWS_DIRECTORY_SERVICE` or `API_GATEWAY` .\n> \n> If `Protocol` includes `FTP` , then `AddressAllocationIds` cannot be associated.\n> \n> If `Protocol` is set only to `SFTP` , the `EndpointType` can be set to `PUBLIC` and the `IdentityProviderType` can be set to `SERVICE_MANAGED` .", "SecurityPolicyName": "Specifies the name of the security policy that is attached to the server.", "Tags": "Key-value pairs that can be used to group and search for servers.", "WorkflowDetails": "Specifies the workflow ID for the workflow to assign and the execution role used for executing the workflow." @@ -38220,10 +38524,10 @@ }, "AWS::Transfer::Server.EndpointDetails": { "attributes": {}, - "description": "The virtual private cloud (VPC) endpoint settings that are configured for your server. When you host your endpoint within your VPC, you can make it accessible only to resources within your VPC, or you can attach Elastic IPs and make it accessible to clients over the internet. You VPC's default security groups are automatically assigned to your endpoint.\n\n> It is recommended that you use `VPC` as the `EndpointType` . With this endpoint type, you have the option to directly associate up to three Elastic IPv4 addresses (BYO IP included) with your server's endpoint and use VPC security groups to restrict traffic by the client's public IP address. This is not possible with `EndpointType` set to `VPC_ENDPOINT` .", + "description": "The virtual private cloud (VPC) endpoint settings that are configured for your server. When you host your endpoint within your VPC, you can make it accessible only to resources within your VPC, or you can attach Elastic IP addresses and make it accessible to clients over the internet. Your VPC's default security groups are automatically assigned to your endpoint.", "properties": { - "AddressAllocationIds": "A list of address allocation IDs that are required to attach an Elastic IP address to your server's endpoint. This is only valid in the `UpdateServer` API.\n\n> This property can only be set when `EndpointType` is set to `VPC` .", - "SecurityGroupIds": "A list of security groups IDs that are available to attach to your server's endpoint.\n\n> This property can only be set when `EndpointType` is set to `VPC` . \n\n*Maximum number of security groups* : 5", + "AddressAllocationIds": "A list of address allocation IDs that are required to attach an Elastic IP address to your server's endpoint.\n\n> This property can only be set when `EndpointType` is set to `VPC` and it is only valid in the `UpdateServer` API.", + "SecurityGroupIds": "A list of security groups IDs that are available to attach to your server's endpoint.\n\n> This property can only be set when `EndpointType` is set to `VPC` .\n> \n> You can edit the `SecurityGroupIds` property in the [UpdateServer](https://docs.aws.amazon.com/transfer/latest/userguide/API_UpdateServer.html) API only if you are changing the `EndpointType` from `PUBLIC` or `VPC_ENDPOINT` to `VPC` . To change security groups associated with your server's VPC endpoint after creation, use the Amazon EC2 [ModifyVpcEndpoint](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_ModifyVpcEndpoint.html) API.", "SubnetIds": "A list of subnet IDs that are required to host your server endpoint in your VPC.\n\n> This property can only be set when `EndpointType` is set to `VPC` .", "VpcEndpointId": "The ID of the VPC endpoint.\n\n> This property can only be set when `EndpointType` is set to `VPC_ENDPOINT` .", "VpcId": "The VPC ID of the virtual private cloud in which the server's endpoint will be hosted.\n\n> This property can only be set when `EndpointType` is set to `VPC` ." @@ -38241,7 +38545,7 @@ }, "AWS::Transfer::Server.Protocol": { "attributes": {}, - "description": "Specifies the file transfer protocol or protocols over which your file transfer protocol client can connect to your server's endpoint. The available protocols are:\n\n- `SFTP` (Secure Shell (SSH) File Transfer Protocol): File transfer over SSH\n- `FTPS` (File Transfer Protocol Secure): File transfer with TLS encryption\n- `FTP` (File Transfer Protocol): Unencrypted file transfer\n\n> If you select `FTPS` , you must choose a certificate stored in AWS Certificate Manager (ACM) which will be used to identify your server when clients connect to it over FTPS.\n> \n> If `Protocol` includes either `FTP` or `FTPS` , then the `EndpointType` must be `VPC` and the `IdentityProviderType` must be `API_GATEWAY` .\n> \n> If `Protocol` includes `FTP` , then `AddressAllocationIds` cannot be associated.\n> \n> If `Protocol` is set only to `SFTP` , the `EndpointType` can be set to `PUBLIC` and the `IdentityProviderType` can be set to `SERVICE_MANAGED` .", + "description": "Specifies the file transfer protocol or protocols over which your file transfer protocol client can connect to your server's endpoint. The available protocols are:\n\n- `SFTP` (Secure Shell (SSH) File Transfer Protocol): File transfer over SSH\n- `FTPS` (File Transfer Protocol Secure): File transfer with TLS encryption\n- `FTP` (File Transfer Protocol): Unencrypted file transfer\n\n> If you select `FTPS` , you must choose a certificate stored in AWS Certificate Manager (ACM) which is used to identify your server when clients connect to it over FTPS.\n> \n> If `Protocol` includes either `FTP` or `FTPS` , then the `EndpointType` must be `VPC` and the `IdentityProviderType` must be `AWS_DIRECTORY_SERVICE` or `API_GATEWAY` .\n> \n> If `Protocol` includes `FTP` , then `AddressAllocationIds` cannot be associated.\n> \n> If `Protocol` is set only to `SFTP` , the `EndpointType` can be set to `PUBLIC` and the `IdentityProviderType` can be set to `SERVICE_MANAGED` .", "properties": {} }, "AWS::Transfer::Server.ProtocolDetails": { @@ -38327,10 +38631,10 @@ "attributes": {}, "description": "The basic building block of a workflow.", "properties": { - "CopyStepDetails": "Details for a step that performs a file copy. Consists of the following values:\n\n- A description\n- An S3 location for the destination of the file copy\n- A flag that indicates whether or not to overwrite an existing file of the same name. The default is `FALSE` .", - "CustomStepDetails": "Details for a step that invokes a lambda function. Consists of the lambda function name, target, and timeout (in seconds).", + "CopyStepDetails": "Details for a step that performs a file copy.\n\nConsists of the following values:\n\n- A description\n- An S3 location for the destination of the file copy.\n- A flag that indicates whether or not to overwrite an existing file of the same name. The default is `FALSE` .", + "CustomStepDetails": "Details for a step that invokes a lambda function.\n\nConsists of the lambda function name, target, and timeout (in seconds).", "DeleteStepDetails": "Details for a step that deletes the file.", - "TagStepDetails": "Details for a step that creates one or more tags. You specify one or more tags: each tag contains a key/value pair.", + "TagStepDetails": "Details for a step that creates one or more tags.\n\nYou specify one or more tags: each tag contains a key/value pair.", "Type": "Currently, the following step types are supported.\n\n- *Copy* : copy the file to another location\n- *Custom* : custom step with a lambda target\n- *Delete* : delete the file\n- *Tag* : add a tag to the file" } }, @@ -38763,23 +39067,23 @@ "ManagedByFirewallManager": "Indicates whether the logging configuration was created by AWS Firewall Manager , as part of an AWS WAF policy configuration. If true, only Firewall Manager can modify or delete the configuration.", "Ref": "`Ref` returns the Amazon Resource Name (ARN) of the web ACL." }, - "description": "Defines an association between logging destinations and a web ACL resource, for logging from AWS WAF . As part of the association, you can specify parts of the standard logging fields to keep out of the logs and you can specify filters so that you log only a subset of the logging records.\n\nFor information about configuring web ACL logging destinations, see [Logging web ACL traffic information](https://docs.aws.amazon.com/waf/latest/developerguide/logging.html) in the *AWS WAF Developer Guide* .", + "description": "Defines an association between logging destinations and a web ACL resource, for logging from AWS WAF . As part of the association, you can specify parts of the standard logging fields to keep out of the logs and you can specify filters so that you log only a subset of the logging records.\n\n> You can define one logging destination per web ACL. \n\nYou can access information about the traffic that AWS WAF inspects using the following steps:\n\n- Create your logging destination. You can use an Amazon CloudWatch Logs log group, an Amazon Simple Storage Service (Amazon S3) bucket, or an Amazon Kinesis Data Firehose. For information about configuring logging destinations and the permissions that are required for each, see [Logging web ACL traffic information](https://docs.aws.amazon.com/waf/latest/developerguide/logging.html) in the *AWS WAF Developer Guide* .\n- Associate your logging destination to your web ACL using a `PutLoggingConfiguration` request.\n\nWhen you successfully enable logging using a `PutLoggingConfiguration` request, AWS WAF creates an additional role or policy that is required to write logs to the logging destination. For an Amazon CloudWatch Logs log group, AWS WAF creates a resource policy on the log group. For an Amazon S3 bucket, AWS WAF creates a bucket policy. For an Amazon Kinesis Data Firehose, AWS WAF creates a service-linked role.\n\nFor additional information about web ACL logging, see [Logging web ACL traffic information](https://docs.aws.amazon.com/waf/latest/developerguide/logging.html) in the *AWS WAF Developer Guide* .", "properties": { - "LogDestinationConfigs": "The Amazon Resource Names (ARNs) of the logging destinations that you want to associate with the web ACL.", + "LogDestinationConfigs": "The logging destination configuration that you want to associate with the web ACL.\n\n> You can associate one logging destination to a web ACL.", "LoggingFilter": "Filtering that specifies which web requests are kept in the logs and which are dropped. You can filter on the rule action and on the web request labels that were applied by matching rules during web ACL evaluation.", - "RedactedFields": "The parts of the request that you want to keep out of the logs. For example, if you redact the `SingleHeader` field, the `HEADER` field in the firehose will be `xxx` .\n\n> You can specify only the following fields for redaction: `UriPath` , `QueryString` , `SingleHeader` , `Method` , and `JsonBody` .", + "RedactedFields": "The parts of the request that you want to keep out of the logs. For example, if you redact the `SingleHeader` field, the `HEADER` field in the logs will be `xxx` .\n\n> You can specify only the following fields for redaction: `UriPath` , `QueryString` , `SingleHeader` , `Method` , and `JsonBody` .", "ResourceArn": "The Amazon Resource Name (ARN) of the web ACL that you want to associate with `LogDestinationConfigs` ." } }, "AWS::WAFv2::LoggingConfiguration.FieldToMatch": { "attributes": {}, - "description": "The parts of the request that you want to keep out of the logs. For example, if you redact the `SingleHeader` field, the `HEADER` field in the firehose will be `xxx` .\n\nJSON specification for a `QueryString` field to match:\n\n`\"FieldToMatch\": { \"QueryString\": {} }`\n\nExample JSON for a `Method` field to match specification:\n\n`\"FieldToMatch\": { \"Method\": { \"Name\": \"DELETE\" } }`", + "description": "The part of a web request that you want AWS WAF to inspect. Include the single `FieldToMatch` type that you want to inspect, with additional specifications as needed, according to the type. You specify a single request component in `FieldToMatch` for each rule statement that requires it. To inspect more than one component of a web request, create a separate rule statement for each component.\n\nJSON specification for a `QueryString` field to match:\n\n`\"FieldToMatch\": { \"QueryString\": {} }`\n\nExample JSON for a `Method` field to match specification:\n\n`\"FieldToMatch\": { \"Method\": { \"Name\": \"DELETE\" } }`", "properties": { - "JsonBody": "Redact the JSON body from the logs.", - "Method": "Redact the method from the logs.", - "QueryString": "Redact the query string from the logs.", - "SingleHeader": "Redact the header from the logs.", - "UriPath": "Redact the URI path from the logs." + "JsonBody": "Inspect the request body as JSON. The request body immediately follows the request headers. This is the part of a request that contains any additional data that you want to send to your web server as the HTTP request body, such as data from a form.\n\nNote that only the first 8 KB (8192 bytes) of the request body are forwarded to AWS WAF for inspection by the underlying host service. If you don't need to inspect more than 8 KB, you can guarantee that you don't allow additional bytes in by combining a statement that inspects the body of the web request, such as `ByteMatchStatement` or `RegexPatternSetReferenceStatement` , with a `SizeConstraintStatement` that enforces an 8 KB size limit on the body of the request. AWS WAF doesn't support inspecting the entire contents of web requests whose bodies exceed the 8 KB limit.", + "Method": "Inspect the HTTP method. The method indicates the type of operation that the request is asking the origin to perform.", + "QueryString": "Inspect the query string. This is the part of a URL that appears after a `?` character, if any.", + "SingleHeader": "Inspect a single header. Provide the name of the header to inspect, for example, `User-Agent` or `Referer` . This setting isn't case sensitive.\n\nExample JSON: `\"SingleHeader\": { \"Name\": \"haystack\" }`", + "UriPath": "Inspect the request URI path. This is the part of a web request that identifies a resource, for example, `/images/daily-ad.jpg` ." } }, "AWS::WAFv2::RegexPatternSet": { @@ -39192,6 +39496,13 @@ "Name": "The name of the rule to exclude." } }, + "AWS::WAFv2::WebACL.FieldIdentifier": { + "attributes": {}, + "description": "The identifier of the username or password field, used in the `ManagedRuleGroupConfig` settings.", + "properties": { + "Identifier": "The name of the username or password field, used in the `ManagedRuleGroupConfig` settings.\n\nWhen the `PayloadType` is `JSON` , the identifier must be in JSON pointer syntax. For example `/form/username` . For information about the JSON Pointer syntax, see the Internet Engineering Task Force (IETF) documentation [JavaScript Object Notation (JSON) Pointer](https://docs.aws.amazon.com/https://tools.ietf.org/html/rfc6901) .\n\nWhen the `PayloadType` is `FORM_ENCODED` , use the HTML form names. For example, `username` ." + } + }, "AWS::WAFv2::WebACL.FieldToMatch": { "attributes": {}, "description": "The part of a web request that you want AWS WAF to inspect. Include the single `FieldToMatch` type that you want to inspect, with additional specifications as needed, according to the type. You specify a single request component in `FieldToMatch` for each rule statement that requires it. To inspect more than one component of a web request, create a separate rule statement for each component.", @@ -39278,11 +39589,22 @@ "Scope": "Specify whether you want to match using the label name or just the namespace." } }, + "AWS::WAFv2::WebACL.ManagedRuleGroupConfig": { + "attributes": {}, + "description": "Additional information that's used by a managed rule group. Most managed rule groups don't require this.\n\nUse this for the account takeover prevention managed rule group `AWSManagedRulesATPRuleSet` , to provide information about the sign-in page of your application.\n\nYou can provide multiple individual `ManagedRuleGroupConfig` objects for any rule group configuration, for example `UsernameField` and `PasswordField` . The configuration that you provide depends on the needs of the managed rule group. For the ATP managed rule group, you provide the following individual configuration objects: `LoginPath` , `PasswordField` , `PayloadType` and `UsernameField` .", + "properties": { + "LoginPath": "The path of the login endpoint for your application. For example, for the URL `https://example.com/web/login` , you would provide the path `/web/login` .", + "PasswordField": "Details about your login page password field.", + "PayloadType": "The payload type for your login endpoint, either JSON or form encoded.", + "UsernameField": "Details about your login page username field." + } + }, "AWS::WAFv2::WebACL.ManagedRuleGroupStatement": { "attributes": {}, "description": "A rule statement used to run the rules that are defined in a managed rule group. To use this, provide the vendor name and the name of the rule group in this statement.\n\nYou can't nest a `ManagedRuleGroupStatement` , for example for use inside a `NotStatement` or `OrStatement` . It can only be referenced as a top-level statement within a rule.", "properties": { "ExcludedRules": "The rules whose actions are set to `COUNT` by the web ACL, regardless of the action that is configured in the rule. This effectively excludes the rule from acting on web requests.", + "ManagedRuleGroupConfigs": "Additional information that's used by a managed rule group. Most managed rule groups don't require this.\n\nUse this for the account takeover prevention managed rule group `AWSManagedRulesATPRuleSet` , to provide information about the sign-in page of your application.\n\nYou can provide multiple individual `ManagedRuleGroupConfig` objects for any rule group configuration, for example `UsernameField` and `PasswordField` . The configuration that you provide depends on the needs of the managed rule group. For the ATP managed rule group, you provide the following individual configuration objects: `LoginPath` , `PasswordField` , `PayloadType` and `UsernameField` .", "Name": "The name of the managed rule group. You use this, along with the vendor name, to identify the rule group.", "ScopeDownStatement": "Statement nested inside a managed rule group statement to narrow the scope of the requests that AWS WAF evaluates using the rule group. Requests that match the scope-down statement are evaluated using the rule group. Requests that don't match the scope-down statement are not a match for the managed rule group statement, without any further evaluation.", "VendorName": "The name of the managed rule group vendor. You use this, along with the rule group name, to identify the rule group.", @@ -39365,10 +39687,10 @@ }, "AWS::WAFv2::WebACL.RuleGroupReferenceStatement": { "attributes": {}, - "description": "A rule statement used to run the rules that are defined in a `RuleGroup` . To use this, create a rule group with your rules, then provide the ARN of the rule group in this statement.\n\nYou cannot nest a `RuleGroupReferenceStatement` , for example for use inside a `NotStatement` or `OrStatement` . It can only be referenced as a top-level statement within a rule.", + "description": "A rule statement used to run the rules that are defined in a `RuleGroup` . To use this, create a rule group with your rules, then provide the ARN of the rule group in this statement.\n\nYou cannot nest a `RuleGroupReferenceStatement` , for example for use inside a `NotStatement` or `OrStatement` . You can only use a rule group reference statement at the top level inside a web ACL.", "properties": { "Arn": "The Amazon Resource Name (ARN) of the entity.", - "ExcludedRules": "The names of rules that are in the referenced rule group, but that you want AWS WAF to exclude from processing for this rule statement." + "ExcludedRules": "The rules in the referenced rule group whose actions are set to `Count` . When you exclude a rule, AWS WAF evaluates it exactly as it would if the rule action setting were `Count` . This is a useful option for testing the rules in a rule group without modifying how they handle your web traffic." } }, "AWS::WAFv2::WebACL.SizeConstraintStatement": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ACMPCA.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ACMPCA.json index b3366d0c9bfa2..dac153e3007d0 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ACMPCA.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ACMPCA.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::ACMPCA::Certificate.ApiPassthrough": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-acmpca-certificate-apipassthrough.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_APS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_APS.json index ee8621a835963..a70041a096054 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_APS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_APS.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::APS::RuleGroupsNamespace": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AccessAnalyzer.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AccessAnalyzer.json index 71dc25887ce30..b299f8945cdd4 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AccessAnalyzer.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AccessAnalyzer.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::AccessAnalyzer::Analyzer.ArchiveRule": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-accessanalyzer-analyzer-archiverule.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AmazonMQ.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AmazonMQ.json index 7f59226829a3e..6698f6c945cdc 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AmazonMQ.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AmazonMQ.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::AmazonMQ::Broker.ConfigurationId": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-amazonmq-broker-configurationid.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Amplify.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Amplify.json index 5333a2757c142..ea80361cefe44 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Amplify.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Amplify.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Amplify::App.AutoBranchCreationConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-amplify-app-autobranchcreationconfig.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AmplifyUIBuilder.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AmplifyUIBuilder.json index 83b2b3ac85213..6c2c648f4a595 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AmplifyUIBuilder.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AmplifyUIBuilder.json @@ -1,6 +1,65 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { + "AWS::AmplifyUIBuilder::Component.ActionParameters": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-amplifyuibuilder-component-actionparameters.html", + "Properties": { + "Anchor": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-amplifyuibuilder-component-actionparameters.html#cfn-amplifyuibuilder-component-actionparameters-anchor", + "Required": false, + "Type": "ComponentProperty", + "UpdateType": "Mutable" + }, + "Fields": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-amplifyuibuilder-component-actionparameters.html#cfn-amplifyuibuilder-component-actionparameters-fields", + "Required": false, + "Type": "ComponentProperties", + "UpdateType": "Mutable" + }, + "Global": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-amplifyuibuilder-component-actionparameters.html#cfn-amplifyuibuilder-component-actionparameters-global", + "Required": false, + "Type": "ComponentProperty", + "UpdateType": "Mutable" + }, + "Id": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-amplifyuibuilder-component-actionparameters.html#cfn-amplifyuibuilder-component-actionparameters-id", + "Required": false, + "Type": "ComponentProperty", + "UpdateType": "Mutable" + }, + "Model": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-amplifyuibuilder-component-actionparameters.html#cfn-amplifyuibuilder-component-actionparameters-model", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "State": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-amplifyuibuilder-component-actionparameters.html#cfn-amplifyuibuilder-component-actionparameters-state", + "Required": false, + "Type": "MutationActionSetStateParameter", + "UpdateType": "Mutable" + }, + "Target": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-amplifyuibuilder-component-actionparameters.html#cfn-amplifyuibuilder-component-actionparameters-target", + "Required": false, + "Type": "ComponentProperty", + "UpdateType": "Mutable" + }, + "Type": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-amplifyuibuilder-component-actionparameters.html#cfn-amplifyuibuilder-component-actionparameters-type", + "Required": false, + "Type": "ComponentProperty", + "UpdateType": "Mutable" + }, + "Url": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-amplifyuibuilder-component-actionparameters.html#cfn-amplifyuibuilder-component-actionparameters-url", + "Required": false, + "Type": "ComponentProperty", + "UpdateType": "Mutable" + } + } + }, "AWS::AmplifyUIBuilder::Component.ComponentBindingPropertiesValue": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-amplifyuibuilder-component-componentbindingpropertiesvalue.html", "Properties": { @@ -88,6 +147,12 @@ "Required": true, "UpdateType": "Mutable" }, + "Events": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-amplifyuibuilder-component-componentchild.html#cfn-amplifyuibuilder-component-componentchild-events", + "Required": false, + "Type": "ComponentEvents", + "UpdateType": "Mutable" + }, "Name": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-amplifyuibuilder-component-componentchild.html#cfn-amplifyuibuilder-component-componentchild-name", "PrimitiveType": "String", @@ -123,6 +188,12 @@ "Required": false, "UpdateType": "Mutable" }, + "OperandType": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-amplifyuibuilder-component-componentconditionproperty.html#cfn-amplifyuibuilder-component-componentconditionproperty-operandtype", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, "Operator": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-amplifyuibuilder-component-componentconditionproperty.html#cfn-amplifyuibuilder-component-componentconditionproperty-operator", "PrimitiveType": "String", @@ -174,6 +245,29 @@ } } }, + "AWS::AmplifyUIBuilder::Component.ComponentEvent": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-amplifyuibuilder-component-componentevent.html", + "Properties": { + "Action": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-amplifyuibuilder-component-componentevent.html#cfn-amplifyuibuilder-component-componentevent-action", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "Parameters": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-amplifyuibuilder-component-componentevent.html#cfn-amplifyuibuilder-component-componentevent-parameters", + "Required": false, + "Type": "ActionParameters", + "UpdateType": "Mutable" + } + } + }, + "AWS::AmplifyUIBuilder::Component.ComponentEvents": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-amplifyuibuilder-component-componentevents.html", + "PrimitiveType": "Json", + "Required": false, + "UpdateType": "Mutable" + }, "AWS::AmplifyUIBuilder::Component.ComponentOverrides": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-amplifyuibuilder-component-componentoverrides.html", "PrimitiveType": "Json", @@ -213,6 +307,12 @@ "Type": "ComponentPropertyBindingProperties", "UpdateType": "Mutable" }, + "ComponentName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-amplifyuibuilder-component-componentproperty.html#cfn-amplifyuibuilder-component-componentproperty-componentname", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, "Concat": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-amplifyuibuilder-component-componentproperty.html#cfn-amplifyuibuilder-component-componentproperty-concat", "ItemType": "ComponentProperty", @@ -256,6 +356,12 @@ "Required": false, "UpdateType": "Mutable" }, + "Property": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-amplifyuibuilder-component-componentproperty.html#cfn-amplifyuibuilder-component-componentproperty-property", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, "Type": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-amplifyuibuilder-component-componentproperty.html#cfn-amplifyuibuilder-component-componentproperty-type", "PrimitiveType": "String", @@ -322,6 +428,29 @@ "Required": false, "UpdateType": "Mutable" }, + "AWS::AmplifyUIBuilder::Component.MutationActionSetStateParameter": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-amplifyuibuilder-component-mutationactionsetstateparameter.html", + "Properties": { + "ComponentName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-amplifyuibuilder-component-mutationactionsetstateparameter.html#cfn-amplifyuibuilder-component-mutationactionsetstateparameter-componentname", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "Property": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-amplifyuibuilder-component-mutationactionsetstateparameter.html#cfn-amplifyuibuilder-component-mutationactionsetstateparameter-property", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "Set": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-amplifyuibuilder-component-mutationactionsetstateparameter.html#cfn-amplifyuibuilder-component-mutationactionsetstateparameter-set", + "Required": true, + "Type": "ComponentProperty", + "UpdateType": "Mutable" + } + } + }, "AWS::AmplifyUIBuilder::Component.Predicate": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-amplifyuibuilder-component-predicate.html", "Properties": { @@ -418,17 +547,11 @@ "AppId": { "PrimitiveType": "String" }, - "CreatedAt": { - "PrimitiveType": "String" - }, "EnvironmentName": { "PrimitiveType": "String" }, "Id": { "PrimitiveType": "String" - }, - "ModifiedAt": { - "PrimitiveType": "String" } }, "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-amplifyuibuilder-component.html", @@ -436,7 +559,7 @@ "BindingProperties": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-amplifyuibuilder-component.html#cfn-amplifyuibuilder-component-bindingproperties", "ItemType": "ComponentBindingPropertiesValue", - "Required": false, + "Required": true, "Type": "Map", "UpdateType": "Mutable" }, @@ -457,29 +580,42 @@ "ComponentType": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-amplifyuibuilder-component.html#cfn-amplifyuibuilder-component-componenttype", "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "Events": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-amplifyuibuilder-component.html#cfn-amplifyuibuilder-component-events", + "ItemType": "ComponentEvent", "Required": false, + "Type": "Map", "UpdateType": "Mutable" }, "Name": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-amplifyuibuilder-component.html#cfn-amplifyuibuilder-component-name", "PrimitiveType": "String", - "Required": false, + "Required": true, "UpdateType": "Mutable" }, "Overrides": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-amplifyuibuilder-component.html#cfn-amplifyuibuilder-component-overrides", "ItemType": "ComponentOverridesValue", - "Required": false, + "Required": true, "Type": "Map", "UpdateType": "Mutable" }, "Properties": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-amplifyuibuilder-component.html#cfn-amplifyuibuilder-component-properties", "ItemType": "ComponentProperty", - "Required": false, + "Required": true, "Type": "Map", "UpdateType": "Mutable" }, + "SchemaVersion": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-amplifyuibuilder-component.html#cfn-amplifyuibuilder-component-schemaversion", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, "SourceId": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-amplifyuibuilder-component.html#cfn-amplifyuibuilder-component-sourceid", "PrimitiveType": "String", @@ -496,7 +632,7 @@ "Variants": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-amplifyuibuilder-component.html#cfn-amplifyuibuilder-component-variants", "ItemType": "ComponentVariant", - "Required": false, + "Required": true, "Type": "List", "UpdateType": "Mutable" } diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApiGateway.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApiGateway.json index b21956183f550..30342b35d19d3 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApiGateway.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApiGateway.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::ApiGateway::ApiKey.StageKey": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-apigateway-apikey-stagekey.html", @@ -892,6 +892,12 @@ "Required": true, "UpdateType": "Immutable" }, + "Id": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-basepathmapping.html#cfn-apigateway-basepathmapping-id", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, "RestApiId": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-basepathmapping.html#cfn-apigateway-basepathmapping-restapiid", "PrimitiveType": "String", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApiGatewayV2.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApiGatewayV2.json index 84c344017d479..a4c11dfddee1e 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApiGatewayV2.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApiGatewayV2.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::ApiGatewayV2::Api.BodyS3Location": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-apigatewayv2-api-bodys3location.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppConfig.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppConfig.json index f9ef46a48999e..8bb66bdfa0514 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppConfig.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppConfig.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::AppConfig::Application.Tags": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appconfig-application-tags.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppFlow.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppFlow.json index 90b63f9d4b274..760499dc8e26d 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppFlow.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppFlow.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::AppFlow::ConnectorProfile.AmplitudeConnectorProfileCredentials": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appflow-connectorprofile-amplitudeconnectorprofilecredentials.html", @@ -953,6 +953,12 @@ "Type": "S3DestinationProperties", "UpdateType": "Mutable" }, + "SAPOData": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appflow-flow-destinationconnectorproperties.html#cfn-appflow-flow-destinationconnectorproperties-sapodata", + "Required": false, + "Type": "SAPODataDestinationProperties", + "UpdateType": "Mutable" + }, "Salesforce": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appflow-flow-destinationconnectorproperties.html#cfn-appflow-flow-destinationconnectorproperties-salesforce", "Required": false, @@ -1234,6 +1240,42 @@ } } }, + "AWS::AppFlow::Flow.SAPODataDestinationProperties": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appflow-flow-sapodatadestinationproperties.html", + "Properties": { + "ErrorHandlingConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appflow-flow-sapodatadestinationproperties.html#cfn-appflow-flow-sapodatadestinationproperties-errorhandlingconfig", + "Required": false, + "Type": "ErrorHandlingConfig", + "UpdateType": "Mutable" + }, + "IdFieldNames": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appflow-flow-sapodatadestinationproperties.html#cfn-appflow-flow-sapodatadestinationproperties-idfieldnames", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "ObjectPath": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appflow-flow-sapodatadestinationproperties.html#cfn-appflow-flow-sapodatadestinationproperties-objectpath", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "SuccessResponseHandlingConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appflow-flow-sapodatadestinationproperties.html#cfn-appflow-flow-sapodatadestinationproperties-successresponsehandlingconfig", + "Required": false, + "Type": "SuccessResponseHandlingConfig", + "UpdateType": "Mutable" + }, + "WriteOperationType": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appflow-flow-sapodatadestinationproperties.html#cfn-appflow-flow-sapodatadestinationproperties-writeoperationtype", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + }, "AWS::AppFlow::Flow.SAPODataSourceProperties": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appflow-flow-sapodatasourceproperties.html", "Properties": { @@ -1525,6 +1567,23 @@ } } }, + "AWS::AppFlow::Flow.SuccessResponseHandlingConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appflow-flow-successresponsehandlingconfig.html", + "Properties": { + "BucketName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appflow-flow-successresponsehandlingconfig.html#cfn-appflow-flow-successresponsehandlingconfig-bucketname", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "BucketPrefix": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appflow-flow-successresponsehandlingconfig.html#cfn-appflow-flow-successresponsehandlingconfig-bucketprefix", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + }, "AWS::AppFlow::Flow.Task": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appflow-flow-task.html", "Properties": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppIntegrations.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppIntegrations.json index fd09492304583..fe801de427892 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppIntegrations.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppIntegrations.json @@ -1,6 +1,29 @@ { - "$version": "53.1.0", + "$version": "59.0.0", "PropertyTypes": { + "AWS::AppIntegrations::DataIntegration.ScheduleConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appintegrations-dataintegration-scheduleconfig.html", + "Properties": { + "FirstExecutionFrom": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appintegrations-dataintegration-scheduleconfig.html#cfn-appintegrations-dataintegration-scheduleconfig-firstexecutionfrom", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "Object": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appintegrations-dataintegration-scheduleconfig.html#cfn-appintegrations-dataintegration-scheduleconfig-object", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "ScheduleExpression": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appintegrations-dataintegration-scheduleconfig.html#cfn-appintegrations-dataintegration-scheduleconfig-scheduleexpression", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + } + } + }, "AWS::AppIntegrations::EventIntegration.EventFilter": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appintegrations-eventintegration-eventfilter.html", "Properties": { @@ -67,6 +90,56 @@ } }, "ResourceTypes": { + "AWS::AppIntegrations::DataIntegration": { + "Attributes": { + "DataIntegrationArn": { + "PrimitiveType": "String" + }, + "Id": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-appintegrations-dataintegration.html", + "Properties": { + "Description": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-appintegrations-dataintegration.html#cfn-appintegrations-dataintegration-description", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "KmsKey": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-appintegrations-dataintegration.html#cfn-appintegrations-dataintegration-kmskey", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "Name": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-appintegrations-dataintegration.html#cfn-appintegrations-dataintegration-name", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "ScheduleConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-appintegrations-dataintegration.html#cfn-appintegrations-dataintegration-scheduleconfig", + "Required": true, + "Type": "ScheduleConfig", + "UpdateType": "Immutable" + }, + "SourceURI": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-appintegrations-dataintegration.html#cfn-appintegrations-dataintegration-sourceuri", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "Tags": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-appintegrations-dataintegration.html#cfn-appintegrations-dataintegration-tags", + "ItemType": "Tag", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + } + } + }, "AWS::AppIntegrations::EventIntegration": { "Attributes": { "Associations": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppMesh.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppMesh.json index 90bf6f838de9c..0fa21840770c8 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppMesh.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppMesh.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::AppMesh::GatewayRoute.GatewayRouteHostnameMatch": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-gatewayroute-gatewayroutehostnamematch.html", @@ -466,6 +466,10 @@ } } }, + "AWS::AppMesh::Mesh.MeshServiceDiscovery": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-mesh-meshservicediscovery.html", + "Properties": {} + }, "AWS::AppMesh::Mesh.MeshSpec": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-mesh-meshspec.html", "Properties": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppRunner.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppRunner.json index 53daf14d81492..f6ec168d966ee 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppRunner.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppRunner.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::AppRunner::Service.AuthenticationConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-apprunner-service-authenticationconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppStream.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppStream.json index a55d1ac749e18..eb23b562ec809 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppStream.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppStream.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::AppStream::AppBlock.S3Location": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appstream-appblock-s3location.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppSync.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppSync.json index 6c9f0a6ffb18c..d4853b9eeec5b 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppSync.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppSync.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::AppSync::DataSource.AuthorizationConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appsync-datasource-authorizationconfig.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApplicationAutoScaling.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApplicationAutoScaling.json index d2d9749e0f26d..4b86fc0650394 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApplicationAutoScaling.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApplicationAutoScaling.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::ApplicationAutoScaling::ScalableTarget.ScalableTargetAction": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-applicationautoscaling-scalabletarget-scalabletargetaction.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApplicationInsights.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApplicationInsights.json index e58b97d5499fe..9c30a33fc0088 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApplicationInsights.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApplicationInsights.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::ApplicationInsights::Application.Alarm": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-applicationinsights-application-alarm.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Athena.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Athena.json index 04ff57563783e..128a384482631 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Athena.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Athena.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Athena::WorkGroup.EncryptionConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-athena-workgroup-encryptionconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AuditManager.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AuditManager.json index c5c162d8c957c..37fcdfb3dcae4 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AuditManager.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AuditManager.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::AuditManager::Assessment.AWSAccount": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-auditmanager-assessment-awsaccount.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AutoScaling.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AutoScaling.json index e15a67931b552..015d7ef11d4f2 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AutoScaling.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AutoScaling.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::AutoScaling::AutoScalingGroup.AcceleratorCountRequest": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-autoscaling-autoscalinggroup-acceleratorcountrequest.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AutoScalingPlans.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AutoScalingPlans.json index 82577d5c09519..11a5c2b5b0099 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AutoScalingPlans.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AutoScalingPlans.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::AutoScalingPlans::ScalingPlan.ApplicationSource": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-autoscalingplans-scalingplan-applicationsource.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Backup.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Backup.json index 2504937a74940..1d33a8b543e37 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Backup.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Backup.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Backup::BackupPlan.AdvancedBackupSettingResourceType": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-backup-backupplan-advancedbackupsettingresourcetype.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Batch.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Batch.json index b53169c1009f9..891e31a407d0f 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Batch.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Batch.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Batch::ComputeEnvironment.ComputeResources": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-batch-computeenvironment-computeresources.html", @@ -24,6 +24,7 @@ }, "Ec2Configuration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-batch-computeenvironment-computeresources.html#cfn-batch-computeenvironment-computeresources-ec2configuration", + "DuplicatesAllowed": true, "ItemType": "Ec2ConfigurationObject", "Required": false, "Type": "List", @@ -49,6 +50,7 @@ }, "InstanceTypes": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-batch-computeenvironment-computeresources.html#cfn-batch-computeenvironment-computeresources-instancetypes", + "DuplicatesAllowed": true, "PrimitiveItemType": "String", "Required": false, "Type": "List", @@ -80,6 +82,7 @@ }, "SecurityGroupIds": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-batch-computeenvironment-computeresources.html#cfn-batch-computeenvironment-computeresources-securitygroupids", + "DuplicatesAllowed": true, "PrimitiveItemType": "String", "Required": false, "Type": "List", @@ -93,6 +96,7 @@ }, "Subnets": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-batch-computeenvironment-computeresources.html#cfn-batch-computeenvironment-computeresources-subnets", + "DuplicatesAllowed": true, "PrimitiveItemType": "String", "Required": true, "Type": "List", @@ -100,8 +104,9 @@ }, "Tags": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-batch-computeenvironment-computeresources.html#cfn-batch-computeenvironment-computeresources-tags", - "PrimitiveType": "Json", + "PrimitiveItemType": "String", "Required": false, + "Type": "Map", "UpdateType": "Immutable" }, "Type": { @@ -764,6 +769,11 @@ }, "ResourceTypes": { "AWS::Batch::ComputeEnvironment": { + "Attributes": { + "ComputeEnvironmentArn": { + "PrimitiveType": "String" + } + }, "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-batch-computeenvironment.html", "Properties": { "ComputeEnvironmentName": { @@ -792,8 +802,9 @@ }, "Tags": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-batch-computeenvironment.html#cfn-batch-computeenvironment-tags", - "PrimitiveType": "Json", + "PrimitiveItemType": "String", "Required": false, + "Type": "Map", "UpdateType": "Immutable" }, "Type": { @@ -883,10 +894,16 @@ } }, "AWS::Batch::JobQueue": { + "Attributes": { + "JobQueueArn": { + "PrimitiveType": "String" + } + }, "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-batch-jobqueue.html", "Properties": { "ComputeEnvironmentOrder": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-batch-jobqueue.html#cfn-batch-jobqueue-computeenvironmentorder", + "DuplicatesAllowed": true, "ItemType": "ComputeEnvironmentOrder", "Required": true, "Type": "List", @@ -918,8 +935,9 @@ }, "Tags": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-batch-jobqueue.html#cfn-batch-jobqueue-tags", - "PrimitiveType": "Json", + "PrimitiveItemType": "String", "Required": false, + "Type": "Map", "UpdateType": "Immutable" } } diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Budgets.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Budgets.json index 7d384d64cc722..dcd3c55f3218a 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Budgets.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Budgets.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Budgets::Budget.BudgetData": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-budgets-budget-budgetdata.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CE.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CE.json index 1d7a639bbe011..fe5d15b420a56 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CE.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CE.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::CE::AnomalySubscription.Subscriber": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ce-anomalysubscription-subscriber.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CUR.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CUR.json index a48d774257752..1566d46908c7b 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CUR.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CUR.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::CUR::ReportDefinition": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cassandra.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cassandra.json index 3f42e4fd6bc74..97eb91f8f45c0 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cassandra.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cassandra.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Cassandra::Table.BillingMode": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cassandra-table-billingmode.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CertificateManager.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CertificateManager.json index 66edc998156a5..5e511759a4f1f 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CertificateManager.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CertificateManager.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::CertificateManager::Account.ExpiryEventsConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-certificatemanager-account-expiryeventsconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Chatbot.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Chatbot.json index 87a2db83de9e9..3575f5459a09e 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Chatbot.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Chatbot.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::Chatbot::SlackChannelConfiguration": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cloud9.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cloud9.json index 8ea1853310b5f..3297e6643bf99 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cloud9.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cloud9.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Cloud9::EnvironmentEC2.Repository": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloud9-environmentec2-repository.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudFormation.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudFormation.json index c28d319dc7788..dddebf6f4b44d 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudFormation.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudFormation.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::CloudFormation::HookVersion.LoggingConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudformation-hookversion-loggingconfig.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudFront.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudFront.json index a5a0a500a5cf0..22c0717588cb8 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudFront.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudFront.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::CloudFront::CachePolicy.CachePolicyConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudfront-cachepolicy-cachepolicyconfig.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudTrail.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudTrail.json index 09409f3fa3c96..2cfb35e3d8823 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudTrail.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudTrail.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::CloudTrail::Trail.DataResource": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudtrail-trail-dataresource.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudWatch.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudWatch.json index f1918bb2b22f0..a59c52f28a48d 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudWatch.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudWatch.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::CloudWatch::Alarm.Dimension": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-dimension.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeArtifact.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeArtifact.json index e12adf601a927..297826596c615 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeArtifact.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeArtifact.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::CodeArtifact::Domain": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeBuild.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeBuild.json index c6d9718e8d200..aa6eab1214a2e 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeBuild.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeBuild.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::CodeBuild::Project.Artifacts": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codebuild-project-artifacts.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeCommit.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeCommit.json index 08486540935ff..c6668b46ef1c0 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeCommit.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeCommit.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::CodeCommit::Repository.Code": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codecommit-repository-code.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeDeploy.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeDeploy.json index 186c6f05310e2..e500317a11195 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeDeploy.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeDeploy.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::CodeDeploy::DeploymentConfig.MinimumHealthyHosts": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codedeploy-deploymentconfig-minimumhealthyhosts.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeGuruProfiler.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeGuruProfiler.json index ad3ad08ed4fdd..07562c3c95b26 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeGuruProfiler.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeGuruProfiler.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::CodeGuruProfiler::ProfilingGroup.Channel": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codeguruprofiler-profilinggroup-channel.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeGuruReviewer.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeGuruReviewer.json index d15cfe26d71de..ba975800ca1fc 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeGuruReviewer.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeGuruReviewer.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::CodeGuruReviewer::RepositoryAssociation": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodePipeline.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodePipeline.json index ef99e67ae3bd7..dd554b9cc6538 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodePipeline.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodePipeline.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::CodePipeline::CustomActionType.ArtifactDetails": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codepipeline-customactiontype-artifactdetails.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStar.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStar.json index d6c57b99c3b09..686431702961f 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStar.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStar.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::CodeStar::GitHubRepository.Code": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codestar-githubrepository-code.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStarConnections.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStarConnections.json index a22b7ce2b9bee..1613ba7e671bd 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStarConnections.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStarConnections.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::CodeStarConnections::Connection": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStarNotifications.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStarNotifications.json index b5dfc0a57544d..2566cb083c272 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStarNotifications.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStarNotifications.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::CodeStarNotifications::NotificationRule.Target": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codestarnotifications-notificationrule-target.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cognito.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cognito.json index e622cf9e10e0f..a17a8d2ae7d53 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cognito.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cognito.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Cognito::IdentityPool.CognitoIdentityProvider": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cognito-identitypool-cognitoidentityprovider.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Config.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Config.json index 73fa976277f7b..059dba0e6bd65 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Config.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Config.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Config::ConfigRule.Scope": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-config-configrule-scope.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Connect.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Connect.json index 0aab5a3a93ca6..353bb7c024107 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Connect.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Connect.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Connect::HoursOfOperation.HoursOfOperationConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-connect-hoursofoperation-hoursofoperationconfig.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CustomerProfiles.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CustomerProfiles.json index 3a99f750ee600..d263c81b4218c 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CustomerProfiles.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CustomerProfiles.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::CustomerProfiles::Integration.ConnectorOperator": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-customerprofiles-integration-connectoroperator.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DAX.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DAX.json index 3ec83b0985bdb..6f03d49c5ad07 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DAX.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DAX.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::DAX::Cluster.SSESpecification": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dax-cluster-ssespecification.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DLM.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DLM.json index ef16e46e91eeb..bff6ea72ec99e 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DLM.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DLM.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::DLM::LifecyclePolicy.Action": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dlm-lifecyclepolicy-action.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DMS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DMS.json index 2c56a7cc4be45..db28a5e1805ee 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DMS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DMS.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::DMS::Endpoint.DocDbSettings": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dms-endpoint-docdbsettings.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataBrew.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataBrew.json index d451a642b4b39..ae8b721fd145b 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataBrew.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataBrew.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::DataBrew::Dataset.CsvOptions": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-databrew-dataset-csvoptions.html", @@ -550,6 +550,12 @@ "Type": "S3Location", "UpdateType": "Mutable" }, + "MaxOutputFiles": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-databrew-job-output.html#cfn-databrew-job-output-maxoutputfiles", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Mutable" + }, "Overwrite": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-databrew-job-output.html#cfn-databrew-job-output-overwrite", "PrimitiveType": "Boolean", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataPipeline.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataPipeline.json index a3c959eaf585a..21d5aa48047be 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataPipeline.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataPipeline.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::DataPipeline::Pipeline.Field": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-datapipeline-pipeline-pipelineobjects-fields.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataSync.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataSync.json index a409e1905d49a..a6ccf78781300 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataSync.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataSync.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::DataSync::LocationEFS.Ec2Config": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-datasync-locationefs-ec2config.html", @@ -309,6 +309,46 @@ } } }, + "AWS::DataSync::LocationFSxLustre": { + "Attributes": { + "LocationArn": { + "PrimitiveType": "String" + }, + "LocationUri": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-datasync-locationfsxlustre.html", + "Properties": { + "FsxFilesystemArn": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-datasync-locationfsxlustre.html#cfn-datasync-locationfsxlustre-fsxfilesystemarn", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "SecurityGroupArns": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-datasync-locationfsxlustre.html#cfn-datasync-locationfsxlustre-securitygrouparns", + "PrimitiveItemType": "String", + "Required": true, + "Type": "List", + "UpdateType": "Immutable" + }, + "Subdirectory": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-datasync-locationfsxlustre.html#cfn-datasync-locationfsxlustre-subdirectory", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "Tags": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-datasync-locationfsxlustre.html#cfn-datasync-locationfsxlustre-tags", + "DuplicatesAllowed": false, + "ItemType": "Tag", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + } + } + }, "AWS::DataSync::LocationFSxWindows": { "Attributes": { "LocationArn": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Detective.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Detective.json index d2b8d0fd9abde..a6b15557080a0 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Detective.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Detective.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::Detective::Graph": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DevOpsGuru.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DevOpsGuru.json index f350855a480c7..ef9a76da445f4 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DevOpsGuru.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DevOpsGuru.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::DevOpsGuru::NotificationChannel.NotificationChannelConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-devopsguru-notificationchannel-notificationchannelconfig.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DirectoryService.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DirectoryService.json index 1ae99c0fc0b8f..cb12cac9d1e62 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DirectoryService.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DirectoryService.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::DirectoryService::MicrosoftAD.VpcSettings": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-directoryservice-microsoftad-vpcsettings.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DocDB.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DocDB.json index 3e017ef280e92..39675ffbc909e 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DocDB.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DocDB.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::DocDB::DBCluster": { @@ -84,13 +84,13 @@ "MasterUserPassword": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-docdb-dbcluster.html#cfn-docdb-dbcluster-masteruserpassword", "PrimitiveType": "String", - "Required": true, + "Required": false, "UpdateType": "Mutable" }, "MasterUsername": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-docdb-dbcluster.html#cfn-docdb-dbcluster-masterusername", "PrimitiveType": "String", - "Required": true, + "Required": false, "UpdateType": "Immutable" }, "Port": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DynamoDB.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DynamoDB.json index 34d3c8dab312f..84cf6ddc6f718 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DynamoDB.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DynamoDB.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::DynamoDB::GlobalTable.AttributeDefinition": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-globaltable-attributedefinition.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EC2.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EC2.json index 1364313bd5e61..121bd07541944 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EC2.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EC2.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::EC2::CapacityReservation.TagSpecification": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-capacityreservation-tagspecification.html", @@ -1171,6 +1171,29 @@ "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance-nodevice.html", "Properties": {} }, + "AWS::EC2::Instance.PrivateDnsNameOptions": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance-privatednsnameoptions.html", + "Properties": { + "EnableResourceNameDnsAAAARecord": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance-privatednsnameoptions.html#cfn-ec2-instance-privatednsnameoptions-enableresourcenamednsaaaarecord", + "PrimitiveType": "Boolean", + "Required": false, + "UpdateType": "Mutable" + }, + "EnableResourceNameDnsARecord": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance-privatednsnameoptions.html#cfn-ec2-instance-privatednsnameoptions-enableresourcenamednsarecord", + "PrimitiveType": "Boolean", + "Required": false, + "UpdateType": "Mutable" + }, + "HostnameType": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance-privatednsnameoptions.html#cfn-ec2-instance-privatednsnameoptions-hostnametype", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + }, "AWS::EC2::Instance.PrivateIpAddressSpecification": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-network-interface-privateipspec.html", "Properties": { @@ -3664,6 +3687,12 @@ "Required": false, "UpdateType": "Immutable" }, + "Priority": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-spotfleet-launchtemplateoverrides.html#cfn-ec2-spotfleet-launchtemplateoverrides-priority", + "PrimitiveType": "Double", + "Required": false, + "UpdateType": "Immutable" + }, "SpotPrice": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-spotfleet-launchtemplateoverrides.html#cfn-ec2-spotfleet-launchtemplateoverrides-spotprice", "PrimitiveType": "String", @@ -5488,6 +5517,12 @@ "Required": false, "UpdateType": "Immutable" }, + "PrivateDnsNameOptions": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html#cfn-ec2-instance-privatednsnameoptions", + "Required": false, + "Type": "PrivateDnsNameOptions", + "UpdateType": "Conditional" + }, "PrivateIpAddress": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html#cfn-ec2-instance-privateipaddress", "PrimitiveType": "String", @@ -7356,7 +7391,7 @@ "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-transitgatewayvpcattachment.html#cfn-ec2-transitgatewayvpcattachment-subnetids", "DuplicatesAllowed": true, "PrimitiveItemType": "String", - "Required": false, + "Required": true, "Type": "List", "UpdateType": "Immutable" }, @@ -7371,13 +7406,13 @@ "TransitGatewayId": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-transitgatewayvpcattachment.html#cfn-ec2-transitgatewayvpcattachment-transitgatewayid", "PrimitiveType": "String", - "Required": false, + "Required": true, "UpdateType": "Immutable" }, "VpcId": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-transitgatewayvpcattachment.html#cfn-ec2-transitgatewayvpcattachment-vpcid", "PrimitiveType": "String", - "Required": false, + "Required": true, "UpdateType": "Immutable" } } diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ECR.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ECR.json index 59fd9802db598..2d218f537b90e 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ECR.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ECR.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::ECR::ReplicationConfiguration.ReplicationConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecr-replicationconfiguration-replicationconfiguration.html", @@ -149,6 +149,23 @@ } } }, + "AWS::ECR::PullThroughCacheRule": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ecr-pullthroughcacherule.html", + "Properties": { + "EcrRepositoryPrefix": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ecr-pullthroughcacherule.html#cfn-ecr-pullthroughcacherule-ecrrepositoryprefix", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "UpstreamRegistryUrl": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ecr-pullthroughcacherule.html#cfn-ecr-pullthroughcacherule-upstreamregistryurl", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + } + } + }, "AWS::ECR::RegistryPolicy": { "Attributes": { "RegistryId": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ECS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ECS.json index c6487ffc8852a..0ee480e4895bc 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ECS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ECS.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::ECS::CapacityProvider.AutoScalingGroupProvider": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-capacityprovider-autoscalinggroupprovider.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EFS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EFS.json index bf5355aad4ec0..bbc443d07d1e6 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EFS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EFS.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::EFS::AccessPoint.AccessPointTag": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-efs-accesspoint-accesspointtag.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EKS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EKS.json index d7400913d4342..2b97e822693e9 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EKS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EKS.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::EKS::Cluster.ClusterLogging": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-eks-cluster-clusterlogging.html", @@ -149,6 +149,72 @@ } } }, + "AWS::EKS::IdentityProviderConfig.OidcIdentityProviderConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-eks-identityproviderconfig-oidcidentityproviderconfig.html", + "Properties": { + "ClientId": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-eks-identityproviderconfig-oidcidentityproviderconfig.html#cfn-eks-identityproviderconfig-oidcidentityproviderconfig-clientid", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "GroupsClaim": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-eks-identityproviderconfig-oidcidentityproviderconfig.html#cfn-eks-identityproviderconfig-oidcidentityproviderconfig-groupsclaim", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "GroupsPrefix": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-eks-identityproviderconfig-oidcidentityproviderconfig.html#cfn-eks-identityproviderconfig-oidcidentityproviderconfig-groupsprefix", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "IssuerUrl": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-eks-identityproviderconfig-oidcidentityproviderconfig.html#cfn-eks-identityproviderconfig-oidcidentityproviderconfig-issuerurl", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "RequiredClaims": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-eks-identityproviderconfig-oidcidentityproviderconfig.html#cfn-eks-identityproviderconfig-oidcidentityproviderconfig-requiredclaims", + "DuplicatesAllowed": false, + "ItemType": "RequiredClaim", + "Required": false, + "Type": "List", + "UpdateType": "Immutable" + }, + "UsernameClaim": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-eks-identityproviderconfig-oidcidentityproviderconfig.html#cfn-eks-identityproviderconfig-oidcidentityproviderconfig-usernameclaim", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "UsernamePrefix": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-eks-identityproviderconfig-oidcidentityproviderconfig.html#cfn-eks-identityproviderconfig-oidcidentityproviderconfig-usernameprefix", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + } + } + }, + "AWS::EKS::IdentityProviderConfig.RequiredClaim": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-eks-identityproviderconfig-requiredclaim.html", + "Properties": { + "Key": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-eks-identityproviderconfig-requiredclaim.html#cfn-eks-identityproviderconfig-requiredclaim-key", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "Value": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-eks-identityproviderconfig-requiredclaim.html#cfn-eks-identityproviderconfig-requiredclaim-value", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + } + } + }, "AWS::EKS::Nodegroup.LaunchTemplateSpecification": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-eks-nodegroup-launchtemplatespecification.html", "Properties": { @@ -433,6 +499,48 @@ } } }, + "AWS::EKS::IdentityProviderConfig": { + "Attributes": { + "IdentityProviderConfigArn": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-eks-identityproviderconfig.html", + "Properties": { + "ClusterName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-eks-identityproviderconfig.html#cfn-eks-identityproviderconfig-clustername", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "IdentityProviderConfigName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-eks-identityproviderconfig.html#cfn-eks-identityproviderconfig-identityproviderconfigname", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "Oidc": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-eks-identityproviderconfig.html#cfn-eks-identityproviderconfig-oidc", + "Required": false, + "Type": "OidcIdentityProviderConfig", + "UpdateType": "Immutable" + }, + "Tags": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-eks-identityproviderconfig.html#cfn-eks-identityproviderconfig-tags", + "DuplicatesAllowed": false, + "ItemType": "Tag", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "Type": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-eks-identityproviderconfig.html#cfn-eks-identityproviderconfig-type", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + } + } + }, "AWS::EKS::Nodegroup": { "Attributes": { "Arn": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EMR.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EMR.json index 96719b9704ef6..1ffa7905a01a5 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EMR.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EMR.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::EMR::Cluster.Application": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticmapreduce-cluster-application.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EMRContainers.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EMRContainers.json index 710136258ca18..a18345b5e07df 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EMRContainers.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EMRContainers.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::EMRContainers::VirtualCluster.ContainerInfo": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-emrcontainers-virtualcluster-containerinfo.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElastiCache.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElastiCache.json index 707b768ecb1a9..512eace7ec712 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElastiCache.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElastiCache.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::ElastiCache::CacheCluster.CloudWatchLogsDestinationDetails": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticache-cachecluster-cloudwatchlogsdestinationdetails.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticBeanstalk.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticBeanstalk.json index 72f62d6dc1a18..8fbfbc0e692b4 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticBeanstalk.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticBeanstalk.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::ElasticBeanstalk::Application.ApplicationResourceLifecycleConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticbeanstalk-application-applicationresourcelifecycleconfig.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticLoadBalancing.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticLoadBalancing.json index 45f1843aa96bf..c8ced355143b0 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticLoadBalancing.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticLoadBalancing.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::ElasticLoadBalancing::LoadBalancer.AccessLoggingPolicy": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-elb-accessloggingpolicy.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticLoadBalancingV2.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticLoadBalancingV2.json index 9022f8c180245..7b8aec57a7721 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticLoadBalancingV2.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticLoadBalancingV2.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::ElasticLoadBalancingV2::Listener.Action": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticloadbalancingv2-listener-action.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Elasticsearch.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Elasticsearch.json index 51a8d954baf3b..ff7e2e746acda 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Elasticsearch.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Elasticsearch.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Elasticsearch::Domain.AdvancedSecurityOptionsInput": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticsearch-domain-advancedsecurityoptionsinput.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EventSchemas.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EventSchemas.json index 70d6eccec39d1..f50e452150aef 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EventSchemas.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EventSchemas.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::EventSchemas::Discoverer.TagsEntry": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-eventschemas-discoverer-tagsentry.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Events.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Events.json index d3030e79a0956..235368cfa05f3 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Events.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Events.json @@ -1,6 +1,164 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { + "AWS::Events::Connection.ApiKeyAuthParameters": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-events-connection-apikeyauthparameters.html", + "Properties": { + "ApiKeyName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-events-connection-apikeyauthparameters.html#cfn-events-connection-apikeyauthparameters-apikeyname", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "ApiKeyValue": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-events-connection-apikeyauthparameters.html#cfn-events-connection-apikeyauthparameters-apikeyvalue", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + } + } + }, + "AWS::Events::Connection.AuthParameters": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-events-connection-authparameters.html", + "Properties": { + "ApiKeyAuthParameters": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-events-connection-authparameters.html#cfn-events-connection-authparameters-apikeyauthparameters", + "Required": false, + "Type": "ApiKeyAuthParameters", + "UpdateType": "Mutable" + }, + "BasicAuthParameters": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-events-connection-authparameters.html#cfn-events-connection-authparameters-basicauthparameters", + "Required": false, + "Type": "BasicAuthParameters", + "UpdateType": "Mutable" + }, + "InvocationHttpParameters": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-events-connection-authparameters.html#cfn-events-connection-authparameters-invocationhttpparameters", + "Required": false, + "Type": "ConnectionHttpParameters", + "UpdateType": "Mutable" + }, + "OAuthParameters": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-events-connection-authparameters.html#cfn-events-connection-authparameters-oauthparameters", + "Required": false, + "Type": "OAuthParameters", + "UpdateType": "Mutable" + } + } + }, + "AWS::Events::Connection.BasicAuthParameters": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-events-connection-basicauthparameters.html", + "Properties": { + "Password": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-events-connection-basicauthparameters.html#cfn-events-connection-basicauthparameters-password", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "Username": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-events-connection-basicauthparameters.html#cfn-events-connection-basicauthparameters-username", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + } + } + }, + "AWS::Events::Connection.ClientParameters": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-events-connection-clientparameters.html", + "Properties": { + "ClientID": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-events-connection-clientparameters.html#cfn-events-connection-clientparameters-clientid", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "ClientSecret": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-events-connection-clientparameters.html#cfn-events-connection-clientparameters-clientsecret", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + } + } + }, + "AWS::Events::Connection.ConnectionHttpParameters": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-events-connection-connectionhttpparameters.html", + "Properties": { + "BodyParameters": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-events-connection-connectionhttpparameters.html#cfn-events-connection-connectionhttpparameters-bodyparameters", + "ItemType": "Parameter", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "HeaderParameters": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-events-connection-connectionhttpparameters.html#cfn-events-connection-connectionhttpparameters-headerparameters", + "ItemType": "Parameter", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "QueryStringParameters": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-events-connection-connectionhttpparameters.html#cfn-events-connection-connectionhttpparameters-querystringparameters", + "ItemType": "Parameter", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + } + } + }, + "AWS::Events::Connection.OAuthParameters": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-events-connection-oauthparameters.html", + "Properties": { + "AuthorizationEndpoint": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-events-connection-oauthparameters.html#cfn-events-connection-oauthparameters-authorizationendpoint", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "ClientParameters": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-events-connection-oauthparameters.html#cfn-events-connection-oauthparameters-clientparameters", + "Required": true, + "Type": "ClientParameters", + "UpdateType": "Mutable" + }, + "HttpMethod": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-events-connection-oauthparameters.html#cfn-events-connection-oauthparameters-httpmethod", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "OAuthHttpParameters": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-events-connection-oauthparameters.html#cfn-events-connection-oauthparameters-oauthhttpparameters", + "Required": false, + "Type": "ConnectionHttpParameters", + "UpdateType": "Mutable" + } + } + }, + "AWS::Events::Connection.Parameter": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-events-connection-parameter.html", + "Properties": { + "IsValueSecret": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-events-connection-parameter.html#cfn-events-connection-parameter-isvaluesecret", + "PrimitiveType": "Boolean", + "Required": false, + "UpdateType": "Mutable" + }, + "Key": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-events-connection-parameter.html#cfn-events-connection-parameter-key", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "Value": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-events-connection-parameter.html#cfn-events-connection-parameter-value", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + } + } + }, "AWS::Events::EventBus.TagEntry": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-events-eventbus-tagentry.html", "Properties": { @@ -707,8 +865,8 @@ "Properties": { "AuthParameters": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-events-connection.html#cfn-events-connection-authparameters", - "PrimitiveType": "Json", "Required": true, + "Type": "AuthParameters", "UpdateType": "Mutable" }, "AuthorizationType": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Evidently.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Evidently.json index bc8f076ad931d..d17ba0b979f20 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Evidently.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Evidently.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Evidently::Experiment.MetricGoalObject": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-evidently-experiment-metricgoalobject.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FIS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FIS.json index e7e6e0151b088..0f5b0f810c8ff 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FIS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FIS.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::FIS::ExperimentTemplate.ExperimentTemplateAction": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-fis-experimenttemplate-experimenttemplateaction.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FMS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FMS.json index f6234f9a11247..d13e5954f1495 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FMS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FMS.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::FMS::Policy.IEMap": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-fms-policy-iemap.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FSx.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FSx.json index 9b3fe76e7d9dc..73f32fa8a75e6 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FSx.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FSx.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::FSx::FileSystem.AuditLogConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-fsx-filesystem-windowsconfiguration-auditlogconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FinSpace.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FinSpace.json index c7191487bf5b5..2bd367e897afb 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FinSpace.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FinSpace.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::FinSpace::Environment.FederationParameters": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-finspace-environment-federationparameters.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Forecast.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Forecast.json index a8dc8d3c2f219..e9013d59a0666 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Forecast.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Forecast.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::Forecast::Dataset": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FraudDetector.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FraudDetector.json index a546b0ba4a61c..7bf297b2a4257 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FraudDetector.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FraudDetector.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::FraudDetector::Detector.EntityType": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-frauddetector-detector-entitytype.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GameLift.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GameLift.json index 3212e3a505c3c..0669af13996bb 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GameLift.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GameLift.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::GameLift::Alias.RoutingStrategy": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-gamelift-alias-routingstrategy.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GlobalAccelerator.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GlobalAccelerator.json index a216c18ba532f..8e9cc088d59ac 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GlobalAccelerator.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GlobalAccelerator.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::GlobalAccelerator::EndpointGroup.EndpointConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-globalaccelerator-endpointgroup-endpointconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Glue.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Glue.json index 2495606f612b1..90d0fde049366 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Glue.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Glue.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Glue::Classifier.CsvClassifier": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-glue-classifier-csvclassifier.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Greengrass.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Greengrass.json index 55d81f27a844e..948e51373320f 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Greengrass.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Greengrass.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Greengrass::ConnectorDefinition.Connector": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-greengrass-connectordefinition-connector.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GreengrassV2.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GreengrassV2.json index 2c58424f564ff..41857626f318b 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GreengrassV2.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GreengrassV2.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::GreengrassV2::ComponentVersion.ComponentDependencyRequirement": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-greengrassv2-componentversion-componentdependencyrequirement.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GroundStation.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GroundStation.json index 9813c1fef3e95..e8ec3aed62033 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GroundStation.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GroundStation.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::GroundStation::Config.AntennaDownlinkConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-groundstation-config-antennadownlinkconfig.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GuardDuty.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GuardDuty.json index 5cee551e6acee..c604431104c74 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GuardDuty.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GuardDuty.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::GuardDuty::Detector.CFNDataSourceConfigurations": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-guardduty-detector-cfndatasourceconfigurations.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_HealthLake.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_HealthLake.json index 19f86d0516aec..57fe856c570e9 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_HealthLake.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_HealthLake.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::HealthLake::FHIRDatastore.KmsEncryptionConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-healthlake-fhirdatastore-kmsencryptionconfig.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IAM.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IAM.json index 6a6dc89ad33ab..c6a876338538a 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IAM.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IAM.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::IAM::Group.Policy": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iam-policy.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IVS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IVS.json index b5db291f0b938..cf6cd0025b11d 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IVS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IVS.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::IVS::RecordingConfiguration.DestinationConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ivs-recordingconfiguration-destinationconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ImageBuilder.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ImageBuilder.json index 35b944d66fe20..feb22b933215e 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ImageBuilder.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ImageBuilder.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::ImageBuilder::ContainerRecipe.ComponentConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-imagebuilder-containerrecipe-componentconfiguration.html", @@ -666,6 +666,9 @@ "ImageId": { "PrimitiveType": "String" }, + "ImageUri": { + "PrimitiveType": "String" + }, "Name": { "PrimitiveType": "String" } @@ -676,7 +679,7 @@ "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-imagebuilder-image.html#cfn-imagebuilder-image-containerrecipearn", "PrimitiveType": "String", "Required": false, - "UpdateType": "Mutable" + "UpdateType": "Immutable" }, "DistributionConfigurationArn": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-imagebuilder-image.html#cfn-imagebuilder-image-distributionconfigurationarn", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Inspector.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Inspector.json index 2692637d3ff2f..54630811777d3 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Inspector.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Inspector.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::Inspector::AssessmentTarget": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_InspectorV2.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_InspectorV2.json index 82b20234a0489..08afea929e819 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_InspectorV2.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_InspectorV2.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::InspectorV2::Filter.DateFilter": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-datefilter.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoT.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoT.json index 743a9fc4592f4..524e8388050d7 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoT.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoT.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::IoT::AccountAuditConfiguration.AuditCheckConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iot-accountauditconfiguration-auditcheckconfiguration.html", @@ -1615,6 +1615,12 @@ "Required": false, "UpdateType": "Immutable" }, + "EnableCachingForHttp": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iot-authorizer.html#cfn-iot-authorizer-enablecachingforhttp", + "PrimitiveType": "Boolean", + "Required": false, + "UpdateType": "Mutable" + }, "SigningDisabled": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iot-authorizer.html#cfn-iot-authorizer-signingdisabled", "PrimitiveType": "Boolean", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoT1Click.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoT1Click.json index d2e6b8fcd524c..5eb1ce6e4c870 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoT1Click.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoT1Click.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::IoT1Click::Project.DeviceTemplate": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iot1click-project-devicetemplate.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTAnalytics.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTAnalytics.json index 143fe90c23f45..de00da04e8560 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTAnalytics.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTAnalytics.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::IoTAnalytics::Channel.ChannelStorage": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-channel-channelstorage.html", @@ -317,13 +317,13 @@ "NumberOfDays": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-dataset-retentionperiod.html#cfn-iotanalytics-dataset-retentionperiod-numberofdays", "PrimitiveType": "Integer", - "Required": true, + "Required": false, "UpdateType": "Mutable" }, "Unlimited": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-dataset-retentionperiod.html#cfn-iotanalytics-dataset-retentionperiod-unlimited", "PrimitiveType": "Boolean", - "Required": true, + "Required": false, "UpdateType": "Mutable" } } diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTCoreDeviceAdvisor.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTCoreDeviceAdvisor.json index d66fac81c2ed3..e1e638619aaee 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTCoreDeviceAdvisor.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTCoreDeviceAdvisor.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::IoTCoreDeviceAdvisor::SuiteDefinition": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTEvents.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTEvents.json index aa721dff4fbdc..63aa8505f8b3a 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTEvents.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTEvents.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::IoTEvents::DetectorModel.Action": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-action.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTFleetHub.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTFleetHub.json index b393d6ee54b1f..ce086ffbf239f 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTFleetHub.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTFleetHub.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::IoTFleetHub::Application": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTSiteWise.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTSiteWise.json index e58e6e2d73819..56e976fbfced8 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTSiteWise.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTSiteWise.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::IoTSiteWise::AccessPolicy.AccessPolicyIdentity": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotsitewise-accesspolicy-accesspolicyidentity.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTThingsGraph.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTThingsGraph.json index c0a5a43501472..1e6c7cb361196 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTThingsGraph.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTThingsGraph.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::IoTThingsGraph::FlowTemplate.DefinitionDocument": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotthingsgraph-flowtemplate-definitiondocument.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTWireless.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTWireless.json index 4d0ffd1486590..1f5b18019a032 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTWireless.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTWireless.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::IoTWireless::DeviceProfile.LoRaWANDeviceProfile": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotwireless-deviceprofile-lorawandeviceprofile.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KMS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KMS.json index fd876340e809d..72371ab85a1ad 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KMS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KMS.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::KMS::Alias": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KafkaConnect.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KafkaConnect.json index 71c697ac04a47..6878e90f81da3 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KafkaConnect.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KafkaConnect.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::KafkaConnect::Connector.ApacheKafkaCluster": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kafkaconnect-connector-apachekafkacluster.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Kendra.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Kendra.json index 64128aaa1274d..4e6247329ab19 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Kendra.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Kendra.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Kendra::DataSource.AccessControlListConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kendra-datasource-accesscontrollistconfiguration.html", @@ -334,6 +334,36 @@ } } }, + "AWS::Kendra::DataSource.CustomDocumentEnrichmentConfiguration": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kendra-datasource-customdocumentenrichmentconfiguration.html", + "Properties": { + "InlineConfigurations": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kendra-datasource-customdocumentenrichmentconfiguration.html#cfn-kendra-datasource-customdocumentenrichmentconfiguration-inlineconfigurations", + "ItemType": "InlineCustomDocumentEnrichmentConfiguration", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "PostExtractionHookConfiguration": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kendra-datasource-customdocumentenrichmentconfiguration.html#cfn-kendra-datasource-customdocumentenrichmentconfiguration-postextractionhookconfiguration", + "Required": false, + "Type": "HookConfiguration", + "UpdateType": "Mutable" + }, + "PreExtractionHookConfiguration": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kendra-datasource-customdocumentenrichmentconfiguration.html#cfn-kendra-datasource-customdocumentenrichmentconfiguration-preextractionhookconfiguration", + "Required": false, + "Type": "HookConfiguration", + "UpdateType": "Mutable" + }, + "RoleArn": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kendra-datasource-customdocumentenrichmentconfiguration.html#cfn-kendra-datasource-customdocumentenrichmentconfiguration-rolearn", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + }, "AWS::Kendra::DataSource.DataSourceConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kendra-datasource-datasourceconfiguration.html", "Properties": { @@ -482,6 +512,82 @@ } } }, + "AWS::Kendra::DataSource.DocumentAttributeCondition": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kendra-datasource-documentattributecondition.html", + "Properties": { + "ConditionDocumentAttributeKey": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kendra-datasource-documentattributecondition.html#cfn-kendra-datasource-documentattributecondition-conditiondocumentattributekey", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "ConditionOnValue": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kendra-datasource-documentattributecondition.html#cfn-kendra-datasource-documentattributecondition-conditiononvalue", + "Required": false, + "Type": "DocumentAttributeValue", + "UpdateType": "Mutable" + }, + "Operator": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kendra-datasource-documentattributecondition.html#cfn-kendra-datasource-documentattributecondition-operator", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + } + } + }, + "AWS::Kendra::DataSource.DocumentAttributeTarget": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kendra-datasource-documentattributetarget.html", + "Properties": { + "TargetDocumentAttributeKey": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kendra-datasource-documentattributetarget.html#cfn-kendra-datasource-documentattributetarget-targetdocumentattributekey", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "TargetDocumentAttributeValue": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kendra-datasource-documentattributetarget.html#cfn-kendra-datasource-documentattributetarget-targetdocumentattributevalue", + "Required": false, + "Type": "DocumentAttributeValue", + "UpdateType": "Mutable" + }, + "TargetDocumentAttributeValueDeletion": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kendra-datasource-documentattributetarget.html#cfn-kendra-datasource-documentattributetarget-targetdocumentattributevaluedeletion", + "PrimitiveType": "Boolean", + "Required": false, + "UpdateType": "Mutable" + } + } + }, + "AWS::Kendra::DataSource.DocumentAttributeValue": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kendra-datasource-documentattributevalue.html", + "Properties": { + "DateValue": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kendra-datasource-documentattributevalue.html#cfn-kendra-datasource-documentattributevalue-datevalue", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "LongValue": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kendra-datasource-documentattributevalue.html#cfn-kendra-datasource-documentattributevalue-longvalue", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Mutable" + }, + "StringListValue": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kendra-datasource-documentattributevalue.html#cfn-kendra-datasource-documentattributevalue-stringlistvalue", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "StringValue": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kendra-datasource-documentattributevalue.html#cfn-kendra-datasource-documentattributevalue-stringvalue", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + }, "AWS::Kendra::DataSource.DocumentsMetadataConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kendra-datasource-documentsmetadataconfiguration.html", "Properties": { @@ -546,6 +652,52 @@ } } }, + "AWS::Kendra::DataSource.HookConfiguration": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kendra-datasource-hookconfiguration.html", + "Properties": { + "InvocationCondition": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kendra-datasource-hookconfiguration.html#cfn-kendra-datasource-hookconfiguration-invocationcondition", + "Required": false, + "Type": "DocumentAttributeCondition", + "UpdateType": "Mutable" + }, + "LambdaArn": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kendra-datasource-hookconfiguration.html#cfn-kendra-datasource-hookconfiguration-lambdaarn", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "S3Bucket": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kendra-datasource-hookconfiguration.html#cfn-kendra-datasource-hookconfiguration-s3bucket", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + } + } + }, + "AWS::Kendra::DataSource.InlineCustomDocumentEnrichmentConfiguration": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kendra-datasource-inlinecustomdocumentenrichmentconfiguration.html", + "Properties": { + "Condition": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kendra-datasource-inlinecustomdocumentenrichmentconfiguration.html#cfn-kendra-datasource-inlinecustomdocumentenrichmentconfiguration-condition", + "Required": false, + "Type": "DocumentAttributeCondition", + "UpdateType": "Mutable" + }, + "DocumentContentDeletion": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kendra-datasource-inlinecustomdocumentenrichmentconfiguration.html#cfn-kendra-datasource-inlinecustomdocumentenrichmentconfiguration-documentcontentdeletion", + "PrimitiveType": "Boolean", + "Required": false, + "UpdateType": "Mutable" + }, + "Target": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kendra-datasource-inlinecustomdocumentenrichmentconfiguration.html#cfn-kendra-datasource-inlinecustomdocumentenrichmentconfiguration-target", + "Required": false, + "Type": "DocumentAttributeTarget", + "UpdateType": "Mutable" + } + } + }, "AWS::Kendra::DataSource.OneDriveConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kendra-datasource-onedriveconfiguration.html", "Properties": { @@ -1582,6 +1734,12 @@ }, "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-kendra-datasource.html", "Properties": { + "CustomDocumentEnrichmentConfiguration": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-kendra-datasource.html#cfn-kendra-datasource-customdocumentenrichmentconfiguration", + "Required": false, + "Type": "CustomDocumentEnrichmentConfiguration", + "UpdateType": "Mutable" + }, "DataSourceConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-kendra-datasource.html#cfn-kendra-datasource-datasourceconfiguration", "Required": false, diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Kinesis.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Kinesis.json index 44f4087bd2d52..208bc9e757d84 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Kinesis.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Kinesis.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Kinesis::Stream.StreamEncryption": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kinesis-stream-streamencryption.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisAnalytics.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisAnalytics.json index c30331e69f940..37318b1b1d591 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisAnalytics.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisAnalytics.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::KinesisAnalytics::Application.CSVMappingParameters": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kinesisanalytics-application-csvmappingparameters.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisAnalyticsV2.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisAnalyticsV2.json index 3c23a41423018..c9a22253a2f7e 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisAnalyticsV2.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisAnalyticsV2.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::KinesisAnalyticsV2::Application.ApplicationCodeConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kinesisanalyticsv2-application-applicationcodeconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisFirehose.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisFirehose.json index 7022f6622ce76..c3432dd2c6e72 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisFirehose.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisFirehose.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::KinesisFirehose::DeliveryStream.AmazonopensearchserviceBufferingHints": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kinesisfirehose-deliverystream-amazonopensearchservicebufferinghints.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisVideo.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisVideo.json index 57b9d6be4d86a..cbe9e5a0fee8b 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisVideo.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisVideo.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::KinesisVideo::SignalingChannel": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LakeFormation.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LakeFormation.json index baf0a61a1f5ba..1da453a20b485 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LakeFormation.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LakeFormation.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::LakeFormation::DataLakeSettings.Admins": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lakeformation-datalakesettings-admins.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lambda.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lambda.json index 915dd0227f10f..eb93de4c0bf80 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lambda.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lambda.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Lambda::Alias.AliasRoutingConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-alias-aliasroutingconfiguration.html", @@ -128,6 +128,30 @@ } } }, + "AWS::Lambda::EventSourceMapping.Filter": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-eventsourcemapping-filter.html", + "Properties": { + "Pattern": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-eventsourcemapping-filter.html#cfn-lambda-eventsourcemapping-filter-pattern", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + }, + "AWS::Lambda::EventSourceMapping.FilterCriteria": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-eventsourcemapping-filtercriteria.html", + "Properties": { + "Filters": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-eventsourcemapping-filtercriteria.html#cfn-lambda-eventsourcemapping-filtercriteria-filters", + "DuplicatesAllowed": false, + "ItemType": "Filter", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + } + } + }, "AWS::Lambda::EventSourceMapping.OnFailure": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-eventsourcemapping-onfailure.html", "Properties": { @@ -484,8 +508,8 @@ }, "FilterCriteria": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-eventsourcemapping.html#cfn-lambda-eventsourcemapping-filtercriteria", - "PrimitiveType": "Json", "Required": false, + "Type": "FilterCriteria", "UpdateType": "Mutable" }, "FunctionName": { @@ -558,7 +582,7 @@ "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-eventsourcemapping.html#cfn-lambda-eventsourcemapping-startingpositiontimestamp", "PrimitiveType": "Double", "Required": false, - "UpdateType": "Mutable" + "UpdateType": "Immutable" }, "Topics": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-eventsourcemapping.html#cfn-lambda-eventsourcemapping-topics", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lex.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lex.json index 58a5b46e0781e..1547db8f8abdc 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lex.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lex.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Lex::Bot.BotLocale": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lex-bot-botlocale.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LicenseManager.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LicenseManager.json index 55a5ac350e955..cace32e328e32 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LicenseManager.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LicenseManager.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::LicenseManager::License.BorrowConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-licensemanager-license-borrowconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lightsail.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lightsail.json index 600edb8be4dc6..f026f3bcb0c96 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lightsail.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lightsail.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Lightsail::Bucket.AccessRules": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lightsail-bucket-accessrules.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Location.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Location.json index cc5d6fb057cb0..7619d660ec8ea 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Location.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Location.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Location::Map.MapConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-location-map-mapconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Logs.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Logs.json index f0e58ced5bffe..1b7e74fc4d1ec 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Logs.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Logs.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Logs::MetricFilter.MetricTransformation": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-logs-metricfilter-metrictransformation.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutEquipment.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutEquipment.json index e46ff5f7c1dcd..9230be162663c 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutEquipment.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutEquipment.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::LookoutEquipment::InferenceScheduler": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutMetrics.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutMetrics.json index 3ad060a63b634..2b149f8160c28 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutMetrics.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutMetrics.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::LookoutMetrics::Alert.Action": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lookoutmetrics-alert-action.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutVision.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutVision.json index 6827017e32a59..7fcd7edfc5ac2 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutVision.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutVision.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::LookoutVision::Project": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MSK.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MSK.json index 14d727432b11b..54d2aa068ca9d 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MSK.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MSK.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::MSK::Cluster.BrokerLogs": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-msk-cluster-brokerlogs.html", @@ -35,6 +35,7 @@ }, "ClientSubnets": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-msk-cluster-brokernodegroupinfo.html#cfn-msk-cluster-brokernodegroupinfo-clientsubnets", + "DuplicatesAllowed": true, "PrimitiveItemType": "String", "Required": true, "Type": "List", @@ -54,6 +55,7 @@ }, "SecurityGroups": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-msk-cluster-brokernodegroupinfo.html#cfn-msk-cluster-brokernodegroupinfo-securitygroups", + "DuplicatesAllowed": true, "PrimitiveItemType": "String", "Required": false, "Type": "List", @@ -381,6 +383,7 @@ "Properties": { "CertificateAuthorityArnList": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-msk-cluster-tls.html#cfn-msk-cluster-tls-certificateauthorityarnlist", + "DuplicatesAllowed": true, "PrimitiveItemType": "String", "Required": false, "Type": "List", @@ -407,7 +410,30 @@ } }, "ResourceTypes": { + "AWS::MSK::BatchScramSecret": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-msk-batchscramsecret.html", + "Properties": { + "ClusterArn": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-msk-batchscramsecret.html#cfn-msk-batchscramsecret-clusterarn", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "SecretArnList": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-msk-batchscramsecret.html#cfn-msk-batchscramsecret-secretarnlist", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + } + } + }, "AWS::MSK::Cluster": { + "Attributes": { + "Arn": { + "PrimitiveType": "String" + } + }, "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-msk-cluster.html", "Properties": { "BrokerNodeGroupInfo": { @@ -434,6 +460,12 @@ "Type": "ConfigurationInfo", "UpdateType": "Mutable" }, + "CurrentVersion": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-msk-cluster.html#cfn-msk-cluster-currentversion", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, "EncryptionInfo": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-msk-cluster.html#cfn-msk-cluster-encryptioninfo", "Required": false, @@ -472,11 +504,47 @@ }, "Tags": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-msk-cluster.html#cfn-msk-cluster-tags", - "PrimitiveType": "Json", + "PrimitiveItemType": "String", "Required": false, + "Type": "Map", "UpdateType": "Immutable" } } + }, + "AWS::MSK::Configuration": { + "Attributes": { + "Arn": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-msk-configuration.html", + "Properties": { + "Description": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-msk-configuration.html#cfn-msk-configuration-description", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "KafkaVersionsList": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-msk-configuration.html#cfn-msk-configuration-kafkaversionslist", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Immutable" + }, + "Name": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-msk-configuration.html#cfn-msk-configuration-name", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "ServerProperties": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-msk-configuration.html#cfn-msk-configuration-serverproperties", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + } + } } } } diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MWAA.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MWAA.json index c62b6c2572271..2d8db8368ece4 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MWAA.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MWAA.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::MWAA::Environment.LoggingConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-mwaa-environment-loggingconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Macie.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Macie.json index 11d37eecb82b7..3d3c12b1f7fcd 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Macie.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Macie.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Macie::FindingsFilter.Criterion": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-macie-findingsfilter-criterion.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ManagedBlockchain.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ManagedBlockchain.json index cf35f4c07206a..038ec243aec4e 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ManagedBlockchain.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ManagedBlockchain.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::ManagedBlockchain::Member.ApprovalThresholdPolicy": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-managedblockchain-member-approvalthresholdpolicy.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaConnect.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaConnect.json index d08f7d0a9ecf3..987a145eb053c 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaConnect.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaConnect.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::MediaConnect::Flow.Encryption": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-mediaconnect-flow-encryption.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaConvert.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaConvert.json index 9ebafc7671ef7..9009c2c6476f1 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaConvert.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaConvert.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::MediaConvert::JobTemplate.AccelerationSettings": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-mediaconvert-jobtemplate-accelerationsettings.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaLive.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaLive.json index 4c2aa220ae5ae..e04e80c6654d7 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaLive.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaLive.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::MediaLive::Channel.AacSettings": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-medialive-channel-aacsettings.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaPackage.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaPackage.json index 1b90c46d7c25a..852f2ae5d2672 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaPackage.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaPackage.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::MediaPackage::Asset.EgressEndpoint": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-mediapackage-asset-egressendpoint.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaStore.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaStore.json index 2eac350bb3c71..b5b8781af9bbb 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaStore.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaStore.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::MediaStore::Container.CorsRule": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-mediastore-container-corsrule.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MemoryDB.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MemoryDB.json index e71df435b0d2a..c75483b4a4218 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MemoryDB.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MemoryDB.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::MemoryDB::Cluster.Endpoint": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-memorydb-cluster-endpoint.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Neptune.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Neptune.json index c77bfa16c3297..231715f6b5b5a 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Neptune.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Neptune.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Neptune::DBCluster.DBClusterRole": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-neptune-dbcluster-dbclusterrole.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NetworkFirewall.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NetworkFirewall.json index 497d1cf41938c..cea445244c7ac 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NetworkFirewall.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NetworkFirewall.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::NetworkFirewall::Firewall.SubnetMapping": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkfirewall-firewall-subnetmapping.html", @@ -56,7 +56,7 @@ "Properties": { "StatefulDefaultActions": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkfirewall-firewallpolicy-firewallpolicy.html#cfn-networkfirewall-firewallpolicy-firewallpolicy-statefuldefaultactions", - "DuplicatesAllowed": false, + "DuplicatesAllowed": true, "PrimitiveItemType": "String", "Required": false, "Type": "List", @@ -70,7 +70,7 @@ }, "StatefulRuleGroupReferences": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkfirewall-firewallpolicy-firewallpolicy.html#cfn-networkfirewall-firewallpolicy-firewallpolicy-statefulrulegroupreferences", - "DuplicatesAllowed": false, + "DuplicatesAllowed": true, "ItemType": "StatefulRuleGroupReference", "Required": false, "Type": "List", @@ -78,7 +78,7 @@ }, "StatelessCustomActions": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkfirewall-firewallpolicy-firewallpolicy.html#cfn-networkfirewall-firewallpolicy-firewallpolicy-statelesscustomactions", - "DuplicatesAllowed": false, + "DuplicatesAllowed": true, "ItemType": "CustomAction", "Required": false, "Type": "List", @@ -86,7 +86,7 @@ }, "StatelessDefaultActions": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkfirewall-firewallpolicy-firewallpolicy.html#cfn-networkfirewall-firewallpolicy-firewallpolicy-statelessdefaultactions", - "DuplicatesAllowed": false, + "DuplicatesAllowed": true, "PrimitiveItemType": "String", "Required": true, "Type": "List", @@ -94,7 +94,7 @@ }, "StatelessFragmentDefaultActions": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkfirewall-firewallpolicy-firewallpolicy.html#cfn-networkfirewall-firewallpolicy-firewallpolicy-statelessfragmentdefaultactions", - "DuplicatesAllowed": false, + "DuplicatesAllowed": true, "PrimitiveItemType": "String", "Required": true, "Type": "List", @@ -102,7 +102,7 @@ }, "StatelessRuleGroupReferences": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkfirewall-firewallpolicy-firewallpolicy.html#cfn-networkfirewall-firewallpolicy-firewallpolicy-statelessrulegroupreferences", - "DuplicatesAllowed": false, + "DuplicatesAllowed": true, "ItemType": "StatelessRuleGroupReference", "Required": false, "Type": "List", @@ -115,7 +115,7 @@ "Properties": { "Dimensions": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkfirewall-firewallpolicy-publishmetricaction.html#cfn-networkfirewall-firewallpolicy-publishmetricaction-dimensions", - "DuplicatesAllowed": false, + "DuplicatesAllowed": true, "ItemType": "Dimension", "Required": true, "Type": "List", @@ -300,7 +300,7 @@ "Properties": { "Definition": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkfirewall-rulegroup-ipset.html#cfn-networkfirewall-rulegroup-ipset-definition", - "DuplicatesAllowed": false, + "DuplicatesAllowed": true, "PrimitiveItemType": "String", "Required": false, "Type": "List", @@ -313,7 +313,7 @@ "Properties": { "DestinationPorts": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkfirewall-rulegroup-matchattributes.html#cfn-networkfirewall-rulegroup-matchattributes-destinationports", - "DuplicatesAllowed": false, + "DuplicatesAllowed": true, "ItemType": "PortRange", "Required": false, "Type": "List", @@ -321,7 +321,7 @@ }, "Destinations": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkfirewall-rulegroup-matchattributes.html#cfn-networkfirewall-rulegroup-matchattributes-destinations", - "DuplicatesAllowed": false, + "DuplicatesAllowed": true, "ItemType": "Address", "Required": false, "Type": "List", @@ -329,7 +329,7 @@ }, "Protocols": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkfirewall-rulegroup-matchattributes.html#cfn-networkfirewall-rulegroup-matchattributes-protocols", - "DuplicatesAllowed": false, + "DuplicatesAllowed": true, "PrimitiveItemType": "Integer", "Required": false, "Type": "List", @@ -337,7 +337,7 @@ }, "SourcePorts": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkfirewall-rulegroup-matchattributes.html#cfn-networkfirewall-rulegroup-matchattributes-sourceports", - "DuplicatesAllowed": false, + "DuplicatesAllowed": true, "ItemType": "PortRange", "Required": false, "Type": "List", @@ -345,7 +345,7 @@ }, "Sources": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkfirewall-rulegroup-matchattributes.html#cfn-networkfirewall-rulegroup-matchattributes-sources", - "DuplicatesAllowed": false, + "DuplicatesAllowed": true, "ItemType": "Address", "Required": false, "Type": "List", @@ -353,7 +353,7 @@ }, "TCPFlags": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkfirewall-rulegroup-matchattributes.html#cfn-networkfirewall-rulegroup-matchattributes-tcpflags", - "DuplicatesAllowed": false, + "DuplicatesAllowed": true, "ItemType": "TCPFlagField", "Required": false, "Type": "List", @@ -383,7 +383,7 @@ "Properties": { "Definition": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkfirewall-rulegroup-portset.html#cfn-networkfirewall-rulegroup-portset-definition", - "DuplicatesAllowed": false, + "DuplicatesAllowed": true, "PrimitiveItemType": "String", "Required": false, "Type": "List", @@ -396,7 +396,7 @@ "Properties": { "Dimensions": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkfirewall-rulegroup-publishmetricaction.html#cfn-networkfirewall-rulegroup-publishmetricaction-dimensions", - "DuplicatesAllowed": false, + "DuplicatesAllowed": true, "ItemType": "Dimension", "Required": true, "Type": "List", @@ -409,7 +409,7 @@ "Properties": { "Actions": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkfirewall-rulegroup-ruledefinition.html#cfn-networkfirewall-rulegroup-ruledefinition-actions", - "DuplicatesAllowed": false, + "DuplicatesAllowed": true, "PrimitiveItemType": "String", "Required": true, "Type": "List", @@ -457,7 +457,7 @@ }, "Settings": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkfirewall-rulegroup-ruleoption.html#cfn-networkfirewall-rulegroup-ruleoption-settings", - "DuplicatesAllowed": false, + "DuplicatesAllowed": true, "PrimitiveItemType": "String", "Required": false, "Type": "List", @@ -501,7 +501,7 @@ }, "StatefulRules": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkfirewall-rulegroup-rulessource.html#cfn-networkfirewall-rulegroup-rulessource-statefulrules", - "DuplicatesAllowed": false, + "DuplicatesAllowed": true, "ItemType": "StatefulRule", "Required": false, "Type": "List", @@ -526,7 +526,7 @@ }, "TargetTypes": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkfirewall-rulegroup-rulessourcelist.html#cfn-networkfirewall-rulegroup-rulessourcelist-targettypes", - "DuplicatesAllowed": false, + "DuplicatesAllowed": true, "PrimitiveItemType": "String", "Required": true, "Type": "List", @@ -534,7 +534,7 @@ }, "Targets": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkfirewall-rulegroup-rulessourcelist.html#cfn-networkfirewall-rulegroup-rulessourcelist-targets", - "DuplicatesAllowed": false, + "DuplicatesAllowed": true, "PrimitiveItemType": "String", "Required": true, "Type": "List", @@ -559,7 +559,7 @@ }, "RuleOptions": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkfirewall-rulegroup-statefulrule.html#cfn-networkfirewall-rulegroup-statefulrule-ruleoptions", - "DuplicatesAllowed": false, + "DuplicatesAllowed": true, "ItemType": "RuleOption", "Required": true, "Type": "List", @@ -600,7 +600,7 @@ "Properties": { "CustomActions": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkfirewall-rulegroup-statelessrulesandcustomactions.html#cfn-networkfirewall-rulegroup-statelessrulesandcustomactions-customactions", - "DuplicatesAllowed": false, + "DuplicatesAllowed": true, "ItemType": "CustomAction", "Required": false, "Type": "List", @@ -608,7 +608,7 @@ }, "StatelessRules": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkfirewall-rulegroup-statelessrulesandcustomactions.html#cfn-networkfirewall-rulegroup-statelessrulesandcustomactions-statelessrules", - "DuplicatesAllowed": false, + "DuplicatesAllowed": true, "ItemType": "StatelessRule", "Required": true, "Type": "List", @@ -621,7 +621,7 @@ "Properties": { "Flags": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkfirewall-rulegroup-tcpflagfield.html#cfn-networkfirewall-rulegroup-tcpflagfield-flags", - "DuplicatesAllowed": false, + "DuplicatesAllowed": true, "PrimitiveItemType": "String", "Required": true, "Type": "List", @@ -629,7 +629,7 @@ }, "Masks": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkfirewall-rulegroup-tcpflagfield.html#cfn-networkfirewall-rulegroup-tcpflagfield-masks", - "DuplicatesAllowed": false, + "DuplicatesAllowed": true, "PrimitiveItemType": "String", "Required": false, "Type": "List", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NetworkManager.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NetworkManager.json index 388aab7179648..46aeea5c8a6b4 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NetworkManager.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NetworkManager.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::NetworkManager::Device.Location": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkmanager-device-location.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NimbleStudio.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NimbleStudio.json index 3ea671def7792..6f1f1dede2f01 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NimbleStudio.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NimbleStudio.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::NimbleStudio::LaunchProfile.StreamConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-nimblestudio-launchprofile-streamconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpenSearchService.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpenSearchService.json index d2ac095d33b5f..4109049a69869 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpenSearchService.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpenSearchService.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::OpenSearchService::Domain.AdvancedSecurityOptionsInput": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-opensearchservice-domain-advancedsecurityoptionsinput.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpsWorks.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpsWorks.json index 8be283a3c43ab..12c75fee328b0 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpsWorks.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpsWorks.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::OpsWorks::App.DataSource": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-opsworks-app-datasource.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpsWorksCM.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpsWorksCM.json index 65964068de60b..c094689aea531 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpsWorksCM.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpsWorksCM.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::OpsWorksCM::Server.EngineAttribute": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-opsworkscm-server-engineattribute.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Panorama.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Panorama.json index 983ae1b7c3dac..bb8f2ea1c04e6 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Panorama.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Panorama.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Panorama::ApplicationInstance.ManifestOverridesPayload": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-panorama-applicationinstance-manifestoverridespayload.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Pinpoint.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Pinpoint.json index 96cc146b21855..d7018ddd4331b 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Pinpoint.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Pinpoint.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Pinpoint::ApplicationSettings.CampaignHook": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-pinpoint-applicationsettings-campaignhook.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_PinpointEmail.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_PinpointEmail.json index 42c364e18c6c2..f2adfa3b5c18d 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_PinpointEmail.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_PinpointEmail.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::PinpointEmail::ConfigurationSet.DeliveryOptions": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-pinpointemail-configurationset-deliveryoptions.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_QLDB.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_QLDB.json index 5c8686b33e4dd..3e84501937b3b 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_QLDB.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_QLDB.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::QLDB::Stream.KinesisConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-qldb-stream-kinesisconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_QuickSight.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_QuickSight.json index 81bb8483aa6f3..1e6c845a8dc67 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_QuickSight.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_QuickSight.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::QuickSight::Analysis.AnalysisError": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-quicksight-analysis-analysiserror.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RAM.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RAM.json index 654bf11d69721..a0d89a1609f3a 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RAM.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RAM.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::RAM::ResourceShare": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RDS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RDS.json index 598a06149e4db..fce9fdd1d7e7e 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RDS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RDS.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::RDS::DBCluster.DBClusterRole": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-dbcluster-dbclusterrole.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RUM.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RUM.json index b4697ff11c7e2..dc594c5704bef 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RUM.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RUM.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::RUM::AppMonitor.AppMonitorConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rum-appmonitor-appmonitorconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Redshift.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Redshift.json index 8a7873ea1822b..822aa9e95ff78 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Redshift.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Redshift.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Redshift::Cluster.Endpoint": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-redshift-cluster-endpoint.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RefactorSpaces.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RefactorSpaces.json index 0bc5a6ce1572f..1b41ea853b3d8 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RefactorSpaces.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RefactorSpaces.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::RefactorSpaces::Application.ApiGatewayProxyInput": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-refactorspaces-application-apigatewayproxyinput.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Rekognition.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Rekognition.json index 6948ee18baafa..b7af4136804a9 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Rekognition.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Rekognition.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::Rekognition::Collection": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ResilienceHub.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ResilienceHub.json index 34ad32bce5129..0a9c707c4346d 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ResilienceHub.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ResilienceHub.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::ResilienceHub::App.PhysicalResourceId": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-resiliencehub-app-physicalresourceid.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ResourceGroups.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ResourceGroups.json index 6edcd25e00bb2..14d578d05832e 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ResourceGroups.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ResourceGroups.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::ResourceGroups::Group.ConfigurationItem": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-resourcegroups-group-configurationitem.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RoboMaker.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RoboMaker.json index 75ab2052e8fc9..5e3103240d1ad 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RoboMaker.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RoboMaker.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::RoboMaker::RobotApplication.RobotSoftwareSuite": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-robomaker-robotapplication-robotsoftwaresuite.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53.json index 04d334225bae1..124eb8d672efc 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Route53::HealthCheck.HealthCheckTag": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53-healthcheck-healthchecktag.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53RecoveryControl.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53RecoveryControl.json index c9e8dc81549b9..a3aadf8cebf78 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53RecoveryControl.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53RecoveryControl.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Route53RecoveryControl::Cluster.ClusterEndpoint": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53recoverycontrol-cluster-clusterendpoint.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53RecoveryReadiness.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53RecoveryReadiness.json index 4c9519f8f4bba..da2e930f5fbfb 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53RecoveryReadiness.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53RecoveryReadiness.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Route53RecoveryReadiness::ResourceSet.DNSTargetResource": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53recoveryreadiness-resourceset-dnstargetresource.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53Resolver.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53Resolver.json index bcacfe963f537..11a7b617a656b 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53Resolver.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53Resolver.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Route53Resolver::FirewallRuleGroup.FirewallRule": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53resolver-firewallrulegroup-firewallrule.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3.json index 2521319f8bda8..3cbb45a36e0bf 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::S3::AccessPoint.PublicAccessBlockConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-accesspoint-publicaccessblockconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3ObjectLambda.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3ObjectLambda.json index 7010b86e556d2..a8854f9f8929b 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3ObjectLambda.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3ObjectLambda.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::S3ObjectLambda::AccessPoint.ObjectLambdaConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3objectlambda-accesspoint-objectlambdaconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3Outposts.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3Outposts.json index 5a45730ca80f1..e3b4d3c74ab97 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3Outposts.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3Outposts.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::S3Outposts::AccessPoint.VpcConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3outposts-accesspoint-vpcconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SDB.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SDB.json index 846b34ddf8442..3ae21ad8babc4 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SDB.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SDB.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::SDB::Domain": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SES.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SES.json index 35f9ff1c7bb05..458ac20410732 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SES.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SES.json @@ -1,11 +1,12 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::SES::ConfigurationSetEventDestination.CloudWatchDestination": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ses-configurationseteventdestination-cloudwatchdestination.html", "Properties": { "DimensionConfigurations": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ses-configurationseteventdestination-cloudwatchdestination.html#cfn-ses-configurationseteventdestination-cloudwatchdestination-dimensionconfigurations", + "DuplicatesAllowed": true, "ItemType": "DimensionConfiguration", "Required": false, "Type": "List", @@ -59,6 +60,7 @@ }, "MatchingEventTypes": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ses-configurationseteventdestination-eventdestination.html#cfn-ses-configurationseteventdestination-eventdestination-matchingeventtypes", + "DuplicatesAllowed": true, "PrimitiveItemType": "String", "Required": true, "Type": "List", @@ -440,6 +442,11 @@ } }, "AWS::SES::ConfigurationSetEventDestination": { + "Attributes": { + "Id": { + "PrimitiveType": "String" + } + }, "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ses-configurationseteventdestination.html", "Properties": { "ConfigurationSetName": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SNS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SNS.json index 77f49a3d0ecc9..8d7fe41bf4807 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SNS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SNS.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::SNS::Topic.Subscription": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sns-subscription.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SQS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SQS.json index 8e6befca3a4fc..822ddd7bf2ba9 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SQS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SQS.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::SQS::Queue": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSM.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSM.json index 0c6982833af11..dcf958b637e95 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSM.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSM.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::SSM::Association.InstanceAssociationOutputLocation": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ssm-association-instanceassociationoutputlocation.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSMContacts.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSMContacts.json index 3b29521554a55..59e2f2305f919 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSMContacts.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSMContacts.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::SSMContacts::Contact.ChannelTargetInfo": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ssmcontacts-contact-channeltargetinfo.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSMIncidents.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSMIncidents.json index 70a57b51d59c8..54bff1c699a44 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSMIncidents.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSMIncidents.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::SSMIncidents::ReplicationSet.RegionConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ssmincidents-replicationset-regionconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSO.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSO.json index 16c9865916db9..065fb33419e4c 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSO.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSO.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::SSO::InstanceAccessControlAttributeConfiguration.AccessControlAttribute": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sso-instanceaccesscontrolattributeconfiguration-accesscontrolattribute.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SageMaker.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SageMaker.json index 2fb4b52f6d26c..0972225ee2065 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SageMaker.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SageMaker.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::SageMaker::App.ResourceSpec": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-app-resourcespec.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SecretsManager.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SecretsManager.json index 4f5fa279a70ab..85e8bb7215378 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SecretsManager.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SecretsManager.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::SecretsManager::RotationSchedule.HostedRotationLambda": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-secretsmanager-rotationschedule-hostedrotationlambda.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SecurityHub.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SecurityHub.json index 9ff503110819e..d77633b0a98a8 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SecurityHub.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SecurityHub.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::SecurityHub::Hub": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceCatalog.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceCatalog.json index 8b98df1669f28..89e18fda9794d 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceCatalog.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceCatalog.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::ServiceCatalog::CloudFormationProduct.ProvisioningArtifactProperties": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-servicecatalog-cloudformationproduct-provisioningartifactproperties.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceCatalogAppRegistry.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceCatalogAppRegistry.json index a8fa4a1d85bd9..6d78e56d74e49 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceCatalogAppRegistry.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceCatalogAppRegistry.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::ServiceCatalogAppRegistry::Application": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceDiscovery.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceDiscovery.json index ffcc6f296fdce..069c3c401ab09 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceDiscovery.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceDiscovery.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::ServiceDiscovery::PrivateDnsNamespace.PrivateDnsPropertiesMutable": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-servicediscovery-privatednsnamespace-privatednspropertiesmutable.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Signer.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Signer.json index 8f77e3170440b..377cadb96a98b 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Signer.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Signer.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Signer::SigningProfile.SignatureValidityPeriod": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-signer-signingprofile-signaturevalidityperiod.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_StepFunctions.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_StepFunctions.json index a095029302874..c4c85447bfe6d 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_StepFunctions.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_StepFunctions.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::StepFunctions::Activity.TagsEntry": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-stepfunctions-activity-tagsentry.html", @@ -208,7 +208,7 @@ "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-stepfunctions-statemachine.html#cfn-stepfunctions-statemachine-statemachinetype", "PrimitiveType": "String", "Required": false, - "UpdateType": "Mutable" + "UpdateType": "Immutable" }, "Tags": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-stepfunctions-statemachine.html#cfn-stepfunctions-statemachine-tags", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Synthetics.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Synthetics.json index 0795f8bf1afa2..fa0af32bb32a1 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Synthetics.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Synthetics.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Synthetics::Canary.ArtifactConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-synthetics-canary-artifactconfig.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Timestream.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Timestream.json index 56e8bfc2e44d5..f5292aa0bca38 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Timestream.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Timestream.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Timestream::ScheduledQuery.DimensionMapping": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-timestream-scheduledquery-dimensionmapping.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Transfer.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Transfer.json index 4f9b1a3751609..ea367242272af 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Transfer.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Transfer.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Transfer::Server.EndpointDetails": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-transfer-server-endpointdetails.html", @@ -257,6 +257,18 @@ "Required": false, "UpdateType": "Mutable" }, + "PostAuthenticationLoginBanner": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-transfer-server.html#cfn-transfer-server-postauthenticationloginbanner", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "PreAuthenticationLoginBanner": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-transfer-server.html#cfn-transfer-server-preauthenticationloginbanner", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, "ProtocolDetails": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-transfer-server.html#cfn-transfer-server-protocoldetails", "Required": false, diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAF.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAF.json index 8dd3faf2ea892..b1e04253166a0 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAF.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAF.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::WAF::ByteMatchSet.ByteMatchTuple": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-waf-bytematchset-bytematchtuples.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAFRegional.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAFRegional.json index dc29e1b679be8..aace044f4e39e 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAFRegional.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAFRegional.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::WAFRegional::ByteMatchSet.ByteMatchTuple": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-wafregional-bytematchset-bytematchtuple.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAFv2.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAFv2.json index 0d85748a8ae1c..8d3c7ab99387c 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAFv2.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAFv2.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::WAFv2::LoggingConfiguration.FieldToMatch": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-wafv2-loggingconfiguration-fieldtomatch.html", @@ -898,6 +898,17 @@ } } }, + "AWS::WAFv2::WebACL.FieldIdentifier": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-wafv2-webacl-fieldidentifier.html", + "Properties": { + "Identifier": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-wafv2-webacl-fieldidentifier.html#cfn-wafv2-webacl-fieldidentifier-identifier", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + } + } + }, "AWS::WAFv2::WebACL.FieldToMatch": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-wafv2-webacl-fieldtomatch.html", "Properties": { @@ -1106,6 +1117,35 @@ } } }, + "AWS::WAFv2::WebACL.ManagedRuleGroupConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-wafv2-webacl-managedrulegroupconfig.html", + "Properties": { + "LoginPath": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-wafv2-webacl-managedrulegroupconfig.html#cfn-wafv2-webacl-managedrulegroupconfig-loginpath", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "PasswordField": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-wafv2-webacl-managedrulegroupconfig.html#cfn-wafv2-webacl-managedrulegroupconfig-passwordfield", + "Required": false, + "Type": "FieldIdentifier", + "UpdateType": "Mutable" + }, + "PayloadType": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-wafv2-webacl-managedrulegroupconfig.html#cfn-wafv2-webacl-managedrulegroupconfig-payloadtype", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "UsernameField": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-wafv2-webacl-managedrulegroupconfig.html#cfn-wafv2-webacl-managedrulegroupconfig-usernamefield", + "Required": false, + "Type": "FieldIdentifier", + "UpdateType": "Mutable" + } + } + }, "AWS::WAFv2::WebACL.ManagedRuleGroupStatement": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-wafv2-webacl-managedrulegroupstatement.html", "Properties": { @@ -1116,6 +1156,13 @@ "Type": "List", "UpdateType": "Mutable" }, + "ManagedRuleGroupConfigs": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-wafv2-webacl-managedrulegroupstatement.html#cfn-wafv2-webacl-managedrulegroupstatement-managedrulegroupconfigs", + "ItemType": "ManagedRuleGroupConfig", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, "Name": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-wafv2-webacl-managedrulegroupstatement.html#cfn-wafv2-webacl-managedrulegroupstatement-name", "PrimitiveType": "String", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Wisdom.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Wisdom.json index 5adfd5f1d1240..4e5aaf71b1512 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Wisdom.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Wisdom.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Wisdom::Assistant.ServerSideEncryptionConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-wisdom-assistant-serversideencryptionconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WorkSpaces.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WorkSpaces.json index 269bf6484c6f2..bcc704cf09e7a 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WorkSpaces.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WorkSpaces.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::WorkSpaces::ConnectionAlias.ConnectionAliasAssociation": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-workspaces-connectionalias-connectionaliasassociation.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_XRay.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_XRay.json index b2680de49535b..fa8f39f841c3d 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_XRay.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_XRay.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::XRay::Group.InsightsConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-xray-group-insightsconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_Alexa_ASK.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_Alexa_ASK.json index eb6ff367ba4b0..37b81dd9b80a9 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_Alexa_ASK.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_Alexa_ASK.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "Alexa::ASK::Skill.AuthenticationConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ask-skill-authenticationconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_Tag.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_Tag.json index 3ac040fc49a91..d66f999a231e5 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_Tag.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_Tag.json @@ -1,5 +1,5 @@ { - "$version": "56.0.0", + "$version": "59.0.0", "PropertyTypes": { "Tag": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-resource-tags.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/001_Version.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/001_Version.json index 44daba90ebe9c..c3a7ac47632f6 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/001_Version.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/001_Version.json @@ -1,3 +1,3 @@ { - "ResourceSpecificationVersion": "56.0.0" + "ResourceSpecificationVersion": "59.0.0" } diff --git a/packages/@aws-cdk/cloud-assembly-schema/package.json b/packages/@aws-cdk/cloud-assembly-schema/package.json index 9b128f55c9de8..8ac885479f264 100644 --- a/packages/@aws-cdk/cloud-assembly-schema/package.json +++ b/packages/@aws-cdk/cloud-assembly-schema/package.json @@ -62,7 +62,7 @@ "devDependencies": { "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "@types/mock-fs": "^4.13.1", "@types/semver": "^7.3.9", "jest": "^27.5.1", diff --git a/packages/@aws-cdk/cloudformation-diff/lib/format-table.ts b/packages/@aws-cdk/cloudformation-diff/lib/format-table.ts index 193223725c9f2..7e7afb98cfa53 100644 --- a/packages/@aws-cdk/cloudformation-diff/lib/format-table.ts +++ b/packages/@aws-cdk/cloudformation-diff/lib/format-table.ts @@ -1,5 +1,5 @@ import * as chalk from 'chalk'; -import * as stringWidth from 'string-width'; +import stringWidth from 'string-width'; import * as table from 'table'; /** diff --git a/packages/@aws-cdk/cloudformation-diff/lib/iam/statement.ts b/packages/@aws-cdk/cloudformation-diff/lib/iam/statement.ts index ea89ad4e597ee..7f83a5561bc76 100644 --- a/packages/@aws-cdk/cloudformation-diff/lib/iam/statement.ts +++ b/packages/@aws-cdk/cloudformation-diff/lib/iam/statement.ts @@ -1,6 +1,9 @@ -import * as deepEqual from 'fast-deep-equal'; import { deepRemoveUndefined } from '../util'; +// namespace object imports won't work in the bundle for function exports +// eslint-disable-next-line @typescript-eslint/no-require-imports +const deepEqual = require('fast-deep-equal'); + export class Statement { /** * Statement ID diff --git a/packages/@aws-cdk/cloudformation-diff/package.json b/packages/@aws-cdk/cloudformation-diff/package.json index 2ee3f60b337b0..a46cf4a5539a8 100644 --- a/packages/@aws-cdk/cloudformation-diff/package.json +++ b/packages/@aws-cdk/cloudformation-diff/package.json @@ -34,7 +34,7 @@ "devDependencies": { "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "@types/string-width": "^4.0.1", "fast-check": "^2.22.0", "jest": "^27.5.1", diff --git a/packages/@aws-cdk/cloudformation-include/package.json b/packages/@aws-cdk/cloudformation-include/package.json index fc32910da3325..8e24b2f22e400 100644 --- a/packages/@aws-cdk/cloudformation-include/package.json +++ b/packages/@aws-cdk/cloudformation-include/package.json @@ -454,7 +454,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1", "ts-jest": "^27.1.3" }, diff --git a/packages/@aws-cdk/core/README.md b/packages/@aws-cdk/core/README.md index d2b1e2c5e5222..041eccef39873 100644 --- a/packages/@aws-cdk/core/README.md +++ b/packages/@aws-cdk/core/README.md @@ -57,6 +57,45 @@ organize their deployments with. If you want to vend a reusable construct, define it as a subclasses of `Construct`: the consumers of your construct will decide where to place it in their own stacks. +## Stack Synthesizers + +Each Stack has a *synthesizer*, an object that determines how and where +the Stack should be synthesized and deployed. The synthesizer controls +aspects like: + +- How does the stack reference assets? (Either through CloudFormation + parameters the CLI supplies, or because the Stack knows a predefined + location where assets will be uploaded). +- What roles are used to deploy the stack? These can be bootstrapped + roles, roles created in some other way, or just the CLI's current + credentials. + +The following synthesizers are available: + +- `DefaultStackSynthesizer`: recommended. Uses predefined asset locations and + roles created by the modern bootstrap template. Access control is done by + controlling who can assume the deploy role. This is the default stack + synthesizer in CDKv2. +- `LegacyStackSynthesizer`: Uses CloudFormation parameters to communicate + asset locations, and the CLI's current permissions to deploy stacks. The + is the default stack synthesizer in CDKv1. +- `CliCredentialsStackSynthesizer`: Uses predefined asset locations, and the + CLI's current permissions. + +Each of these synthesizers takes configuration arguments. To configure +a stack with a synthesizer, pass it as one of its properties: + +```ts +new MyStack(app, 'MyStack', { + synthesizer: new DefaultStackSynthesizer({ + fileAssetsBucketName: 'my-orgs-asset-bucket', + }), +}); +``` + +For more information on bootstrapping accounts and customizing synthesis, +see [Bootstrapping in the CDK Developer Guide](https://docs.aws.amazon.com/cdk/latest/guide/bootstrapping.html). + ## Nested Stacks [Nested stacks](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-nested-stacks.html) are stacks created as part of other stacks. You create a nested stack within another stack by using the `NestedStack` construct. diff --git a/packages/@aws-cdk/core/lib/arn.ts b/packages/@aws-cdk/core/lib/arn.ts index a04f03baf466f..2f6cb68e2dc95 100644 --- a/packages/@aws-cdk/core/lib/arn.ts +++ b/packages/@aws-cdk/core/lib/arn.ts @@ -417,8 +417,6 @@ function parseArnShape(arn: string): 'token' | string[] { // Tokens won't contain ":", so this won't break them. const components = arn.split(':'); - // const [/* arn */, partition, service, /* region */ , /* account */ , resource] = components; - const partition = components.length > 1 ? components[1] : undefined; if (!partition) { throw new Error('The `partition` component (2nd component) of an ARN is required: ' + arn); diff --git a/packages/@aws-cdk/core/lib/asset-staging.ts b/packages/@aws-cdk/core/lib/asset-staging.ts index 5ecafd9d3da56..ee1f2bafc6a04 100644 --- a/packages/@aws-cdk/core/lib/asset-staging.ts +++ b/packages/@aws-cdk/core/lib/asset-staging.ts @@ -4,7 +4,6 @@ import * as path from 'path'; import * as cxapi from '@aws-cdk/cx-api'; import { Construct } from 'constructs'; import * as fs from 'fs-extra'; -import * as minimatch from 'minimatch'; import { AssetHashType, AssetOptions, FileAssetPackaging } from './assets'; import { BundlingOptions, BundlingOutput } from './bundling'; import { FileSystem, FingerprintOptions } from './fs'; @@ -188,9 +187,7 @@ export class AssetStaging extends CoreConstruct { let skip = false; if (props.bundling) { // Check if we actually have to bundle for this stack - const bundlingStacks: string[] = this.node.tryGetContext(cxapi.BUNDLING_STACKS) ?? ['*']; - // bundlingStacks is of the form `Stage/Stack`, convert it to `Stage-Stack` before comparing to stack name - skip = !bundlingStacks.find(pattern => minimatch(Stack.of(this).stackName, pattern.replace('/', '-'))); + skip = !Stack.of(this).bundlingRequired; const bundling = props.bundling; stageThisAsset = () => this.stageByBundling(bundling, skip); } else { diff --git a/packages/@aws-cdk/core/lib/assets.ts b/packages/@aws-cdk/core/lib/assets.ts index e0f48ea73e9e5..7466ded8e6d60 100644 --- a/packages/@aws-cdk/core/lib/assets.ts +++ b/packages/@aws-cdk/core/lib/assets.ts @@ -256,6 +256,9 @@ export interface FileAssetLocation { /** * The HTTP URL of this asset on Amazon S3. * + * This value suitable for inclusion in a CloudFormation template, and + * may be an encoded token. + * * Example value: `https://s3-us-east-1.amazonaws.com/mybucket/myobject` */ readonly httpUrl: string; @@ -263,6 +266,9 @@ export interface FileAssetLocation { /** * The S3 URL of this asset on Amazon S3. * + * This value suitable for inclusion in a CloudFormation template, and + * may be an encoded token. + * * Example value: `s3://mybucket/myobject` */ readonly s3ObjectUrl: string; @@ -285,6 +291,16 @@ export interface FileAssetLocation { * key via the bucket and no additional parameters have to be granted anymore. */ readonly kmsKeyArn?: string; + + /** + * Like `s3ObjectUrl`, but not suitable for CloudFormation consumption + * + * If there are placeholders in the S3 URL, they will be returned unreplaced + * and un-evaluated. + * + * @default - This feature cannot be used + */ + readonly s3ObjectUrlWithPlaceholders?: string; } /** diff --git a/packages/@aws-cdk/core/lib/nested-stack.ts b/packages/@aws-cdk/core/lib/nested-stack.ts index 39cc59ebd366f..e1248d69888aa 100644 --- a/packages/@aws-cdk/core/lib/nested-stack.ts +++ b/packages/@aws-cdk/core/lib/nested-stack.ts @@ -205,6 +205,16 @@ export class NestedStack extends Stack { return false; } + // When adding tags to nested stack, the tags need to be added to all the resources in + // in nested stack, which is handled by the `tags` property, But to tag the + // tags have to be added in the parent stack CfnStack resource. The CfnStack resource created + // by this class dont share the same TagManager as that of the one exposed by the `tag` property of the + // class, all the tags need to be copied to the CfnStack resource before synthesizing the resource. + // See https://github.com/aws/aws-cdk/pull/19128 + Object.entries(this.tags.tagValues()).forEach(([key, value]) => { + this.resource.tags.setTag(key, value); + }); + const cfn = JSON.stringify(this._toCloudFormation()); const templateHash = crypto.createHash('sha256').update(cfn).digest('hex'); diff --git a/packages/@aws-cdk/core/lib/stack-synthesizers/_asset-manifest-builder.ts b/packages/@aws-cdk/core/lib/stack-synthesizers/_asset-manifest-builder.ts new file mode 100644 index 0000000000000..b1e121399cf4a --- /dev/null +++ b/packages/@aws-cdk/core/lib/stack-synthesizers/_asset-manifest-builder.ts @@ -0,0 +1,219 @@ +import * as fs from 'fs'; +import * as path from 'path'; + +import * as cxschema from '@aws-cdk/cloud-assembly-schema'; +import { FileAssetSource, FileAssetLocation, FileAssetPackaging, DockerImageAssetSource, DockerImageAssetLocation } from '../assets'; +import { Fn } from '../cfn-fn'; +import { ISynthesisSession } from '../construct-compat'; +import { Stack } from '../stack'; +import { resolvedOr } from './_shared'; + +/** + * Build an manifest from assets added to a stack synthesizer + */ +export class AssetManifestBuilder { + private readonly files: NonNullable = {}; + private readonly dockerImages: NonNullable = {}; + + public addFileAssetDefault( + asset: FileAssetSource, + stack: Stack, + bucketName: string, + bucketPrefix: string, + role?: RoleOptions, + ): FileAssetLocation { + validateFileAssetSource(asset); + + const extension = + asset.fileName != undefined ? path.extname(asset.fileName) : ''; + const objectKey = + bucketPrefix + + asset.sourceHash + + (asset.packaging === FileAssetPackaging.ZIP_DIRECTORY + ? '.zip' + : extension); + + // Add to manifest + this.files[asset.sourceHash] = { + source: { + path: asset.fileName, + executable: asset.executable, + packaging: asset.packaging, + }, + destinations: { + [this.manifestEnvName(stack)]: { + bucketName: bucketName, + objectKey, + region: resolvedOr(stack.region, undefined), + assumeRoleArn: role?.assumeRoleArn, + assumeRoleExternalId: role?.assumeRoleExternalId, + }, + }, + }; + + const { region, urlSuffix } = stackLocationOrInstrinsics(stack); + const httpUrl = cfnify( + `https://s3.${region}.${urlSuffix}/${bucketName}/${objectKey}`, + ); + const s3ObjectUrlWithPlaceholders = `s3://${bucketName}/${objectKey}`; + + // Return CFN expression + // + // 's3ObjectUrlWithPlaceholders' is intended for the CLI. The CLI ultimately needs a + // 'https://s3.REGION.amazonaws.com[.cn]/name/hash' URL to give to CloudFormation. + // However, there's no way for us to actually know the URL_SUFFIX in the framework, so + // we can't construct that URL. Instead, we record the 's3://.../...' form, and the CLI + // transforms it to the correct 'https://.../' URL before calling CloudFormation. + return { + bucketName: cfnify(bucketName), + objectKey, + httpUrl, + s3ObjectUrl: cfnify(s3ObjectUrlWithPlaceholders), + s3ObjectUrlWithPlaceholders, + s3Url: httpUrl, + }; + } + + public addDockerImageAssetDefault( + asset: DockerImageAssetSource, + stack: Stack, + repositoryName: string, + dockerTagPrefix: string, + role?: RoleOptions, + ): DockerImageAssetLocation { + validateDockerImageAssetSource(asset); + const imageTag = dockerTagPrefix + asset.sourceHash; + + // Add to manifest + this.dockerImages[asset.sourceHash] = { + source: { + executable: asset.executable, + directory: asset.directoryName, + dockerBuildArgs: asset.dockerBuildArgs, + dockerBuildTarget: asset.dockerBuildTarget, + dockerFile: asset.dockerFile, + networkMode: asset.networkMode, + }, + destinations: { + [this.manifestEnvName(stack)]: { + repositoryName: repositoryName, + imageTag, + region: resolvedOr(stack.region, undefined), + assumeRoleArn: role?.assumeRoleArn, + assumeRoleExternalId: role?.assumeRoleExternalId, + }, + }, + }; + + const { account, region, urlSuffix } = stackLocationOrInstrinsics(stack); + + // Return CFN expression + return { + repositoryName: cfnify(repositoryName), + imageUri: cfnify( + `${account}.dkr.ecr.${region}.${urlSuffix}/${repositoryName}:${imageTag}`, + ), + }; + } + + /** + * Write the manifest to disk, and add it to the synthesis session + * + * Reutrn the artifact Id + */ + public writeManifest( + stack: Stack, + session: ISynthesisSession, + additionalProps: Partial = {}, + ): string { + const artifactId = `${stack.artifactId}.assets`; + const manifestFile = `${artifactId}.json`; + const outPath = path.join(session.assembly.outdir, manifestFile); + + const manifest: cxschema.AssetManifest = { + version: cxschema.Manifest.version(), + files: this.files, + dockerImages: this.dockerImages, + }; + + fs.writeFileSync(outPath, JSON.stringify(manifest, undefined, 2)); + + session.assembly.addArtifact(artifactId, { + type: cxschema.ArtifactType.ASSET_MANIFEST, + properties: { + file: manifestFile, + ...additionalProps, + }, + }); + + return artifactId; + } + + private manifestEnvName(stack: Stack): string { + return [ + resolvedOr(stack.account, 'current_account'), + resolvedOr(stack.region, 'current_region'), + ].join('-'); + } +} + +export interface RoleOptions { + readonly assumeRoleArn?: string; + readonly assumeRoleExternalId?: string; +} + +function validateFileAssetSource(asset: FileAssetSource) { + if (!!asset.executable === !!asset.fileName) { + throw new Error(`Exactly one of 'fileName' or 'executable' is required, got: ${JSON.stringify(asset)}`); + } + + if (!!asset.packaging !== !!asset.fileName) { + throw new Error(`'packaging' is expected in combination with 'fileName', got: ${JSON.stringify(asset)}`); + } +} + +function validateDockerImageAssetSource(asset: DockerImageAssetSource) { + if (!!asset.executable === !!asset.directoryName) { + throw new Error(`Exactly one of 'directoryName' or 'executable' is required, got: ${JSON.stringify(asset)}`); + } + + check('dockerBuildArgs'); + check('dockerBuildTarget'); + check('dockerFile'); + + function check(key: K) { + if (asset[key] && !asset.directoryName) { + throw new Error(`'${key}' is only allowed in combination with 'directoryName', got: ${JSON.stringify(asset)}`); + } + } +} + +/** + * Return the stack locations if they're concrete, or the original CFN intrisics otherwise + * + * We need to return these instead of the tokenized versions of the strings, + * since we must accept those same ${AWS::AccountId}/${AWS::Region} placeholders + * in bucket names and role names (in order to allow environment-agnostic stacks). + * + * We'll wrap a single {Fn::Sub} around the final string in order to replace everything, + * but we can't have the token system render part of the string to {Fn::Join} because + * the CFN specification doesn't allow the {Fn::Sub} template string to be an arbitrary + * expression--it must be a string literal. + */ +function stackLocationOrInstrinsics(stack: Stack) { + return { + account: resolvedOr(stack.account, '${AWS::AccountId}'), + region: resolvedOr(stack.region, '${AWS::Region}'), + urlSuffix: resolvedOr(stack.urlSuffix, '${AWS::URLSuffix}'), + }; +} + +/** + * If the string still contains placeholders, wrap it in a Fn::Sub so they will be substituted at CFN deployment time + * + * (This happens to work because the placeholders we picked map directly onto CFN + * placeholders. If they didn't we'd have to do a transformation here). + */ +function cfnify(s: string): string { + return s.indexOf('${') > -1 ? Fn.sub(s) : s; +} \ No newline at end of file diff --git a/packages/@aws-cdk/core/lib/stack-synthesizers/_shared.ts b/packages/@aws-cdk/core/lib/stack-synthesizers/_shared.ts index a9b9e0d7acb5d..91251259c111d 100644 --- a/packages/@aws-cdk/core/lib/stack-synthesizers/_shared.ts +++ b/packages/@aws-cdk/core/lib/stack-synthesizers/_shared.ts @@ -1,7 +1,12 @@ import * as crypto from 'crypto'; +import * as fs from 'fs'; +import * as path from 'path'; import * as cxschema from '@aws-cdk/cloud-assembly-schema'; +import * as cxapi from '@aws-cdk/cx-api'; +import { FileAssetSource, FileAssetPackaging } from '../assets'; import { ConstructNode, IConstruct, ISynthesisSession } from '../construct-compat'; import { Stack } from '../stack'; +import { Token } from '../token'; /** * Shared logic of writing stack artifact to the Cloud Assembly @@ -122,4 +127,60 @@ export function assertBound(x: A | undefined): asserts x is NonNullable { function nonEmptyDict(xs: Record) { return Object.keys(xs).length > 0 ? xs : undefined; +} + +/** + * A "replace-all" function that doesn't require us escaping a literal string to a regex + */ +function replaceAll(s: string, search: string, replace: string) { + return s.split(search).join(replace); +} + +export class StringSpecializer { + constructor(private readonly stack: Stack, private readonly qualifier: string) { + } + + /** + * Function to replace placeholders in the input string as much as possible + * + * We replace: + * - ${Qualifier}: always + * - ${AWS::AccountId}, ${AWS::Region}: only if we have the actual values available + * - ${AWS::Partition}: never, since we never have the actual partition value. + */ + public specialize(s: string): string { + s = replaceAll(s, '${Qualifier}', this.qualifier); + return cxapi.EnvironmentPlaceholders.replace(s, { + region: resolvedOr(this.stack.region, cxapi.EnvironmentPlaceholders.CURRENT_REGION), + accountId: resolvedOr(this.stack.account, cxapi.EnvironmentPlaceholders.CURRENT_ACCOUNT), + partition: cxapi.EnvironmentPlaceholders.CURRENT_PARTITION, + }); + } + + /** + * Specialize only the qualifier + */ + public qualifierOnly(s: string): string { + return replaceAll(s, '${Qualifier}', this.qualifier); + } +} + +/** + * Return the given value if resolved or fall back to a default + */ +export function resolvedOr(x: string, def: A): string | A { + return Token.isUnresolved(x) ? def : x; +} + +export function stackTemplateFileAsset(stack: Stack, session: ISynthesisSession): FileAssetSource { + const templatePath = path.join(session.assembly.outdir, stack.templateFile); + const template = fs.readFileSync(templatePath, { encoding: 'utf-8' }); + + const sourceHash = contentHash(template); + + return { + fileName: stack.templateFile, + packaging: FileAssetPackaging.FILE, + sourceHash, + }; } \ No newline at end of file diff --git a/packages/@aws-cdk/core/lib/stack-synthesizers/bootstrapless-synthesizer.ts b/packages/@aws-cdk/core/lib/stack-synthesizers/bootstrapless-synthesizer.ts index 1a9a2ab8ee0cc..d1526edb79891 100644 --- a/packages/@aws-cdk/core/lib/stack-synthesizers/bootstrapless-synthesizer.ts +++ b/packages/@aws-cdk/core/lib/stack-synthesizers/bootstrapless-synthesizer.ts @@ -24,11 +24,19 @@ export interface BootstraplessSynthesizerProps { } /** - * A special synthesizer that behaves similarly to DefaultStackSynthesizer, - * but doesn't require bootstrapping the environment it operates in. - * Because of that, stacks using it cannot have assets inside of them. + * Synthesizer that reuses bootstrap roles from a different region + * + * A special synthesizer that behaves similarly to `DefaultStackSynthesizer`, + * but doesn't require bootstrapping the environment it operates in. Instead, + * it will re-use the Roles that were created for a different region (which + * is possible because IAM is a global service). + * + * However, it will not assume asset buckets or repositories have been created, + * and therefore does not support assets. + * * Used by the CodePipeline construct for the support stacks needed for - * cross-region replication S3 buckets. + * cross-region replication S3 buckets. App builders do not need to use this + * synthesizer directly. */ export class BootstraplessSynthesizer extends DefaultStackSynthesizer { constructor(props: BootstraplessSynthesizerProps) { diff --git a/packages/@aws-cdk/core/lib/stack-synthesizers/cli-credentials-synthesizer.ts b/packages/@aws-cdk/core/lib/stack-synthesizers/cli-credentials-synthesizer.ts new file mode 100644 index 0000000000000..0f268297999b3 --- /dev/null +++ b/packages/@aws-cdk/core/lib/stack-synthesizers/cli-credentials-synthesizer.ts @@ -0,0 +1,174 @@ +import * as cxapi from '@aws-cdk/cx-api'; +import { DockerImageAssetLocation, DockerImageAssetSource, FileAssetLocation, FileAssetSource } from '../assets'; +import { ISynthesisSession } from '../construct-compat'; +import { Stack } from '../stack'; +import { Token } from '../token'; +import { AssetManifestBuilder } from './_asset-manifest-builder'; +import { assertBound, StringSpecializer, stackTemplateFileAsset } from './_shared'; +import { BOOTSTRAP_QUALIFIER_CONTEXT, DefaultStackSynthesizer } from './default-synthesizer'; +import { StackSynthesizer } from './stack-synthesizer'; + +/** + * Properties for the CliCredentialsStackSynthesizer + */ +export interface CliCredentialsStackSynthesizerProps { + /** + * Name of the S3 bucket to hold file assets + * + * You must supply this if you have given a non-standard name to the staging bucket. + * + * The placeholders `${Qualifier}`, `${AWS::AccountId}` and `${AWS::Region}` will + * be replaced with the values of qualifier and the stack's account and region, + * respectively. + * + * @default DefaultStackSynthesizer.DEFAULT_FILE_ASSETS_BUCKET_NAME + */ + readonly fileAssetsBucketName?: string; + + /** + * Name of the ECR repository to hold Docker Image assets + * + * You must supply this if you have given a non-standard name to the ECR repository. + * + * The placeholders `${Qualifier}`, `${AWS::AccountId}` and `${AWS::Region}` will + * be replaced with the values of qualifier and the stack's account and region, + * respectively. + * + * @default DefaultStackSynthesizer.DEFAULT_IMAGE_ASSETS_REPOSITORY_NAME + */ + readonly imageAssetsRepositoryName?: string; + + /** + * Qualifier to disambiguate multiple environments in the same account + * + * You can use this and leave the other naming properties empty if you have deployed + * the bootstrap environment with standard names but only differnet qualifiers. + * + * @default - Value of context key '@aws-cdk/core:bootstrapQualifier' if set, otherwise `DefaultStackSynthesizer.DEFAULT_QUALIFIER` + */ + readonly qualifier?: string; + + /** + * bucketPrefix to use while storing S3 Assets + * + * @default - DefaultStackSynthesizer.DEFAULT_FILE_ASSET_PREFIX + */ + readonly bucketPrefix?: string; + + /** + * A prefix to use while tagging and uploading Docker images to ECR. + * + * This does not add any separators - the source hash will be appended to + * this string directly. + * + * @default - DefaultStackSynthesizer.DEFAULT_DOCKER_ASSET_PREFIX + */ + readonly dockerTagPrefix?: string; +} + +/** + * A synthesizer that uses conventional asset locations, but not conventional deployment roles + * + * Instead of assuming the bootstrapped deployment roles, all stack operations will be performed + * using the CLI's current credentials. + * + * - This synthesizer does not support deploying to accounts to which the CLI does not have + * credentials. It also does not support deploying using **CDK Pipelines**. For either of those + * features, use `DefaultStackSynthesizer`. + * - This synthesizer requires an S3 bucket and ECR repository with well-known names. To + * not depend on those, use `LegacyStackSynthesizer`. + * + * Be aware that your CLI credentials must be valid for the duration of the + * entire deployment. If you are using session credentials, make sure the + * session lifetime is long enough. + * + * By default, expects the environment to have been bootstrapped with just the staging resources + * of the Bootstrap Stack V2 (also known as "modern bootstrap stack"). You can override + * the default names using the synthesizer's construction properties. + */ +export class CliCredentialsStackSynthesizer extends StackSynthesizer { + private stack?: Stack; + private qualifier?: string; + private bucketName?: string; + private repositoryName?: string; + private bucketPrefix?: string; + private dockerTagPrefix?: string; + + private readonly assetManifest = new AssetManifestBuilder(); + + constructor(private readonly props: CliCredentialsStackSynthesizerProps = {}) { + super(); + + for (const key in props) { + if (props.hasOwnProperty(key)) { + validateNoToken(key as keyof CliCredentialsStackSynthesizerProps); + } + } + + function validateNoToken(key: A) { + const prop = props[key]; + if (typeof prop === 'string' && Token.isUnresolved(prop)) { + throw new Error(`DefaultSynthesizer property '${key}' cannot contain tokens; only the following placeholder strings are allowed: ` + [ + '${Qualifier}', + cxapi.EnvironmentPlaceholders.CURRENT_REGION, + cxapi.EnvironmentPlaceholders.CURRENT_ACCOUNT, + cxapi.EnvironmentPlaceholders.CURRENT_PARTITION, + ].join(', ')); + } + } + } + + public bind(stack: Stack): void { + if (this.stack !== undefined) { + throw new Error('A StackSynthesizer can only be used for one Stack: create a new instance to use with a different Stack'); + } + + this.stack = stack; + + const qualifier = this.props.qualifier ?? stack.node.tryGetContext(BOOTSTRAP_QUALIFIER_CONTEXT) ?? DefaultStackSynthesizer.DEFAULT_QUALIFIER; + this.qualifier = qualifier; + + const spec = new StringSpecializer(stack, qualifier); + + /* eslint-disable max-len */ + this.bucketName = spec.specialize(this.props.fileAssetsBucketName ?? DefaultStackSynthesizer.DEFAULT_FILE_ASSETS_BUCKET_NAME); + this.repositoryName = spec.specialize(this.props.imageAssetsRepositoryName ?? DefaultStackSynthesizer.DEFAULT_IMAGE_ASSETS_REPOSITORY_NAME); + this.bucketPrefix = spec.specialize(this.props.bucketPrefix ?? DefaultStackSynthesizer.DEFAULT_FILE_ASSET_PREFIX); + this.dockerTagPrefix = spec.specialize(this.props.dockerTagPrefix ?? DefaultStackSynthesizer.DEFAULT_DOCKER_ASSET_PREFIX); + /* eslint-enable max-len */ + } + + public addFileAsset(asset: FileAssetSource): FileAssetLocation { + assertBound(this.stack); + assertBound(this.bucketName); + assertBound(this.bucketPrefix); + + return this.assetManifest.addFileAssetDefault(asset, this.stack, this.bucketName, this.bucketPrefix); + } + + public addDockerImageAsset(asset: DockerImageAssetSource): DockerImageAssetLocation { + assertBound(this.stack); + assertBound(this.repositoryName); + assertBound(this.dockerTagPrefix); + + return this.assetManifest.addDockerImageAssetDefault(asset, this.stack, this.repositoryName, this.dockerTagPrefix); + } + + /** + * Synthesize the associated stack to the session + */ + public synthesize(session: ISynthesisSession): void { + assertBound(this.stack); + assertBound(this.qualifier); + + this.synthesizeStackTemplate(this.stack, session); + + const templateAsset = this.addFileAsset(stackTemplateFileAsset(this.stack, session)); + const assetManifestId = this.assetManifest.writeManifest(this.stack, session); + + this.emitStackArtifact(this.stack, session, { + stackTemplateAssetObjectUrl: templateAsset.s3ObjectUrlWithPlaceholders, + additionalDependencies: [assetManifestId], + }); + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/core/lib/stack-synthesizers/default-synthesizer.ts b/packages/@aws-cdk/core/lib/stack-synthesizers/default-synthesizer.ts index 70b30a375dd37..8f8e79ac467b9 100644 --- a/packages/@aws-cdk/core/lib/stack-synthesizers/default-synthesizer.ts +++ b/packages/@aws-cdk/core/lib/stack-synthesizers/default-synthesizer.ts @@ -1,15 +1,13 @@ -import * as fs from 'fs'; -import * as path from 'path'; -import * as cxschema from '@aws-cdk/cloud-assembly-schema'; import * as cxapi from '@aws-cdk/cx-api'; -import { DockerImageAssetLocation, DockerImageAssetSource, FileAssetLocation, FileAssetPackaging, FileAssetSource } from '../assets'; +import { DockerImageAssetLocation, DockerImageAssetSource, FileAssetLocation, FileAssetSource } from '../assets'; import { Fn } from '../cfn-fn'; import { CfnParameter } from '../cfn-parameter'; import { CfnRule } from '../cfn-rule'; import { ISynthesisSession } from '../construct-compat'; import { Stack } from '../stack'; import { Token } from '../token'; -import { assertBound, contentHash } from './_shared'; +import { AssetManifestBuilder } from './_asset-manifest-builder'; +import { assertBound, StringSpecializer, stackTemplateFileAsset } from './_shared'; import { StackSynthesizer } from './stack-synthesizer'; export const BOOTSTRAP_QUALIFIER_CONTEXT = '@aws-cdk/core:bootstrapQualifier'; @@ -218,13 +216,19 @@ export interface DefaultStackSynthesizerProps { } /** - * Uses conventionally named roles and reify asset storage locations + * Uses conventionally named roles and asset storage locations * - * This synthesizer is the only StackSynthesizer that generates - * an asset manifest, and is required to deploy CDK applications using the - * `@aws-cdk/app-delivery` CI/CD library. + * This synthesizer: * - * Requires the environment to have been bootstrapped with Bootstrap Stack V2. + * - Supports cross-account deployments (the CLI can have credentials to one + * account, and you can still deploy to another account by assuming roles with + * well-known names in the other account). + * - Supports the **CDK Pipelines** library. + * + * Requires the environment to have been bootstrapped with Bootstrap Stack V2 + * (also known as "modern bootstrap stack"). The synthesizer adds a version + * check to the template, to make sure the bootstrap stack is recent enough + * to support all features expected by this synthesizer. */ export class DefaultStackSynthesizer extends StackSynthesizer { /** @@ -300,8 +304,7 @@ export class DefaultStackSynthesizer extends StackSynthesizer { private dockerTagPrefix?: string; private bootstrapStackVersionSsmParameter?: string; - private readonly files: NonNullable = {}; - private readonly dockerImages: NonNullable = {}; + private assetManifest = new AssetManifestBuilder(); constructor(private readonly props: DefaultStackSynthesizerProps = {}) { super(); @@ -336,117 +339,45 @@ export class DefaultStackSynthesizer extends StackSynthesizer { const qualifier = this.props.qualifier ?? stack.node.tryGetContext(BOOTSTRAP_QUALIFIER_CONTEXT) ?? DefaultStackSynthesizer.DEFAULT_QUALIFIER; this.qualifier = qualifier; - // Function to replace placeholders in the input string as much as possible - // - // We replace: - // - ${Qualifier}: always - // - ${AWS::AccountId}, ${AWS::Region}: only if we have the actual values available - // - ${AWS::Partition}: never, since we never have the actual partition value. - const specialize = (s: string) => { - s = replaceAll(s, '${Qualifier}', qualifier); - return cxapi.EnvironmentPlaceholders.replace(s, { - region: resolvedOr(stack.region, cxapi.EnvironmentPlaceholders.CURRENT_REGION), - accountId: resolvedOr(stack.account, cxapi.EnvironmentPlaceholders.CURRENT_ACCOUNT), - partition: cxapi.EnvironmentPlaceholders.CURRENT_PARTITION, - }); - }; + const spec = new StringSpecializer(stack, qualifier); /* eslint-disable max-len */ - this.bucketName = specialize(this.props.fileAssetsBucketName ?? DefaultStackSynthesizer.DEFAULT_FILE_ASSETS_BUCKET_NAME); - this.repositoryName = specialize(this.props.imageAssetsRepositoryName ?? DefaultStackSynthesizer.DEFAULT_IMAGE_ASSETS_REPOSITORY_NAME); - this._deployRoleArn = specialize(this.props.deployRoleArn ?? DefaultStackSynthesizer.DEFAULT_DEPLOY_ROLE_ARN); - this._cloudFormationExecutionRoleArn = specialize(this.props.cloudFormationExecutionRole ?? DefaultStackSynthesizer.DEFAULT_CLOUDFORMATION_ROLE_ARN); - this.fileAssetPublishingRoleArn = specialize(this.props.fileAssetPublishingRoleArn ?? DefaultStackSynthesizer.DEFAULT_FILE_ASSET_PUBLISHING_ROLE_ARN); - this.imageAssetPublishingRoleArn = specialize(this.props.imageAssetPublishingRoleArn ?? DefaultStackSynthesizer.DEFAULT_IMAGE_ASSET_PUBLISHING_ROLE_ARN); - this.lookupRoleArn = specialize(this.props.lookupRoleArn ?? DefaultStackSynthesizer.DEFAULT_LOOKUP_ROLE_ARN); - this.bucketPrefix = specialize(this.props.bucketPrefix ?? DefaultStackSynthesizer.DEFAULT_FILE_ASSET_PREFIX); - this.dockerTagPrefix = specialize(this.props.dockerTagPrefix ?? DefaultStackSynthesizer.DEFAULT_DOCKER_ASSET_PREFIX); - this.bootstrapStackVersionSsmParameter = replaceAll( - this.props.bootstrapStackVersionSsmParameter ?? DefaultStackSynthesizer.DEFAULT_BOOTSTRAP_STACK_VERSION_SSM_PARAMETER, - '${Qualifier}', - qualifier, - ); + this.bucketName = spec.specialize(this.props.fileAssetsBucketName ?? DefaultStackSynthesizer.DEFAULT_FILE_ASSETS_BUCKET_NAME); + this.repositoryName = spec.specialize(this.props.imageAssetsRepositoryName ?? DefaultStackSynthesizer.DEFAULT_IMAGE_ASSETS_REPOSITORY_NAME); + this._deployRoleArn = spec.specialize(this.props.deployRoleArn ?? DefaultStackSynthesizer.DEFAULT_DEPLOY_ROLE_ARN); + this._cloudFormationExecutionRoleArn = spec.specialize(this.props.cloudFormationExecutionRole ?? DefaultStackSynthesizer.DEFAULT_CLOUDFORMATION_ROLE_ARN); + this.fileAssetPublishingRoleArn = spec.specialize(this.props.fileAssetPublishingRoleArn ?? DefaultStackSynthesizer.DEFAULT_FILE_ASSET_PUBLISHING_ROLE_ARN); + this.imageAssetPublishingRoleArn = spec.specialize(this.props.imageAssetPublishingRoleArn ?? DefaultStackSynthesizer.DEFAULT_IMAGE_ASSET_PUBLISHING_ROLE_ARN); + this.lookupRoleArn = spec.specialize(this.props.lookupRoleArn ?? DefaultStackSynthesizer.DEFAULT_LOOKUP_ROLE_ARN); + this.bucketPrefix = spec.specialize(this.props.bucketPrefix ?? DefaultStackSynthesizer.DEFAULT_FILE_ASSET_PREFIX); + this.dockerTagPrefix = spec.specialize(this.props.dockerTagPrefix ?? DefaultStackSynthesizer.DEFAULT_DOCKER_ASSET_PREFIX); + this.bootstrapStackVersionSsmParameter = spec.qualifierOnly(this.props.bootstrapStackVersionSsmParameter ?? DefaultStackSynthesizer.DEFAULT_BOOTSTRAP_STACK_VERSION_SSM_PARAMETER); /* eslint-enable max-len */ } public addFileAsset(asset: FileAssetSource): FileAssetLocation { assertBound(this.stack); assertBound(this.bucketName); - validateFileAssetSource(asset); - - const extension = asset.fileName != undefined ? path.extname(asset.fileName) : ''; - const objectKey = this.bucketPrefix + asset.sourceHash + (asset.packaging === FileAssetPackaging.ZIP_DIRECTORY ? '.zip' : extension); + assertBound(this.bucketPrefix); - // Add to manifest - this.files[asset.sourceHash] = { - source: { - path: asset.fileName, - executable: asset.executable, - packaging: asset.packaging, - }, - destinations: { - [this.manifestEnvName]: { - bucketName: this.bucketName, - objectKey, - region: resolvedOr(this.stack.region, undefined), - assumeRoleArn: this.fileAssetPublishingRoleArn, - assumeRoleExternalId: this.props.fileAssetPublishingExternalId, - }, - }, - }; - - const { region, urlSuffix } = stackLocationOrInstrinsics(this.stack); - const httpUrl = cfnify(`https://s3.${region}.${urlSuffix}/${this.bucketName}/${objectKey}`); - const s3ObjectUrl = cfnify(`s3://${this.bucketName}/${objectKey}`); - - // Return CFN expression - return { - bucketName: cfnify(this.bucketName), - objectKey, - httpUrl, - s3ObjectUrl, - s3Url: httpUrl, - }; + return this.assetManifest.addFileAssetDefault(asset, this.stack, this.bucketName, this.bucketPrefix, { + assumeRoleArn: this.fileAssetPublishingRoleArn, + assumeRoleExternalId: this.props.fileAssetPublishingExternalId, + }); } public addDockerImageAsset(asset: DockerImageAssetSource): DockerImageAssetLocation { assertBound(this.stack); assertBound(this.repositoryName); - validateDockerImageAssetSource(asset); - - const imageTag = this.dockerTagPrefix + asset.sourceHash; - - // Add to manifest - this.dockerImages[asset.sourceHash] = { - source: { - executable: asset.executable, - directory: asset.directoryName, - dockerBuildArgs: asset.dockerBuildArgs, - dockerBuildTarget: asset.dockerBuildTarget, - dockerFile: asset.dockerFile, - networkMode: asset.networkMode, - }, - destinations: { - [this.manifestEnvName]: { - repositoryName: this.repositoryName, - imageTag, - region: resolvedOr(this.stack.region, undefined), - assumeRoleArn: this.imageAssetPublishingRoleArn, - assumeRoleExternalId: this.props.imageAssetPublishingExternalId, - }, - }, - }; + assertBound(this.dockerTagPrefix); - const { account, region, urlSuffix } = stackLocationOrInstrinsics(this.stack); - - // Return CFN expression - return { - repositoryName: cfnify(this.repositoryName), - imageUri: cfnify(`${account}.dkr.ecr.${region}.${urlSuffix}/${this.repositoryName}:${imageTag}`), - }; + return this.assetManifest.addDockerImageAssetDefault(asset, this.stack, this.repositoryName, this.dockerTagPrefix, { + assumeRoleArn: this.imageAssetPublishingRoleArn, + assumeRoleExternalId: this.props.imageAssetPublishingExternalId, + }); } - protected synthesizeStackTemplate(stack: Stack, session: ISynthesisSession): void { + protected synthesizeStackTemplate(stack: Stack, session: ISynthesisSession) { stack._synthesizeTemplate(session, this.lookupRoleArn); } @@ -468,19 +399,21 @@ export class DefaultStackSynthesizer extends StackSynthesizer { this.synthesizeStackTemplate(this.stack, session); - // Add the stack's template to the artifact manifest - const templateManifestUrl = this.addStackTemplateToAssetManifest(session); + const templateAsset = this.addFileAsset(stackTemplateFileAsset(this.stack, session)); - const artifactId = this.writeAssetManifest(session); + const assetManifestId = this.assetManifest.writeManifest(this.stack, session, { + requiresBootstrapStackVersion: MIN_BOOTSTRAP_STACK_VERSION, + bootstrapStackVersionSsmParameter: this.bootstrapStackVersionSsmParameter, + }); this.emitStackArtifact(this.stack, session, { assumeRoleExternalId: this.props.deployRoleExternalId, assumeRoleArn: this._deployRoleArn, cloudFormationExecutionRoleArn: this._cloudFormationExecutionRoleArn, - stackTemplateAssetObjectUrl: templateManifestUrl, + stackTemplateAssetObjectUrl: templateAsset.s3ObjectUrlWithPlaceholders, requiresBootstrapStackVersion: MIN_BOOTSTRAP_STACK_VERSION, bootstrapStackVersionSsmParameter: this.bootstrapStackVersionSsmParameter, - additionalDependencies: [artifactId], + additionalDependencies: [assetManifestId], lookupRole: this.useLookupRoleForStackOperations && this.lookupRoleArn ? { arn: this.lookupRoleArn, assumeRoleExternalId: this.props.lookupRoleExternalId, @@ -513,126 +446,6 @@ export class DefaultStackSynthesizer extends StackSynthesizer { protected get stack(): Stack | undefined { return this._stack; } - - /** - * Add the stack's template as one of the manifest assets - * - * This will make it get uploaded to S3 automatically by S3-assets. Return - * the manifest URL. - * - * (We can't return the location returned from `addFileAsset`, as that - * contains CloudFormation intrinsics which can't go into the manifest). - */ - private addStackTemplateToAssetManifest(session: ISynthesisSession) { - assertBound(this.stack); - - const templatePath = path.join(session.assembly.outdir, this.stack.templateFile); - const template = fs.readFileSync(templatePath, { encoding: 'utf-8' }); - - const sourceHash = contentHash(template); - - this.addFileAsset({ - fileName: this.stack.templateFile, - packaging: FileAssetPackaging.FILE, - sourceHash, - }); - - // We should technically return an 'https://s3.REGION.amazonaws.com[.cn]/name/hash' URL here, - // because that is what CloudFormation expects to see. - // - // However, there's no way for us to actually know the UrlSuffix a priori, so we can't construct it here. - // - // Instead, we'll have a protocol with the CLI that we put an 's3://.../...' URL here, and the CLI - // is going to resolve it to the correct 'https://.../' URL before it gives it to CloudFormation. - // - // ALSO: it would be great to reuse the return value of `addFileAsset()` here, except those contain - // CloudFormation REFERENCES to locations, not actual locations (can contain `{ Ref: AWS::Region }` and - // `{ Ref: SomeParameter }` etc). We therefore have to duplicate some logic here :(. - const extension = path.extname(this.stack.templateFile); - return `s3://${this.bucketName}/${this.bucketPrefix}${sourceHash}${extension}`; - } - - /** - * Write an asset manifest to the Cloud Assembly, return the artifact IDs written - */ - private writeAssetManifest(session: ISynthesisSession): string { - assertBound(this.stack); - - const artifactId = `${this.stack.artifactId}.assets`; - const manifestFile = `${artifactId}.json`; - const outPath = path.join(session.assembly.outdir, manifestFile); - - const manifest: cxschema.AssetManifest = { - version: cxschema.Manifest.version(), - files: this.files, - dockerImages: this.dockerImages, - }; - - fs.writeFileSync(outPath, JSON.stringify(manifest, undefined, 2)); - session.assembly.addArtifact(artifactId, { - type: cxschema.ArtifactType.ASSET_MANIFEST, - properties: { - file: manifestFile, - requiresBootstrapStackVersion: MIN_BOOTSTRAP_STACK_VERSION, - bootstrapStackVersionSsmParameter: this.bootstrapStackVersionSsmParameter, - }, - }); - - return artifactId; - } - - private get manifestEnvName(): string { - assertBound(this.stack); - - return [ - resolvedOr(this.stack.account, 'current_account'), - resolvedOr(this.stack.region, 'current_region'), - ].join('-'); - } -} - -/** - * Return the given value if resolved or fall back to a default - */ -function resolvedOr(x: string, def: A): string | A { - return Token.isUnresolved(x) ? def : x; -} - -/** - * A "replace-all" function that doesn't require us escaping a literal string to a regex - */ -function replaceAll(s: string, search: string, replace: string) { - return s.split(search).join(replace); -} - -/** - * If the string still contains placeholders, wrap it in a Fn::Sub so they will be substituted at CFN deployment time - * - * (This happens to work because the placeholders we picked map directly onto CFN - * placeholders. If they didn't we'd have to do a transformation here). - */ -function cfnify(s: string): string { - return s.indexOf('${') > -1 ? Fn.sub(s) : s; -} - -/** - * Return the stack locations if they're concrete, or the original CFN intrisics otherwise - * - * We need to return these instead of the tokenized versions of the strings, - * since we must accept those same ${AWS::AccountId}/${AWS::Region} placeholders - * in bucket names and role names (in order to allow environment-agnostic stacks). - * - * We'll wrap a single {Fn::Sub} around the final string in order to replace everything, - * but we can't have the token system render part of the string to {Fn::Join} because - * the CFN specification doesn't allow the {Fn::Sub} template string to be an arbitrary - * expression--it must be a string literal. - */ -function stackLocationOrInstrinsics(stack: Stack) { - return { - account: resolvedOr(stack.account, '${AWS::AccountId}'), - region: resolvedOr(stack.region, '${AWS::Region}'), - urlSuffix: resolvedOr(stack.urlSuffix, '${AWS::URLSuffix}'), - }; } /** @@ -675,29 +488,3 @@ function range(startIncl: number, endExcl: number) { return ret; } - -function validateFileAssetSource(asset: FileAssetSource) { - if (!!asset.executable === !!asset.fileName) { - throw new Error(`Exactly one of 'fileName' or 'executable' is required, got: ${JSON.stringify(asset)}`); - } - - if (!!asset.packaging !== !!asset.fileName) { - throw new Error(`'packaging' is expected in combination with 'fileName', got: ${JSON.stringify(asset)}`); - } -} - -function validateDockerImageAssetSource(asset: DockerImageAssetSource) { - if (!!asset.executable === !!asset.directoryName) { - throw new Error(`Exactly one of 'directoryName' or 'executable' is required, got: ${JSON.stringify(asset)}`); - } - - check('dockerBuildArgs'); - check('dockerBuildTarget'); - check('dockerFile'); - - function check(key: K) { - if (asset[key] && !asset.directoryName) { - throw new Error(`'${key}' is only allowed in combination with 'directoryName', got: ${JSON.stringify(asset)}`); - } - } -} diff --git a/packages/@aws-cdk/core/lib/stack-synthesizers/index.ts b/packages/@aws-cdk/core/lib/stack-synthesizers/index.ts index db5f8e4d3f656..2a7a4060dcf53 100644 --- a/packages/@aws-cdk/core/lib/stack-synthesizers/index.ts +++ b/packages/@aws-cdk/core/lib/stack-synthesizers/index.ts @@ -4,3 +4,4 @@ export * from './legacy'; export * from './bootstrapless-synthesizer'; export * from './nested'; export * from './stack-synthesizer'; +export * from './cli-credentials-synthesizer'; diff --git a/packages/@aws-cdk/core/lib/stack-synthesizers/legacy.ts b/packages/@aws-cdk/core/lib/stack-synthesizers/legacy.ts index 185dd9730e9d2..204f3b8ba6827 100644 --- a/packages/@aws-cdk/core/lib/stack-synthesizers/legacy.ts +++ b/packages/@aws-cdk/core/lib/stack-synthesizers/legacy.ts @@ -24,10 +24,22 @@ const ASSETS_ECR_REPOSITORY_NAME = 'aws-cdk/assets'; const ASSETS_ECR_REPOSITORY_NAME_OVERRIDE_CONTEXT_KEY = 'assets-ecr-repository-name'; /** - * Use the original deployment environment + * Use the CDK classic way of referencing assets * - * This deployment environment is restricted in cross-environment deployments, - * CI/CD deployments, and will use up CloudFormation parameters in your template. + * This synthesizer will generate CloudFormation parameters for every referenced + * asset, and use the CLI's current credentials to deploy the stack. + * + * - It does not support cross-account deployment (the CLI must have credentials + * to the account you are trying to deploy to). + * - It cannot be used with **CDK Pipelines**. To deploy using CDK Pipelines, + * you must use the `DefaultStackSynthesizer`. + * - Each asset will take up a CloudFormation Parameter in your template. Keep in + * mind that there is a maximum of 200 parameters in a CloudFormation template. + * To use determinstic asset locations instead, use `CliCredentialsStackSynthesizer`. + * + * Be aware that your CLI credentials must be valid for the duration of the + * entire deployment. If you are using session credentials, make sure the + * session lifetime is long enough. * * This is the only StackSynthesizer that supports customizing asset behavior * by overriding `Stack.addFileAsset()` and `Stack.addDockerImageAsset()`. diff --git a/packages/@aws-cdk/core/lib/stack-synthesizers/nested.ts b/packages/@aws-cdk/core/lib/stack-synthesizers/nested.ts index 8eb05d34cba9e..ff5f1def0652f 100644 --- a/packages/@aws-cdk/core/lib/stack-synthesizers/nested.ts +++ b/packages/@aws-cdk/core/lib/stack-synthesizers/nested.ts @@ -6,9 +6,12 @@ import { StackSynthesizer } from './stack-synthesizer'; import { IStackSynthesizer } from './types'; /** - * Deployment environment for a nested stack + * Synthesizer for a nested stack * - * Interoperates with the StackSynthesizer of the parent stack. + * Forwards all calls to the parent stack's synthesizer. + * + * This synthesizer is automatically used for `NestedStack` constructs. + * App builder do not need to use this class directly. */ export class NestedStackSynthesizer extends StackSynthesizer { private stack?: Stack; diff --git a/packages/@aws-cdk/core/lib/stack-synthesizers/stack-synthesizer.ts b/packages/@aws-cdk/core/lib/stack-synthesizers/stack-synthesizer.ts index ea7c7745f2419..75e4b46bf015f 100644 --- a/packages/@aws-cdk/core/lib/stack-synthesizers/stack-synthesizer.ts +++ b/packages/@aws-cdk/core/lib/stack-synthesizers/stack-synthesizer.ts @@ -47,7 +47,6 @@ export abstract class StackSynthesizer implements IStackSynthesizer { stack._synthesizeTemplate(session); } - /** * Write the stack artifact to the session * diff --git a/packages/@aws-cdk/core/lib/stack.ts b/packages/@aws-cdk/core/lib/stack.ts index 0efd45fc14b3f..d6278d05834e3 100644 --- a/packages/@aws-cdk/core/lib/stack.ts +++ b/packages/@aws-cdk/core/lib/stack.ts @@ -3,6 +3,7 @@ import * as path from 'path'; import * as cxschema from '@aws-cdk/cloud-assembly-schema'; import * as cxapi from '@aws-cdk/cx-api'; import { IConstruct, Construct, Node } from 'constructs'; +import * as minimatch from 'minimatch'; import { Annotations } from './annotations'; import { App } from './app'; import { Arn, ArnComponents, ArnFormat } from './arn'; @@ -1153,6 +1154,19 @@ export class Stack extends CoreConstruct implements ITaggable { return makeStackName(ids); } + + /** + * Indicates whether the stack requires bundling or not + */ + public get bundlingRequired() { + const bundlingStacks: string[] = this.node.tryGetContext(cxapi.BUNDLING_STACKS) ?? ['*']; + + // bundlingStacks is of the form `Stage/Stack`, convert it to `Stage-Stack` before comparing to stack name + return bundlingStacks.some(pattern => minimatch( + this.stackName, + pattern.replace('/', '-'), + )); + } } function merge(template: any, fragment: any): void { diff --git a/packages/@aws-cdk/core/package.json b/packages/@aws-cdk/core/package.json index da4f6dafb1175..852c03fa918df 100644 --- a/packages/@aws-cdk/core/package.json +++ b/packages/@aws-cdk/core/package.json @@ -180,7 +180,7 @@ "@aws-cdk/pkglint": "0.0.0", "@types/aws-lambda": "^8.10.92", "@types/fs-extra": "^8.1.2", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "@types/lodash": "^4.14.178", "@types/minimatch": "^3.0.5", "@types/node": "^10.17.60", diff --git a/packages/@aws-cdk/core/rosetta/default.ts-fixture b/packages/@aws-cdk/core/rosetta/default.ts-fixture index 26a25736acb17..e0da717734235 100644 --- a/packages/@aws-cdk/core/rosetta/default.ts-fixture +++ b/packages/@aws-cdk/core/rosetta/default.ts-fixture @@ -23,6 +23,7 @@ import { CustomResource, CustomResourceProvider, CustomResourceProviderRuntime, + DefaultStackSynthesizer, DependableTrait, Duration, Fn, diff --git a/packages/@aws-cdk/core/test/stack-synthesis/clicreds-synthesis.test.ts b/packages/@aws-cdk/core/test/stack-synthesis/clicreds-synthesis.test.ts new file mode 100644 index 0000000000000..3fab5ef7e0b5f --- /dev/null +++ b/packages/@aws-cdk/core/test/stack-synthesis/clicreds-synthesis.test.ts @@ -0,0 +1,257 @@ +import * as fs from 'fs'; +import * as cxschema from '@aws-cdk/cloud-assembly-schema'; +import * as cxapi from '@aws-cdk/cx-api'; +import { App, Aws, CfnResource, CliCredentialsStackSynthesizer, FileAssetPackaging, Stack } from '../../lib'; +import { evaluateCFN } from '../evaluate-cfn'; + +const CFN_CONTEXT = { + 'AWS::Region': 'the_region', + 'AWS::AccountId': 'the_account', + 'AWS::URLSuffix': 'domain.aws', +}; + +let app: App; +let stack: Stack; +describe('CLI creds synthesis', () => { + beforeEach(() => { + app = new App(); + stack = new Stack(app, 'Stack', { + synthesizer: new CliCredentialsStackSynthesizer(), + }); + }); + + test('stack template is in asset manifest', () => { + // GIVEN + new CfnResource(stack, 'Resource', { + type: 'Some::Resource', + }); + + // WHEN + const asm = app.synth(); + + // THEN -- the S3 url is advertised on the stack artifact + const stackArtifact = asm.getStackArtifact('Stack'); + + const templateObjectKey = last(stackArtifact.stackTemplateAssetObjectUrl?.split('/')); + + expect(stackArtifact.stackTemplateAssetObjectUrl).toEqual(`s3://cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}/${templateObjectKey}`); + + // THEN - the template is in the asset manifest + const manifestArtifact = asm.artifacts.filter(isAssetManifest)[0]; + expect(manifestArtifact).toBeDefined(); + const manifest: cxschema.AssetManifest = JSON.parse(fs.readFileSync(manifestArtifact.file, { encoding: 'utf-8' })); + + const firstFile = (manifest.files ? manifest.files[Object.keys(manifest.files)[0]] : undefined) ?? {}; + + expect(firstFile).toEqual({ + source: { path: 'Stack.template.json', packaging: 'file' }, + destinations: { + 'current_account-current_region': { + bucketName: 'cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}', + objectKey: templateObjectKey, + }, + }, + }); + }); + + test('add file asset', () => { + // WHEN + const location = stack.synthesizer.addFileAsset({ + fileName: __filename, + packaging: FileAssetPackaging.FILE, + sourceHash: 'abcdef', + }); + + // THEN - we have a fixed asset location with region placeholders + expect(evalCFN(location.bucketName)).toEqual('cdk-hnb659fds-assets-the_account-the_region'); + expect(evalCFN(location.s3Url)).toEqual('https://s3.the_region.domain.aws/cdk-hnb659fds-assets-the_account-the_region/abcdef.js'); + + // THEN - object key contains source hash somewhere + expect(location.objectKey.indexOf('abcdef')).toBeGreaterThan(-1); + }); + + test('add docker image asset', () => { + // WHEN + const location = stack.synthesizer.addDockerImageAsset({ + directoryName: '.', + sourceHash: 'abcdef', + }); + + // THEN - we have a fixed asset location with region placeholders + expect(evalCFN(location.repositoryName)).toEqual('cdk-hnb659fds-container-assets-the_account-the_region'); + expect(evalCFN(location.imageUri)).toEqual('the_account.dkr.ecr.the_region.domain.aws/cdk-hnb659fds-container-assets-the_account-the_region:abcdef'); + + + }); + + test('synthesis', () => { + // GIVEN + stack.synthesizer.addFileAsset({ + fileName: __filename, + packaging: FileAssetPackaging.FILE, + sourceHash: 'abcdef', + }); + stack.synthesizer.addDockerImageAsset({ + directoryName: '.', + sourceHash: 'abcdef', + }); + + // WHEN + const asm = app.synth(); + + // THEN - we have an asset manifest with both assets and the stack template in there + const manifestArtifact = getAssetManifest(asm); + const manifest = readAssetManifest(manifestArtifact); + + expect(Object.keys(manifest.files || {}).length).toEqual(2); + expect(Object.keys(manifest.dockerImages || {}).length).toEqual(1); + }); + + test('customize publishing resources', () => { + // GIVEN + const myapp = new App(); + + // WHEN + const mystack = new Stack(myapp, 'mystack', { + synthesizer: new CliCredentialsStackSynthesizer({ + fileAssetsBucketName: 'file-asset-bucket', + imageAssetsRepositoryName: 'image-ecr-repository', + }), + }); + + mystack.synthesizer.addFileAsset({ + fileName: __filename, + packaging: FileAssetPackaging.FILE, + sourceHash: 'file-asset-hash', + }); + + mystack.synthesizer.addDockerImageAsset({ + directoryName: '.', + sourceHash: 'docker-asset-hash', + }); + + // THEN + const asm = myapp.synth(); + const manifest = readAssetManifest(getAssetManifest(asm)); + + expect(manifest.files?.['file-asset-hash']?.destinations?.['current_account-current_region']).toEqual({ + bucketName: 'file-asset-bucket', + objectKey: 'file-asset-hash.js', + }); + + expect(manifest.dockerImages?.['docker-asset-hash']?.destinations?.['current_account-current_region']).toEqual({ + repositoryName: 'image-ecr-repository', + imageTag: 'docker-asset-hash', + }); + }); + + test('synthesis with bucketPrefix', () => { + // GIVEN + const myapp = new App(); + + // WHEN + const mystack = new Stack(myapp, 'mystack-bucketPrefix', { + synthesizer: new CliCredentialsStackSynthesizer({ + fileAssetsBucketName: 'file-asset-bucket', + bucketPrefix: '000000000000/', + }), + }); + + mystack.synthesizer.addFileAsset({ + fileName: __filename, + packaging: FileAssetPackaging.FILE, + sourceHash: 'file-asset-hash-with-prefix', + }); + + // WHEN + const asm = myapp.synth(); + + // THEN -- the S3 url is advertised on the stack artifact + const stackArtifact = asm.getStackArtifact('mystack-bucketPrefix'); + + // THEN - we have an asset manifest with both assets and the stack template in there + const manifest = readAssetManifest(getAssetManifest(asm)); + + // THEN + expect(manifest.files?.['file-asset-hash-with-prefix']?.destinations?.['current_account-current_region']).toEqual({ + bucketName: 'file-asset-bucket', + objectKey: '000000000000/file-asset-hash-with-prefix.js', + }); + + const templateHash = last(stackArtifact.stackTemplateAssetObjectUrl?.split('/')); + + expect(stackArtifact.stackTemplateAssetObjectUrl).toEqual(`s3://file-asset-bucket/000000000000/${templateHash}`); + }); + + test('synthesis with dockerPrefix', () => { + // GIVEN + const myapp = new App(); + + // WHEN + const mystack = new Stack(myapp, 'mystack-dockerPrefix', { + synthesizer: new CliCredentialsStackSynthesizer({ + dockerTagPrefix: 'test-prefix-', + }), + }); + + mystack.synthesizer.addDockerImageAsset({ + directoryName: 'some-folder', + sourceHash: 'docker-asset-hash', + }); + + const asm = myapp.synth(); + + // THEN + const manifest = readAssetManifest(getAssetManifest(asm)); + const imageTag = manifest.dockerImages?.['docker-asset-hash']?.destinations?.['current_account-current_region'].imageTag; + expect(imageTag).toEqual('test-prefix-docker-asset-hash'); + }); + + test('cannot use same synthesizer for multiple stacks', () => { + // GIVEN + const synthesizer = new CliCredentialsStackSynthesizer(); + + // WHEN + new Stack(app, 'Stack2', { synthesizer }); + expect(() => { + new Stack(app, 'Stack3', { synthesizer }); + }).toThrow(/A StackSynthesizer can only be used for one Stack/); + + }); +}); + +test('get an exception when using tokens for parameters', () => { + expect(() => { + // GIVEN + new CliCredentialsStackSynthesizer({ + fileAssetsBucketName: `my-bucket-${Aws.REGION}`, + }); + }).toThrow(/cannot contain tokens/); +}); + +/** + * Evaluate a possibly string-containing value the same way CFN would do + * + * (Be invariant to the specific Fn::Sub or Fn::Join we would output) + */ +function evalCFN(value: any) { + return evaluateCFN(stack.resolve(value), CFN_CONTEXT); +} + +function isAssetManifest(x: cxapi.CloudArtifact): x is cxapi.AssetManifestArtifact { + return x instanceof cxapi.AssetManifestArtifact; +} + +function getAssetManifest(asm: cxapi.CloudAssembly): cxapi.AssetManifestArtifact { + const manifestArtifact = asm.artifacts.filter(isAssetManifest)[0]; + if (!manifestArtifact) { throw new Error('no asset manifest in assembly'); } + return manifestArtifact; +} + +function readAssetManifest(manifestArtifact: cxapi.AssetManifestArtifact): cxschema.AssetManifest { + return JSON.parse(fs.readFileSync(manifestArtifact.file, { encoding: 'utf-8' })); +} + +function last(xs?: A[]): A | undefined { + return xs ? xs[xs.length - 1] : undefined; +} diff --git a/packages/@aws-cdk/core/test/stack.test.ts b/packages/@aws-cdk/core/test/stack.test.ts index b344dbbbff0be..e41796bccb624 100644 --- a/packages/@aws-cdk/core/test/stack.test.ts +++ b/packages/@aws-cdk/core/test/stack.test.ts @@ -1191,6 +1191,38 @@ describe('stack', () => { expect(new Stack(app, 'Stack', { analyticsReporting: true })._versionReportingEnabled).toBeDefined(); }); + + test('requires bundling when wildcard is specified in BUNDLING_STACKS', () => { + const app = new App(); + const stack = new Stack(app, 'Stack'); + stack.node.setContext(cxapi.BUNDLING_STACKS, ['*']); + expect(stack.bundlingRequired).toBe(true); + + }); + + test('requires bundling when stackName has an exact match in BUNDLING_STACKS', () => { + const app = new App(); + const stack = new Stack(app, 'Stack'); + stack.node.setContext(cxapi.BUNDLING_STACKS, ['Stack']); + expect(stack.bundlingRequired).toBe(true); + + }); + + test('does not require bundling when no item from BUILDING_STACKS matches stackName', () => { + const app = new App(); + const stack = new Stack(app, 'Stack'); + stack.node.setContext(cxapi.BUNDLING_STACKS, ['Stac']); + expect(stack.bundlingRequired).toBe(false); + + }); + + test('does not require bundling when BUNDLING_STACKS is empty', () => { + const app = new App(); + const stack = new Stack(app, 'Stack'); + stack.node.setContext(cxapi.BUNDLING_STACKS, []); + expect(stack.bundlingRequired).toBe(false); + + }); }); describe('regionalFact', () => { diff --git a/packages/@aws-cdk/custom-resources/lib/provider-framework/runtime/framework.ts b/packages/@aws-cdk/custom-resources/lib/provider-framework/runtime/framework.ts index 181968611d354..9c2d8a4bfc0fc 100644 --- a/packages/@aws-cdk/custom-resources/lib/provider-framework/runtime/framework.ts +++ b/packages/@aws-cdk/custom-resources/lib/provider-framework/runtime/framework.ts @@ -73,6 +73,7 @@ async function isComplete(event: AWSCDKAsyncCustomResource.IsCompleteRequest) { const response = { ...event, + ...isCompleteResult, Data: { ...event.Data, ...isCompleteResult.Data, diff --git a/packages/@aws-cdk/custom-resources/lib/provider-framework/types.d.ts b/packages/@aws-cdk/custom-resources/lib/provider-framework/types.d.ts index 9a9536eac078b..288dc217c7f82 100644 --- a/packages/@aws-cdk/custom-resources/lib/provider-framework/types.d.ts +++ b/packages/@aws-cdk/custom-resources/lib/provider-framework/types.d.ts @@ -4,7 +4,7 @@ /** * these types can be accessed without needing to `import` the module. * e.g. `AWSCDKAsyncCustomResource.OnEventRequest` - */ + */ export as namespace AWSCDKAsyncCustomResource; /** @@ -105,6 +105,11 @@ export interface IsCompleteResponse { */ readonly IsComplete: boolean; + /** + * If present, overrides the PhysicalResourceId of OnEventResponse with the PhysicalResourceId of IsCompleteResponse. + */ + readonly PhysicalResourceId?: string; + /** * Additional/changes to resource attributes. This hash will be merged with the one returned from `OnEventResponse`. */ diff --git a/packages/@aws-cdk/custom-resources/package.json b/packages/@aws-cdk/custom-resources/package.json index 5ee0eb2d5e71e..af0a8eaa7d508 100644 --- a/packages/@aws-cdk/custom-resources/package.json +++ b/packages/@aws-cdk/custom-resources/package.json @@ -89,7 +89,7 @@ "@aws-cdk/pkglint": "0.0.0", "@types/aws-lambda": "^8.10.92", "@types/fs-extra": "^8.1.2", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "@types/sinon": "^9.0.11", "aws-sdk": "^2.848.0", "aws-sdk-mock": "5.6.0", diff --git a/packages/@aws-cdk/custom-resources/test/provider-framework/runtime.test.ts b/packages/@aws-cdk/custom-resources/test/provider-framework/runtime.test.ts index d2af0a4fafd2d..751e33e6408e0 100644 --- a/packages/@aws-cdk/custom-resources/test/provider-framework/runtime.test.ts +++ b/packages/@aws-cdk/custom-resources/test/provider-framework/runtime.test.ts @@ -169,6 +169,23 @@ describe('PhysicalResourceId', () => { }); }); + test('UPDATE: can override the physical ID with the actual on isComplete', async () => { + // GIVEN + mocks.onEventImplMock = async () => ({ PhysicalResourceId: 'TemporaryPhysicalId' }); + mocks.isCompleteImplMock = async () => ({ IsComplete: true, PhysicalResourceId: 'NewPhysicalId' }); + + // WHEN + await simulateEvent({ + RequestType: 'Update', + PhysicalResourceId: 'CurrentPhysicalId', + }); + + // THEN + expectCloudFormationSuccess({ + PhysicalResourceId: 'NewPhysicalId', + }); + }); + test('DELETE: cannot change the physical resource ID during a delete', async () => { // GIVEN mocks.onEventImplMock = async () => ({ PhysicalResourceId: 'NewPhysicalId' }); diff --git a/packages/@aws-cdk/cx-api/lib/artifacts/cloudformation-artifact.ts b/packages/@aws-cdk/cx-api/lib/artifacts/cloudformation-artifact.ts index 3e6f395b5c99d..f601131d9f532 100644 --- a/packages/@aws-cdk/cx-api/lib/artifacts/cloudformation-artifact.ts +++ b/packages/@aws-cdk/cx-api/lib/artifacts/cloudformation-artifact.ts @@ -37,9 +37,10 @@ export class CloudFormationStackArtifact extends CloudArtifact { public readonly stackName: string; /** - * A string that represents this stack. Should only be used in user interfaces. - * If the stackName and artifactId are the same, it will just return that. Otherwise, - * it will return something like " ()" + * A string that represents this stack. Should only be used in user + * interfaces. If the stackName has not been set explicitly, or has been set + * to artifactId, it will return the hierarchicalId of the stack. Otherwise, + * it will return something like " ()" */ public readonly displayName: string; @@ -148,8 +149,8 @@ export class CloudFormationStackArtifact extends CloudArtifact { this.assets = this.findMetadataByType(cxschema.ArtifactMetadataEntryType.ASSET).map(e => e.data as cxschema.AssetMetadataEntry); this.displayName = this.stackName === artifactId - ? this.stackName - : `${artifactId} (${this.stackName})`; + ? this.hierarchicalId + : `${this.hierarchicalId} (${this.stackName})`; this.name = this.stackName; // backwards compat this.originalName = this.stackName; diff --git a/packages/@aws-cdk/cx-api/package.json b/packages/@aws-cdk/cx-api/package.json index 090cb95dfaffb..90941529df1f3 100644 --- a/packages/@aws-cdk/cx-api/package.json +++ b/packages/@aws-cdk/cx-api/package.json @@ -68,7 +68,7 @@ "devDependencies": { "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "@types/mock-fs": "^4.13.1", "@types/semver": "^7.3.9", "jest": "^27.5.1", diff --git a/packages/@aws-cdk/cx-api/test/cloud-assembly.test.ts b/packages/@aws-cdk/cx-api/test/cloud-assembly.test.ts index 2151e2345620c..804d1e43e16b6 100644 --- a/packages/@aws-cdk/cx-api/test/cloud-assembly.test.ts +++ b/packages/@aws-cdk/cx-api/test/cloud-assembly.test.ts @@ -132,7 +132,22 @@ test('getStackArtifact retrieves a stack by artifact id', () => { expect(assembly.getStackArtifact('stack1').id).toEqual('stack1'); }); -test('displayName shows both artifact ID and stack name if needed', () => { +test('displayName shows hierarchical ID for nested stack without explicit stackName', () => { + const assembly = new CloudAssembly(path.join(FIXTURES, 'nested-stacks')); + const stackArtifact = assembly.getStackArtifact('topLevelStackNestedStackDAC87084'); + expect(stackArtifact.hierarchicalId).toStrictEqual('topLevelStack/nestedStack'); + expect(stackArtifact.displayName).toStrictEqual('topLevelStack/nestedStack'); +}); + +test('displayName shows hierarchical ID and stackName for nested stack with explicit stackName', () => { + const assembly = new CloudAssembly(path.join(FIXTURES, 'nested-stacks')); + const nestedStack = assembly.getStackArtifact('topLevelStackNestedStackWithStackName6D28EAEF'); + expect(nestedStack.hierarchicalId).toStrictEqual('topLevelStack/nestedStackWithStackName'); + expect(nestedStack.stackName).toStrictEqual('explicitStackName'); + expect(nestedStack.displayName).toStrictEqual('topLevelStack/nestedStackWithStackName (explicitStackName)'); +}); + +test('displayName shows both hierarchical ID and stack name if needed', () => { const a1 = new CloudAssembly(path.join(FIXTURES, 'multiple-stacks-same-name')); expect(a1.getStackArtifact('stack1').displayName).toStrictEqual('stack1 (the-physical-name-of-the-stack)'); expect(a1.getStackArtifact('stack2').displayName).toStrictEqual('stack2 (the-physical-name-of-the-stack)'); diff --git a/packages/@aws-cdk/cx-api/test/fixtures/nested-stacks/manifest.json b/packages/@aws-cdk/cx-api/test/fixtures/nested-stacks/manifest.json new file mode 100644 index 0000000000000..8d732d2105e2d --- /dev/null +++ b/packages/@aws-cdk/cx-api/test/fixtures/nested-stacks/manifest.json @@ -0,0 +1,30 @@ +{ + "version": "0.0.0", + "artifacts": { + "topLevelStack": { + "type": "aws:cloudformation:stack", + "environment": "aws://111111111111/us-east-1", + "properties": { + "templateFile": "topLevelStack.template.json" + }, + "displayName": "topLevelStack" + }, + "topLevelStackNestedStackDAC87084": { + "type": "aws:cloudformation:stack", + "environment": "aws://111111111111/us-east-1", + "properties": { + "templateFile": "nestedStack.template.json" + }, + "displayName": "topLevelStack/nestedStack" + }, + "topLevelStackNestedStackWithStackName6D28EAEF": { + "type": "aws:cloudformation:stack", + "environment": "aws://111111111111/us-east-1", + "properties": { + "templateFile": "nestedStackWithStackName.template.json", + "stackName": "explicitStackName" + }, + "displayName": "topLevelStack/nestedStackWithStackName" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/cx-api/test/fixtures/nested-stacks/nestedStack.template.json b/packages/@aws-cdk/cx-api/test/fixtures/nested-stacks/nestedStack.template.json new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/packages/@aws-cdk/cx-api/test/fixtures/nested-stacks/nestedStackWithStackName.template.json b/packages/@aws-cdk/cx-api/test/fixtures/nested-stacks/nestedStackWithStackName.template.json new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/packages/@aws-cdk/cx-api/test/fixtures/nested-stacks/topLevelStack.template.json b/packages/@aws-cdk/cx-api/test/fixtures/nested-stacks/topLevelStack.template.json new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/packages/@aws-cdk/example-construct-library/package.json b/packages/@aws-cdk/example-construct-library/package.json index 40dcc891bc1e9..0846135bf2e90 100644 --- a/packages/@aws-cdk/example-construct-library/package.json +++ b/packages/@aws-cdk/example-construct-library/package.json @@ -77,7 +77,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/lambda-layer-awscli/layer/requirements.txt b/packages/@aws-cdk/lambda-layer-awscli/layer/requirements.txt index ffa39b9aca8d1..96070a4e696a9 100644 --- a/packages/@aws-cdk/lambda-layer-awscli/layer/requirements.txt +++ b/packages/@aws-cdk/lambda-layer-awscli/layer/requirements.txt @@ -1 +1 @@ -awscli==1.22.54 +awscli==1.22.68 diff --git a/packages/@aws-cdk/lambda-layer-awscli/package.json b/packages/@aws-cdk/lambda-layer-awscli/package.json index e4aa927d4d7df..7daf454a10df1 100644 --- a/packages/@aws-cdk/lambda-layer-awscli/package.json +++ b/packages/@aws-cdk/lambda-layer-awscli/package.json @@ -78,7 +78,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/lambda-layer-kubectl/package.json b/packages/@aws-cdk/lambda-layer-kubectl/package.json index a71a3ffded402..2a2223166c3ee 100644 --- a/packages/@aws-cdk/lambda-layer-kubectl/package.json +++ b/packages/@aws-cdk/lambda-layer-kubectl/package.json @@ -77,7 +77,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "pkglint": { diff --git a/packages/@aws-cdk/lambda-layer-node-proxy-agent/.no-packagejson-validator b/packages/@aws-cdk/lambda-layer-node-proxy-agent/.no-packagejson-validator new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/packages/@aws-cdk/lambda-layer-node-proxy-agent/README.md b/packages/@aws-cdk/lambda-layer-node-proxy-agent/README.md index f27c51013b3fc..da6471a4950da 100644 --- a/packages/@aws-cdk/lambda-layer-node-proxy-agent/README.md +++ b/packages/@aws-cdk/lambda-layer-node-proxy-agent/README.md @@ -23,4 +23,4 @@ declare const fn: lambda.Function; fn.addLayers(new NodeProxyAgentLayer(this, 'NodeProxyAgentLayer')); ``` -[`proxy-agent`](https://www.npmjs.com/package/proxy-agent) will be installed under `/opt/nodejs/node_modules`. +[`proxy-agent`](https://www.npmjs.com/package/proxy-agent) will be installed under `/nodejs/node_modules`. diff --git a/packages/@aws-cdk/lambda-layer-node-proxy-agent/layer/Dockerfile b/packages/@aws-cdk/lambda-layer-node-proxy-agent/layer/Dockerfile index 2e3f644258652..0166da75f4651 100644 --- a/packages/@aws-cdk/lambda-layer-node-proxy-agent/layer/Dockerfile +++ b/packages/@aws-cdk/lambda-layer-node-proxy-agent/layer/Dockerfile @@ -1,8 +1,6 @@ # base lambda image FROM public.ecr.aws/lambda/nodejs:latest -ARG PROXY_AGENT_VERSION=5.0.0 - USER root RUN mkdir -p /opt WORKDIR /tmp @@ -19,7 +17,8 @@ RUN yum update -y \ # RUN mkdir -p /opt/nodejs -RUN cd /opt/nodejs && npm install proxy-agent@${PROXY_AGENT_VERSION} +COPY package*.json /opt/nodejs/ +RUN cd /opt/nodejs && npm ci && rm package*.json # # create the bundle diff --git a/packages/@aws-cdk/lambda-layer-node-proxy-agent/layer/build.sh b/packages/@aws-cdk/lambda-layer-node-proxy-agent/layer/build.sh index 6a84896b9d991..d45f9d47a77d7 100755 --- a/packages/@aws-cdk/lambda-layer-node-proxy-agent/layer/build.sh +++ b/packages/@aws-cdk/lambda-layer-node-proxy-agent/layer/build.sh @@ -3,7 +3,7 @@ set -euo pipefail cd $(dirname $0) -echo ">> Building AWS Lambda layer inside a docker image..." +echo ">> Building AWS Lambda layer inside a docker image for Proxy Agent..." TAG='aws-lambda-node-proxy-agent' diff --git a/packages/@aws-cdk/lambda-layer-node-proxy-agent/layer/package-lock.json b/packages/@aws-cdk/lambda-layer-node-proxy-agent/layer/package-lock.json new file mode 100644 index 0000000000000..19220af66d40b --- /dev/null +++ b/packages/@aws-cdk/lambda-layer-node-proxy-agent/layer/package-lock.json @@ -0,0 +1,1137 @@ +{ + "name": "proxy-agent-layer", + "version": "0.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "proxy-agent-layer", + "version": "0.0.0", + "license": "ISC", + "devDependencies": { + "proxy-agent": "^5.0.0" + } + }, + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/acorn": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ast-types": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", + "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", + "dev": true, + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/bytes": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.1.tgz", + "integrity": "sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "node_modules/data-uri-to-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz", + "integrity": "sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/degenerator": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-3.0.1.tgz", + "integrity": "sha512-LFsIFEeLPlKvAKXu7j3ssIG6RT0TbI7/GhsqrI0DnHASEQjXQ0LUSYcjJteGgRGmZbl1TnMSxpNQIAiJ7Du5TQ==", + "dev": true, + "dependencies": { + "ast-types": "^0.13.2", + "escodegen": "^1.8.1", + "esprima": "^4.0.0", + "vm2": "^3.9.3" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/escodegen": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", + "dev": true, + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=4.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "node_modules/file-uri-to-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-2.0.0.tgz", + "integrity": "sha512-hjPFI8oE/2iQPVe4gbrJ73Pp+Xfub2+WI2LlXDbsaJBwT5wuMh35WNWVYYTpnz895shtwfyutMFLFywpQAFdLg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/ftp": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", + "integrity": "sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=", + "dev": true, + "dependencies": { + "readable-stream": "1.1.x", + "xregexp": "2.0.0" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/get-uri": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-3.0.2.tgz", + "integrity": "sha512-+5s0SJbGoyiJTZZ2JTpFPLMPSch72KEqGOTvQsBqg0RBWvwhWUSYZFAtz3TPW0GXJuLBJPts1E241iHg+VRfhg==", + "dev": true, + "dependencies": { + "@tootallnate/once": "1", + "data-uri-to-buffer": "3", + "debug": "4", + "file-uri-to-path": "2", + "fs-extra": "^8.1.0", + "ftp": "^0.3.10" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.9", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", + "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", + "dev": true + }, + "node_modules/http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "dev": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "dev": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", + "dev": true + }, + "node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/netmask": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", + "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/pac-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-5.0.0.tgz", + "integrity": "sha512-CcFG3ZtnxO8McDigozwE3AqAw15zDvGH+OjXO4kzf7IkEKkQ4gxQ+3sdF50WmhQ4P/bVusXcqNE2S3XrNURwzQ==", + "dev": true, + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4", + "get-uri": "3", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "5", + "pac-resolver": "^5.0.0", + "raw-body": "^2.2.0", + "socks-proxy-agent": "5" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/pac-resolver": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-5.0.0.tgz", + "integrity": "sha512-H+/A6KitiHNNW+bxBKREk2MCGSxljfqRX76NjummWEYIat7ldVXRU3dhRIE3iXZ0nvGBk6smv3nntxKkzRL8NA==", + "dev": true, + "dependencies": { + "degenerator": "^3.0.1", + "ip": "^1.1.5", + "netmask": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-5.0.0.tgz", + "integrity": "sha512-gkH7BkvLVkSfX9Dk27W6TyNOWWZWRilRfk1XxGNWOYJ2TuedAv1yFpCaU9QSBmBe716XOTNpYNOzhysyw8xn7g==", + "dev": true, + "dependencies": { + "agent-base": "^6.0.0", + "debug": "4", + "http-proxy-agent": "^4.0.0", + "https-proxy-agent": "^5.0.0", + "lru-cache": "^5.1.1", + "pac-proxy-agent": "^5.0.0", + "proxy-from-env": "^1.0.0", + "socks-proxy-agent": "^5.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true + }, + "node_modules/raw-body": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.2.tgz", + "integrity": "sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ==", + "dev": true, + "dependencies": { + "bytes": "3.1.1", + "http-errors": "1.8.1", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "dev": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.1.tgz", + "integrity": "sha512-kLQ9N5ucj8uIcxrDwjm0Jsqk06xdpBjGNQtpXy4Q8/QY2k+fY7nZH8CARy+hkbG+SGAovmzzuauCpBlb8FrnBA==", + "dev": true, + "dependencies": { + "ip": "^1.1.5", + "smart-buffer": "^4.1.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-5.0.1.tgz", + "integrity": "sha512-vZdmnjb9a2Tz6WEQVIurybSwElwPxMZaIc7PzqbJTrezcKNznv6giT7J7tZDZ1BojVaa1jvO/UiUdhDVB0ACoQ==", + "dev": true, + "dependencies": { + "agent-base": "^6.0.2", + "debug": "4", + "socks": "^2.3.3" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", + "dev": true + }, + "node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vm2": { + "version": "3.9.8", + "resolved": "https://registry.npmjs.org/vm2/-/vm2-3.9.8.tgz", + "integrity": "sha512-/1PYg/BwdKzMPo8maOZ0heT7DLI0DAFTm7YQaz/Lim9oIaFZsJs3EdtalvXuBfZwczNwsYhju75NW4d6E+4q+w==", + "dev": true, + "dependencies": { + "acorn": "^8.7.0", + "acorn-walk": "^8.2.0" + }, + "bin": { + "vm2": "bin/vm2" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/xregexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", + "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + }, + "dependencies": { + "@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true + }, + "acorn": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", + "dev": true + }, + "acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true + }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "requires": { + "debug": "4" + } + }, + "ast-types": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", + "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", + "dev": true, + "requires": { + "tslib": "^2.0.1" + } + }, + "bytes": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.1.tgz", + "integrity": "sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg==", + "dev": true + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "data-uri-to-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz", + "integrity": "sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==", + "dev": true + }, + "debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "degenerator": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-3.0.1.tgz", + "integrity": "sha512-LFsIFEeLPlKvAKXu7j3ssIG6RT0TbI7/GhsqrI0DnHASEQjXQ0LUSYcjJteGgRGmZbl1TnMSxpNQIAiJ7Du5TQ==", + "dev": true, + "requires": { + "ast-types": "^0.13.2", + "escodegen": "^1.8.1", + "esprima": "^4.0.0", + "vm2": "^3.9.3" + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "escodegen": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", + "dev": true, + "requires": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "file-uri-to-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-2.0.0.tgz", + "integrity": "sha512-hjPFI8oE/2iQPVe4gbrJ73Pp+Xfub2+WI2LlXDbsaJBwT5wuMh35WNWVYYTpnz895shtwfyutMFLFywpQAFdLg==", + "dev": true + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "ftp": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", + "integrity": "sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=", + "dev": true, + "requires": { + "readable-stream": "1.1.x", + "xregexp": "2.0.0" + } + }, + "get-uri": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-3.0.2.tgz", + "integrity": "sha512-+5s0SJbGoyiJTZZ2JTpFPLMPSch72KEqGOTvQsBqg0RBWvwhWUSYZFAtz3TPW0GXJuLBJPts1E241iHg+VRfhg==", + "dev": true, + "requires": { + "@tootallnate/once": "1", + "data-uri-to-buffer": "3", + "debug": "4", + "file-uri-to-path": "2", + "fs-extra": "^8.1.0", + "ftp": "^0.3.10" + } + }, + "graceful-fs": { + "version": "4.2.9", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", + "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", + "dev": true + }, + "http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + } + }, + "http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + } + }, + "https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "netmask": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", + "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", + "dev": true + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "pac-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-5.0.0.tgz", + "integrity": "sha512-CcFG3ZtnxO8McDigozwE3AqAw15zDvGH+OjXO4kzf7IkEKkQ4gxQ+3sdF50WmhQ4P/bVusXcqNE2S3XrNURwzQ==", + "dev": true, + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4", + "get-uri": "3", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "5", + "pac-resolver": "^5.0.0", + "raw-body": "^2.2.0", + "socks-proxy-agent": "5" + } + }, + "pac-resolver": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-5.0.0.tgz", + "integrity": "sha512-H+/A6KitiHNNW+bxBKREk2MCGSxljfqRX76NjummWEYIat7ldVXRU3dhRIE3iXZ0nvGBk6smv3nntxKkzRL8NA==", + "dev": true, + "requires": { + "degenerator": "^3.0.1", + "ip": "^1.1.5", + "netmask": "^2.0.1" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-5.0.0.tgz", + "integrity": "sha512-gkH7BkvLVkSfX9Dk27W6TyNOWWZWRilRfk1XxGNWOYJ2TuedAv1yFpCaU9QSBmBe716XOTNpYNOzhysyw8xn7g==", + "dev": true, + "requires": { + "agent-base": "^6.0.0", + "debug": "4", + "http-proxy-agent": "^4.0.0", + "https-proxy-agent": "^5.0.0", + "lru-cache": "^5.1.1", + "pac-proxy-agent": "^5.0.0", + "proxy-from-env": "^1.0.0", + "socks-proxy-agent": "^5.0.0" + } + }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true + }, + "raw-body": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.2.tgz", + "integrity": "sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ==", + "dev": true, + "requires": { + "bytes": "3.1.1", + "http-errors": "1.8.1", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true + }, + "smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "dev": true + }, + "socks": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.1.tgz", + "integrity": "sha512-kLQ9N5ucj8uIcxrDwjm0Jsqk06xdpBjGNQtpXy4Q8/QY2k+fY7nZH8CARy+hkbG+SGAovmzzuauCpBlb8FrnBA==", + "dev": true, + "requires": { + "ip": "^1.1.5", + "smart-buffer": "^4.1.0" + } + }, + "socks-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-5.0.1.tgz", + "integrity": "sha512-vZdmnjb9a2Tz6WEQVIurybSwElwPxMZaIc7PzqbJTrezcKNznv6giT7J7tZDZ1BojVaa1jvO/UiUdhDVB0ACoQ==", + "dev": true, + "requires": { + "agent-base": "^6.0.2", + "debug": "4", + "socks": "^2.3.3" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true + }, + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", + "dev": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true + }, + "vm2": { + "version": "3.9.8", + "resolved": "https://registry.npmjs.org/vm2/-/vm2-3.9.8.tgz", + "integrity": "sha512-/1PYg/BwdKzMPo8maOZ0heT7DLI0DAFTm7YQaz/Lim9oIaFZsJs3EdtalvXuBfZwczNwsYhju75NW4d6E+4q+w==", + "dev": true, + "requires": { + "acorn": "^8.7.0", + "acorn-walk": "^8.2.0" + } + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, + "xregexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", + "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=", + "dev": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } +} diff --git a/packages/@aws-cdk/lambda-layer-node-proxy-agent/layer/package.json b/packages/@aws-cdk/lambda-layer-node-proxy-agent/layer/package.json new file mode 100644 index 0000000000000..d6e8118c9b4df --- /dev/null +++ b/packages/@aws-cdk/lambda-layer-node-proxy-agent/layer/package.json @@ -0,0 +1,12 @@ +{ + "name": "proxy-agent-layer", + "private": true, + "version": "0.0.0", + "description": "", + "devDependencies": { + "proxy-agent": "^5.0.0" + }, + "keywords": [], + "author": "", + "license": "ISC" +} diff --git a/packages/@aws-cdk/lambda-layer-node-proxy-agent/package.json b/packages/@aws-cdk/lambda-layer-node-proxy-agent/package.json index 146f31a109482..8f0dfffef911b 100644 --- a/packages/@aws-cdk/lambda-layer-node-proxy-agent/package.json +++ b/packages/@aws-cdk/lambda-layer-node-proxy-agent/package.json @@ -77,7 +77,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/pipelines/README.md b/packages/@aws-cdk/pipelines/README.md index 09679d761cb09..8571bd5cf2576 100644 --- a/packages/@aws-cdk/pipelines/README.md +++ b/packages/@aws-cdk/pipelines/README.md @@ -150,21 +150,9 @@ pipeline will automatically reconfigure itself to deploy those new stages and stacks. (Note that have to *bootstrap* all environments before the above code -will work, see the section **CDK Environment Bootstrapping** below). - -## CDK Versioning - -This library uses prerelease features of the CDK framework, which can be enabled -by adding the following to `cdk.json`: - -```js -{ - // ... - "context": { - "@aws-cdk/core:newStyleStackSynthesis": true - } -} -``` +will work, and switch on "Modern synthesis" if you are using +CDKv1. See the section **CDK Environment Bootstrapping** below for +more information). ## Provisioning the pipeline @@ -350,6 +338,40 @@ const pipeline = new pipelines.CodePipeline(this, 'Pipeline', { You can adapt these examples to your own situation. +#### Migrating from buildspec.yml files + +You may currently have the build instructions for your CodeBuild Projects in a +`buildspec.yml` file in your source repository. In addition to your build +commands, the CodeBuild Project's buildspec also controls some information that +CDK Pipelines manages for you, like artifact identifiers, input artifact +locations, Docker authorization, and exported variables. + +Since there is no way in general for CDK Pipelines to modify the file in your +resource repository, CDK Pipelines configures the BuildSpec directly on the +CodeBuild Project, instead of loading it from the `buildspec.yml` file. +This requires a pipeline self-mutation to update. + +To avoid this, put your build instructions in a separate script, for example +`build.sh`, and call that script from the build `commands` array: + +```ts +declare const source: pipelines.IFileSetProducer; + +const pipeline = new pipelines.CodePipeline(this, 'Pipeline', { + synth: new pipelines.ShellStep('Synth', { + input: source, + commands: [ + // Abstract over doing the build + './build.sh', + ], + }) +}); +``` + +Doing so keeps your exact build instructions in sync with your source code in +the source repository where it belongs, and provides a convenient build script +for developers at the same time. + #### CodePipeline Sources In CodePipeline, *Sources* define where the source of your application lives. @@ -404,6 +426,16 @@ const bucket = s3.Bucket.fromBucketName(this, 'Bucket', 'my-bucket'); pipelines.CodePipelineSource.s3(bucket, 'my/source.zip'); ``` +##### ECR + +You can use a Docker image in ECR as the source of the pipeline. The pipeline will be +triggered every time an image is pushed to ECR: + +```ts +const repository = new ecr.Repository(this, 'Repository'); +pipelines.CodePipelineSource.ecr(repository); +``` + #### Additional inputs `ShellStep` allows passing in more than one input: additional @@ -768,6 +800,13 @@ class MyJenkinsStep extends pipelines.Step implements pipelines.ICodePipelineAct private readonly input: pipelines.FileSet, ) { super('MyJenkinsStep'); + + // This is necessary if your step accepts things like environment variables + // that may contain outputs from other steps. It doesn't matter what the + // structure is, as long as it contains the values that may contain outputs. + this.discoverReferencedOutputs({ + env: { /* ... */ } + }); } public produceAction(stage: codepipeline.IStage, options: pipelines.ProduceActionOptions): pipelines.CodePipelineActionFactoryResult { diff --git a/packages/@aws-cdk/pipelines/lib/blueprint/manual-approval.ts b/packages/@aws-cdk/pipelines/lib/blueprint/manual-approval.ts index 859c279533fa3..31b93f5b9cf87 100644 --- a/packages/@aws-cdk/pipelines/lib/blueprint/manual-approval.ts +++ b/packages/@aws-cdk/pipelines/lib/blueprint/manual-approval.ts @@ -33,5 +33,7 @@ export class ManualApprovalStep extends Step { super(id); this.comment = props.comment; + + this.discoverReferencedOutputs(props.comment); } } \ No newline at end of file diff --git a/packages/@aws-cdk/pipelines/lib/blueprint/shell-step.ts b/packages/@aws-cdk/pipelines/lib/blueprint/shell-step.ts index d36f0999fca17..fa01624e9635a 100644 --- a/packages/@aws-cdk/pipelines/lib/blueprint/shell-step.ts +++ b/packages/@aws-cdk/pipelines/lib/blueprint/shell-step.ts @@ -87,7 +87,6 @@ export interface ShellStepProps { * @default - No primary output */ readonly primaryOutputDirectory?: string; - } /** @@ -152,6 +151,11 @@ export class ShellStep extends Step { this.env = props.env ?? {}; this.envFromCfnOutputs = mapValues(props.envFromCfnOutputs ?? {}, StackOutputReference.fromCfnOutput); + // 'env' is the only thing that can contain outputs + this.discoverReferencedOutputs({ + env: this.env, + }); + // Inputs if (props.input) { const fileSet = props.input.primaryOutput; diff --git a/packages/@aws-cdk/pipelines/lib/blueprint/step.ts b/packages/@aws-cdk/pipelines/lib/blueprint/step.ts index 65f4636b2ecbc..c17402f22e850 100644 --- a/packages/@aws-cdk/pipelines/lib/blueprint/step.ts +++ b/packages/@aws-cdk/pipelines/lib/blueprint/step.ts @@ -1,4 +1,5 @@ import { Stack, Token } from '@aws-cdk/core'; +import { StepOutput } from '../helpers-internal/step-output'; import { FileSet, IFileSetProducer } from './file-set'; /** @@ -39,7 +40,7 @@ export abstract class Step implements IFileSetProducer { private _primaryOutput?: FileSet; - private _dependencies: Step[] = []; + private _dependencies = new Set(); constructor( /** Identifier for this step */ @@ -54,7 +55,10 @@ export abstract class Step implements IFileSetProducer { * Return the steps this step depends on, based on the FileSets it requires */ public get dependencies(): Step[] { - return this.dependencyFileSets.map(f => f.producer).concat(this._dependencies); + return Array.from(new Set([ + ...this.dependencyFileSets.map(f => f.producer), + ...this._dependencies, + ])); } /** @@ -79,7 +83,7 @@ export abstract class Step implements IFileSetProducer { * Add a dependency on another step. */ public addStepDependency(step: Step) { - this._dependencies.push(step); + this._dependencies.add(step); } /** @@ -97,6 +101,21 @@ export abstract class Step implements IFileSetProducer { protected configurePrimaryOutput(fs: FileSet) { this._primaryOutput = fs; } + + /** + * Crawl the given structure for references to StepOutputs and add dependencies on all steps found + * + * Should be called by subclasses based on what the user passes in as + * construction properties. The format of the structure passed in here does + * not have to correspond exactly to what gets rendered into the engine, it + * just needs to contain the same amount of data. + */ + protected discoverReferencedOutputs(structure: any) { + for (const output of StepOutput.findAll(structure)) { + this._dependencies.add(output.step); + StepOutput.recordProducer(output); + } + } } /** @@ -128,5 +147,4 @@ export interface StackSteps { * @default - no additional steps */ readonly post?: Step[]; - } \ No newline at end of file diff --git a/packages/@aws-cdk/pipelines/lib/codepipeline/codebuild-step.ts b/packages/@aws-cdk/pipelines/lib/codepipeline/codebuild-step.ts index f835e261aba3d..c50d715e2cbe9 100644 --- a/packages/@aws-cdk/pipelines/lib/codepipeline/codebuild-step.ts +++ b/packages/@aws-cdk/pipelines/lib/codepipeline/codebuild-step.ts @@ -1,8 +1,10 @@ -import { Duration } from '@aws-cdk/core'; import * as codebuild from '@aws-cdk/aws-codebuild'; import * as ec2 from '@aws-cdk/aws-ec2'; import * as iam from '@aws-cdk/aws-iam'; +import { Duration } from '@aws-cdk/core'; import { ShellStep, ShellStepProps } from '../blueprint'; +import { mergeBuildSpecs } from './private/buildspecs'; +import { makeCodePipelineOutput } from './private/outputs'; /** * Construction props for a CodeBuildStep @@ -96,6 +98,17 @@ export interface CodeBuildStepProps extends ShellStepProps { /** * Run a script as a CodeBuild Project + * + * The BuildSpec must be available inline--it cannot reference a file + * on disk. If your current build instructions are in a file like + * `buildspec.yml` in your repository, extract them to a script + * (say, `build.sh`) and invoke that script as part of the build: + * + * ```ts + * new pipelines.CodeBuildStep('Synth', { + * commands: ['./build.sh'], + * }); + * ``` */ export class CodeBuildStep extends ShellStep { /** @@ -105,13 +118,6 @@ export class CodeBuildStep extends ShellStep { */ public readonly projectName?: string; - /** - * Additional configuration that can only be configured via BuildSpec - * - * @default - No value specified at construction time, use defaults - */ - public readonly partialBuildSpec?: codebuild.BuildSpec; - /** * The VPC where to execute the SimpleSynth. * @@ -164,13 +170,16 @@ export class CodeBuildStep extends ShellStep { readonly timeout?: Duration; private _project?: codebuild.IProject; + private _partialBuildSpec?: codebuild.BuildSpec; + private readonly exportedVariables = new Set(); + private exportedVarsRendered = false; constructor(id: string, props: CodeBuildStepProps) { super(id, props); this.projectName = props.projectName; this.buildEnvironment = props.buildEnvironment; - this.partialBuildSpec = props.partialBuildSpec; + this._partialBuildSpec = props.partialBuildSpec; this.vpc = props.vpc; this.subnetSelection = props.subnetSelection; this.role = props.role; @@ -198,6 +207,44 @@ export class CodeBuildStep extends ShellStep { return this.project.grantPrincipal; } + /** + * Additional configuration that can only be configured via BuildSpec + * + * Contains exported variables + * + * @default - Contains the exported variables + */ + public get partialBuildSpec(): codebuild.BuildSpec | undefined { + this.exportedVarsRendered = true; + + const varsBuildSpec = this.exportedVariables.size > 0 ? codebuild.BuildSpec.fromObject({ + version: '0.2', + env: { + 'exported-variables': Array.from(this.exportedVariables), + }, + }) : undefined; + + return mergeBuildSpecs(varsBuildSpec, this._partialBuildSpec); + } + + /** + * Reference a CodePipeline variable defined by the CodeBuildStep. + * + * The variable must be set in the shell of the CodeBuild step when + * it finishes its `post_build` phase. + * + * @param variableName the name of the variable for reference. + */ + public exportedVariable(variableName: string): string { + if (this.exportedVarsRendered && !this.exportedVariables.has(variableName)) { + throw new Error('exportVariable(): Pipeline has already been produced, cannot call this function anymore'); + } + + this.exportedVariables.add(variableName); + + return makeCodePipelineOutput(this, variableName); + } + /** * Set the internal project value * diff --git a/packages/@aws-cdk/pipelines/lib/codepipeline/codepipeline-action-factory.ts b/packages/@aws-cdk/pipelines/lib/codepipeline/codepipeline-action-factory.ts index 62c9fa86d025b..734c2fefa0128 100644 --- a/packages/@aws-cdk/pipelines/lib/codepipeline/codepipeline-action-factory.ts +++ b/packages/@aws-cdk/pipelines/lib/codepipeline/codepipeline-action-factory.ts @@ -23,6 +23,15 @@ export interface ProduceActionOptions { */ readonly runOrder: number; + /** + * If this step is producing outputs, the variables namespace assigned to it + * + * Pass this on to the Action you are creating. + * + * @default - Step doesn't produce any outputs + */ + readonly variablesNamespace?: string; + /** * Helper object to translate FileSets to CodePipeline Artifacts */ @@ -87,6 +96,8 @@ export interface ICodePipelineActionFactory { export interface CodePipelineActionFactoryResult { /** * How many RunOrders were consumed + * + * If you add 1 action, return the value 1 here. */ readonly runOrdersConsumed: number; diff --git a/packages/@aws-cdk/pipelines/lib/codepipeline/codepipeline-source.ts b/packages/@aws-cdk/pipelines/lib/codepipeline/codepipeline-source.ts index dd40d0d6cf0e7..0f95d41f5c940 100644 --- a/packages/@aws-cdk/pipelines/lib/codepipeline/codepipeline-source.ts +++ b/packages/@aws-cdk/pipelines/lib/codepipeline/codepipeline-source.ts @@ -3,12 +3,14 @@ import * as cp from '@aws-cdk/aws-codepipeline'; import { Artifact } from '@aws-cdk/aws-codepipeline'; import * as cp_actions from '@aws-cdk/aws-codepipeline-actions'; import { Action, CodeCommitTrigger, GitHubTrigger, S3Trigger } from '@aws-cdk/aws-codepipeline-actions'; +import { IRepository } from '@aws-cdk/aws-ecr'; import * as iam from '@aws-cdk/aws-iam'; import { IBucket } from '@aws-cdk/aws-s3'; -import { SecretValue, Token } from '@aws-cdk/core'; +import { Fn, SecretValue, Token } from '@aws-cdk/core'; import { Node } from 'constructs'; import { FileSet, Step } from '../blueprint'; import { CodePipelineActionFactoryResult, ProduceActionOptions, ICodePipelineActionFactory } from './codepipeline-action-factory'; +import { makeCodePipelineOutput } from './private/outputs'; /** * Factory for CodePipeline source steps @@ -56,6 +58,22 @@ export abstract class CodePipelineSource extends Step implements ICodePipelineAc return new S3Source(bucket, objectKey, props); } + /** + * Returns an ECR source. + * + * @param repository The repository that will be watched for changes. + * @param props The options, which include the image tag to be checked for changes. + * + * @example + * declare const repository: ecr.IRepository; + * pipelines.CodePipelineSource.ecr(repository, { + * imageTag: 'latest', + * }); + */ + public static ecr(repository: IRepository, props: ECRSourceOptions = {}): CodePipelineSource { + return new ECRSource(repository, props); + } + /** * Returns a CodeStar connection source. A CodeStar connection allows AWS CodePipeline to * access external resources, such as repositories in GitHub, GitHub Enterprise or @@ -104,12 +122,50 @@ export abstract class CodePipelineSource extends Step implements ICodePipelineAc public produceAction(stage: cp.IStage, options: ProduceActionOptions): CodePipelineActionFactoryResult { const output = options.artifacts.toCodePipeline(this.primaryOutput!); - const action = this.getAction(output, options.actionName, options.runOrder); + + const action = this.getAction(output, options.actionName, options.runOrder, options.variablesNamespace); stage.addAction(action); return { runOrdersConsumed: 1 }; } - protected abstract getAction(output: Artifact, actionName: string, runOrder: number): Action; + protected abstract getAction(output: Artifact, actionName: string, runOrder: number, variablesNamespace?: string): Action; + + /** + * Return an attribute of the current source revision + * + * These values can be passed into the environment variables of pipeline steps, + * so your steps can access information about the source revision. + * + * What attributes are available depends on the type of source. These attributes + * are supported: + * + * - GitHub, CodeCommit, and CodeStarSourceConnection + * - `AuthorDate` + * - `BranchName` + * - `CommitId` + * - `CommitMessage` + * - GitHub, CodeCommit and ECR + * - `RepositoryName` + * - GitHub and CodeCommit + * - `CommitterDate` + * - GitHub + * - `CommitUrl` + * - CodeStarSourceConnection + * - `FullRepositoryName` + * - S3 + * - `ETag` + * - `VersionId` + * - ECR + * - `ImageDigest` + * - `ImageTag` + * - `ImageURI` + * - `RegistryId` + * + * @see https://docs.aws.amazon.com/codepipeline/latest/userguide/reference-variables.html#reference-variables-list + */ + public sourceAttribute(name: string): string { + return makeCodePipelineOutput(this, name); + } } /** @@ -173,7 +229,7 @@ class GitHubSource extends CodePipelineSource { this.configurePrimaryOutput(new FileSet('Source', this)); } - protected getAction(output: Artifact, actionName: string, runOrder: number) { + protected getAction(output: Artifact, actionName: string, runOrder: number, variablesNamespace?: string) { return new cp_actions.GitHubSourceAction({ output, actionName, @@ -183,6 +239,7 @@ class GitHubSource extends CodePipelineSource { repo: this.repo, branch: this.branch, trigger: this.props.trigger, + variablesNamespace, }); } } @@ -216,7 +273,7 @@ class S3Source extends CodePipelineSource { this.configurePrimaryOutput(new FileSet('Source', this)); } - protected getAction(output: Artifact, _actionName: string, runOrder: number) { + protected getAction(output: Artifact, _actionName: string, runOrder: number, variablesNamespace?: string) { return new cp_actions.S3SourceAction({ output, // Bucket names are guaranteed to conform to ActionName restrictions @@ -225,6 +282,47 @@ class S3Source extends CodePipelineSource { bucketKey: this.objectKey, trigger: this.props.trigger, bucket: this.bucket, + variablesNamespace, + }); + } +} + +/** + * Options for ECR sources + */ +export interface ECRSourceOptions { + /** + * The image tag that will be checked for changes. + * + * @default latest + */ + readonly imageTag?: string; + + /** + * The action name used for this source in the CodePipeline + * + * @default - The repository name + */ + readonly actionName?: string; +} + +class ECRSource extends CodePipelineSource { + constructor(readonly repository: IRepository, readonly props: ECRSourceOptions) { + super(Node.of(repository).addr); + + this.configurePrimaryOutput(new FileSet('Source', this)); + } + + protected getAction(output: Artifact, _actionName: string, runOrder: number, variablesNamespace: string) { + // RepositoryName can contain '/' that is not a valid ActionName character, use '_' instead + const formattedRepositoryName = Fn.join('_', Fn.split('/', this.repository.repositoryName)); + return new cp_actions.EcrSourceAction({ + output, + actionName: this.props.actionName ?? formattedRepositoryName, + runOrder, + repository: this.repository, + imageTag: this.props.imageTag, + variablesNamespace, }); } } @@ -284,7 +382,7 @@ class CodeStarConnectionSource extends CodePipelineSource { this.configurePrimaryOutput(new FileSet('Source', this)); } - protected getAction(output: Artifact, actionName: string, runOrder: number) { + protected getAction(output: Artifact, actionName: string, runOrder: number, variablesNamespace?: string) { return new cp_actions.CodeStarConnectionsSourceAction({ output, actionName, @@ -295,6 +393,7 @@ class CodeStarConnectionSource extends CodePipelineSource { branch: this.branch, codeBuildCloneOutput: this.props.codeBuildCloneOutput, triggerOnPush: this.props.triggerOnPush, + variablesNamespace, }); } } @@ -341,7 +440,7 @@ class CodeCommitSource extends CodePipelineSource { this.configurePrimaryOutput(new FileSet('Source', this)); } - protected getAction(output: Artifact, _actionName: string, runOrder: number) { + protected getAction(output: Artifact, _actionName: string, runOrder: number, variablesNamespace?: string) { return new cp_actions.CodeCommitSourceAction({ output, // Guaranteed to be okay as action name @@ -352,6 +451,7 @@ class CodeCommitSource extends CodePipelineSource { repository: this.repository, eventRole: this.props.eventRole, codeBuildCloneOutput: this.props.codeBuildCloneOutput, + variablesNamespace, }); } } diff --git a/packages/@aws-cdk/pipelines/lib/codepipeline/codepipeline.ts b/packages/@aws-cdk/pipelines/lib/codepipeline/codepipeline.ts index 0beae3ea56fa1..84562b07aec8b 100644 --- a/packages/@aws-cdk/pipelines/lib/codepipeline/codepipeline.ts +++ b/packages/@aws-cdk/pipelines/lib/codepipeline/codepipeline.ts @@ -18,10 +18,11 @@ import { toPosixPath } from '../private/fs'; import { actionName, stackVariableNamespace } from '../private/identifiers'; import { enumerate, flatten, maybeSuffix, noUndefined } from '../private/javascript'; import { writeTemplateConfiguration } from '../private/template-configuration'; -import { CodeBuildFactory, mergeCodeBuildOptions } from './_codebuild-factory'; import { ArtifactMap } from './artifact-map'; import { CodeBuildStep } from './codebuild-step'; import { CodePipelineActionFactoryResult, ICodePipelineActionFactory } from './codepipeline-action-factory'; +import { CodeBuildFactory, mergeCodeBuildOptions } from './private/codebuild-factory'; +import { namespaceStepOutputs } from './private/outputs'; /** @@ -418,9 +419,14 @@ export class CodePipeline extends PipelineBase { const factory = this.actionFromNode(node); const nodeType = this.nodeTypeFromNode(node); + const name = actionName(node, sharedParent); + + const variablesNamespace = node.data?.type === 'step' + ? namespaceStepOutputs(node.data.step, pipelineStage, name) + : undefined; const result = factory.produceAction(pipelineStage, { - actionName: actionName(node, sharedParent), + actionName: name, runOrder, artifacts: this.artifacts, scope: obtainScope(this.pipeline, stageName), @@ -429,6 +435,7 @@ export class CodePipeline extends PipelineBase { // If this step happens to produce a CodeBuild job, set the default options codeBuildDefaults: nodeType ? this.codeBuildDefaultsFor(nodeType) : undefined, beforeSelfMutation, + variablesNamespace, }); if (node.data?.type === 'self-update') { diff --git a/packages/@aws-cdk/pipelines/lib/codepipeline/private/buildspecs.ts b/packages/@aws-cdk/pipelines/lib/codepipeline/private/buildspecs.ts new file mode 100644 index 0000000000000..f904d7c174629 --- /dev/null +++ b/packages/@aws-cdk/pipelines/lib/codepipeline/private/buildspecs.ts @@ -0,0 +1,10 @@ +import * as codebuild from '@aws-cdk/aws-codebuild'; + +export function mergeBuildSpecs(a: codebuild.BuildSpec, b?: codebuild.BuildSpec): codebuild.BuildSpec; +export function mergeBuildSpecs(a: codebuild.BuildSpec | undefined, b: codebuild.BuildSpec): codebuild.BuildSpec; +export function mergeBuildSpecs(a?: codebuild.BuildSpec, b?: codebuild.BuildSpec): codebuild.BuildSpec | undefined; +export function mergeBuildSpecs(a?: codebuild.BuildSpec, b?: codebuild.BuildSpec) { + if (!a || !b) { return a ?? b; } + return codebuild.mergeBuildSpecs(a, b); +} + diff --git a/packages/@aws-cdk/pipelines/lib/codepipeline/_codebuild-factory.ts b/packages/@aws-cdk/pipelines/lib/codepipeline/private/codebuild-factory.ts similarity index 94% rename from packages/@aws-cdk/pipelines/lib/codepipeline/_codebuild-factory.ts rename to packages/@aws-cdk/pipelines/lib/codepipeline/private/codebuild-factory.ts index 3414554cd5197..84a0cf934a4ca 100644 --- a/packages/@aws-cdk/pipelines/lib/codepipeline/_codebuild-factory.ts +++ b/packages/@aws-cdk/pipelines/lib/codepipeline/private/codebuild-factory.ts @@ -7,15 +7,17 @@ import * as ec2 from '@aws-cdk/aws-ec2'; import * as iam from '@aws-cdk/aws-iam'; import { IDependable, Stack, Token } from '@aws-cdk/core'; import { Construct, Node } from 'constructs'; -import { FileSetLocation, ShellStep, StackOutputReference } from '../blueprint'; -import { PipelineQueries } from '../helpers-internal/pipeline-queries'; -import { cloudAssemblyBuildSpecDir, obtainScope } from '../private/construct-internals'; -import { hash, stackVariableNamespace } from '../private/identifiers'; -import { mapValues, mkdict, noEmptyObject, noUndefined, partition } from '../private/javascript'; -import { ArtifactMap } from './artifact-map'; -import { CodeBuildStep } from './codebuild-step'; -import { CodeBuildOptions } from './codepipeline'; -import { ICodePipelineActionFactory, ProduceActionOptions, CodePipelineActionFactoryResult } from './codepipeline-action-factory'; +import { FileSetLocation, ShellStep, StackOutputReference } from '../../blueprint'; +import { PipelineQueries } from '../../helpers-internal/pipeline-queries'; +import { StepOutput } from '../../helpers-internal/step-output'; +import { cloudAssemblyBuildSpecDir, obtainScope } from '../../private/construct-internals'; +import { hash, stackVariableNamespace } from '../../private/identifiers'; +import { mapValues, mkdict, noEmptyObject, noUndefined, partition } from '../../private/javascript'; +import { ArtifactMap } from '../artifact-map'; +import { CodeBuildStep } from '../codebuild-step'; +import { CodeBuildOptions } from '../codepipeline'; +import { ICodePipelineActionFactory, ProduceActionOptions, CodePipelineActionFactoryResult } from '../codepipeline-action-factory'; +import { mergeBuildSpecs } from './buildspecs'; export interface CodeBuildFactoryProps { /** @@ -110,6 +112,11 @@ export interface CodeBuildFactoryProps { * @default false */ readonly isSynth?: boolean; + + /** + * StepOutputs produced by this CodeBuild step + */ + readonly producedStepOutputs?: StepOutput[]; } /** @@ -129,6 +136,7 @@ export class CodeBuildFactory implements ICodePipelineActionFactory { outputs: shellStep.outputs, stepId: shellStep.id, installCommands: shellStep.installCommands, + producedStepOutputs: StepOutput.producedStepOutputs(shellStep), ...additional, }); } @@ -314,6 +322,7 @@ export class CodeBuildFactory implements ICodePipelineActionFactory { outputs: outputArtifacts, project, runOrder: options.runOrder, + variablesNamespace: options.variablesNamespace, // Inclusion of the hash here will lead to the pipeline structure for any changes // made the config of the underlying CodeBuild Project. @@ -421,14 +430,6 @@ function mergeBuildEnvironments(a?: codebuild.BuildEnvironment, b?: codebuild.Bu }; } -export function mergeBuildSpecs(a: codebuild.BuildSpec, b?: codebuild.BuildSpec): codebuild.BuildSpec; -export function mergeBuildSpecs(a: codebuild.BuildSpec | undefined, b: codebuild.BuildSpec): codebuild.BuildSpec; -export function mergeBuildSpecs(a?: codebuild.BuildSpec, b?: codebuild.BuildSpec): codebuild.BuildSpec | undefined; -export function mergeBuildSpecs(a?: codebuild.BuildSpec, b?: codebuild.BuildSpec) { - if (!a || !b) { return a ?? b; } - return codebuild.mergeBuildSpecs(a, b); -} - function isDefined(x: A | undefined): x is NonNullable { return x !== undefined; } @@ -452,7 +453,7 @@ function serializeBuildEnvironment(env: codebuild.BuildEnvironment) { * Whether the given string contains a reference to a CodePipeline variable */ function containsPipelineVariable(s: string) { - return !!s.match(/#\{[^}]+\}/); + return !!s.match(/#\{[^}]+\}/) || StepOutput.findAll(s).length > 0; } /** @@ -507,4 +508,4 @@ function filterBuildSpecCommands(buildSpec: codebuild.BuildSpec, osType: ec2.Ope } return [undefined, x]; } -} \ No newline at end of file +} diff --git a/packages/@aws-cdk/pipelines/lib/codepipeline/private/outputs.ts b/packages/@aws-cdk/pipelines/lib/codepipeline/private/outputs.ts new file mode 100644 index 0000000000000..f721cb3e5212e --- /dev/null +++ b/packages/@aws-cdk/pipelines/lib/codepipeline/private/outputs.ts @@ -0,0 +1,38 @@ +import * as cp from '@aws-cdk/aws-codepipeline'; +import { Step } from '../../blueprint/step'; +import { StepOutput } from '../../helpers-internal'; + +const CODEPIPELINE_ENGINE_NAME = 'codepipeline'; + +export function makeCodePipelineOutput(step: Step, variableName: string) { + return new StepOutput(step, CODEPIPELINE_ENGINE_NAME, variableName).toString(); +} + +/** + * If the step is producing outputs, determine a variableNamespace for it, and configure that on the outputs + */ +export function namespaceStepOutputs(step: Step, stage: cp.IStage, name: string): string | undefined { + let ret: string | undefined; + for (const output of StepOutput.producedStepOutputs(step)) { + ret = namespaceName(stage, name); + if (output.engineName !== CODEPIPELINE_ENGINE_NAME) { + throw new Error(`Found unrecognized output type: ${output.engineName}`); + } + + if (typeof output.engineSpecificInformation !== 'string') { + throw new Error(`CodePipeline requires that 'engineSpecificInformation' is a string, got: ${JSON.stringify(output.engineSpecificInformation)}`); + } + output.defineResolution(`#{${ret}.${output.engineSpecificInformation}}`); + } + return ret; +} + +/** + * Generate a variable namespace from stage and action names + * + * Variable namespaces cannot have '.', but they can have '@'. Other than that, + * action names are more limited so they translate easily. + */ +export function namespaceName(stage: cp.IStage, name: string) { + return `${stage.stageName}/${name}`.replace(/[^a-zA-Z0-9@_-]/g, '@'); +} \ No newline at end of file diff --git a/packages/@aws-cdk/pipelines/lib/helpers-internal/index.ts b/packages/@aws-cdk/pipelines/lib/helpers-internal/index.ts index 6709f7c84488f..8f081e10d88d8 100644 --- a/packages/@aws-cdk/pipelines/lib/helpers-internal/index.ts +++ b/packages/@aws-cdk/pipelines/lib/helpers-internal/index.ts @@ -1,2 +1,3 @@ export * from './pipeline-graph'; -export * from './graph'; \ No newline at end of file +export * from './graph'; +export * from './step-output'; \ No newline at end of file diff --git a/packages/@aws-cdk/pipelines/lib/helpers-internal/step-output.ts b/packages/@aws-cdk/pipelines/lib/helpers-internal/step-output.ts new file mode 100644 index 0000000000000..eb71485184f68 --- /dev/null +++ b/packages/@aws-cdk/pipelines/lib/helpers-internal/step-output.ts @@ -0,0 +1,160 @@ +import { IResolvable, IResolveContext, Token, Tokenization } from '@aws-cdk/core'; +import { Step } from '../blueprint/step'; + + +const STEP_OUTPUT_SYM = Symbol.for('@aws-cdk/pipelines.StepOutput'); + +const PRODUCED_OUTPUTS_SYM = Symbol.for('@aws-cdk/pipelines.outputs'); + + +/** + * A symbolic reference to a value produced by another step + * + * Generating and consuming outputs is engine-specific. Many engines will be + * able to support a feature like "outputs", but it's not guaranteed that + * all of them will. + * + * Outputs can only be generated by engine-specific steps (CodeBuildStep instead + * of ShellStep, etc), but can (currently) be consumed anywhere(*). When + * an engine-specific step generates an Output, it should put a well-known + * string and arbitrary data that is useful to the engine into the engine-specific + * fields on the StepOutput. + * + * The graph blueprint will take care of dependencies and ordering, the engine + * is responsible interpreting and rendering StepOutputs. The engine should call + * `defineResolution()` on all outputs. + * + * StepOutputs currently purposely aren't part of the public API because users + * shouldn't see the innards poking out. So, instead of keeping state on `Step`, + * we keep side-state here in a WeakMap which can be accessed via static members + * on `StepOutput`. + * + * (*) If we need to restrict this, we add the checking and erroring in the engine. + */ +export class StepOutput implements IResolvable { + /** + * Return true if the given IResolvable is a StepOutput + */ + public static isStepOutput(resolvable: IResolvable): resolvable is StepOutput { + return !!(resolvable as any)[STEP_OUTPUT_SYM]; + } + + /** + * Find all StepOutputs referenced in the given structure + */ + public static findAll(structure: any): StepOutput[] { + return findAllStepOutputs(structure); + } + + /** + * Return the produced outputs for the given step + */ + public static producedStepOutputs(step: Step): StepOutput[] { + return (step as any)[PRODUCED_OUTPUTS_SYM] ?? []; + } + + /** + * Add produced outputs for the given step + */ + public static recordProducer(...outputs: StepOutput[]) { + for (const output of outputs) { + const step = output.step; + let list = (step as any)[PRODUCED_OUTPUTS_SYM]; + if (!list) { + list = []; + (step as any)[PRODUCED_OUTPUTS_SYM] = list; + } + list.push(...outputs); + } + } + + /** + * The step that produces this output + */ + public readonly step: Step; + + /** + * Name of the engine for which this output is intended + */ + public readonly engineName: string; + + /** + * Additional data on the output, to be interpreted by the engine + */ + public readonly engineSpecificInformation: any; + + public readonly creationStack: string[] = []; + private resolution: any = undefined; + + constructor(step: Step, engineName: string, engineSpecificInformation: any) { + this.step = step; + this.engineName = engineName; + this.engineSpecificInformation = engineSpecificInformation; + Object.defineProperty(this, STEP_OUTPUT_SYM, { value: true }); + } + + /** + * Define the resolved value for this StepOutput. + * + * Should be called by the engine. + */ + public defineResolution(value: any) { + this.resolution = value; + } + + public resolve(_context: IResolveContext) { + if (this.resolution === undefined) { + throw new Error(`Output for step ${this.step} not configured. Either the step is not in the pipeline, or this engine does not support Outputs for this step.`); + } + return this.resolution; + } + + public toString(): string { + return Token.asString(this); + } +} + +function findAllStepOutputs(structure: any): StepOutput[] { + const ret = new Set(); + recurse(structure); + return Array.from(ret); + + function checkToken(x?: IResolvable) { + if (x && StepOutput.isStepOutput(x)) { + ret.add(x); + return true; + } + + // Return false if it wasn't a Token in the first place (in which case we recurse) + return x !== undefined; + } + + function recurse(x: any): void { + if (!x) { return; } + + if (Tokenization.isResolvable(x)) { + checkToken(x); + return; + } + if (Array.isArray(x)) { + if (!checkToken(Tokenization.reverseList(x))) { + x.forEach(recurse); + } + return; + } + if (typeof x === 'number') { + checkToken(Tokenization.reverseNumber(x)); + return; + } + if (typeof x === 'string') { + Tokenization.reverseString(x).tokens.forEach(checkToken); + return; + } + if (typeof x === 'object') { + for (const [k, v] of Object.entries(x)) { + recurse(k); + recurse(v); + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/pipelines/package.json b/packages/@aws-cdk/pipelines/package.json index 1249fa706977b..53fd337d2df98 100644 --- a/packages/@aws-cdk/pipelines/package.json +++ b/packages/@aws-cdk/pipelines/package.json @@ -48,7 +48,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "aws-sdk": "^2.848.0" }, "peerDependencies": { diff --git a/packages/@aws-cdk/pipelines/test/codepipeline/codebuild-step.test.ts b/packages/@aws-cdk/pipelines/test/codepipeline/codebuild-step.test.ts index 393f1ffb965ba..5b9538a5a4d00 100644 --- a/packages/@aws-cdk/pipelines/test/codepipeline/codebuild-step.test.ts +++ b/packages/@aws-cdk/pipelines/test/codepipeline/codebuild-step.test.ts @@ -141,4 +141,70 @@ test('envFromOutputs works even with very long stage and stack names', () => { }); // THEN - did not throw an error about identifier lengths +}); + +test('exportedVariables', () => { + const pipeline = new ModernTestGitHubNpmPipeline(pipelineStack, 'Cdk'); + + // GIVEN + const producer = new cdkp.CodeBuildStep('Produce', { + commands: ['export MY_VAR=hello'], + }); + + const consumer = new cdkp.CodeBuildStep('Consume', { + env: { + THE_VAR: producer.exportedVariable('MY_VAR'), + }, + commands: [ + 'echo "The variable was: $THE_VAR"', + ], + }); + + // WHEN + pipeline.addWave('MyWave', { + post: [consumer, producer], + }); + + // THEN + const template = Template.fromStack(pipelineStack); + template.hasResourceProperties('AWS::CodePipeline::Pipeline', { + Stages: [ + { Name: 'Source' }, + { Name: 'Build' }, + { Name: 'UpdatePipeline' }, + { + Name: 'MyWave', + Actions: [ + Match.objectLike({ + Name: 'Produce', + Namespace: 'MyWave@Produce', + RunOrder: 1, + }), + Match.objectLike({ + Name: 'Consume', + RunOrder: 2, + Configuration: Match.objectLike({ + EnvironmentVariables: Match.serializedJson(Match.arrayWith([ + { + name: 'THE_VAR', + type: 'PLAINTEXT', + value: '#{MyWave@Produce.MY_VAR}', + }, + ])), + }), + }), + ], + }, + ], + }); + + template.hasResourceProperties('AWS::CodeBuild::Project', { + Source: { + BuildSpec: Match.serializedJson(Match.objectLike({ + env: { + 'exported-variables': ['MY_VAR'], + }, + })), + }, + }); }); \ No newline at end of file diff --git a/packages/@aws-cdk/pipelines/test/codepipeline/codepipeline-sources.test.ts b/packages/@aws-cdk/pipelines/test/codepipeline/codepipeline-sources.test.ts index 46fb468c37623..93284d031d11c 100644 --- a/packages/@aws-cdk/pipelines/test/codepipeline/codepipeline-sources.test.ts +++ b/packages/@aws-cdk/pipelines/test/codepipeline/codepipeline-sources.test.ts @@ -1,6 +1,7 @@ import { Capture, Match, Template } from '@aws-cdk/assertions'; import * as ccommit from '@aws-cdk/aws-codecommit'; import { CodeCommitTrigger, GitHubTrigger } from '@aws-cdk/aws-codepipeline-actions'; +import * as ecr from '@aws-cdk/aws-ecr'; import { AnyPrincipal, Role } from '@aws-cdk/aws-iam'; import * as s3 from '@aws-cdk/aws-s3'; import { SecretValue, Stack, Token } from '@aws-cdk/core'; @@ -75,9 +76,9 @@ test('CodeCommit source honors all valid properties', () => { }); test('S3 source handles tokenized names correctly', () => { - const buckit = new s3.Bucket(pipelineStack, 'Buckit'); + const bucket = new s3.Bucket(pipelineStack, 'Bucket'); new ModernTestGitHubNpmPipeline(pipelineStack, 'Pipeline', { - input: cdkp.CodePipelineSource.s3(buckit, 'thefile.zip'), + input: cdkp.CodePipelineSource.s3(bucket, 'thefile.zip'), }); Template.fromStack(pipelineStack).hasResourceProperties('AWS::CodePipeline::Pipeline', { @@ -96,6 +97,40 @@ test('S3 source handles tokenized names correctly', () => { }); }); +test('ECR source handles tokenized and namespaced names correctly', () => { + const repository = new ecr.Repository(pipelineStack, 'Repository', { repositoryName: 'namespace/repo' }); + new ModernTestGitHubNpmPipeline(pipelineStack, 'Pipeline', { + input: cdkp.CodePipelineSource.ecr(repository), + }); + + const template = Template.fromStack(pipelineStack); + template.hasResourceProperties('AWS::CodePipeline::Pipeline', { + Stages: Match.arrayWith([{ + Name: 'Source', + Actions: [ + Match.objectLike({ + Configuration: Match.objectLike({ + RepositoryName: { Ref: Match.anyValue() }, + }), + Name: Match.objectLike({ + 'Fn::Join': [ + '_', + { + 'Fn::Split': [ + '/', + { + Ref: Match.anyValue(), + }, + ], + }, + ], + }), + }), + ], + }]), + }); +}); + test('GitHub source honors all valid properties', () => { new ModernTestGitHubNpmPipeline(pipelineStack, 'Pipeline', { input: cdkp.CodePipelineSource.gitHub('owner/repo', 'main', { @@ -178,4 +213,45 @@ test('artifact names are never longer than 128 characters', () => { }); expect(artifactId.asString().length).toBeLessThanOrEqual(128); +}); + +test('can use source attributes in pipeline', () => { + const gitHub = cdkp.CodePipelineSource.gitHub('owner/my-repo', 'main'); + + // WHEN + new ModernTestGitHubNpmPipeline(pipelineStack, 'Pipeline', { + input: gitHub, + synth: new cdkp.ShellStep('Synth', { + env: { + GITHUB_URL: gitHub.sourceAttribute('CommitUrl'), + }, + commands: [ + 'echo "Click here: $GITHUB_URL"', + ], + }), + selfMutation: false, + }); + + Template.fromStack(pipelineStack).hasResourceProperties('AWS::CodePipeline::Pipeline', { + Stages: [ + { Name: 'Source' }, + { + Name: 'Build', + Actions: [ + { + Name: 'Synth', + Configuration: Match.objectLike({ + EnvironmentVariables: Match.serializedJson([ + { + name: 'GITHUB_URL', + type: 'PLAINTEXT', + value: '#{Source@owner_my-repo.CommitUrl}', + }, + ]), + }), + }, + ], + }, + ], + }); }); \ No newline at end of file diff --git a/packages/@aws-cdk/pipelines/test/integ.newpipeline-with-vpc.expected.json b/packages/@aws-cdk/pipelines/test/integ.newpipeline-with-vpc.expected.json index 4bd2e638afb4c..8aa6f3c8893ca 100644 --- a/packages/@aws-cdk/pipelines/test/integ.newpipeline-with-vpc.expected.json +++ b/packages/@aws-cdk/pipelines/test/integ.newpipeline-with-vpc.expected.json @@ -2462,4 +2462,4 @@ ] } } -} \ No newline at end of file +} diff --git a/packages/@aws-cdk/pipelines/test/integ.newpipeline.expected.json b/packages/@aws-cdk/pipelines/test/integ.newpipeline.expected.json index 37cd5d99fd7f8..414a43cc3fd0e 100644 --- a/packages/@aws-cdk/pipelines/test/integ.newpipeline.expected.json +++ b/packages/@aws-cdk/pipelines/test/integ.newpipeline.expected.json @@ -2383,4 +2383,4 @@ ] } } -} \ No newline at end of file +} diff --git a/packages/@aws-cdk/pipelines/test/integ.pipeline-with-variables.expected.json b/packages/@aws-cdk/pipelines/test/integ.pipeline-with-variables.expected.json new file mode 100644 index 0000000000000..ccc779347f32f --- /dev/null +++ b/packages/@aws-cdk/pipelines/test/integ.pipeline-with-variables.expected.json @@ -0,0 +1,1014 @@ +{ + "Resources": { + "PipelineArtifactsBucketAEA9A052": { + "Type": "AWS::S3::Bucket", + "Properties": { + "BucketEncryption": { + "ServerSideEncryptionConfiguration": [ + { + "ServerSideEncryptionByDefault": { + "SSEAlgorithm": "aws:kms" + } + } + ] + }, + "PublicAccessBlockConfiguration": { + "BlockPublicAcls": true, + "BlockPublicPolicy": true, + "IgnorePublicAcls": true, + "RestrictPublicBuckets": true + } + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + }, + "PipelineArtifactsBucketPolicyF53CCC52": { + "Type": "AWS::S3::BucketPolicy", + "Properties": { + "Bucket": { + "Ref": "PipelineArtifactsBucketAEA9A052" + }, + "PolicyDocument": { + "Statement": [ + { + "Action": "s3:*", + "Condition": { + "Bool": { + "aws:SecureTransport": "false" + } + }, + "Effect": "Deny", + "Principal": { + "AWS": "*" + }, + "Resource": [ + { + "Fn::GetAtt": [ + "PipelineArtifactsBucketAEA9A052", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "PipelineArtifactsBucketAEA9A052", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + } + } + }, + "PipelineRoleB27FAA37": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "codepipeline.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "PipelineRoleDefaultPolicy7BDC1ABB": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "s3:GetObject*", + "s3:GetBucket*", + "s3:List*", + "s3:DeleteObject*", + "s3:PutObject", + "s3:PutObjectLegalHold", + "s3:PutObjectRetention", + "s3:PutObjectTagging", + "s3:PutObjectVersionTagging", + "s3:Abort*" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "PipelineArtifactsBucketAEA9A052", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "PipelineArtifactsBucketAEA9A052", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + }, + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "PipelineBuildSynthCodePipelineActionRole4E7A6C97", + "Arn" + ] + } + }, + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "PipelineMyWaveProduceCodePipelineActionRoleE0DCE9D3", + "Arn" + ] + } + }, + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "PipelineMyWaveConsumeCodePipelineActionRole7FAA4EFA", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "PipelineRoleDefaultPolicy7BDC1ABB", + "Roles": [ + { + "Ref": "PipelineRoleB27FAA37" + } + ] + } + }, + "Pipeline9850B417": { + "Type": "AWS::CodePipeline::Pipeline", + "Properties": { + "RoleArn": { + "Fn::GetAtt": [ + "PipelineRoleB27FAA37", + "Arn" + ] + }, + "Stages": [ + { + "Actions": [ + { + "ActionTypeId": { + "Category": "Source", + "Owner": "ThirdParty", + "Provider": "GitHub", + "Version": "1" + }, + "Configuration": { + "Owner": "cdklabs", + "Repo": "construct-hub-probe", + "Branch": "main", + "OAuthToken": "{{resolve:secretsmanager:github-token:SecretString:::}}", + "PollForSourceChanges": true + }, + "Name": "cdklabs_construct-hub-probe", + "OutputArtifacts": [ + { + "Name": "cdklabs_construct_hub_probe_Source" + } + ], + "RunOrder": 1 + } + ], + "Name": "Source" + }, + { + "Actions": [ + { + "ActionTypeId": { + "Category": "Build", + "Owner": "AWS", + "Provider": "CodeBuild", + "Version": "1" + }, + "Configuration": { + "ProjectName": { + "Ref": "PipelineBuildSynthCdkBuildProject6BEFA8E6" + } + }, + "InputArtifacts": [ + { + "Name": "cdklabs_construct_hub_probe_Source" + } + ], + "Name": "Synth", + "OutputArtifacts": [ + { + "Name": "Synth_Output" + } + ], + "RoleArn": { + "Fn::GetAtt": [ + "PipelineBuildSynthCodePipelineActionRole4E7A6C97", + "Arn" + ] + }, + "RunOrder": 1 + } + ], + "Name": "Build" + }, + { + "Actions": [ + { + "ActionTypeId": { + "Category": "Build", + "Owner": "AWS", + "Provider": "CodeBuild", + "Version": "1" + }, + "Configuration": { + "ProjectName": { + "Ref": "PipelineMyWaveProduce884410D6" + } + }, + "InputArtifacts": [ + { + "Name": "cdklabs_construct_hub_probe_Source" + } + ], + "Name": "Produce", + "Namespace": "MyWave@Produce", + "RoleArn": { + "Fn::GetAtt": [ + "PipelineMyWaveProduceCodePipelineActionRoleE0DCE9D3", + "Arn" + ] + }, + "RunOrder": 1 + }, + { + "ActionTypeId": { + "Category": "Build", + "Owner": "AWS", + "Provider": "CodeBuild", + "Version": "1" + }, + "Configuration": { + "ProjectName": { + "Ref": "PipelineMyWaveConsumeC5D5CCD7" + }, + "EnvironmentVariables": "[{\"name\":\"THE_VAR\",\"type\":\"PLAINTEXT\",\"value\":\"#{MyWave@Produce.MY_VAR}\"}]" + }, + "InputArtifacts": [ + { + "Name": "cdklabs_construct_hub_probe_Source" + } + ], + "Name": "Consume", + "RoleArn": { + "Fn::GetAtt": [ + "PipelineMyWaveConsumeCodePipelineActionRole7FAA4EFA", + "Arn" + ] + }, + "RunOrder": 2 + } + ], + "Name": "MyWave" + } + ], + "ArtifactStore": { + "Location": { + "Ref": "PipelineArtifactsBucketAEA9A052" + }, + "Type": "S3" + }, + "RestartExecutionOnUpdate": true + }, + "DependsOn": [ + "PipelineRoleDefaultPolicy7BDC1ABB", + "PipelineRoleB27FAA37" + ] + }, + "PipelineBuildSynthCdkBuildProjectRole231EEA2A": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "codebuild.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "PipelineBuildSynthCdkBuildProjectRoleDefaultPolicyFB6C941C": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:test-region:12345678:log-group:/aws/codebuild/", + { + "Ref": "PipelineBuildSynthCdkBuildProject6BEFA8E6" + } + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:test-region:12345678:log-group:/aws/codebuild/", + { + "Ref": "PipelineBuildSynthCdkBuildProject6BEFA8E6" + }, + ":*" + ] + ] + } + ] + }, + { + "Action": [ + "codebuild:CreateReportGroup", + "codebuild:CreateReport", + "codebuild:UpdateReport", + "codebuild:BatchPutTestCases", + "codebuild:BatchPutCodeCoverages" + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":codebuild:test-region:12345678:report-group/", + { + "Ref": "PipelineBuildSynthCdkBuildProject6BEFA8E6" + }, + "-*" + ] + ] + } + }, + { + "Action": [ + "s3:GetObject*", + "s3:GetBucket*", + "s3:List*", + "s3:DeleteObject*", + "s3:PutObject", + "s3:PutObjectLegalHold", + "s3:PutObjectRetention", + "s3:PutObjectTagging", + "s3:PutObjectVersionTagging", + "s3:Abort*" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "PipelineArtifactsBucketAEA9A052", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "PipelineArtifactsBucketAEA9A052", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "PipelineBuildSynthCdkBuildProjectRoleDefaultPolicyFB6C941C", + "Roles": [ + { + "Ref": "PipelineBuildSynthCdkBuildProjectRole231EEA2A" + } + ] + } + }, + "PipelineBuildSynthCdkBuildProject6BEFA8E6": { + "Type": "AWS::CodeBuild::Project", + "Properties": { + "Artifacts": { + "Type": "CODEPIPELINE" + }, + "Environment": { + "ComputeType": "BUILD_GENERAL1_SMALL", + "Image": "aws/codebuild/standard:5.0", + "ImagePullCredentialsType": "CODEBUILD", + "PrivilegedMode": false, + "Type": "LINUX_CONTAINER" + }, + "ServiceRole": { + "Fn::GetAtt": [ + "PipelineBuildSynthCdkBuildProjectRole231EEA2A", + "Arn" + ] + }, + "Source": { + "BuildSpec": "{\n \"version\": \"0.2\",\n \"phases\": {\n \"build\": {\n \"commands\": [\n \"mkdir cdk.out\",\n \"touch cdk.out/dummy\"\n ]\n }\n },\n \"artifacts\": {\n \"base-directory\": \"cdk.out\",\n \"files\": \"**/*\"\n }\n}", + "Type": "CODEPIPELINE" + }, + "Cache": { + "Type": "NO_CACHE" + }, + "Description": "Pipeline step VariablePipelineStack/Pipeline/Build/Synth", + "EncryptionKey": "alias/aws/s3" + } + }, + "PipelineBuildSynthCodePipelineActionRole4E7A6C97": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::12345678:root" + ] + ] + } + } + } + ], + "Version": "2012-10-17" + } + } + }, + "PipelineBuildSynthCodePipelineActionRoleDefaultPolicy92C90290": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "codebuild:BatchGetBuilds", + "codebuild:StartBuild", + "codebuild:StopBuild" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "PipelineBuildSynthCdkBuildProject6BEFA8E6", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "PipelineBuildSynthCodePipelineActionRoleDefaultPolicy92C90290", + "Roles": [ + { + "Ref": "PipelineBuildSynthCodePipelineActionRole4E7A6C97" + } + ] + } + }, + "PipelineMyWaveProduceRole24E3565D": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "codebuild.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "PipelineMyWaveProduceRoleDefaultPolicy209239D4": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:test-region:12345678:log-group:/aws/codebuild/", + { + "Ref": "PipelineMyWaveProduce884410D6" + } + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:test-region:12345678:log-group:/aws/codebuild/", + { + "Ref": "PipelineMyWaveProduce884410D6" + }, + ":*" + ] + ] + } + ] + }, + { + "Action": [ + "codebuild:CreateReportGroup", + "codebuild:CreateReport", + "codebuild:UpdateReport", + "codebuild:BatchPutTestCases", + "codebuild:BatchPutCodeCoverages" + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":codebuild:test-region:12345678:report-group/", + { + "Ref": "PipelineMyWaveProduce884410D6" + }, + "-*" + ] + ] + } + }, + { + "Action": [ + "s3:GetObject*", + "s3:GetBucket*", + "s3:List*" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "PipelineArtifactsBucketAEA9A052", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "PipelineArtifactsBucketAEA9A052", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "PipelineMyWaveProduceRoleDefaultPolicy209239D4", + "Roles": [ + { + "Ref": "PipelineMyWaveProduceRole24E3565D" + } + ] + } + }, + "PipelineMyWaveProduce884410D6": { + "Type": "AWS::CodeBuild::Project", + "Properties": { + "Artifacts": { + "Type": "CODEPIPELINE" + }, + "Environment": { + "ComputeType": "BUILD_GENERAL1_SMALL", + "Image": "aws/codebuild/standard:5.0", + "ImagePullCredentialsType": "CODEBUILD", + "PrivilegedMode": false, + "Type": "LINUX_CONTAINER" + }, + "ServiceRole": { + "Fn::GetAtt": [ + "PipelineMyWaveProduceRole24E3565D", + "Arn" + ] + }, + "Source": { + "BuildSpec": "{\n \"version\": \"0.2\",\n \"env\": {\n \"exported-variables\": [\n \"MY_VAR\"\n ]\n },\n \"phases\": {\n \"build\": {\n \"commands\": [\n \"export MY_VAR=hello\"\n ]\n }\n }\n}", + "Type": "CODEPIPELINE" + }, + "Cache": { + "Type": "NO_CACHE" + }, + "Description": "Pipeline step VariablePipelineStack/Pipeline/MyWave/Produce", + "EncryptionKey": "alias/aws/s3" + } + }, + "PipelineMyWaveProduceCodePipelineActionRoleE0DCE9D3": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::12345678:root" + ] + ] + } + } + } + ], + "Version": "2012-10-17" + } + } + }, + "PipelineMyWaveProduceCodePipelineActionRoleDefaultPolicy34DCB79A": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "codebuild:BatchGetBuilds", + "codebuild:StartBuild", + "codebuild:StopBuild" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "PipelineMyWaveProduce884410D6", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "PipelineMyWaveProduceCodePipelineActionRoleDefaultPolicy34DCB79A", + "Roles": [ + { + "Ref": "PipelineMyWaveProduceCodePipelineActionRoleE0DCE9D3" + } + ] + } + }, + "PipelineMyWaveConsumeRole2A96FF33": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "codebuild.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "PipelineMyWaveConsumeRoleDefaultPolicyC80F0194": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:test-region:12345678:log-group:/aws/codebuild/", + { + "Ref": "PipelineMyWaveConsumeC5D5CCD7" + } + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:test-region:12345678:log-group:/aws/codebuild/", + { + "Ref": "PipelineMyWaveConsumeC5D5CCD7" + }, + ":*" + ] + ] + } + ] + }, + { + "Action": [ + "codebuild:CreateReportGroup", + "codebuild:CreateReport", + "codebuild:UpdateReport", + "codebuild:BatchPutTestCases", + "codebuild:BatchPutCodeCoverages" + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":codebuild:test-region:12345678:report-group/", + { + "Ref": "PipelineMyWaveConsumeC5D5CCD7" + }, + "-*" + ] + ] + } + }, + { + "Action": [ + "s3:GetObject*", + "s3:GetBucket*", + "s3:List*" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "PipelineArtifactsBucketAEA9A052", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "PipelineArtifactsBucketAEA9A052", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "PipelineMyWaveConsumeRoleDefaultPolicyC80F0194", + "Roles": [ + { + "Ref": "PipelineMyWaveConsumeRole2A96FF33" + } + ] + } + }, + "PipelineMyWaveConsumeC5D5CCD7": { + "Type": "AWS::CodeBuild::Project", + "Properties": { + "Artifacts": { + "Type": "CODEPIPELINE" + }, + "Environment": { + "ComputeType": "BUILD_GENERAL1_SMALL", + "Image": "aws/codebuild/standard:5.0", + "ImagePullCredentialsType": "CODEBUILD", + "PrivilegedMode": false, + "Type": "LINUX_CONTAINER" + }, + "ServiceRole": { + "Fn::GetAtt": [ + "PipelineMyWaveConsumeRole2A96FF33", + "Arn" + ] + }, + "Source": { + "BuildSpec": "{\n \"version\": \"0.2\",\n \"phases\": {\n \"build\": {\n \"commands\": [\n \"echo \\\"The variable was: $THE_VAR\\\"\"\n ]\n }\n }\n}", + "Type": "CODEPIPELINE" + }, + "Cache": { + "Type": "NO_CACHE" + }, + "Description": "Pipeline step VariablePipelineStack/Pipeline/MyWave/Consume", + "EncryptionKey": "alias/aws/s3" + } + }, + "PipelineMyWaveConsumeCodePipelineActionRole7FAA4EFA": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::12345678:root" + ] + ] + } + } + } + ], + "Version": "2012-10-17" + } + } + }, + "PipelineMyWaveConsumeCodePipelineActionRoleDefaultPolicy3666898A": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "codebuild:BatchGetBuilds", + "codebuild:StartBuild", + "codebuild:StopBuild" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "PipelineMyWaveConsumeC5D5CCD7", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "PipelineMyWaveConsumeCodePipelineActionRoleDefaultPolicy3666898A", + "Roles": [ + { + "Ref": "PipelineMyWaveConsumeCodePipelineActionRole7FAA4EFA" + } + ] + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/pipelines/test/integ.pipeline-with-variables.ts b/packages/@aws-cdk/pipelines/test/integ.pipeline-with-variables.ts new file mode 100644 index 0000000000000..2a2351375ef62 --- /dev/null +++ b/packages/@aws-cdk/pipelines/test/integ.pipeline-with-variables.ts @@ -0,0 +1,52 @@ +// eslint-disable-next-line import/no-extraneous-dependencies +/// !cdk-integ VariablePipelineStack pragma:set-context:@aws-cdk/core:newStyleStackSynthesis=true +import { GitHubTrigger } from '@aws-cdk/aws-codepipeline-actions'; +import { App, Stack, StackProps } from '@aws-cdk/core'; +import { Construct } from 'constructs'; +import * as pipelines from '../lib'; + +class PipelineStack extends Stack { + constructor(scope: Construct, id: string, props?: StackProps) { + super(scope, id, props); + + const pipeline = new pipelines.CodePipeline(this, 'Pipeline', { + synth: new pipelines.ShellStep('Synth', { + input: pipelines.CodePipelineSource.gitHub('cdklabs/construct-hub-probe', 'main', { + trigger: GitHubTrigger.POLL, + }), + commands: ['mkdir cdk.out', 'touch cdk.out/dummy'], + }), + selfMutation: false, + }); + + const producer = new pipelines.CodeBuildStep('Produce', { + commands: ['export MY_VAR=hello'], + }); + + const consumer = new pipelines.CodeBuildStep('Consume', { + env: { + THE_VAR: producer.exportedVariable('MY_VAR'), + }, + commands: [ + 'echo "The variable was: $THE_VAR"', + ], + }); + + // WHEN + pipeline.addWave('MyWave', { + post: [consumer, producer], + }); + } +} + +const app = new App({ + context: { + '@aws-cdk/core:newStyleStackSynthesis': '1', + }, +}); + +new PipelineStack(app, 'VariablePipelineStack', { + env: { account: process.env.CDK_DEFAULT_ACCOUNT, region: process.env.CDK_DEFAULT_REGION }, +}); + +app.synth(); \ No newline at end of file diff --git a/packages/@aws-cdk/region-info/package.json b/packages/@aws-cdk/region-info/package.json index f3400ed30b3e4..701e87c62a2c7 100644 --- a/packages/@aws-cdk/region-info/package.json +++ b/packages/@aws-cdk/region-info/package.json @@ -63,7 +63,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0", "@types/fs-extra": "^8.1.2", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "fs-extra": "^9.1.0" }, "repository": { diff --git a/packages/@aws-cdk/triggers/.eslintrc.js b/packages/@aws-cdk/triggers/.eslintrc.js new file mode 100644 index 0000000000000..2658ee8727166 --- /dev/null +++ b/packages/@aws-cdk/triggers/.eslintrc.js @@ -0,0 +1,3 @@ +const baseConfig = require('@aws-cdk/cdk-build-tools/config/eslintrc'); +baseConfig.parserOptions.project = __dirname + '/tsconfig.json'; +module.exports = baseConfig; diff --git a/packages/@aws-cdk/triggers/.gitignore b/packages/@aws-cdk/triggers/.gitignore new file mode 100644 index 0000000000000..d8a8561d50885 --- /dev/null +++ b/packages/@aws-cdk/triggers/.gitignore @@ -0,0 +1,19 @@ +*.js +*.js.map +*.d.ts +tsconfig.json +node_modules +*.generated.ts +dist +.jsii + +.LAST_BUILD +.nyc_output +coverage +nyc.config.js +.LAST_PACKAGE +*.snk +!.eslintrc.js +!jest.config.js + +junit.xml \ No newline at end of file diff --git a/packages/@aws-cdk/triggers/.npmignore b/packages/@aws-cdk/triggers/.npmignore new file mode 100644 index 0000000000000..6077c04a3e8a3 --- /dev/null +++ b/packages/@aws-cdk/triggers/.npmignore @@ -0,0 +1,28 @@ +# Don't include original .ts files when doing `npm pack` +*.ts +!*.d.ts +coverage +.nyc_output +*.tgz + +dist +.LAST_PACKAGE +.LAST_BUILD +!*.js + +# Include .jsii +!.jsii + +*.snk + +*.tsbuildinfo + +tsconfig.json +.eslintrc.js +jest.config.js + +# exclude cdk artifacts +**/cdk.out +junit.xml +!*.lit.ts +test/ \ No newline at end of file diff --git a/packages/@aws-cdk/triggers/LICENSE b/packages/@aws-cdk/triggers/LICENSE new file mode 100644 index 0000000000000..82ad00bb02d0b --- /dev/null +++ b/packages/@aws-cdk/triggers/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2018-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/@aws-cdk/triggers/NOTICE b/packages/@aws-cdk/triggers/NOTICE new file mode 100644 index 0000000000000..1b7adbb891265 --- /dev/null +++ b/packages/@aws-cdk/triggers/NOTICE @@ -0,0 +1,2 @@ +AWS Cloud Development Kit (AWS CDK) +Copyright 2018-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. diff --git a/packages/@aws-cdk/triggers/README.md b/packages/@aws-cdk/triggers/README.md new file mode 100644 index 0000000000000..4ed41ce05ca0a --- /dev/null +++ b/packages/@aws-cdk/triggers/README.md @@ -0,0 +1,94 @@ +# Triggers + + +--- + +![cdk-constructs: Stable](https://img.shields.io/badge/cdk--constructs-stable-success.svg?style=for-the-badge) + +--- + + + +Triggers allows you to execute code during deployments. This can be used for a +variety of use cases such as: + +* Self tests: validate something after a resource/construct been provisioned +* Data priming: add initial data to resources after they are created +* Preconditions: check things such as account limits or external dependencies + before deployment. + +## Usage + +The `TriggerFunction` construct will define an AWS Lambda function which is +triggered *during* deployment: + +```ts +import * as lambda from '@aws-cdk/aws-lambda'; +import * as triggers from '@aws-cdk/triggers'; +import { Stack } from '@aws-cdk/core'; + +declare const stack: Stack; + +new triggers.TriggerFunction(stack, 'MyTrigger', { + runtime: lambda.Runtime.NODEJS_12_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(__dirname + '/my-trigger'), +}); +``` + +In the above example, the AWS Lambda function defined in `myLambdaFunction` will +be invoked when the stack is deployed. + +## Trigger Failures + +If the trigger handler fails (e.g. an exception is raised), the CloudFormation +deployment will fail, as if a resource failed to provision. This makes it easy +to implement "self tests" via triggers by simply making a set of assertions on +some provisioned infrastructure. + +## Order of Execution + +By default, a trigger will be executed by CloudFormation after the associated +handler is provisioned. This means that if the handler takes an implicit +dependency on other resources (e.g. via environment variables), those resources +will be provisioned *before* the trigger is executed. + +In most cases, implicit ordering should be sufficient, but you can also use +`executeAfter` and `executeBefore` to control the order of execution. + +The following example defines the following order: `(hello, world) => myTrigger => goodbye`. +The resources under `hello` and `world` will be provisioned in +parallel, and then the trigger `myTrigger` will be executed. Only then the +resources under `goodbye` will be provisioned: + +```ts +import { Construct, Node } from 'constructs'; +import * as triggers from '@aws-cdk/triggers'; + +declare const myTrigger: triggers.Trigger; +declare const hello: Construct; +declare const world: Construct; +declare const goodbye: Construct; + +myTrigger.executeAfter(hello, world); +myTrigger.executeBefore(goodbye); +``` + +Note that `hello` and `world` are construct *scopes*. This means that they can +be specific resources (such as an `s3.Bucket` object) or groups of resources +composed together into constructs. + +## Re-execution of Triggers + +By default, `executeOnHandlerChange` is enabled. This implies that the trigger +is re-executed every time the handler function code or configuration changes. If +this option is disabled, the trigger will be executed only once upon first +deployment. + +In the future we will consider adding support for additional re-execution modes: + +* `executeOnEveryDeployment: boolean` - re-executes every time the stack is + deployed (add random "salt" during synthesis). +* `executeOnResourceChange: Construct[]` - re-executes when one of the resources + under the specified scopes has changed (add the hash the CloudFormation + resource specs). diff --git a/packages/@aws-cdk/triggers/jest.config.js b/packages/@aws-cdk/triggers/jest.config.js new file mode 100644 index 0000000000000..3a2fd93a1228a --- /dev/null +++ b/packages/@aws-cdk/triggers/jest.config.js @@ -0,0 +1,2 @@ +const baseConfig = require('@aws-cdk/cdk-build-tools/config/jest.config'); +module.exports = baseConfig; diff --git a/packages/@aws-cdk/triggers/lib/index.ts b/packages/@aws-cdk/triggers/lib/index.ts new file mode 100644 index 0000000000000..1e2bf5e2dab37 --- /dev/null +++ b/packages/@aws-cdk/triggers/lib/index.ts @@ -0,0 +1,2 @@ +export * from './trigger'; +export * from './trigger-function'; \ No newline at end of file diff --git a/packages/@aws-cdk/triggers/lib/lambda/.gitignore b/packages/@aws-cdk/triggers/lib/lambda/.gitignore new file mode 100644 index 0000000000000..eef5e8dd7e177 --- /dev/null +++ b/packages/@aws-cdk/triggers/lib/lambda/.gitignore @@ -0,0 +1 @@ +__entrypoint__.js diff --git a/packages/@aws-cdk/triggers/lib/lambda/index.ts b/packages/@aws-cdk/triggers/lib/lambda/index.ts new file mode 100644 index 0000000000000..7975ac5b56bc0 --- /dev/null +++ b/packages/@aws-cdk/triggers/lib/lambda/index.ts @@ -0,0 +1,56 @@ +/* eslint-disable no-console */ + +// eslint-disable-next-line import/no-extraneous-dependencies +import * as AWS from 'aws-sdk'; + +export type InvokeFunction = (functionName: string) => Promise; + +export const invoke: InvokeFunction = async functionName => { + const lambda = new AWS.Lambda(); + const invokeRequest = { FunctionName: functionName }; + console.log({ invokeRequest }); + const invokeResponse = await lambda.invoke(invokeRequest).promise(); + console.log({ invokeResponse }); + return invokeResponse; +}; + +export async function handler(event: AWSLambda.CloudFormationCustomResourceEvent) { + console.log({ event }); + + if (event.RequestType === 'Delete') { + console.log('not calling trigger on DELETE'); + return; + } + + const handlerArn = event.ResourceProperties.HandlerArn; + if (!handlerArn) { + throw new Error('The "HandlerArn" property is required'); + } + + const invokeResponse = await invoke(handlerArn); + + if (invokeResponse.StatusCode !== 200) { + throw new Error(`Trigger handler failed with status code ${invokeResponse.StatusCode}`); + } + + // if the lambda function throws an error, parse the error message and fail + if (invokeResponse.FunctionError) { + throw new Error(parseError(invokeResponse.Payload?.toString())); + } +}; + +/** + * Parse the error message from the lambda function. + */ +function parseError(payload: string | undefined): string { + console.log(`Error payload: ${payload}`); + if (!payload) { return 'unknown handler error'; } + try { + const error = JSON.parse(payload); + const concat = [error.errorMessage, error.trace].filter(x => x).join('\n'); + return concat.length > 0 ? concat : payload; + } catch (e) { + // fall back to just returning the payload + return payload; + } +} diff --git a/packages/@aws-cdk/triggers/lib/trigger-function.ts b/packages/@aws-cdk/triggers/lib/trigger-function.ts new file mode 100644 index 0000000000000..6504c9f5d1334 --- /dev/null +++ b/packages/@aws-cdk/triggers/lib/trigger-function.ts @@ -0,0 +1,37 @@ +import * as lambda from '@aws-cdk/aws-lambda'; +import { Construct } from 'constructs'; +import { ITrigger, Trigger, TriggerOptions } from '.'; + +/** + * Props for `InvokeFunction`. + */ +export interface TriggerFunctionProps extends lambda.FunctionProps, TriggerOptions { +} + +/** + * Invokes an AWS Lambda function during deployment. + */ +export class TriggerFunction extends lambda.Function implements ITrigger { + + /** + * The underlying trigger resource. + */ + public readonly trigger: Trigger; + + constructor(scope: Construct, id: string, props: TriggerFunctionProps) { + super(scope, id, props); + + this.trigger = new Trigger(this, 'Trigger', { + ...props, + handler: this, + }); + } + + public executeAfter(...scopes: Construct[]): void { + this.trigger.executeAfter(...scopes); + } + + public executeBefore(...scopes: Construct[]): void { + this.trigger.executeBefore(...scopes); + } +} diff --git a/packages/@aws-cdk/triggers/lib/trigger.ts b/packages/@aws-cdk/triggers/lib/trigger.ts new file mode 100644 index 0000000000000..88299f2373294 --- /dev/null +++ b/packages/@aws-cdk/triggers/lib/trigger.ts @@ -0,0 +1,141 @@ +import { join } from 'path'; +import * as lambda from '@aws-cdk/aws-lambda'; +import { CustomResource, CustomResourceProvider, CustomResourceProviderRuntime, IConstruct } from '@aws-cdk/core'; + +import { Construct, Node } from 'constructs'; + +// 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 as CoreConstruct } from '@aws-cdk/core'; + +/** + * Interface for triggers. + */ +export interface ITrigger extends IConstruct { + /** + * Adds trigger dependencies. Execute this trigger only after these construct + * scopes have been provisioned. + * + * @param scopes A list of construct scopes which this trigger will depend on. + */ + executeAfter(...scopes: Construct[]): void; + + /** + * Adds this trigger as a dependency on other constructs. This means that this + * trigger will get executed *before* the given construct(s). + * + * @param scopes A list of construct scopes which will take a dependency on + * this trigger. + */ + executeBefore(...scopes: Construct[]): void; +} + +/** + * Options for `Trigger`. + */ +export interface TriggerOptions { + /** + * Adds trigger dependencies. Execute this trigger only after these construct + * scopes have been provisioned. + * + * You can also use `trigger.executeAfter()` to add additional dependencies. + * + * @default [] + */ + readonly executeAfter?: Construct[]; + + /** + * Adds this trigger as a dependency on other constructs. This means that this + * trigger will get executed *before* the given construct(s). + * + * You can also use `trigger.executeBefore()` to add additional dependants. + * + * @default [] + */ + readonly executeBefore?: Construct[]; + + /** + * Re-executes the trigger every time the handler changes. + * + * This implies that the trigger is associated with the `currentVersion` of + * the handler, which gets recreated every time the handler or its + * configuration is updated. + * + * @default true + */ + readonly executeOnHandlerChange?: boolean; +} + +/** + * Props for `Trigger`. + */ +export interface TriggerProps extends TriggerOptions { + /** + * The AWS Lambda function of the handler to execute. + */ + readonly handler: lambda.Function; +} + +/** + * Triggers an AWS Lambda function during deployment. + */ +export class Trigger extends CoreConstruct implements ITrigger { + constructor(scope: Construct, id: string, props: TriggerProps) { + super(scope, id); + + const handlerArn = this.determineHandlerArn(props); + const provider = CustomResourceProvider.getOrCreateProvider(this, 'AWSCDK.TriggerCustomResourceProvider', { + runtime: CustomResourceProviderRuntime.NODEJS_14_X, + codeDirectory: join(__dirname, 'lambda'), + policyStatements: [ + { + Effect: 'Allow', + Action: ['lambda:InvokeFunction'], + Resource: [handlerArn], + }, + ], + }); + + new CustomResource(this, 'Default', { + resourceType: 'Custom::Trigger', + serviceToken: provider.serviceToken, + properties: { + HandlerArn: handlerArn, + }, + }); + + this.executeAfter(...props.executeAfter ?? []); + this.executeBefore(...props.executeBefore ?? []); + } + + public executeAfter(...scopes: Construct[]): void { + Node.of(this).addDependency(...scopes); + } + + public executeBefore(...scopes: Construct[]): void { + for (const s of scopes) { + Node.of(s).addDependency(this); + } + } + + private determineHandlerArn(props: TriggerProps) { + return props.handler.currentVersion.functionArn; + // const executeOnHandlerChange = props.executeOnHandlerChange ?? true; + // if (executeOnHandlerChange) { + // } + + // return props.handler.functionArn; + } +} + +/** + * Determines + */ +export enum TriggerInvalidation { + /** + * The trigger will be executed every time the handler (or its configuration) + * changes. This is implemented by associated the trigger with the `currentVersion` + * of the AWS Lambda function, which gets recreated every time the handler changes. + */ + HANDLER_CHANGE = 'WHEN_FUNCTION_CHANGES', +} \ No newline at end of file diff --git a/packages/@aws-cdk/triggers/package.json b/packages/@aws-cdk/triggers/package.json new file mode 100644 index 0000000000000..762ea94a0220b --- /dev/null +++ b/packages/@aws-cdk/triggers/package.json @@ -0,0 +1,117 @@ +{ + "name": "@aws-cdk/triggers", + "version": "0.0.0", + "description": "Execute AWS Lambda functions during deployment", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "jsii": { + "outdir": "dist", + "targets": { + "java": { + "package": "software.amazon.awscdk.triggers", + "maven": { + "groupId": "software.amazon.awscdk", + "artifactId": "cdk-triggers" + } + }, + "dotnet": { + "namespace": "Amazon.CDK.Triggers", + "packageId": "Amazon.CDK.Triggers", + "iconUrl": "https://raw.githubusercontent.com/aws/aws-cdk/master/logo/default-256-dark.png" + }, + "python": { + "distName": "aws-cdk.triggers", + "module": "aws_cdk.triggers", + "classifiers": [ + "Framework :: AWS CDK", + "Framework :: AWS CDK :: 1" + ] + } + }, + "projectReferences": true, + "metadata": { + "jsii": { + "rosetta": { + "strict": true + } + } + } + }, + "repository": { + "type": "git", + "url": "https://github.com/aws/aws-cdk.git", + "directory": "packages/@aws-cdk/triggers" + }, + "scripts": { + "build": "cdk-build", + "watch": "cdk-watch", + "lint": "cdk-lint", + "test": "cdk-test", + "integ": "cdk-integ", + "pkglint": "pkglint -f", + "package": "cdk-package", + "awslint": "cdk-awslint", + "build+test": "yarn build && yarn test", + "build+test+package": "yarn build+test && yarn package", + "compat": "cdk-compat", + "rosetta:extract": "yarn --silent jsii-rosetta extract", + "build+extract": "yarn build && yarn rosetta:extract", + "build+test+extract": "yarn build+test && yarn rosetta:extract" + }, + "keywords": [ + "aws", + "cdk", + "example", + "construct", + "library", + "triggers" + ], + "author": { + "name": "Amazon Web Services", + "url": "https://aws.amazon.com", + "organization": true + }, + "license": "Apache-2.0", + "devDependencies": { + "@aws-cdk/assertions": "0.0.0", + "@aws-cdk/cdk-build-tools": "0.0.0", + "@aws-cdk/cdk-integ-tools": "0.0.0", + "@aws-cdk/aws-sns": "0.0.0", + "aws-sdk": "^2.848.0", + "@aws-cdk/pkglint": "0.0.0", + "@types/jest": "^27.4.1", + "jest": "^27.5.1" + }, + "dependencies": { + "@aws-cdk/aws-lambda": "0.0.0", + "@aws-cdk/core": "0.0.0", + "constructs": "^3.3.69" + }, + "homepage": "https://github.com/aws/aws-cdk", + "peerDependencies": { + "@aws-cdk/aws-lambda": "0.0.0", + "@aws-cdk/core": "0.0.0", + "constructs": "^3.3.69" + }, + "engines": { + "node": ">= 10.13.0 <13 || >=13.7.0" + }, + "stability": "stable", + "maturity": "stable", + "awscdkio": { + "announce": false + }, + "cdk-build": { + "env": { + "AWSLINT_BASE_CONSTRUCT": true + } + }, + "publishConfig": { + "tag": "latest" + }, + "awslint": { + "exclude": [ + "ref-via-interface:@aws-cdk/triggers.TriggerProps.handler" + ] + } +} diff --git a/packages/@aws-cdk/triggers/test/integ.triggers.expected.json b/packages/@aws-cdk/triggers/test/integ.triggers.expected.json new file mode 100644 index 0000000000000..94a0cf390bc50 --- /dev/null +++ b/packages/@aws-cdk/triggers/test/integ.triggers.expected.json @@ -0,0 +1,203 @@ +{ + "Resources": { + "Topic198E71B3E": { + "Type": "AWS::SNS::Topic", + "DependsOn": [ + "MyFunctionTriggerDB129D7B" + ] + }, + "Topic269377B75": { + "Type": "AWS::SNS::Topic" + }, + "MyFunctionServiceRole3C357FF2": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "MyFunction3BAA72D1": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "exports.handler = function() { console.log(\"hi\"); };" + }, + "Role": { + "Fn::GetAtt": [ + "MyFunctionServiceRole3C357FF2", + "Arn" + ] + }, + "Handler": "index.handler", + "Runtime": "nodejs12.x" + }, + "DependsOn": [ + "MyFunctionServiceRole3C357FF2" + ] + }, + "MyFunctionCurrentVersion197490AF776ea8de2edf446759649703b18110a4": { + "Type": "AWS::Lambda::Version", + "Properties": { + "FunctionName": { + "Ref": "MyFunction3BAA72D1" + } + } + }, + "MyFunctionTriggerDB129D7B": { + "Type": "Custom::Trigger", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "AWSCDKTriggerCustomResourceProviderCustomResourceProviderHandler97BECD91", + "Arn" + ] + }, + "HandlerArn": { + "Ref": "MyFunctionCurrentVersion197490AF776ea8de2edf446759649703b18110a4" + } + }, + "DependsOn": [ + "Topic269377B75" + ], + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "AWSCDKTriggerCustomResourceProviderCustomResourceProviderRoleE18FAF0A": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ] + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + } + ], + "Policies": [ + { + "PolicyName": "Inline", + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "lambda:InvokeFunction" + ], + "Resource": [ + { + "Ref": "MyFunctionCurrentVersion197490AF776ea8de2edf446759649703b18110a4" + } + ] + } + ] + } + } + ] + } + }, + "AWSCDKTriggerCustomResourceProviderCustomResourceProviderHandler97BECD91": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "S3Bucket": { + "Ref": "AssetParameters9a94767d68ec7d462ebafb65903f259f527cae0775d02a4eb2db7ac720bc61ffS3Bucket8B4BAF9C" + }, + "S3Key": { + "Fn::Join": [ + "", + [ + { + "Fn::Select": [ + 0, + { + "Fn::Split": [ + "||", + { + "Ref": "AssetParameters9a94767d68ec7d462ebafb65903f259f527cae0775d02a4eb2db7ac720bc61ffS3VersionKey2B3BD417" + } + ] + } + ] + }, + { + "Fn::Select": [ + 1, + { + "Fn::Split": [ + "||", + { + "Ref": "AssetParameters9a94767d68ec7d462ebafb65903f259f527cae0775d02a4eb2db7ac720bc61ffS3VersionKey2B3BD417" + } + ] + } + ] + } + ] + ] + } + }, + "Timeout": 900, + "MemorySize": 128, + "Handler": "__entrypoint__.handler", + "Role": { + "Fn::GetAtt": [ + "AWSCDKTriggerCustomResourceProviderCustomResourceProviderRoleE18FAF0A", + "Arn" + ] + }, + "Runtime": "nodejs14.x" + }, + "DependsOn": [ + "AWSCDKTriggerCustomResourceProviderCustomResourceProviderRoleE18FAF0A" + ] + } + }, + "Parameters": { + "AssetParameters9a94767d68ec7d462ebafb65903f259f527cae0775d02a4eb2db7ac720bc61ffS3Bucket8B4BAF9C": { + "Type": "String", + "Description": "S3 bucket for asset \"9a94767d68ec7d462ebafb65903f259f527cae0775d02a4eb2db7ac720bc61ff\"" + }, + "AssetParameters9a94767d68ec7d462ebafb65903f259f527cae0775d02a4eb2db7ac720bc61ffS3VersionKey2B3BD417": { + "Type": "String", + "Description": "S3 key for asset version \"9a94767d68ec7d462ebafb65903f259f527cae0775d02a4eb2db7ac720bc61ff\"" + }, + "AssetParameters9a94767d68ec7d462ebafb65903f259f527cae0775d02a4eb2db7ac720bc61ffArtifactHash4518D68D": { + "Type": "String", + "Description": "Artifact hash for asset \"9a94767d68ec7d462ebafb65903f259f527cae0775d02a4eb2db7ac720bc61ff\"" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/triggers/test/integ.triggers.ts b/packages/@aws-cdk/triggers/test/integ.triggers.ts new file mode 100644 index 0000000000000..ad9a7e104438b --- /dev/null +++ b/packages/@aws-cdk/triggers/test/integ.triggers.ts @@ -0,0 +1,21 @@ +import * as lambda from '@aws-cdk/aws-lambda'; +import * as sns from '@aws-cdk/aws-sns'; +import { App, Stack } from '@aws-cdk/core'; +import * as triggers from '../lib'; + +const app = new App(); +const stack = new Stack(app, 'MyStack'); + +const topic1 = new sns.Topic(stack, 'Topic1'); +const topic2 = new sns.Topic(stack, 'Topic2'); + +const trigger = new triggers.TriggerFunction(stack, 'MyFunction', { + runtime: lambda.Runtime.NODEJS_12_X, + handler: 'index.handler', + code: lambda.Code.fromInline('exports.handler = function() { console.log("hi"); };'), + executeBefore: [topic1], +}); + +trigger.executeAfter(topic2); + +app.synth(); \ No newline at end of file diff --git a/packages/@aws-cdk/triggers/test/trigger-handler.test.ts b/packages/@aws-cdk/triggers/test/trigger-handler.test.ts new file mode 100644 index 0000000000000..ab2081c86c572 --- /dev/null +++ b/packages/@aws-cdk/triggers/test/trigger-handler.test.ts @@ -0,0 +1,86 @@ +import * as lambda from '../lib/lambda'; + +afterEach(() => { + jest.resetAllMocks(); +}); + +const handlerArn = 'arn:aws:lambda:us-east-1:123456789012:function:MyTrigger'; +const mockRequest = { + LogicalResourceId: 'MyTrigger', + StackId: 'arn:aws:cloudformation:us-east-1:123456789012:stack/MyStack/12345678-1234-1234-1234-123456789012', + ResponseURL: 'https://cloudformation-custom-resource-response-MyTrigger/', + ResourceProperties: { + ServiceToken: 'arn:aws:lambda:us-east-1:123456789012:function:MyFunction', + HandlerArn: handlerArn, + }, + RequestId: 'MyRequestId', + ResourceType: 'Custom::Trigger', + ServiceToken: 'arn:aws:lambda:us-east-1:123456789012:function:MyFunction', +}; + +test('Create', async () => { + const invokeMock = jest.spyOn(lambda, 'invoke').mockResolvedValue({ + StatusCode: 200, + }); + + await lambda.handler({ RequestType: 'Create', ...mockRequest }); + + expect(invokeMock).toBeCalledTimes(1); + expect(invokeMock).toBeCalledWith(handlerArn); +}); + +test('Update', async () => { + const invokeMock = jest.spyOn(lambda, 'invoke').mockResolvedValue({ + StatusCode: 200, + }); + + await lambda.handler({ RequestType: 'Update', PhysicalResourceId: 'PRID', OldResourceProperties: {}, ...mockRequest }); + + expect(invokeMock).toBeCalledTimes(1); + expect(invokeMock).toBeCalledWith(handlerArn); +}); + +test('Delete - handler not called', async () => { + const invokeMock = jest.spyOn(lambda, 'invoke'); + await lambda.handler({ RequestType: 'Delete', PhysicalResourceId: 'PRID', ...mockRequest }); + expect(invokeMock).not.toBeCalled(); +}); + +test('non-200 status code throws an error', async () => { + const invokeMock = jest.spyOn(lambda, 'invoke').mockResolvedValue({ + StatusCode: 500, + }); + + await expect(lambda.handler({ RequestType: 'Create', ...mockRequest })) + .rejects + .toMatchObject({ message: 'Trigger handler failed with status code 500' }); + + expect(invokeMock).toBeCalledTimes(1); + expect(invokeMock).toBeCalledWith(handlerArn); +}); + +describe('function error', () => { + + const makeTest = (payload: string | undefined, expectedError: string) => { + return async () => { + const invokeMock = jest.spyOn(lambda, 'invoke').mockResolvedValue({ + StatusCode: 200, + FunctionError: 'Unhandled', + Payload: payload, + }); + + await expect(lambda.handler({ RequestType: 'Create', ...mockRequest })) + .rejects + .toMatchObject({ message: expectedError }); + + expect(invokeMock).toBeCalledTimes(1); + expect(invokeMock).toBeCalledWith(handlerArn); + }; + }; + + test('undefined payload', makeTest(undefined, 'unknown handler error')); + test('empty payload', makeTest('', 'unknown handler error')); + test('invalid JSON payload', makeTest('{', '{')); + test('valid JSON payload', makeTest('{"errorMessage": "my error"}', 'my error')); + test('with stack trace', makeTest('{"errorMessage": "my error", "trace": "my stack trace"}', 'my error\nmy stack trace')); +}); diff --git a/packages/@aws-cdk/triggers/test/triggers.test.ts b/packages/@aws-cdk/triggers/test/triggers.test.ts new file mode 100644 index 0000000000000..dd89046c6475a --- /dev/null +++ b/packages/@aws-cdk/triggers/test/triggers.test.ts @@ -0,0 +1,67 @@ +import { Template } from '@aws-cdk/assertions'; +import * as lambda from '@aws-cdk/aws-lambda'; +import * as sns from '@aws-cdk/aws-sns'; +import { Stack } from '@aws-cdk/core'; +import * as triggers from '../lib'; + +test('minimal', () => { + // GIVEN + const stack = new Stack(); + + // WHEN + new triggers.TriggerFunction(stack, 'MyTrigger', { + handler: 'index.handler', + runtime: lambda.Runtime.NODEJS_12_X, + code: lambda.Code.fromInline('foo'), + }); + + // THEN + const template = Template.fromStack(stack); + template.hasResourceProperties('AWS::Lambda::Function', {}); + template.hasResourceProperties('Custom::Trigger', { + HandlerArn: { Ref: 'MyTriggerCurrentVersion8802742B707afb4f5c680fa04113c095ec4e8b5d' }, + }); +}); + +test('before/after', () => { + // GIVEN + const stack = new Stack(); + const topic1 = new sns.Topic(stack, 'Topic1'); + const topic2 = new sns.Topic(stack, 'Topic2'); + const topic3 = new sns.Topic(stack, 'Topic3'); + const topic4 = new sns.Topic(stack, 'Topic4'); + + // WHEN + const myTrigger = new triggers.TriggerFunction(stack, 'MyTrigger', { + runtime: lambda.Runtime.NODEJS_12_X, + code: lambda.Code.fromInline('zoo'), + handler: 'index.handler', + + // through props + executeAfter: [topic1], + executeBefore: [topic3], + }); + + // through methods + myTrigger.executeBefore(topic4); + myTrigger.executeAfter(topic2); + + // THEN + const triggerId = 'MyTrigger5A0C728D'; + const topic1Id = 'Topic198E71B3E'; + const topic2Id = 'Topic269377B75'; + const topic3Id = 'Topic3DEAE47A7'; + const topic4Id = 'Topic4F5C0CEE2'; + + const template = Template.fromStack(stack); + const resources = template.toJSON().Resources; + + const dependsOn = (sourceId: string, targetId: string) => { + expect(resources[sourceId].DependsOn).toContain(targetId); + }; + + dependsOn(triggerId, topic1Id); + dependsOn(triggerId, topic2Id); + dependsOn(topic3Id, triggerId); + dependsOn(topic4Id, triggerId); +}); diff --git a/packages/@aws-cdk/yaml-cfn/package.json b/packages/@aws-cdk/yaml-cfn/package.json index dc7e2e4598ad1..819ed1a4c77d1 100644 --- a/packages/@aws-cdk/yaml-cfn/package.json +++ b/packages/@aws-cdk/yaml-cfn/package.json @@ -79,7 +79,7 @@ "@aws-cdk/assertions": "0.0.0", "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "@types/yaml": "^1.9.7", "jest": "^27.5.1" }, diff --git a/packages/@monocdk-experiment/assert/package.json b/packages/@monocdk-experiment/assert/package.json index 5d16ebc9bc656..afbce52f06eb8 100644 --- a/packages/@monocdk-experiment/assert/package.json +++ b/packages/@monocdk-experiment/assert/package.json @@ -34,7 +34,7 @@ "license": "Apache-2.0", "devDependencies": { "@monocdk-experiment/rewrite-imports": "0.0.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "@types/node": "^10.17.60", "@aws-cdk/cdk-build-tools": "0.0.0", "constructs": "^3.3.69", diff --git a/packages/@monocdk-experiment/rewrite-imports/package.json b/packages/@monocdk-experiment/rewrite-imports/package.json index fa08f9e613038..2e36b49a7b51f 100644 --- a/packages/@monocdk-experiment/rewrite-imports/package.json +++ b/packages/@monocdk-experiment/rewrite-imports/package.json @@ -36,7 +36,7 @@ }, "devDependencies": { "@types/glob": "^7.2.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "@types/node": "^10.17.60", "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0" diff --git a/packages/aws-cdk-lib/README.md b/packages/aws-cdk-lib/README.md index 017a85437675c..b9c8689353109 100644 --- a/packages/aws-cdk-lib/README.md +++ b/packages/aws-cdk-lib/README.md @@ -88,6 +88,45 @@ organize their deployments with. If you want to vend a reusable construct, define it as a subclasses of `Construct`: the consumers of your construct will decide where to place it in their own stacks. +## Stack Synthesizers + +Each Stack has a *synthesizer*, an object that determines how and where +the Stack should be synthesized and deployed. The synthesizer controls +aspects like: + +- How does the stack reference assets? (Either through CloudFormation + parameters the CLI supplies, or because the Stack knows a predefined + location where assets will be uploaded). +- What roles are used to deploy the stack? These can be bootstrapped + roles, roles created in some other way, or just the CLI's current + credentials. + +The following synthesizers are available: + +- `DefaultStackSynthesizer`: recommended. Uses predefined asset locations and + roles created by the modern bootstrap template. Access control is done by + controlling who can assume the deploy role. This is the default stack + synthesizer in CDKv2. +- `LegacyStackSynthesizer`: Uses CloudFormation parameters to communicate + asset locations, and the CLI's current permissions to deploy stacks. The + is the default stack synthesizer in CDKv1. +- `CliCredentialsStackSynthesizer`: Uses predefined asset locations, and the + CLI's current permissions. + +Each of these synthesizers takes configuration arguments. To configure +a stack with a synthesizer, pass it as one of its properties: + +```ts +new MyStack(app, 'MyStack', { + synthesizer: new DefaultStackSynthesizer({ + fileAssetsBucketName: 'my-orgs-asset-bucket', + }), +}); +``` + +For more information on bootstrapping accounts and customizing synthesis, +see [Bootstrapping in the CDK Developer Guide](https://docs.aws.amazon.com/cdk/latest/guide/bootstrapping.html). + ## Nested Stacks [Nested stacks](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-nested-stacks.html) are stacks created as part of other stacks. You create a nested stack within another stack by using the `NestedStack` construct. diff --git a/packages/aws-cdk-lib/package.json b/packages/aws-cdk-lib/package.json index 367c45ef8fcf4..9e2d24647660d 100644 --- a/packages/aws-cdk-lib/package.json +++ b/packages/aws-cdk-lib/package.json @@ -233,6 +233,7 @@ "@aws-cdk/aws-iotanalytics": "0.0.0", "@aws-cdk/aws-iotcoredeviceadvisor": "0.0.0", "@aws-cdk/aws-iotevents": "0.0.0", + "@aws-cdk/aws-iotevents-actions": "0.0.0", "@aws-cdk/aws-iotfleethub": "0.0.0", "@aws-cdk/aws-iotsitewise": "0.0.0", "@aws-cdk/aws-iotthingsgraph": "0.0.0", @@ -348,11 +349,12 @@ "@aws-cdk/pipelines": "0.0.0", "@aws-cdk/pkglint": "0.0.0", "@aws-cdk/region-info": "0.0.0", + "@aws-cdk/triggers": "0.0.0", "@aws-cdk/ubergen": "0.0.0", "@types/fs-extra": "^8.1.2", "@types/node": "^10.17.60", "constructs": "^3.3.69", - "esbuild": "^0.14.21", + "esbuild": "^0.14.23", "fs-extra": "^9.1.0", "ts-node": "^9.1.1", "typescript": "~3.8.3" diff --git a/packages/aws-cdk-lib/scripts/verify-imports-resolve-same.ts b/packages/aws-cdk-lib/scripts/verify-imports-resolve-same.ts index ad15896f072b0..99b8ca286a1e2 100644 --- a/packages/aws-cdk-lib/scripts/verify-imports-resolve-same.ts +++ b/packages/aws-cdk-lib/scripts/verify-imports-resolve-same.ts @@ -84,7 +84,7 @@ async function compileAndResolve(fileName: string, contents: string, symbolName: } // Return the filename - const srcFile = sym.declarations?.[0].getSourceFile().fileName.replace(/.ts|.js|.d.ts/, ''); + const srcFile = sym.declarations?.[0].getSourceFile().fileName.replace(/[.](ts|js|d\.ts)$/, ''); if (!srcFile) { console.log(sym); throw new Error(`Symbol ${symbolName} in '${contents}' does not resolve to a source location`); diff --git a/packages/aws-cdk-migration/package.json b/packages/aws-cdk-migration/package.json index 5b0832f7cf86e..fc601186248ca 100644 --- a/packages/aws-cdk-migration/package.json +++ b/packages/aws-cdk-migration/package.json @@ -39,7 +39,7 @@ }, "devDependencies": { "@types/glob": "^7.2.0", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "@types/node": "^10.17.60", "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0" diff --git a/packages/aws-cdk/NOTICE b/packages/aws-cdk/NOTICE index 1b7adbb891265..2fdce4d2a0591 100644 --- a/packages/aws-cdk/NOTICE +++ b/packages/aws-cdk/NOTICE @@ -1,2 +1,16 @@ AWS Cloud Development Kit (AWS CDK) Copyright 2018-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Third party attributions of this package can be found in the THIRD_PARTY_LICENSES file \ No newline at end of file diff --git a/packages/aws-cdk/README.md b/packages/aws-cdk/README.md index 027dc574572f5..54adb46a964bd 100644 --- a/packages/aws-cdk/README.md +++ b/packages/aws-cdk/README.md @@ -11,18 +11,20 @@ The AWS CDK Toolkit provides the `cdk` command-line interface that can be used to work with AWS CDK applications. -Command | Description -----------------------------------|------------------------------------------------------------------------------------- -[`cdk docs`](#cdk-docs) | Access the online documentation -[`cdk init`](#cdk-init) | Start a new CDK project (app or library) -[`cdk list`](#cdk-list) | List stacks in an application -[`cdk synth`](#cdk-synthesize) | Synthesize a CDK app to CloudFormation template(s) -[`cdk diff`](#cdk-diff) | Diff stacks against current state -[`cdk deploy`](#cdk-deploy) | Deploy a stack into an AWS account -[`cdk watch`](#cdk-watch) | Watches a CDK app for deployable and hotswappable changes -[`cdk destroy`](#cdk-destroy) | Deletes a stack from an AWS account -[`cdk bootstrap`](#cdk-bootstrap) | Deploy a toolkit stack to support deploying large stacks & artifacts -[`cdk doctor`](#cdk-doctor) | Inspect the environment and produce information useful for troubleshooting +Command | Description +--------------------------------------|--------------------------------------------------------------------------------- +[`cdk docs`](#cdk-docs) | Access the online documentation +[`cdk init`](#cdk-init) | Start a new CDK project (app or library) +[`cdk list`](#cdk-list) | List stacks in an application +[`cdk synth`](#cdk-synthesize) | Synthesize a CDK app to CloudFormation template(s) +[`cdk diff`](#cdk-diff) | Diff stacks against current state +[`cdk deploy`](#cdk-deploy) | Deploy a stack into an AWS account +[`cdk watch`](#cdk-watch) | Watches a CDK app for deployable and hotswappable changes +[`cdk destroy`](#cdk-destroy) | Deletes a stack from an AWS account +[`cdk bootstrap`](#cdk-bootstrap) | Deploy a toolkit stack to support deploying large stacks & artifacts +[`cdk doctor`](#cdk-doctor) | Inspect the environment and produce information useful for troubleshooting +[`cdk acknowledge`](#cdk-acknowledge) | Acknowledge (and hide) a notice by issue number +[`cdk notices`](#cdk-notices) | List all relevant notices for the application This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) project. @@ -346,7 +348,8 @@ $ cdk deploy --hotswap [StackNames] This will attempt to perform a faster, short-circuit deployment if possible (for example, if you only changed the code of a Lambda function in your CDK app, but nothing else in your CDK code), -skipping CloudFormation, and updating the affected resources directly. +skipping CloudFormation, and updating the affected resources directly; +this includes changes to resources in nested stacks. If the tool detects that the change does not support hotswapping, it will fall back and perform a full CloudFormation deployment, exactly like `cdk deploy` does without the `--hotswap` flag. @@ -503,6 +506,102 @@ $ cdk doctor - AWS_SDK_LOAD_CONFIG = 1 ``` +## Notices + +CDK Notices are important messages regarding security vulnerabilities, regressions, and usage of unsupported +versions. Relevant notices appear on every command by default. For example, + +```console +$ cdk deploy + +... # Normal output of the command + +NOTICES + +16603 Toggling off auto_delete_objects for Bucket empties the bucket + + Overview: If a stack is deployed with an S3 bucket with + auto_delete_objects=True, and then re-deployed with + auto_delete_objects=False, all the objects in the bucket + will be deleted. + + Affected versions: <1.126.0. + + More information at: https://github.com/aws/aws-cdk/issues/16603 + + +17061 Error when building EKS cluster with monocdk import + + Overview: When using monocdk/aws-eks to build a stack containing + an EKS cluster, error is thrown about missing + lambda-layer-node-proxy-agent/layer/package.json. + + Affected versions: >=1.126.0 <=1.130.0. + + More information at: https://github.com/aws/aws-cdk/issues/17061 + + +If you don’t want to see an notice anymore, use "cdk acknowledge ID". For example, "cdk acknowledge 16603". +``` + +You can suppress warnings in a variety of ways: + +- per individual execution: + + `cdk deploy --no-notices` + +- disable all notices indefinitely through context in `cdk.json`: + + ```json + { + "notices": false, + "context": { + ... + } + } + ``` + +- acknowleding individual notices via `cdk acknowledge` (see below). + +### `cdk acknowledge` + +To hide a particular notice that has been addressed or does not apply, call `cdk acknowledge` with the ID of +the notice: + +```console +$cdk acknowledge 16603 +``` + +> Please note that the acknowledgements are made project by project. If you acknowledge an notice in one CDK +> project, it will still appear on other projects when you run any CDK commands, unless you have suppressed +> or disabled notices. + + +### `cdk notices` + +List the notices that are relevant to the current CDK repository, regardless of context flags or notices that +have been acknowledged: + +```console +$ cdk notices + +NOTICES + +16603 Toggling off auto_delete_objects for Bucket empties the bucket + + Overview: if a stack is deployed with an S3 bucket with + auto_delete_objects=True, and then re-deployed with + auto_delete_objects=False, all the objects in the bucket + will be deleted. + + Affected versions: framework: <=2.15.0 >=2.10.0 + + More information at: https://github.com/aws/aws-cdk/issues/16603 + + +If you don’t want to see a notice anymore, use "cdk acknowledge ". For example, "cdk acknowledge 16603". +``` + ### Bundling By default asset bundling is skipped for `cdk list` and `cdk destroy`. For `cdk deploy`, `cdk diff` diff --git a/packages/aws-cdk/THIRD_PARTY_LICENSES b/packages/aws-cdk/THIRD_PARTY_LICENSES new file mode 100644 index 0000000000000..f36cbfb82a1b9 --- /dev/null +++ b/packages/aws-cdk/THIRD_PARTY_LICENSES @@ -0,0 +1,3768 @@ +The aws-cdk package includes the following third-party software/licensing: + +** source-map@0.6.1 - https://www.npmjs.com/package/source-map/v/0.6.1 | BSD-3-Clause + +Copyright (c) 2009-2011, Mozilla Foundation and contributors +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the names of the Mozilla Foundation nor the names of project + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +---------------- + +** buffer-from@1.1.2 - https://www.npmjs.com/package/buffer-from/v/1.1.2 | MIT +MIT License + +Copyright (c) 2016, 2018 Linus Unnebäck + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +---------------- + +** source-map-support@0.5.21 - https://www.npmjs.com/package/source-map-support/v/0.5.21 | MIT + +---------------- + +** color-name@1.1.4 - https://www.npmjs.com/package/color-name/v/1.1.4 | MIT +The MIT License (MIT) +Copyright (c) 2015 Dmitry Ivanov + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +---------------- + +** color-convert@2.0.1 - https://www.npmjs.com/package/color-convert/v/2.0.1 | MIT +Copyright (c) 2011-2016 Heather Arthur + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + + +---------------- + +** ansi-styles@4.3.0 - https://www.npmjs.com/package/ansi-styles/v/4.3.0 | MIT +MIT License + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +---------------- + +** has-flag@4.0.0 - https://www.npmjs.com/package/has-flag/v/4.0.0 | MIT +MIT License + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +---------------- + +** supports-color@7.2.0 - https://www.npmjs.com/package/supports-color/v/7.2.0 | MIT +MIT License + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +---------------- + +** chalk@4.1.2 - https://www.npmjs.com/package/chalk/v/4.1.2 | MIT +MIT License + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +---------------- + +** universalify@2.0.0 - https://www.npmjs.com/package/universalify/v/2.0.0 | MIT +(The MIT License) + +Copyright (c) 2017, Ryan Zimmerman + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the 'Software'), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +---------------- + +** graceful-fs@4.2.9 - https://www.npmjs.com/package/graceful-fs/v/4.2.9 | ISC +The ISC License + +Copyright (c) Isaac Z. Schlueter, Ben Noordhuis, and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +---------------- + +** fs-extra@9.1.0 - https://www.npmjs.com/package/fs-extra/v/9.1.0 | MIT +(The MIT License) + +Copyright (c) 2011-2017 JP Richardson + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files +(the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +---------------- + +** at-least-node@1.0.0 - https://www.npmjs.com/package/at-least-node/v/1.0.0 | ISC +The ISC License +Copyright (c) 2020 Ryan Zimmerman + +Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +---------------- + +** jsonfile@6.1.0 - https://www.npmjs.com/package/jsonfile/v/6.1.0 | MIT +(The MIT License) + +Copyright (c) 2012-2015, JP Richardson + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files +(the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +---------------- + +** yaml@1.10.2 - https://www.npmjs.com/package/yaml/v/1.10.2 | ISC +Copyright 2018 Eemeli Aro + +Permission to use, copy, modify, and/or distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright notice +and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. + + +---------------- + +** jsonschema@1.4.0 - https://www.npmjs.com/package/jsonschema/v/1.4.0 | MIT +jsonschema is licensed under MIT license. + +Copyright (C) 2012-2015 Tom de Grunt + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +---------------- + +** semver@7.3.5 - https://www.npmjs.com/package/semver/v/7.3.5 | ISC +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +---------------- + +** yallist@4.0.0 - https://www.npmjs.com/package/yallist/v/4.0.0 | ISC +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +---------------- + +** lru-cache@6.0.0 - https://www.npmjs.com/package/lru-cache/v/6.0.0 | ISC +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +---------------- + +** aws-sdk@2.1079.0 - https://www.npmjs.com/package/aws-sdk/v/2.1079.0 | Apache-2.0 +AWS SDK for JavaScript +Copyright 2012-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + +This product includes software developed at +Amazon Web Services, Inc. (http://aws.amazon.com/). + + +---------------- + +** jmespath@0.16.0 - https://www.npmjs.com/package/jmespath/v/0.16.0 | Apache-2.0 +Copyright 2014 James Saryerwinnie + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + +---------------- + +** uuid@3.3.2 - https://www.npmjs.com/package/uuid/v/3.3.2 | MIT + +---------------- + +** xml2js@0.4.19 - https://www.npmjs.com/package/xml2js/v/0.4.19 | MIT +Copyright 2010, 2011, 2012, 2013. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + + +---------------- + +** xmlbuilder@9.0.7 - https://www.npmjs.com/package/xmlbuilder/v/9.0.7 | MIT +The MIT License (MIT) + +Copyright (c) 2013 Ozgur Ozcitak + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +---------------- + +** sax@1.2.4 - https://www.npmjs.com/package/sax/v/1.2.4 | ISC +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +==== + +`String.fromCodePoint` by Mathias Bynens used according to terms of MIT +License, as follows: + + Copyright Mathias Bynens + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +---------------- + +** fast-deep-equal@3.1.3 - https://www.npmjs.com/package/fast-deep-equal/v/3.1.3 | MIT +MIT License + +Copyright (c) 2017 Evgeny Poberezkin + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +---------------- + +** ansi-regex@5.0.1 - https://www.npmjs.com/package/ansi-regex/v/5.0.1 | MIT +MIT License + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +---------------- + +** strip-ansi@6.0.1 - https://www.npmjs.com/package/strip-ansi/v/6.0.1 | MIT +MIT License + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +---------------- + +** is-fullwidth-code-point@3.0.0 - https://www.npmjs.com/package/is-fullwidth-code-point/v/3.0.0 | MIT +MIT License + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +---------------- + +** emoji-regex@8.0.0 - https://www.npmjs.com/package/emoji-regex/v/8.0.0 | MIT +Copyright Mathias Bynens + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +---------------- + +** string-width@4.2.3 - https://www.npmjs.com/package/string-width/v/4.2.3 | MIT +MIT License + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +---------------- + +** astral-regex@2.0.0 - https://www.npmjs.com/package/astral-regex/v/2.0.0 | MIT +MIT License + +Copyright (c) Kevin Mårtensson (github.com/kevva) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +---------------- + +** slice-ansi@4.0.0 - https://www.npmjs.com/package/slice-ansi/v/4.0.0 | MIT +MIT License + +Copyright (c) DC +Copyright (c) Sindre Sorhus (https://sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +---------------- + +** table@6.8.0 - https://www.npmjs.com/package/table/v/6.8.0 | BSD-3-Clause +Copyright (c) 2018, Gajus Kuizinas (http://gajus.com/) +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Gajus Kuizinas (http://gajus.com/) nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL ANUARY BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +---------------- + +** ajv@8.10.0 - https://www.npmjs.com/package/ajv/v/8.10.0 | MIT +The MIT License (MIT) + +Copyright (c) 2015-2021 Evgeny Poberezkin + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + + +---------------- + +** lodash.truncate@4.4.2 - https://www.npmjs.com/package/lodash.truncate/v/4.4.2 | MIT +Copyright jQuery Foundation and other contributors + +Based on Underscore.js, copyright Jeremy Ashkenas, +DocumentCloud and Investigative Reporters & Editors + +This software consists of voluntary contributions made by many +individuals. For exact contribution history, see the revision history +available at https://github.com/lodash/lodash + +The following license applies to all parts of this software except as +documented below: + +==== + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +==== + +Copyright and related rights for sample code are waived via CC0. Sample +code is defined as all source code displayed within the prose of the +documentation. + +CC0: http://creativecommons.org/publicdomain/zero/1.0/ + +==== + +Files located in the node_modules and vendor directories are externally +maintained libraries used by this software which have their own +licenses; we recommend you read them, as their terms may differ from the +terms above. + + +---------------- + +** diff@5.0.0 - https://www.npmjs.com/package/diff/v/5.0.0 | BSD-3-Clause +Software License Agreement (BSD License) + +Copyright (c) 2009-2015, Kevin Decker + +All rights reserved. + +Redistribution and use of this software in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of Kevin Decker nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------- + +** mute-stream@0.0.8 - https://www.npmjs.com/package/mute-stream/v/0.0.8 | ISC +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +---------------- + +** read@1.0.7 - https://www.npmjs.com/package/read/v/1.0.7 | ISC +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +---------------- + +** promptly@3.2.0 - https://www.npmjs.com/package/promptly/v/3.2.0 | MIT +The MIT License (MIT) + +Copyright (c) 2018 Made With MOXY Lda + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +---------------- + +** yallist@3.1.1 - https://www.npmjs.com/package/yallist/v/3.1.1 | ISC +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +---------------- + +** lru-cache@5.1.1 - https://www.npmjs.com/package/lru-cache/v/5.1.1 | ISC +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +---------------- + +** ms@2.1.2 - https://www.npmjs.com/package/ms/v/2.1.2 | MIT + +---------------- + +** debug@4.3.3 - https://www.npmjs.com/package/debug/v/4.3.3 | MIT +(The MIT License) + +Copyright (c) 2014-2017 TJ Holowaychuk +Copyright (c) 2018-2021 Josh Junon + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software +and associated documentation files (the 'Software'), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + + +---------------- + +** agent-base@6.0.2 - https://www.npmjs.com/package/agent-base/v/6.0.2 | MIT + +---------------- + +** proxy-from-env@1.1.0 - https://www.npmjs.com/package/proxy-from-env/v/1.1.0 | MIT +The MIT License + +Copyright (C) 2016-2018 Rob Wu + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +---------------- + +** data-uri-to-buffer@3.0.1 - https://www.npmjs.com/package/data-uri-to-buffer/v/3.0.1 | MIT + +---------------- + +** get-uri@3.0.2 - https://www.npmjs.com/package/get-uri/v/3.0.2 | MIT + +---------------- + +** universalify@0.1.2 - https://www.npmjs.com/package/universalify/v/0.1.2 | MIT +(The MIT License) + +Copyright (c) 2017, Ryan Zimmerman + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the 'Software'), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +---------------- + +** fs-extra@8.1.0 - https://www.npmjs.com/package/fs-extra/v/8.1.0 | MIT +(The MIT License) + +Copyright (c) 2011-2017 JP Richardson + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files +(the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +---------------- + +** jsonfile@4.0.0 - https://www.npmjs.com/package/jsonfile/v/4.0.0 | MIT +(The MIT License) + +Copyright (c) 2012-2015, JP Richardson + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files +(the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +---------------- + +** file-uri-to-path@2.0.0 - https://www.npmjs.com/package/file-uri-to-path/v/2.0.0 | MIT +Copyright (c) 2014 Nathan Rajlich + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +---------------- + +** @tootallnate/once@1.1.2 - https://www.npmjs.com/package/@tootallnate/once/v/1.1.2 | MIT + +---------------- + +** isarray@0.0.1 - https://www.npmjs.com/package/isarray/v/0.0.1 | MIT + +---------------- + +** core-util-is@1.0.3 - https://www.npmjs.com/package/core-util-is/v/1.0.3 | MIT +Copyright Node.js contributors. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + + +---------------- + +** inherits@2.0.4 - https://www.npmjs.com/package/inherits/v/2.0.4 | ISC +The ISC License + +Copyright (c) Isaac Z. Schlueter + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. + + + +---------------- + +** readable-stream@1.1.14 - https://www.npmjs.com/package/readable-stream/v/1.1.14 | MIT +Copyright Joyent, Inc. and other Node contributors. All rights reserved. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + + +---------------- + +** string_decoder@0.10.31 - https://www.npmjs.com/package/string_decoder/v/0.10.31 | MIT +Copyright Joyent, Inc. and other Node contributors. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the +following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + + +---------------- + +** xregexp@2.0.0 - https://www.npmjs.com/package/xregexp/v/2.0.0 | MIT + +---------------- + +** ftp@0.3.10 - https://www.npmjs.com/package/ftp/v/0.3.10 | MIT +Copyright Brian White. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + +---------------- + +** bytes@3.1.2 - https://www.npmjs.com/package/bytes/v/3.1.2 | MIT +(The MIT License) + +Copyright (c) 2012-2014 TJ Holowaychuk +Copyright (c) 2015 Jed Watson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +---------------- + +** depd@2.0.0 - https://www.npmjs.com/package/depd/v/2.0.0 | MIT +(The MIT License) + +Copyright (c) 2014-2018 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +---------------- + +** setprototypeof@1.2.0 - https://www.npmjs.com/package/setprototypeof/v/1.2.0 | ISC +Copyright (c) 2015, Wes Todd + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +---------------- + +** statuses@2.0.1 - https://www.npmjs.com/package/statuses/v/2.0.1 | MIT + +The MIT License (MIT) + +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2016 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +---------------- + +** toidentifier@1.0.1 - https://www.npmjs.com/package/toidentifier/v/1.0.1 | MIT +MIT License + +Copyright (c) 2016 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +---------------- + +** http-errors@2.0.0 - https://www.npmjs.com/package/http-errors/v/2.0.0 | MIT + +The MIT License (MIT) + +Copyright (c) 2014 Jonathan Ong me@jongleberry.com +Copyright (c) 2016 Douglas Christopher Wilson doug@somethingdoug.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +---------------- + +** safer-buffer@2.1.2 - https://www.npmjs.com/package/safer-buffer/v/2.1.2 | MIT +MIT License + +Copyright (c) 2018 Nikita Skovoroda + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +---------------- + +** iconv-lite@0.4.24 - https://www.npmjs.com/package/iconv-lite/v/0.4.24 | MIT +Copyright (c) 2011 Alexander Shtuchkin + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + + +---------------- + +** unpipe@1.0.0 - https://www.npmjs.com/package/unpipe/v/1.0.0 | MIT +(The MIT License) + +Copyright (c) 2015 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +---------------- + +** raw-body@2.5.0 - https://www.npmjs.com/package/raw-body/v/2.5.0 | MIT +The MIT License (MIT) + +Copyright (c) 2013-2014 Jonathan Ong +Copyright (c) 2014-2015 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +---------------- + +** http-proxy-agent@4.0.1 - https://www.npmjs.com/package/http-proxy-agent/v/4.0.1 | MIT + +---------------- + +** https-proxy-agent@5.0.0 - https://www.npmjs.com/package/https-proxy-agent/v/5.0.0 | MIT + +---------------- + +** ip@1.1.5 - https://www.npmjs.com/package/ip/v/1.1.5 | MIT + +---------------- + +** smart-buffer@4.2.0 - https://www.npmjs.com/package/smart-buffer/v/4.2.0 | MIT +The MIT License (MIT) + +Copyright (c) 2013-2017 Josh Glazebrook + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +---------------- + +** socks@2.6.2 - https://www.npmjs.com/package/socks/v/2.6.2 | MIT +The MIT License (MIT) + +Copyright (c) 2013 Josh Glazebrook + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +---------------- + +** socks-proxy-agent@5.0.1 - https://www.npmjs.com/package/socks-proxy-agent/v/5.0.1 | MIT + +---------------- + +** estraverse@4.3.0 - https://www.npmjs.com/package/estraverse/v/4.3.0 | BSD-2-Clause +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +---------------- + +** esutils@2.0.3 - https://www.npmjs.com/package/esutils/v/2.0.3 | BSD-2-Clause +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +---------------- + +** escodegen@1.14.3 - https://www.npmjs.com/package/escodegen/v/1.14.3 | BSD-2-Clause +Copyright (C) 2012 Yusuke Suzuki (twitter: @Constellation) and other contributors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +---------------- + +** esprima@4.0.1 - https://www.npmjs.com/package/esprima/v/4.0.1 | BSD-2-Clause +Copyright JS Foundation and other contributors, https://js.foundation/ + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +---------------- + +** tslib@2.3.1 - https://www.npmjs.com/package/tslib/v/2.3.1 | 0BSD +Copyright (c) Microsoft Corporation. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. + +---------------- + +** ast-types@0.13.4 - https://www.npmjs.com/package/ast-types/v/0.13.4 | MIT +Copyright (c) 2013 Ben Newman + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +---------------- + +** vm2@3.9.8 - https://www.npmjs.com/package/vm2/v/3.9.8 | MIT + +---------------- + +** acorn@8.7.0 - https://www.npmjs.com/package/acorn/v/8.7.0 | MIT +MIT License + +Copyright (C) 2012-2020 by various contributors (see AUTHORS) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +---------------- + +** acorn-walk@8.2.0 - https://www.npmjs.com/package/acorn-walk/v/8.2.0 | MIT +MIT License + +Copyright (C) 2012-2020 by various contributors (see AUTHORS) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +---------------- + +** degenerator@3.0.2 - https://www.npmjs.com/package/degenerator/v/3.0.2 | MIT + +---------------- + +** pac-resolver@5.0.0 - https://www.npmjs.com/package/pac-resolver/v/5.0.0 | MIT + +---------------- + +** netmask@2.0.2 - https://www.npmjs.com/package/netmask/v/2.0.2 | MIT + +---------------- + +** pac-proxy-agent@5.0.0 - https://www.npmjs.com/package/pac-proxy-agent/v/5.0.0 | MIT + +---------------- + +** proxy-agent@5.0.0 - https://www.npmjs.com/package/proxy-agent/v/5.0.0 | MIT + +---------------- + +** uuid@8.3.2 - https://www.npmjs.com/package/uuid/v/8.3.2 | MIT + +---------------- + +** mime@2.6.0 - https://www.npmjs.com/package/mime/v/2.6.0 | MIT +The MIT License (MIT) + +Copyright (c) 2010 Benjamin Thomas, Robert Kieffer + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +---------------- + +** fs.realpath@1.0.0 - https://www.npmjs.com/package/fs.realpath/v/1.0.0 | ISC +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +---- + +This library bundles a version of the `fs.realpath` and `fs.realpathSync` +methods from Node.js v0.10 under the terms of the Node.js MIT license. + +Node's license follows, also included at the header of `old.js` which contains +the licensed code: + + Copyright Joyent, Inc. and other Node contributors. + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + +---------------- + +** concat-map@0.0.1 - https://www.npmjs.com/package/concat-map/v/0.0.1 | MIT +This software is released under the MIT license: + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +---------------- + +** balanced-match@1.0.2 - https://www.npmjs.com/package/balanced-match/v/1.0.2 | MIT + +---------------- + +** brace-expansion@1.1.11 - https://www.npmjs.com/package/brace-expansion/v/1.1.11 | MIT +MIT License + +Copyright (c) 2013 Julian Gruber + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +---------------- + +** minimatch@3.1.2 - https://www.npmjs.com/package/minimatch/v/3.1.2 | ISC +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +---------------- + +** path-is-absolute@1.0.1 - https://www.npmjs.com/package/path-is-absolute/v/1.0.1 | MIT +The MIT License (MIT) + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +---------------- + +** glob@7.2.0 - https://www.npmjs.com/package/glob/v/7.2.0 | ISC +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +## Glob Logo + +Glob's logo created by Tanya Brassie , licensed +under a Creative Commons Attribution-ShareAlike 4.0 International License +https://creativecommons.org/licenses/by-sa/4.0/ + + +---------------- + +** wrappy@1.0.2 - https://www.npmjs.com/package/wrappy/v/1.0.2 | ISC +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +---------------- + +** once@1.4.0 - https://www.npmjs.com/package/once/v/1.4.0 | ISC +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +---------------- + +** inflight@1.0.6 - https://www.npmjs.com/package/inflight/v/1.0.6 | ISC +The ISC License + +Copyright (c) Isaac Z. Schlueter + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +---------------- + +** readdir-glob@1.1.1 - https://www.npmjs.com/package/readdir-glob/v/1.1.1 | Apache-2.0 + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2020 Yann Armelin + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +---------------- + +** async@3.2.3 - https://www.npmjs.com/package/async/v/3.2.3 | MIT +Copyright (c) 2010-2018 Caolan McMahon + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +---------------- + +** process-nextick-args@2.0.1 - https://www.npmjs.com/package/process-nextick-args/v/2.0.1 | MIT + +---------------- + +** isarray@1.0.0 - https://www.npmjs.com/package/isarray/v/1.0.0 | MIT + +---------------- + +** readable-stream@2.3.7 - https://www.npmjs.com/package/readable-stream/v/2.3.7 | MIT +Node.js is licensed for use as follows: + +""" +Copyright Node.js contributors. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. +""" + +This license applies to parts of Node.js originating from the +https://github.com/joyent/node repository: + +""" +Copyright Joyent, Inc. and other Node contributors. All rights reserved. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. +""" + + +---------------- + +** safe-buffer@5.1.2 - https://www.npmjs.com/package/safe-buffer/v/5.1.2 | MIT +The MIT License (MIT) + +Copyright (c) Feross Aboukhadijeh + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +---------------- + +** util-deprecate@1.0.2 - https://www.npmjs.com/package/util-deprecate/v/1.0.2 | MIT +(The MIT License) + +Copyright (c) 2014 Nathan Rajlich + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + + +---------------- + +** string_decoder@1.1.1 - https://www.npmjs.com/package/string_decoder/v/1.1.1 | MIT +Node.js is licensed for use as follows: + +""" +Copyright Node.js contributors. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. +""" + +This license applies to parts of Node.js originating from the +https://github.com/joyent/node repository: + +""" +Copyright Joyent, Inc. and other Node contributors. All rights reserved. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. +""" + + + +---------------- + +** lazystream@1.0.1 - https://www.npmjs.com/package/lazystream/v/1.0.1 | MIT +Copyright (c) 2013 J. Pommerening, contributors. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + + + +---------------- + +** normalize-path@3.0.0 - https://www.npmjs.com/package/normalize-path/v/3.0.0 | MIT +The MIT License (MIT) + +Copyright (c) 2014-2018, Jon Schlinkert. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +---------------- + +** lodash.defaults@4.2.0 - https://www.npmjs.com/package/lodash.defaults/v/4.2.0 | MIT +Copyright jQuery Foundation and other contributors + +Based on Underscore.js, copyright Jeremy Ashkenas, +DocumentCloud and Investigative Reporters & Editors + +This software consists of voluntary contributions made by many +individuals. For exact contribution history, see the revision history +available at https://github.com/lodash/lodash + +The following license applies to all parts of this software except as +documented below: + +==== + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +==== + +Copyright and related rights for sample code are waived via CC0. Sample +code is defined as all source code displayed within the prose of the +documentation. + +CC0: http://creativecommons.org/publicdomain/zero/1.0/ + +==== + +Files located in the node_modules and vendor directories are externally +maintained libraries used by this software which have their own +licenses; we recommend you read them, as their terms may differ from the +terms above. + + +---------------- + +** lodash.flatten@4.4.0 - https://www.npmjs.com/package/lodash.flatten/v/4.4.0 | MIT +Copyright jQuery Foundation and other contributors + +Based on Underscore.js, copyright Jeremy Ashkenas, +DocumentCloud and Investigative Reporters & Editors + +This software consists of voluntary contributions made by many +individuals. For exact contribution history, see the revision history +available at https://github.com/lodash/lodash + +The following license applies to all parts of this software except as +documented below: + +==== + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +==== + +Copyright and related rights for sample code are waived via CC0. Sample +code is defined as all source code displayed within the prose of the +documentation. + +CC0: http://creativecommons.org/publicdomain/zero/1.0/ + +==== + +Files located in the node_modules and vendor directories are externally +maintained libraries used by this software which have their own +licenses; we recommend you read them, as their terms may differ from the +terms above. + + +---------------- + +** lodash.difference@4.5.0 - https://www.npmjs.com/package/lodash.difference/v/4.5.0 | MIT +Copyright jQuery Foundation and other contributors + +Based on Underscore.js, copyright Jeremy Ashkenas, +DocumentCloud and Investigative Reporters & Editors + +This software consists of voluntary contributions made by many +individuals. For exact contribution history, see the revision history +available at https://github.com/lodash/lodash + +The following license applies to all parts of this software except as +documented below: + +==== + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +==== + +Copyright and related rights for sample code are waived via CC0. Sample +code is defined as all source code displayed within the prose of the +documentation. + +CC0: http://creativecommons.org/publicdomain/zero/1.0/ + +==== + +Files located in the node_modules and vendor directories are externally +maintained libraries used by this software which have their own +licenses; we recommend you read them, as their terms may differ from the +terms above. + + +---------------- + +** lodash.union@4.6.0 - https://www.npmjs.com/package/lodash.union/v/4.6.0 | MIT +Copyright jQuery Foundation and other contributors + +Based on Underscore.js, copyright Jeremy Ashkenas, +DocumentCloud and Investigative Reporters & Editors + +This software consists of voluntary contributions made by many +individuals. For exact contribution history, see the revision history +available at https://github.com/lodash/lodash + +The following license applies to all parts of this software except as +documented below: + +==== + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +==== + +Copyright and related rights for sample code are waived via CC0. Sample +code is defined as all source code displayed within the prose of the +documentation. + +CC0: http://creativecommons.org/publicdomain/zero/1.0/ + +==== + +Files located in the node_modules and vendor directories are externally +maintained libraries used by this software which have their own +licenses; we recommend you read them, as their terms may differ from the +terms above. + + +---------------- + +** lodash.isplainobject@4.0.6 - https://www.npmjs.com/package/lodash.isplainobject/v/4.0.6 | MIT +Copyright jQuery Foundation and other contributors + +Based on Underscore.js, copyright Jeremy Ashkenas, +DocumentCloud and Investigative Reporters & Editors + +This software consists of voluntary contributions made by many +individuals. For exact contribution history, see the revision history +available at https://github.com/lodash/lodash + +The following license applies to all parts of this software except as +documented below: + +==== + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +==== + +Copyright and related rights for sample code are waived via CC0. Sample +code is defined as all source code displayed within the prose of the +documentation. + +CC0: http://creativecommons.org/publicdomain/zero/1.0/ + +==== + +Files located in the node_modules and vendor directories are externally +maintained libraries used by this software which have their own +licenses; we recommend you read them, as their terms may differ from the +terms above. + + +---------------- + +** archiver-utils@2.1.0 - https://www.npmjs.com/package/archiver-utils/v/2.1.0 | MIT +Copyright (c) 2015 Chris Talkington. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +---------------- + +** archiver@5.3.0 - https://www.npmjs.com/package/archiver/v/5.3.0 | MIT +Copyright (c) 2012-2014 Chris Talkington, contributors. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +---------------- + +** readable-stream@3.6.0 - https://www.npmjs.com/package/readable-stream/v/3.6.0 | MIT +Node.js is licensed for use as follows: + +""" +Copyright Node.js contributors. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. +""" + +This license applies to parts of Node.js originating from the +https://github.com/joyent/node repository: + +""" +Copyright Joyent, Inc. and other Node contributors. All rights reserved. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. +""" + + +---------------- + +** safe-buffer@5.2.1 - https://www.npmjs.com/package/safe-buffer/v/5.2.1 | MIT +The MIT License (MIT) + +Copyright (c) Feross Aboukhadijeh + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +---------------- + +** string_decoder@1.3.0 - https://www.npmjs.com/package/string_decoder/v/1.3.0 | MIT +Node.js is licensed for use as follows: + +""" +Copyright Node.js contributors. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. +""" + +This license applies to parts of Node.js originating from the +https://github.com/joyent/node repository: + +""" +Copyright Joyent, Inc. and other Node contributors. All rights reserved. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. +""" + + + +---------------- + +** compress-commons@4.1.1 - https://www.npmjs.com/package/compress-commons/v/4.1.1 | MIT +Copyright (c) 2014 Chris Talkington, contributors. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +---------------- + +** buffer-crc32@0.2.13 - https://www.npmjs.com/package/buffer-crc32/v/0.2.13 | MIT +The MIT License + +Copyright (c) 2013 Brian J. Brennan + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +---------------- + +** crc-32@1.2.1 - https://www.npmjs.com/package/crc-32/v/1.2.1 | Apache-2.0 + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright (C) 2014-present SheetJS LLC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +---------------- + +** crc32-stream@4.0.2 - https://www.npmjs.com/package/crc32-stream/v/4.0.2 | MIT +Copyright (c) 2014 Chris Talkington, contributors. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +---------------- + +** zip-stream@4.1.0 - https://www.npmjs.com/package/zip-stream/v/4.1.0 | MIT +Copyright (c) 2014 Chris Talkington, contributors. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +---------------- + +** bl@4.1.0 - https://www.npmjs.com/package/bl/v/4.1.0 | MIT + +---------------- + +** tar-stream@2.2.0 - https://www.npmjs.com/package/tar-stream/v/2.2.0 | MIT +The MIT License (MIT) + +Copyright (c) 2014 Mathias Buus + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +---------------- + +** fs-constants@1.0.0 - https://www.npmjs.com/package/fs-constants/v/1.0.0 | MIT +The MIT License (MIT) + +Copyright (c) 2018 Mathias Buus + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +---------------- + +** end-of-stream@1.4.4 - https://www.npmjs.com/package/end-of-stream/v/1.4.4 | MIT +The MIT License (MIT) + +Copyright (c) 2014 Mathias Buus + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +---------------- + +** wrap-ansi@7.0.0 - https://www.npmjs.com/package/wrap-ansi/v/7.0.0 | MIT +MIT License + +Copyright (c) Sindre Sorhus (https://sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +---------------- + +** @jsii/check-node@1.54.0 - https://www.npmjs.com/package/@jsii/check-node/v/1.54.0 | Apache-2.0 +jsii +Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + +---------------- + +** brace-expansion@2.0.1 - https://www.npmjs.com/package/brace-expansion/v/2.0.1 | MIT +MIT License + +Copyright (c) 2013 Julian Gruber + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +---------------- + +** minimatch@5.0.0 - https://www.npmjs.com/package/minimatch/v/5.0.0 | ISC +The ISC License + +Copyright (c) 2011-2022 Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +---------------- + +** picomatch@2.3.1 - https://www.npmjs.com/package/picomatch/v/2.3.1 | MIT +The MIT License (MIT) + +Copyright (c) 2017-present, Jon Schlinkert. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +---------------- + +** readdirp@3.6.0 - https://www.npmjs.com/package/readdirp/v/3.6.0 | MIT +MIT License + +Copyright (c) 2012-2019 Thorsten Lorenz, Paul Miller (https://paulmillr.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +---------------- + +** anymatch@3.1.2 - https://www.npmjs.com/package/anymatch/v/3.1.2 | ISC +The ISC License + +Copyright (c) 2019 Elan Shanker, Paul Miller (https://paulmillr.com) + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +---------------- + +** is-extglob@2.1.1 - https://www.npmjs.com/package/is-extglob/v/2.1.1 | MIT +The MIT License (MIT) + +Copyright (c) 2014-2016, Jon Schlinkert + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +---------------- + +** is-glob@4.0.3 - https://www.npmjs.com/package/is-glob/v/4.0.3 | MIT +The MIT License (MIT) + +Copyright (c) 2014-2017, Jon Schlinkert. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +---------------- + +** glob-parent@5.1.2 - https://www.npmjs.com/package/glob-parent/v/5.1.2 | ISC +The ISC License + +Copyright (c) 2015, 2019 Elan Shanker + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +---------------- + +** braces@3.0.2 - https://www.npmjs.com/package/braces/v/3.0.2 | MIT +The MIT License (MIT) + +Copyright (c) 2014-2018, Jon Schlinkert. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +---------------- + +** is-number@7.0.0 - https://www.npmjs.com/package/is-number/v/7.0.0 | MIT +The MIT License (MIT) + +Copyright (c) 2014-present, Jon Schlinkert. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +---------------- + +** to-regex-range@5.0.1 - https://www.npmjs.com/package/to-regex-range/v/5.0.1 | MIT +The MIT License (MIT) + +Copyright (c) 2015-present, Jon Schlinkert. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +---------------- + +** fill-range@7.0.1 - https://www.npmjs.com/package/fill-range/v/7.0.1 | MIT +The MIT License (MIT) + +Copyright (c) 2014-present, Jon Schlinkert. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +---------------- + +** binary-extensions@2.2.0 - https://www.npmjs.com/package/binary-extensions/v/2.2.0 | MIT +MIT License + +Copyright (c) 2019 Sindre Sorhus (https://sindresorhus.com), Paul Miller (https://paulmillr.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +---------------- + +** is-binary-path@2.1.0 - https://www.npmjs.com/package/is-binary-path/v/2.1.0 | MIT +MIT License + +Copyright (c) 2019 Sindre Sorhus (https://sindresorhus.com), Paul Miller (https://paulmillr.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +---------------- + +** chokidar@3.5.3 - https://www.npmjs.com/package/chokidar/v/3.5.3 | MIT +The MIT License (MIT) + +Copyright (c) 2012-2019 Paul Miller (https://paulmillr.com), Elan Shanker + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the “Software”), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +---------------- + +** camelcase@6.3.0 - https://www.npmjs.com/package/camelcase/v/6.3.0 | MIT +MIT License + +Copyright (c) Sindre Sorhus (https://sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +---------------- + +** decamelize@5.0.1 - https://www.npmjs.com/package/decamelize/v/5.0.1 | MIT +MIT License + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +---------------- + +** y18n@5.0.8 - https://www.npmjs.com/package/y18n/v/5.0.8 | ISC +Copyright (c) 2015, Contributors + +Permission to use, copy, modify, and/or distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright notice +and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. + + +---------------- + +** yargs-parser@20.2.9 - https://www.npmjs.com/package/yargs-parser/v/20.2.9 | ISC +Copyright (c) 2016, Contributors + +Permission to use, copy, modify, and/or distribute this software +for any purpose with or without fee is hereby granted, provided +that the above copyright notice and this permission notice +appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE +LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES +OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +---------------- + +** cliui@7.0.4 - https://www.npmjs.com/package/cliui/v/7.0.4 | ISC +Copyright (c) 2015, Contributors + +Permission to use, copy, modify, and/or distribute this software +for any purpose with or without fee is hereby granted, provided +that the above copyright notice and this permission notice +appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE +LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES +OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +---------------- + +** escalade@3.1.1 - https://www.npmjs.com/package/escalade/v/3.1.1 | MIT +MIT License + +Copyright (c) Luke Edwards (lukeed.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +---------------- + +** get-caller-file@2.0.5 - https://www.npmjs.com/package/get-caller-file/v/2.0.5 | ISC + +---------------- + +** require-directory@2.1.1 - https://www.npmjs.com/package/require-directory/v/2.1.1 | MIT +The MIT License (MIT) + +Copyright (c) 2011 Troy Goode + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +---------------- + +** yargs@16.2.0 - https://www.npmjs.com/package/yargs/v/16.2.0 | MIT +MIT License + +Copyright 2010 James Halliday (mail@substack.net); Modified work Copyright 2014 Contributors (ben@npmjs.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +---------------- diff --git a/packages/aws-cdk/bin/cdk.ts b/packages/aws-cdk/bin/cdk.ts index 67c46168f6793..4f2652b107236 100644 --- a/packages/aws-cdk/bin/cdk.ts +++ b/packages/aws-cdk/bin/cdk.ts @@ -1,575 +1,3 @@ -#!/usr/bin/env node -import 'source-map-support/register'; -import * as cxapi from '@aws-cdk/cx-api'; -import '@jsii/check-node/run'; -import * as chalk from 'chalk'; -import * as yargs from 'yargs'; +import { cli } from '../lib'; -import { SdkProvider } from '../lib/api/aws-auth'; -import { BootstrapSource, Bootstrapper } from '../lib/api/bootstrap'; -import { CloudFormationDeployments } from '../lib/api/cloudformation-deployments'; -import { StackSelector } from '../lib/api/cxapp/cloud-assembly'; -import { CloudExecutable } from '../lib/api/cxapp/cloud-executable'; -import { execProgram } from '../lib/api/cxapp/exec'; -import { ToolkitInfo } from '../lib/api/toolkit-info'; -import { StackActivityProgress } from '../lib/api/util/cloudformation/stack-activity-monitor'; -import { CdkToolkit } from '../lib/cdk-toolkit'; -import { realHandler as context } from '../lib/commands/context'; -import { realHandler as docs } from '../lib/commands/docs'; -import { realHandler as doctor } from '../lib/commands/doctor'; -import { RequireApproval } from '../lib/diff'; -import { availableInitLanguages, cliInit, printAvailableTemplates } from '../lib/init'; -import { data, debug, error, print, setLogLevel } from '../lib/logging'; -import { PluginHost } from '../lib/plugin'; -import { serializeStructure } from '../lib/serialize'; -import { Command, Configuration, Settings } from '../lib/settings'; -import * as version from '../lib/version'; - -/* eslint-disable max-len */ -/* eslint-disable @typescript-eslint/no-shadow */ // yargs - -async function parseCommandLineArguments() { - // Use the following configuration for array arguments: - // - // { type: 'array', default: [], nargs: 1, requiresArg: true } - // - // The default behavior of yargs is to eat all strings following an array argument: - // - // ./prog --arg one two positional => will parse to { arg: ['one', 'two', 'positional'], _: [] } (so no positional arguments) - // ./prog --arg one two -- positional => does not help, for reasons that I can't understand. Still gets parsed incorrectly. - // - // By using the config above, every --arg will only consume one argument, so you can do the following: - // - // ./prog --arg one --arg two position => will parse to { arg: ['one', 'two'], _: ['positional'] }. - - const defaultBrowserCommand: { [key in NodeJS.Platform]?: string } = { - darwin: 'open %u', - win32: 'start %u', - }; - - const initTemplateLanguages = await availableInitLanguages(); - return yargs - .env('CDK') - .usage('Usage: cdk -a COMMAND') - .option('app', { type: 'string', alias: 'a', desc: 'REQUIRED: command-line for executing your app or a cloud assembly directory (e.g. "node bin/my-app.js")', requiresArg: true }) - .option('context', { type: 'array', alias: 'c', desc: 'Add contextual string parameter (KEY=VALUE)', nargs: 1, requiresArg: true }) - .option('plugin', { type: 'array', alias: 'p', desc: 'Name or path of a node package that extend the CDK features. Can be specified multiple times', nargs: 1 }) - .option('trace', { type: 'boolean', desc: 'Print trace for stack warnings' }) - .option('strict', { type: 'boolean', desc: 'Do not construct stacks with warnings' }) - .option('lookups', { type: 'boolean', desc: 'Perform context lookups (synthesis fails if this is disabled and context lookups need to be performed)', default: true }) - .option('ignore-errors', { type: 'boolean', default: false, desc: 'Ignores synthesis errors, which will likely produce an invalid output' }) - .option('json', { type: 'boolean', alias: 'j', desc: 'Use JSON output instead of YAML when templates are printed to STDOUT', default: false }) - .option('verbose', { type: 'boolean', alias: 'v', desc: 'Show debug logs (specify multiple times to increase verbosity)', default: false }) - .count('verbose') - .option('debug', { type: 'boolean', desc: 'Enable emission of additional debugging information, such as creation stack traces of tokens', default: false }) - .option('profile', { type: 'string', desc: 'Use the indicated AWS profile as the default environment', requiresArg: true }) - .option('proxy', { type: 'string', desc: 'Use the indicated proxy. Will read from HTTPS_PROXY environment variable if not specified', requiresArg: true }) - .option('ca-bundle-path', { type: 'string', desc: 'Path to CA certificate to use when validating HTTPS requests. Will read from AWS_CA_BUNDLE environment variable if not specified', requiresArg: true }) - .option('ec2creds', { type: 'boolean', alias: 'i', default: undefined, desc: 'Force trying to fetch EC2 instance credentials. Default: guess EC2 instance status' }) - .option('version-reporting', { type: 'boolean', desc: 'Include the "AWS::CDK::Metadata" resource in synthesized templates (enabled by default)', default: undefined }) - .option('path-metadata', { type: 'boolean', desc: 'Include "aws:cdk:path" CloudFormation metadata for each resource (enabled by default)', default: true }) - .option('asset-metadata', { type: 'boolean', desc: 'Include "aws:asset:*" CloudFormation metadata for resources that uses assets (enabled by default)', default: true }) - .option('role-arn', { type: 'string', alias: 'r', desc: 'ARN of Role to use when invoking CloudFormation', default: undefined, requiresArg: true }) - .option('staging', { type: 'boolean', desc: 'Copy assets to the output directory (use --no-staging to disable, needed for local debugging the source files with SAM CLI)', default: true }) - .option('output', { type: 'string', alias: 'o', desc: 'Emits the synthesized cloud assembly into a directory (default: cdk.out)', requiresArg: true }) - .option('no-color', { type: 'boolean', desc: 'Removes colors and other style from console output', default: false }) - .command(['list [STACKS..]', 'ls [STACKS..]'], 'Lists all stacks in the app', yargs => yargs - .option('long', { type: 'boolean', default: false, alias: 'l', desc: 'Display environment information for each stack' }), - ) - .command(['synthesize [STACKS..]', 'synth [STACKS..]'], 'Synthesizes and prints the CloudFormation template for this stack', yargs => yargs - .option('exclusively', { type: 'boolean', alias: 'e', desc: 'Only synthesize requested stacks, don\'t include dependencies' }) - .option('validation', { type: 'boolean', desc: 'After synthesis, validate stacks with the "validateOnSynth" attribute set (can also be controlled with CDK_VALIDATION)', default: true }) - .option('quiet', { type: 'boolean', alias: 'q', desc: 'Do not output CloudFormation Template to stdout', default: false })) - .command('bootstrap [ENVIRONMENTS..]', 'Deploys the CDK toolkit stack into an AWS environment', yargs => yargs - .option('bootstrap-bucket-name', { type: 'string', alias: ['b', 'toolkit-bucket-name'], desc: 'The name of the CDK toolkit bucket; bucket will be created and must not exist', default: undefined }) - .option('bootstrap-kms-key-id', { type: 'string', desc: 'AWS KMS master key ID used for the SSE-KMS encryption', default: undefined, conflicts: 'bootstrap-customer-key' }) - .option('bootstrap-customer-key', { type: 'boolean', desc: 'Create a Customer Master Key (CMK) for the bootstrap bucket (you will be charged but can customize permissions, modern bootstrapping only)', default: undefined, conflicts: 'bootstrap-kms-key-id' }) - .option('qualifier', { type: 'string', desc: 'String which must be unique for each bootstrap stack. You must configure it on your CDK app if you change this from the default.', default: undefined }) - .option('public-access-block-configuration', { type: 'boolean', desc: 'Block public access configuration on CDK toolkit bucket (enabled by default) ', default: undefined }) - .option('tags', { type: 'array', alias: 't', desc: 'Tags to add for the stack (KEY=VALUE)', nargs: 1, requiresArg: true, default: [] }) - .option('execute', { type: 'boolean', desc: 'Whether to execute ChangeSet (--no-execute will NOT execute the ChangeSet)', default: true }) - .option('trust', { type: 'array', desc: 'The AWS account IDs that should be trusted to perform deployments into this environment (may be repeated, modern bootstrapping only)', default: [], nargs: 1, requiresArg: true }) - .option('trust-for-lookup', { type: 'array', desc: 'The AWS account IDs that should be trusted to look up values in this environment (may be repeated, modern bootstrapping only)', default: [], nargs: 1, requiresArg: true }) - .option('cloudformation-execution-policies', { type: 'array', desc: 'The Managed Policy ARNs that should be attached to the role performing deployments into this environment (may be repeated, modern bootstrapping only)', default: [], nargs: 1, requiresArg: true }) - .option('force', { alias: 'f', type: 'boolean', desc: 'Always bootstrap even if it would downgrade template version', default: false }) - .option('termination-protection', { type: 'boolean', default: undefined, desc: 'Toggle CloudFormation termination protection on the bootstrap stacks' }) - .option('show-template', { type: 'boolean', desc: 'Instead of actual bootstrapping, print the current CLI\'s bootstrapping template to stdout for customization', default: false }) - .option('toolkit-stack-name', { type: 'string', desc: 'The name of the CDK toolkit stack to create', requiresArg: true }) - .option('template', { type: 'string', requiresArg: true, desc: 'Use the template from the given file instead of the built-in one (use --show-template to obtain an example)' }), - ) - .command('deploy [STACKS..]', 'Deploys the stack(s) named STACKS into your AWS account', yargs => yargs - .option('all', { type: 'boolean', default: false, desc: 'Deploy all available stacks' }) - .option('build-exclude', { type: 'array', alias: 'E', nargs: 1, desc: 'Do not rebuild asset with the given ID. Can be specified multiple times', default: [] }) - .option('exclusively', { type: 'boolean', alias: 'e', desc: 'Only deploy requested stacks, don\'t include dependencies' }) - .option('require-approval', { type: 'string', choices: [RequireApproval.Never, RequireApproval.AnyChange, RequireApproval.Broadening], desc: 'What security-sensitive changes need manual approval' }) - .option('ci', { type: 'boolean', desc: 'Force CI detection', default: process.env.CI !== undefined }) - .option('notification-arns', { type: 'array', desc: 'ARNs of SNS topics that CloudFormation will notify with stack related events', nargs: 1, requiresArg: true }) - // @deprecated(v2) -- tags are part of the Cloud Assembly and tags specified here will be overwritten on the next deployment - .option('tags', { type: 'array', alias: 't', desc: 'Tags to add to the stack (KEY=VALUE), overrides tags from Cloud Assembly (deprecated)', nargs: 1, requiresArg: true }) - .option('execute', { type: 'boolean', desc: 'Whether to execute ChangeSet (--no-execute will NOT execute the ChangeSet)', default: true }) - .option('change-set-name', { type: 'string', desc: 'Name of the CloudFormation change set to create' }) - .option('force', { alias: 'f', type: 'boolean', desc: 'Always deploy stack even if templates are identical', default: false }) - .option('parameters', { type: 'array', desc: 'Additional parameters passed to CloudFormation at deploy time (STACK:KEY=VALUE)', nargs: 1, requiresArg: true, default: {} }) - .option('outputs-file', { type: 'string', alias: 'O', desc: 'Path to file where stack outputs will be written as JSON', requiresArg: true }) - .option('previous-parameters', { type: 'boolean', default: true, desc: 'Use previous values for existing parameters (you must specify all parameters on every deployment if this is disabled)' }) - .option('toolkit-stack-name', { type: 'string', desc: 'The name of the existing CDK toolkit stack (only used for app using legacy synthesis)', requiresArg: true }) - .option('progress', { type: 'string', choices: [StackActivityProgress.BAR, StackActivityProgress.EVENTS], desc: 'Display mode for stack activity events' }) - .option('rollback', { - type: 'boolean', - desc: "Rollback stack to stable state on failure. Defaults to 'true', iterate more rapidly with --no-rollback or -R. " + - 'Note: do **not** disable this flag for deployments with resource replacements, as that will always fail', - }) - // Hack to get '-R' as an alias for '--no-rollback', suggested by: https://github.com/yargs/yargs/issues/1729 - .option('R', { type: 'boolean', hidden: true }).middleware(yargsNegativeAlias('R', 'rollback'), true) - .option('hotswap', { - type: 'boolean', - desc: "Attempts to perform a 'hotswap' deployment, " + - 'which skips CloudFormation and updates the resources directly, ' + - 'and falls back to a full deployment if that is not possible. ' + - 'Do not use this in production environments', - }) - .option('watch', { - type: 'boolean', - desc: 'Continuously observe the project files, ' + - 'and deploy the given stack(s) automatically when changes are detected. ' + - 'Implies --hotswap by default', - }) - .options('logs', { - type: 'boolean', - default: true, - desc: 'Show CloudWatch log events from all resources in the selected Stacks in the terminal. ' + - "'true' by default, use --no-logs to turn off. " + - "Only in effect if specified alongside the '--watch' option", - }), - ) - .command('watch [STACKS..]', "Shortcut for 'deploy --watch'", yargs => yargs - // I'm fairly certain none of these options, present for 'deploy', make sense for 'watch': - // .option('all', { type: 'boolean', default: false, desc: 'Deploy all available stacks' }) - // .option('ci', { type: 'boolean', desc: 'Force CI detection', default: process.env.CI !== undefined }) - // @deprecated(v2) -- tags are part of the Cloud Assembly and tags specified here will be overwritten on the next deployment - // .option('tags', { type: 'array', alias: 't', desc: 'Tags to add to the stack (KEY=VALUE), overrides tags from Cloud Assembly (deprecated)', nargs: 1, requiresArg: true }) - // .option('execute', { type: 'boolean', desc: 'Whether to execute ChangeSet (--no-execute will NOT execute the ChangeSet)', default: true }) - // These options, however, are more subtle - I could be convinced some of these should also be available for 'watch': - // .option('require-approval', { type: 'string', choices: [RequireApproval.Never, RequireApproval.AnyChange, RequireApproval.Broadening], desc: 'What security-sensitive changes need manual approval' }) - // .option('parameters', { type: 'array', desc: 'Additional parameters passed to CloudFormation at deploy time (STACK:KEY=VALUE)', nargs: 1, requiresArg: true, default: {} }) - // .option('previous-parameters', { type: 'boolean', default: true, desc: 'Use previous values for existing parameters (you must specify all parameters on every deployment if this is disabled)' }) - // .option('outputs-file', { type: 'string', alias: 'O', desc: 'Path to file where stack outputs will be written as JSON', requiresArg: true }) - // .option('notification-arns', { type: 'array', desc: 'ARNs of SNS topics that CloudFormation will notify with stack related events', nargs: 1, requiresArg: true }) - .option('build-exclude', { type: 'array', alias: 'E', nargs: 1, desc: 'Do not rebuild asset with the given ID. Can be specified multiple times', default: [] }) - .option('exclusively', { type: 'boolean', alias: 'e', desc: 'Only deploy requested stacks, don\'t include dependencies' }) - .option('change-set-name', { type: 'string', desc: 'Name of the CloudFormation change set to create' }) - .option('force', { alias: 'f', type: 'boolean', desc: 'Always deploy stack even if templates are identical', default: false }) - .option('toolkit-stack-name', { type: 'string', desc: 'The name of the existing CDK toolkit stack (only used for app using legacy synthesis)', requiresArg: true }) - .option('progress', { type: 'string', choices: [StackActivityProgress.BAR, StackActivityProgress.EVENTS], desc: 'Display mode for stack activity events' }) - .option('rollback', { - type: 'boolean', - desc: "Rollback stack to stable state on failure. Defaults to 'true', iterate more rapidly with --no-rollback or -R. " + - 'Note: do **not** disable this flag for deployments with resource replacements, as that will always fail', - }) - // same hack for -R as above in 'deploy' - .option('R', { type: 'boolean', hidden: true }).middleware(yargsNegativeAlias('R', 'rollback'), true) - .option('hotswap', { - type: 'boolean', - desc: "Attempts to perform a 'hotswap' deployment, " + - 'which skips CloudFormation and updates the resources directly, ' + - 'and falls back to a full deployment if that is not possible. ' + - "'true' by default, use --no-hotswap to turn off", - }) - .options('logs', { - type: 'boolean', - default: true, - desc: 'Show CloudWatch log events from all resources in the selected Stacks in the terminal. ' + - "'true' by default, use --no-logs to turn off", - }), - ) - .command('destroy [STACKS..]', 'Destroy the stack(s) named STACKS', yargs => yargs - .option('all', { type: 'boolean', default: false, desc: 'Destroy all available stacks' }) - .option('exclusively', { type: 'boolean', alias: 'e', desc: 'Only destroy requested stacks, don\'t include dependees' }) - .option('force', { type: 'boolean', alias: 'f', desc: 'Do not ask for confirmation before destroying the stacks' })) - .command('diff [STACKS..]', 'Compares the specified stack with the deployed stack or a local template file, and returns with status 1 if any difference is found', yargs => yargs - .option('exclusively', { type: 'boolean', alias: 'e', desc: 'Only diff requested stacks, don\'t include dependencies' }) - .option('context-lines', { type: 'number', desc: 'Number of context lines to include in arbitrary JSON diff rendering', default: 3, requiresArg: true }) - .option('template', { type: 'string', desc: 'The path to the CloudFormation template to compare with', requiresArg: true }) - .option('strict', { type: 'boolean', desc: 'Do not filter out AWS::CDK::Metadata resources', default: false }) - .option('security-only', { type: 'boolean', desc: 'Only diff for broadened security changes', default: false }) - .option('fail', { type: 'boolean', desc: 'Fail with exit code 1 in case of diff', default: false })) - .command('metadata [STACK]', 'Returns all metadata associated with this stack') - .command('init [TEMPLATE]', 'Create a new, empty CDK project from a template.', yargs => yargs - .option('language', { type: 'string', alias: 'l', desc: 'The language to be used for the new project (default can be configured in ~/.cdk.json)', choices: initTemplateLanguages }) - .option('list', { type: 'boolean', desc: 'List the available templates' }) - .option('generate-only', { type: 'boolean', default: false, desc: 'If true, only generates project files, without executing additional operations such as setting up a git repo, installing dependencies or compiling the project' }), - ) - .command('context', 'Manage cached context values', yargs => yargs - .option('reset', { alias: 'e', desc: 'The context key (or its index) to reset', type: 'string', requiresArg: true }) - .option('clear', { desc: 'Clear all context', type: 'boolean' })) - .command(['docs', 'doc'], 'Opens the reference documentation in a browser', yargs => yargs - .option('browser', { - alias: 'b', - desc: 'the command to use to open the browser, using %u as a placeholder for the path of the file to open', - type: 'string', - default: process.platform in defaultBrowserCommand ? defaultBrowserCommand[process.platform] : 'xdg-open %u', - })) - .command('doctor', 'Check your set-up for potential problems') - .version(version.DISPLAY_VERSION) - .demandCommand(1, '') // just print help - .recommendCommands() - .help() - .alias('h', 'help') - .epilogue([ - 'If your app has a single stack, there is no need to specify the stack name', - 'If one of cdk.json or ~/.cdk.json exists, options specified there will be used as defaults. Settings in cdk.json take precedence.', - ].join('\n\n')) - .argv; -} - -if (!process.stdout.isTTY) { - // Disable chalk color highlighting - process.env.FORCE_COLOR = '0'; -} - -async function initCommandLine() { - const argv = await parseCommandLineArguments(); - if (argv.verbose) { - setLogLevel(argv.verbose); - } - debug('CDK toolkit version:', version.DISPLAY_VERSION); - debug('Command line arguments:', argv); - - const configuration = new Configuration({ - commandLineArguments: { - ...argv, - _: argv._ as [Command, ...string[]], // TypeScript at its best - }, - }); - await configuration.load(); - - const sdkProvider = await SdkProvider.withAwsCliCompatibleDefaults({ - profile: configuration.settings.get(['profile']), - ec2creds: argv.ec2creds, - httpOptions: { - proxyAddress: argv.proxy, - caBundlePath: argv['ca-bundle-path'], - }, - }); - - const cloudFormation = new CloudFormationDeployments({ sdkProvider }); - - const cloudExecutable = new CloudExecutable({ - configuration, - sdkProvider, - synthesizer: execProgram, - }); - - /** Function to load plug-ins, using configurations additively. */ - function loadPlugins(...settings: Settings[]) { - const loaded = new Set(); - for (const source of settings) { - const plugins: string[] = source.get(['plugin']) || []; - for (const plugin of plugins) { - const resolved = tryResolve(plugin); - if (loaded.has(resolved)) { continue; } - debug(`Loading plug-in: ${chalk.green(plugin)} from ${chalk.blue(resolved)}`); - PluginHost.instance.load(plugin); - loaded.add(resolved); - } - } - - function tryResolve(plugin: string): string { - try { - return require.resolve(plugin); - } catch (e) { - error(`Unable to resolve plugin ${chalk.green(plugin)}: ${e.stack}`); - throw new Error(`Unable to resolve plug-in: ${plugin}`); - } - } - } - - loadPlugins(configuration.settings); - - const cmd = argv._[0]; - - if (typeof(cmd) !== 'string') { - throw new Error(`First argument should be a string. Got: ${cmd} (${typeof(cmd)})`); - } - - // Bundle up global objects so the commands have access to them - const commandOptions = { args: argv, configuration, aws: sdkProvider }; - - try { - - let returnValue = undefined; - - switch (cmd) { - case 'context': - returnValue = await context(commandOptions); - break; - case 'docs': - returnValue = await docs(commandOptions); - break; - case 'doctor': - returnValue = await doctor(commandOptions); - break; - } - - if (returnValue === undefined) { - returnValue = await main(cmd, argv); - } - - if (typeof returnValue === 'object') { - return toJsonOrYaml(returnValue); - } else if (typeof returnValue === 'string') { - return returnValue; - } else { - return returnValue; - } - } finally { - await version.displayVersionMessage(); - } - - async function main(command: string, args: any): Promise { - const toolkitStackName: string = ToolkitInfo.determineName(configuration.settings.get(['toolkitStackName'])); - debug(`Toolkit stack: ${chalk.bold(toolkitStackName)}`); - - if (args.all && args.STACKS) { - throw new Error('You must either specify a list of Stacks or the `--all` argument'); - } - - args.STACKS = args.STACKS || []; - args.ENVIRONMENTS = args.ENVIRONMENTS || []; - - const selector: StackSelector = { - allTopLevel: args.all, - patterns: args.STACKS, - }; - - const cli = new CdkToolkit({ - cloudExecutable, - cloudFormation, - verbose: argv.trace || argv.verbose > 0, - ignoreErrors: argv['ignore-errors'], - strict: argv.strict, - configuration, - sdkProvider, - }); - - switch (command) { - case 'ls': - case 'list': - return cli.list(args.STACKS, { long: args.long }); - - case 'diff': - const enableDiffNoFail = isFeatureEnabled(configuration, cxapi.ENABLE_DIFF_NO_FAIL); - return cli.diff({ - stackNames: args.STACKS, - exclusively: args.exclusively, - templatePath: args.template, - strict: args.strict, - contextLines: args.contextLines, - securityOnly: args.securityOnly, - fail: args.fail || !enableDiffNoFail, - }); - - case 'bootstrap': - const source: BootstrapSource = determineBootsrapVersion(args, configuration); - - const bootstrapper = new Bootstrapper(source); - - if (args.showTemplate) { - return bootstrapper.showTemplate(); - } - - return cli.bootstrap(args.ENVIRONMENTS, bootstrapper, { - roleArn: args.roleArn, - force: argv.force, - toolkitStackName: toolkitStackName, - execute: args.execute, - tags: configuration.settings.get(['tags']), - terminationProtection: args.terminationProtection, - parameters: { - bucketName: configuration.settings.get(['toolkitBucket', 'bucketName']), - kmsKeyId: configuration.settings.get(['toolkitBucket', 'kmsKeyId']), - createCustomerMasterKey: args.bootstrapCustomerKey, - qualifier: args.qualifier, - publicAccessBlockConfiguration: args.publicAccessBlockConfiguration, - trustedAccounts: arrayFromYargs(args.trust), - trustedAccountsForLookup: arrayFromYargs(args.trustForLookup), - cloudFormationExecutionPolicies: arrayFromYargs(args.cloudformationExecutionPolicies), - }, - }); - - case 'deploy': - const parameterMap: { [name: string]: string | undefined } = {}; - for (const parameter of args.parameters) { - if (typeof parameter === 'string') { - const keyValue = (parameter as string).split('='); - parameterMap[keyValue[0]] = keyValue.slice(1).join('='); - } - } - return cli.deploy({ - selector, - exclusively: args.exclusively, - toolkitStackName, - roleArn: args.roleArn, - notificationArns: args.notificationArns, - requireApproval: configuration.settings.get(['requireApproval']), - reuseAssets: args['build-exclude'], - tags: configuration.settings.get(['tags']), - execute: args.execute, - changeSetName: args.changeSetName, - force: args.force, - parameters: parameterMap, - usePreviousParameters: args['previous-parameters'], - outputsFile: configuration.settings.get(['outputsFile']), - progress: configuration.settings.get(['progress']), - ci: args.ci, - rollback: configuration.settings.get(['rollback']), - hotswap: args.hotswap, - watch: args.watch, - traceLogs: args.logs, - }); - - case 'watch': - return cli.watch({ - selector, - // parameters: parameterMap, - // usePreviousParameters: args['previous-parameters'], - // outputsFile: configuration.settings.get(['outputsFile']), - // requireApproval: configuration.settings.get(['requireApproval']), - // notificationArns: args.notificationArns, - exclusively: args.exclusively, - toolkitStackName, - roleArn: args.roleArn, - reuseAssets: args['build-exclude'], - changeSetName: args.changeSetName, - force: args.force, - progress: configuration.settings.get(['progress']), - rollback: configuration.settings.get(['rollback']), - hotswap: args.hotswap, - traceLogs: args.logs, - }); - - case 'destroy': - return cli.destroy({ - selector, - exclusively: args.exclusively, - force: args.force, - roleArn: args.roleArn, - }); - - case 'synthesize': - case 'synth': - if (args.exclusively) { - return cli.synth(args.STACKS, args.exclusively, args.quiet, args.validation); - } else { - return cli.synth(args.STACKS, true, args.quiet, args.validation); - } - - - case 'metadata': - return cli.metadata(args.STACK); - - case 'init': - const language = configuration.settings.get(['language']); - if (args.list) { - return printAvailableTemplates(language); - } else { - return cliInit(args.TEMPLATE, language, undefined, args.generateOnly); - } - case 'version': - return data(version.DISPLAY_VERSION); - - default: - throw new Error('Unknown command: ' + command); - } - } - - function toJsonOrYaml(object: any): string { - return serializeStructure(object, argv.json); - } -} - -/** - * Determine which version of bootstrapping - * (legacy, or "new") should be used. - */ -function determineBootsrapVersion(args: { template?: string }, configuration: Configuration): BootstrapSource { - const isV1 = version.DISPLAY_VERSION.startsWith('1.'); - return isV1 ? determineV1BootstrapSource(args, configuration) : determineV2BootstrapSource(args); -} - -function determineV1BootstrapSource(args: { template?: string }, configuration: Configuration): BootstrapSource { - let source: BootstrapSource; - if (args.template) { - print(`Using bootstrapping template from ${args.template}`); - source = { source: 'custom', templateFile: args.template }; - } else if (process.env.CDK_NEW_BOOTSTRAP) { - print('CDK_NEW_BOOTSTRAP set, using new-style bootstrapping'); - source = { source: 'default' }; - } else if (isFeatureEnabled(configuration, cxapi.NEW_STYLE_STACK_SYNTHESIS_CONTEXT)) { - print(`'${cxapi.NEW_STYLE_STACK_SYNTHESIS_CONTEXT}' context set, using new-style bootstrapping`); - source = { source: 'default' }; - } else { - // in V1, the "legacy" bootstrapping is the default - source = { source: 'legacy' }; - } - return source; -} - -function determineV2BootstrapSource(args: { template?: string }): BootstrapSource { - let source: BootstrapSource; - if (args.template) { - print(`Using bootstrapping template from ${args.template}`); - source = { source: 'custom', templateFile: args.template }; - } else if (process.env.CDK_LEGACY_BOOTSTRAP) { - print('CDK_LEGACY_BOOTSTRAP set, using legacy-style bootstrapping'); - source = { source: 'legacy' }; - } else { - // in V2, the "new" bootstrapping is the default - source = { source: 'default' }; - } - return source; -} - -function isFeatureEnabled(configuration: Configuration, featureFlag: string) { - return configuration.context.get(featureFlag) ?? cxapi.futureFlagDefault(featureFlag); -} - -/** - * Translate a Yargs input array to something that makes more sense in a programming language - * model (telling the difference between absence and an empty array) - * - * - An empty array is the default case, meaning the user didn't pass any arguments. We return - * undefined. - * - If the user passed a single empty string, they did something like `--array=`, which we'll - * take to mean they passed an empty array. - */ -function arrayFromYargs(xs: string[]): string[] | undefined { - if (xs.length === 0) { return undefined; } - return xs.filter(x => x !== ''); -} - -function yargsNegativeAlias(shortName: S, longName: L) { - return (argv: T) => { - if (shortName in argv && argv[shortName]) { - (argv as any)[longName] = false; - } - return argv; - }; -} - -initCommandLine() - .then(value => { - if (value == null) { return; } - if (typeof value === 'string') { - data(value); - } else if (typeof value === 'number') { - process.exitCode = value; - } - }) - .catch(err => { - error(err.message); - if (err.stack) { - debug(err.stack); - } - process.exitCode = 1; - }); +cli(); diff --git a/packages/aws-cdk/lib/api/bootstrap/bootstrap-environment.ts b/packages/aws-cdk/lib/api/bootstrap/bootstrap-environment.ts index 7877368710c5f..a7b63214a3c80 100644 --- a/packages/aws-cdk/lib/api/bootstrap/bootstrap-environment.ts +++ b/packages/aws-cdk/lib/api/bootstrap/bootstrap-environment.ts @@ -3,6 +3,7 @@ import * as path from 'path'; import * as cxapi from '@aws-cdk/cx-api'; import { warning } from '../../logging'; import { loadStructuredFile, toYAML } from '../../serialize'; +import { rootDir } from '../../util/directories'; import { SdkProvider } from '../aws-auth'; import { DeployStackResult } from '../deploy-stack'; import { BootstrapEnvironmentOptions, BootstrappingParameters } from './bootstrap-props'; @@ -170,7 +171,7 @@ export class Bootstrapper { case 'custom': return loadStructuredFile(this.source.templateFile); case 'default': - return loadStructuredFile(path.join(__dirname, 'bootstrap-template.yaml')); + return loadStructuredFile(path.join(rootDir(), 'lib', 'api', 'bootstrap', 'bootstrap-template.yaml')); case 'legacy': return legacyBootstrapTemplate(params); } diff --git a/packages/aws-cdk/lib/api/cloudformation-deployments.ts b/packages/aws-cdk/lib/api/cloudformation-deployments.ts index 835d8f9ad3015..60b883f13fb40 100644 --- a/packages/aws-cdk/lib/api/cloudformation-deployments.ts +++ b/packages/aws-cdk/lib/api/cloudformation-deployments.ts @@ -1,13 +1,13 @@ -import * as path from 'path'; import * as cxapi from '@aws-cdk/cx-api'; import { AssetManifest } from 'cdk-assets'; -import * as fs from 'fs-extra'; import { Tag } from '../cdk-toolkit'; import { debug, warning } from '../logging'; import { publishAssets } from '../util/asset-publishing'; -import { Mode, SdkProvider, ISDK } from './aws-auth'; +import { Mode } from './aws-auth/credentials'; +import { ISDK } from './aws-auth/sdk'; +import { SdkProvider } from './aws-auth/sdk-provider'; import { deployStack, DeployStackResult, destroyStack } from './deploy-stack'; -import { LazyListStackResources, ListStackResources } from './evaluate-cloudformation-template'; +import { loadCurrentTemplateWithNestedStacks, loadCurrentTemplate } from './nested-stack-helpers'; import { ToolkitInfo } from './toolkit-info'; import { CloudFormationStack, Template } from './util/cloudformation'; import { StackActivityProgress } from './util/cloudformation/stack-activity-monitor'; @@ -281,21 +281,13 @@ export class CloudFormationDeployments { public async readCurrentTemplateWithNestedStacks(rootStackArtifact: cxapi.CloudFormationStackArtifact): Promise