diff --git a/CHANGELOG.v2.alpha.md b/CHANGELOG.v2.alpha.md index afc9d44d8dfaa..06f4c22fb8660 100644 --- a/CHANGELOG.v2.alpha.md +++ b/CHANGELOG.v2.alpha.md @@ -2,6 +2,8 @@ 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. +## [2.116.1-alpha.0](https://github.com/aws/aws-cdk/compare/v2.116.0-alpha.0...v2.116.1-alpha.0) (2023-12-22) + ## [2.116.0-alpha.0](https://github.com/aws/aws-cdk/compare/v2.115.0-alpha.0...v2.116.0-alpha.0) (2023-12-21) diff --git a/CHANGELOG.v2.md b/CHANGELOG.v2.md index 455f61f07757b..d73963e702114 100644 --- a/CHANGELOG.v2.md +++ b/CHANGELOG.v2.md @@ -2,6 +2,13 @@ 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. +## [2.116.1](https://github.com/aws/aws-cdk/compare/v2.116.0...v2.116.1) (2023-12-22) + + +### Bug Fixes + +* **core:** core constructs fail with `Error: Cannot find module '../dist/core/.generated'` ([#28467](https://github.com/aws/aws-cdk/issues/28467)) ([e8be128](https://github.com/aws/aws-cdk/commit/e8be12836cdb73b74cd36e19e5cec52258304933)), closes [#28251](https://github.com/aws/aws-cdk/issues/28251) [#28465](https://github.com/aws/aws-cdk/issues/28465) + ## [2.116.0](https://github.com/aws/aws-cdk/compare/v2.115.0...v2.116.0) (2023-12-21) diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/http/integ.api.js.snapshot/aws-cdk-aws-apigatewayv2.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/http/integ.api.js.snapshot/aws-cdk-aws-apigatewayv2.assets.json new file mode 100644 index 0000000000000..2a97a56ed3ab4 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/http/integ.api.js.snapshot/aws-cdk-aws-apigatewayv2.assets.json @@ -0,0 +1,19 @@ +{ + "version": "35.0.0", + "files": { + "f753b6c52b805082d600dd33b6be3b816c0954f254acf84347e2447774db5100": { + "source": { + "path": "aws-cdk-aws-apigatewayv2.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "f753b6c52b805082d600dd33b6be3b816c0954f254acf84347e2447774db5100.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/http/integ.api.js.snapshot/aws-cdk-aws-apigatewayv2.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/http/integ.api.js.snapshot/aws-cdk-aws-apigatewayv2.template.json new file mode 100644 index 0000000000000..36bd57da384f9 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/http/integ.api.js.snapshot/aws-cdk-aws-apigatewayv2.template.json @@ -0,0 +1,55 @@ +{ + "Resources": { + "HttpApiF5A9A8A7": { + "Type": "AWS::ApiGatewayV2::Api", + "Properties": { + "Name": "HttpApi", + "ProtocolType": "HTTP" + } + }, + "HttpApiDefaultStage3EEB07D6": { + "Type": "AWS::ApiGatewayV2::Stage", + "Properties": { + "ApiId": { + "Ref": "HttpApiF5A9A8A7" + }, + "AutoDeploy": true, + "StageName": "$default" + } + } + }, + "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-testing/framework-integ/test/aws-apigatewayv2/test/http/integ.api.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/http/integ.api.js.snapshot/cdk.out new file mode 100644 index 0000000000000..c5cb2e5de6344 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/http/integ.api.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"35.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/http/integ.api.js.snapshot/httpapiDefaultTestDeployAssert77633A40.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/http/integ.api.js.snapshot/httpapiDefaultTestDeployAssert77633A40.assets.json new file mode 100644 index 0000000000000..1b6f704767526 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/http/integ.api.js.snapshot/httpapiDefaultTestDeployAssert77633A40.assets.json @@ -0,0 +1,19 @@ +{ + "version": "35.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "httpapiDefaultTestDeployAssert77633A40.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/http/integ.api.js.snapshot/httpapiDefaultTestDeployAssert77633A40.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/http/integ.api.js.snapshot/httpapiDefaultTestDeployAssert77633A40.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/http/integ.api.js.snapshot/httpapiDefaultTestDeployAssert77633A40.template.json @@ -0,0 +1,36 @@ +{ + "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-testing/framework-integ/test/aws-apigatewayv2/test/http/integ.api.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/http/integ.api.js.snapshot/integ.json new file mode 100644 index 0000000000000..1b3ad22cef14a --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/http/integ.api.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "35.0.0", + "testCases": { + "http-api/DefaultTest": { + "stacks": [ + "aws-cdk-aws-apigatewayv2" + ], + "assertionStack": "http-api/DefaultTest/DeployAssert", + "assertionStackName": "httpapiDefaultTestDeployAssert77633A40" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/http/integ.api.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/http/integ.api.js.snapshot/manifest.json new file mode 100644 index 0000000000000..91e40a0cbe7bb --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/http/integ.api.js.snapshot/manifest.json @@ -0,0 +1,119 @@ +{ + "version": "35.0.0", + "artifacts": { + "aws-cdk-aws-apigatewayv2.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-cdk-aws-apigatewayv2.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-cdk-aws-apigatewayv2": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-cdk-aws-apigatewayv2.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/f753b6c52b805082d600dd33b6be3b816c0954f254acf84347e2447774db5100.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-cdk-aws-apigatewayv2.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "aws-cdk-aws-apigatewayv2.assets" + ], + "metadata": { + "/aws-cdk-aws-apigatewayv2/HttpApi/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "HttpApiF5A9A8A7" + } + ], + "/aws-cdk-aws-apigatewayv2/HttpApi/DefaultStage/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "HttpApiDefaultStage3EEB07D6" + } + ], + "/aws-cdk-aws-apigatewayv2/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-aws-apigatewayv2/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-cdk-aws-apigatewayv2" + }, + "httpapiDefaultTestDeployAssert77633A40.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "httpapiDefaultTestDeployAssert77633A40.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "httpapiDefaultTestDeployAssert77633A40": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "httpapiDefaultTestDeployAssert77633A40.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "httpapiDefaultTestDeployAssert77633A40.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "httpapiDefaultTestDeployAssert77633A40.assets" + ], + "metadata": { + "/http-api/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/http-api/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "http-api/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/http/integ.api.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/http/integ.api.js.snapshot/tree.json new file mode 100644 index 0000000000000..d17481862eddf --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/http/integ.api.js.snapshot/tree.json @@ -0,0 +1,154 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "aws-cdk-aws-apigatewayv2": { + "id": "aws-cdk-aws-apigatewayv2", + "path": "aws-cdk-aws-apigatewayv2", + "children": { + "HttpApi": { + "id": "HttpApi", + "path": "aws-cdk-aws-apigatewayv2/HttpApi", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-aws-apigatewayv2/HttpApi/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ApiGatewayV2::Api", + "aws:cdk:cloudformation:props": { + "name": "HttpApi", + "protocolType": "HTTP" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_apigatewayv2.CfnApi", + "version": "0.0.0" + } + }, + "DefaultStage": { + "id": "DefaultStage", + "path": "aws-cdk-aws-apigatewayv2/HttpApi/DefaultStage", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-aws-apigatewayv2/HttpApi/DefaultStage/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ApiGatewayV2::Stage", + "aws:cdk:cloudformation:props": { + "apiId": { + "Ref": "HttpApiF5A9A8A7" + }, + "autoDeploy": true, + "stageName": "$default" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_apigatewayv2.CfnStage", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_apigatewayv2.HttpStage", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_apigatewayv2.HttpApi", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-aws-apigatewayv2/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-aws-apigatewayv2/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "http-api": { + "id": "http-api", + "path": "http-api", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "http-api/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "http-api/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "http-api/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "http-api/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "http-api/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/http/integ.api.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/http/integ.api.ts new file mode 100644 index 0000000000000..dac08621b9906 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/http/integ.api.ts @@ -0,0 +1,14 @@ +#!/usr/bin/env node +import { IntegTest } from '@aws-cdk/integ-tests-alpha'; +import * as cdk from 'aws-cdk-lib'; +import * as apigw from 'aws-cdk-lib/aws-apigatewayv2'; + +const app = new cdk.App(); +const stack = new cdk.Stack(app, 'aws-cdk-aws-apigatewayv2'); + +new apigw.HttpApi(stack, 'HttpApi'); + +new IntegTest(app, 'http-api', { + testCases: [stack], +}); + diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/websocket/integ.api.js.snapshot/aws-cdk-aws-apigatewayv2.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/websocket/integ.api.js.snapshot/aws-cdk-aws-apigatewayv2.assets.json new file mode 100644 index 0000000000000..57cb00af71146 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/websocket/integ.api.js.snapshot/aws-cdk-aws-apigatewayv2.assets.json @@ -0,0 +1,19 @@ +{ + "version": "35.0.0", + "files": { + "21500b34598d560b1f62ae0eb2fab8201e073b18c3d28b7d69eefbfdb686d481": { + "source": { + "path": "aws-cdk-aws-apigatewayv2.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21500b34598d560b1f62ae0eb2fab8201e073b18c3d28b7d69eefbfdb686d481.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/websocket/integ.api.js.snapshot/aws-cdk-aws-apigatewayv2.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/websocket/integ.api.js.snapshot/aws-cdk-aws-apigatewayv2.template.json new file mode 100644 index 0000000000000..f01269f88b4d5 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/websocket/integ.api.js.snapshot/aws-cdk-aws-apigatewayv2.template.json @@ -0,0 +1,46 @@ +{ + "Resources": { + "WebSocketApi34BCF99B": { + "Type": "AWS::ApiGatewayV2::Api", + "Properties": { + "Name": "WebSocketApi", + "ProtocolType": "WEBSOCKET", + "RouteSelectionExpression": "$request.body.action" + } + } + }, + "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-testing/framework-integ/test/aws-apigatewayv2/test/websocket/integ.api.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/websocket/integ.api.js.snapshot/cdk.out new file mode 100644 index 0000000000000..c5cb2e5de6344 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/websocket/integ.api.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"35.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/websocket/integ.api.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/websocket/integ.api.js.snapshot/integ.json new file mode 100644 index 0000000000000..929aef5464bc2 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/websocket/integ.api.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "35.0.0", + "testCases": { + "web-socket-api/DefaultTest": { + "stacks": [ + "aws-cdk-aws-apigatewayv2" + ], + "assertionStack": "web-socket-api/DefaultTest/DeployAssert", + "assertionStackName": "websocketapiDefaultTestDeployAssert230DE1C6" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/websocket/integ.api.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/websocket/integ.api.js.snapshot/manifest.json new file mode 100644 index 0000000000000..c3977ff8c048b --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/websocket/integ.api.js.snapshot/manifest.json @@ -0,0 +1,113 @@ +{ + "version": "35.0.0", + "artifacts": { + "aws-cdk-aws-apigatewayv2.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-cdk-aws-apigatewayv2.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-cdk-aws-apigatewayv2": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-cdk-aws-apigatewayv2.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21500b34598d560b1f62ae0eb2fab8201e073b18c3d28b7d69eefbfdb686d481.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-cdk-aws-apigatewayv2.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "aws-cdk-aws-apigatewayv2.assets" + ], + "metadata": { + "/aws-cdk-aws-apigatewayv2/WebSocketApi/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "WebSocketApi34BCF99B" + } + ], + "/aws-cdk-aws-apigatewayv2/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-aws-apigatewayv2/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-cdk-aws-apigatewayv2" + }, + "websocketapiDefaultTestDeployAssert230DE1C6.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "websocketapiDefaultTestDeployAssert230DE1C6.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "websocketapiDefaultTestDeployAssert230DE1C6": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "websocketapiDefaultTestDeployAssert230DE1C6.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "websocketapiDefaultTestDeployAssert230DE1C6.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "websocketapiDefaultTestDeployAssert230DE1C6.assets" + ], + "metadata": { + "/web-socket-api/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/web-socket-api/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "web-socket-api/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/websocket/integ.api.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/websocket/integ.api.js.snapshot/tree.json new file mode 100644 index 0000000000000..96a63513767f1 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/websocket/integ.api.js.snapshot/tree.json @@ -0,0 +1,127 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "aws-cdk-aws-apigatewayv2": { + "id": "aws-cdk-aws-apigatewayv2", + "path": "aws-cdk-aws-apigatewayv2", + "children": { + "WebSocketApi": { + "id": "WebSocketApi", + "path": "aws-cdk-aws-apigatewayv2/WebSocketApi", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-aws-apigatewayv2/WebSocketApi/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ApiGatewayV2::Api", + "aws:cdk:cloudformation:props": { + "name": "WebSocketApi", + "protocolType": "WEBSOCKET", + "routeSelectionExpression": "$request.body.action" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_apigatewayv2.CfnApi", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_apigatewayv2.WebSocketApi", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-aws-apigatewayv2/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-aws-apigatewayv2/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "web-socket-api": { + "id": "web-socket-api", + "path": "web-socket-api", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "web-socket-api/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "web-socket-api/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "web-socket-api/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "web-socket-api/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "web-socket-api/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/websocket/integ.api.js.snapshot/websocketapiDefaultTestDeployAssert230DE1C6.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/websocket/integ.api.js.snapshot/websocketapiDefaultTestDeployAssert230DE1C6.assets.json new file mode 100644 index 0000000000000..a441519e712ae --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/websocket/integ.api.js.snapshot/websocketapiDefaultTestDeployAssert230DE1C6.assets.json @@ -0,0 +1,19 @@ +{ + "version": "35.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "websocketapiDefaultTestDeployAssert230DE1C6.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/websocket/integ.api.js.snapshot/websocketapiDefaultTestDeployAssert230DE1C6.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/websocket/integ.api.js.snapshot/websocketapiDefaultTestDeployAssert230DE1C6.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/websocket/integ.api.js.snapshot/websocketapiDefaultTestDeployAssert230DE1C6.template.json @@ -0,0 +1,36 @@ +{ + "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-testing/framework-integ/test/aws-apigatewayv2/test/websocket/integ.api.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/websocket/integ.api.ts new file mode 100644 index 0000000000000..83fc1e845168d --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2/test/websocket/integ.api.ts @@ -0,0 +1,14 @@ +#!/usr/bin/env node +import { IntegTest } from '@aws-cdk/integ-tests-alpha'; +import * as cdk from 'aws-cdk-lib'; +import * as apigw from 'aws-cdk-lib/aws-apigatewayv2'; + +const app = new cdk.App(); +const stack = new cdk.Stack(app, 'aws-cdk-aws-apigatewayv2'); + +new apigw.WebSocketApi(stack, 'WebSocketApi'); + +new IntegTest(app, 'web-socket-api', { + testCases: [stack], +}); + diff --git a/packages/aws-cdk-lib/.npmignore b/packages/aws-cdk-lib/.npmignore index 60e48f52cdd0f..04bd4687b89d0 100644 --- a/packages/aws-cdk-lib/.npmignore +++ b/packages/aws-cdk-lib/.npmignore @@ -16,6 +16,7 @@ coverage build-tools dist !custom-resource-handlers/dist/ +!core/lib/dist/ scripts .LAST_BUILD .LAST_PACKAGE @@ -30,9 +31,11 @@ tsconfig.json # exclude cdk artifacts **/cdk.out junit.xml - !*.lit.ts +# exclude additional documention +core/adr/ + # keep class map for cloudformation-include !cloudformation-include/cfn-types-2-classes.json diff --git a/packages/aws-cdk-lib/aws-apigatewayv2/README.md b/packages/aws-cdk-lib/aws-apigatewayv2/README.md index dcf5e9c0b40fc..e5604dafebf1a 100644 --- a/packages/aws-cdk-lib/aws-apigatewayv2/README.md +++ b/packages/aws-cdk-lib/aws-apigatewayv2/README.md @@ -13,6 +13,7 @@ - [Metrics](#metrics) - [VPC Link](#vpc-link) - [Private Integration](#private-integration) + - [Generating ARN for Execute API](#generating-arn-for-execute-api) - [WebSocket API](#websocket-api) - [Manage Connections Permission](#manage-connections-permission) - [Managing access to WebSocket APIs](#managing-access-to-websocket-apis) @@ -325,6 +326,19 @@ clients outside of the VPC. These integrations can be found in the [aws-apigatewayv2-integrations](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_apigatewayv2_integrations-readme.html) constructs library. +### Generating ARN for Execute API + +The arnForExecuteApi function in AWS CDK is designed to generate Amazon Resource Names (ARNs) for Execute API operations. This is particularly useful when you need to create ARNs dynamically based on different parameters like HTTP method, API path, and stage. + +```ts +const api = new apigwv2.HttpApi(this, 'my-api'); +const arn = api.arnForExecuteApi('GET', '/myApiPath', 'dev'); +``` + +- Ensure that the path parameter, if provided, starts with '/'. +- The 'ANY' method can be used for matching any HTTP methods not explicitly defined. +- The function gracefully handles undefined parameters by using wildcards, making it flexible for various API configurations. + ## WebSocket API A WebSocket API in API Gateway is a collection of WebSocket routes that are integrated with backend HTTP endpoints, @@ -405,6 +419,16 @@ To import an existing WebSocketApi: const webSocketApi = apigwv2.WebSocketApi.fromWebSocketApiAttributes(this, 'mywsapi', { webSocketId: 'api-1234' }); ``` +To generate an ARN for Execute API: + +```ts +const api = new apigwv2.WebSocketApi(this, 'mywsapi'); +const arn = api.arnForExecuteApi('GET', '/myApiPath', 'dev'); +``` + +For a detailed explanation of this function, including usage and examples, please refer to the [Generating ARN for Execute API](#generating-arn-for-execute-api) section under HTTP API. + + ### 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-lib/aws-apigatewayv2/lib/http/api.ts b/packages/aws-cdk-lib/aws-apigatewayv2/lib/http/api.ts index a9a605ec917b6..877c853be7dbf 100644 --- a/packages/aws-cdk-lib/aws-apigatewayv2/lib/http/api.ts +++ b/packages/aws-cdk-lib/aws-apigatewayv2/lib/http/api.ts @@ -6,7 +6,7 @@ import { IHttpStage, HttpStage, HttpStageOptions } from './stage'; import { VpcLink, VpcLinkProps } from './vpc-link'; import { CfnApi, CfnApiProps } from '.././index'; import { Metric, MetricOptions } from '../../../aws-cloudwatch'; -import { Duration } from '../../../core'; +import { ArnFormat, Duration, Stack, Token } from '../../../core'; import { IApi } from '../common/api'; import { ApiBase } from '../common/base'; import { DomainMappingOptions } from '../common/stage'; @@ -81,6 +81,18 @@ export interface IHttpApi extends IApi { * Add a new VpcLink */ addVpcLink(options: VpcLinkProps): VpcLink + + /** + * Get the "execute-api" ARN. + * When 'ANY' is passed to the method, an ARN with the method set to '*' is obtained. + * + * @default - The default behavior applies when no specific method, path, or stage is provided. + * In this case, the ARN will cover all methods, all resources, and all stages of this API. + * Specifically, if 'method' is not specified, it defaults to '*', representing all methods. + * If 'path' is not specified, it defaults to '/*', representing all paths. + * If 'stage' is not specified, it also defaults to '*', representing all stages. + */ + arnForExecuteApi(method?: string, path?: string, stage?: string): string; } /** @@ -291,6 +303,23 @@ abstract class HttpApiBase extends ApiBase implements IHttpApi { // note that th return vpcLink; } + + public arnForExecuteApi(method?: string, path?: string, stage?: string): string { + if (path && !Token.isUnresolved(path) && !path.startsWith('/')) { + throw new Error(`Path must start with '/': ${path}`); + } + + if (method && method.toUpperCase() === 'ANY') { + method = '*'; + } + + return Stack.of(this).formatArn({ + service: 'execute-api', + resource: this.httpApiId, + arnFormat: ArnFormat.SLASH_RESOURCE_NAME, + resourceName: `${stage ?? '*'}/${method ?? '*'}${path ?? '/*'}`, + }); + } } /** diff --git a/packages/aws-cdk-lib/aws-apigatewayv2/lib/websocket/api.ts b/packages/aws-cdk-lib/aws-apigatewayv2/lib/websocket/api.ts index c8e27c97e3fdf..9c1ed6d821c1a 100644 --- a/packages/aws-cdk-lib/aws-apigatewayv2/lib/websocket/api.ts +++ b/packages/aws-cdk-lib/aws-apigatewayv2/lib/websocket/api.ts @@ -2,7 +2,7 @@ import { Construct } from 'constructs'; import { WebSocketRoute, WebSocketRouteOptions } from './route'; import { CfnApi } from '.././index'; import { Grant, IGrantable } from '../../../aws-iam'; -import { Stack } from '../../../core'; +import { ArnFormat, Stack, Token } from '../../../core'; import { IApi } from '../common/api'; import { ApiBase } from '../common/base'; @@ -188,4 +188,31 @@ export class WebSocketApi extends ApiBase implements IWebSocketApi { resourceArns: [`${arn}/*/*/@connections/*`], }); } + + /** + * Get the "execute-api" ARN. + * When 'ANY' is passed to the method, an ARN with the method set to '*' is obtained. + * + * @default - The default behavior applies when no specific method, path, or stage is provided. + * In this case, the ARN will cover all methods, all resources, and all stages of this API. + * Specifically, if 'method' is not specified, it defaults to '*', representing all methods. + * If 'path' is not specified, it defaults to '/*', representing all paths. + * If 'stage' is not specified, it also defaults to '*', representing all stages. + */ + public arnForExecuteApi(method?: string, path?: string, stage?: string): string { + if (path && !Token.isUnresolved(path) && !path.startsWith('/')) { + throw new Error(`Path must start with '/': ${path}`); + } + + if (method && method.toUpperCase() === 'ANY') { + method = '*'; + } + + return Stack.of(this).formatArn({ + service: 'execute-api', + resource: this.apiId, + arnFormat: ArnFormat.SLASH_RESOURCE_NAME, + resourceName: `${stage ?? '*'}/${method ?? '*'}${path ?? '/*'}`, + }); + } } diff --git a/packages/aws-cdk-lib/aws-apigatewayv2/test/http/api.test.ts b/packages/aws-cdk-lib/aws-apigatewayv2/test/http/api.test.ts index 1affa4b47566b..e703dbd9d7d56 100644 --- a/packages/aws-cdk-lib/aws-apigatewayv2/test/http/api.test.ts +++ b/packages/aws-cdk-lib/aws-apigatewayv2/test/http/api.test.ts @@ -528,6 +528,71 @@ describe('HttpApi', () => { }); }); }); + + test('get arnForExecuteApi', () => { + const stack = new Stack(); + const api = new HttpApi(stack, 'api'); + + expect(stack.resolve(api.arnForExecuteApi('method', '/path', 'stage'))).toEqual({ + 'Fn::Join': ['', [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':execute-api:', + { Ref: 'AWS::Region' }, + ':', + { Ref: 'AWS::AccountId' }, + ':', + stack.resolve(api.apiId), + '/stage/method/path', + ]], + }); + }); + + test('get arnForExecuteApi with default values', () => { + const stack = new Stack(); + const api = new HttpApi(stack, 'api'); + + expect(stack.resolve(api.arnForExecuteApi())).toEqual({ + 'Fn::Join': ['', [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':execute-api:', + { Ref: 'AWS::Region' }, + ':', + { Ref: 'AWS::AccountId' }, + ':', + stack.resolve(api.apiId), + '/*/*/*', + ]], + }); + }); + + test('get arnForExecuteApi with ANY method', () => { + const stack = new Stack(); + const api = new HttpApi(stack, 'api'); + + expect(stack.resolve(api.arnForExecuteApi('ANY', '/path', 'stage'))).toEqual({ + 'Fn::Join': ['', [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':execute-api:', + { Ref: 'AWS::Region' }, + ':', + { Ref: 'AWS::AccountId' }, + ':', + stack.resolve(api.apiId), + '/stage/*/path', + ]], + }); + }); + + test('throws when call arnForExecuteApi method with specifing a string that does not start with / for the path argument.', () => { + const stack = new Stack(); + const api = new HttpApi(stack, 'api'); + + expect(() => api.arnForExecuteApi('method', 'path', 'stage')) + .toThrow("Path must start with '/': path"); + }); }); class DummyRouteIntegration extends HttpRouteIntegration { diff --git a/packages/aws-cdk-lib/aws-apigatewayv2/test/websocket/api.test.ts b/packages/aws-cdk-lib/aws-apigatewayv2/test/websocket/api.test.ts index 91b4ad90e6a3b..8abe6d44c1340 100644 --- a/packages/aws-cdk-lib/aws-apigatewayv2/test/websocket/api.test.ts +++ b/packages/aws-cdk-lib/aws-apigatewayv2/test/websocket/api.test.ts @@ -148,6 +148,71 @@ describe('WebSocketApi', () => { expect(() => api.apiEndpoint).toThrow(/apiEndpoint is not configured/); }); + test('get arnForExecuteApi', () => { + const stack = new Stack(); + const api = new WebSocketApi(stack, 'api'); + + expect(stack.resolve(api.arnForExecuteApi('method', '/path', 'stage'))).toEqual({ + 'Fn::Join': ['', [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':execute-api:', + { Ref: 'AWS::Region' }, + ':', + { Ref: 'AWS::AccountId' }, + ':', + stack.resolve(api.apiId), + '/stage/method/path', + ]], + }); + }); + + test('get arnForExecuteApi with default values', () => { + const stack = new Stack(); + const api = new WebSocketApi(stack, 'api'); + + expect(stack.resolve(api.arnForExecuteApi())).toEqual({ + 'Fn::Join': ['', [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':execute-api:', + { Ref: 'AWS::Region' }, + ':', + { Ref: 'AWS::AccountId' }, + ':', + stack.resolve(api.apiId), + '/*/*/*', + ]], + }); + }); + + test('get arnForExecuteApi with ANY method', () => { + const stack = new Stack(); + const api = new WebSocketApi(stack, 'api'); + + expect(stack.resolve(api.arnForExecuteApi('ANY', '/path', 'stage'))).toEqual({ + 'Fn::Join': ['', [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':execute-api:', + { Ref: 'AWS::Region' }, + ':', + { Ref: 'AWS::AccountId' }, + ':', + stack.resolve(api.apiId), + '/stage/*/path', + ]], + }); + }); + + test('throws when call arnForExecuteApi method with specifing a string that does not start with / for the path argument.', () => { + const stack = new Stack(); + const api = new WebSocketApi(stack, 'api'); + + expect(() => api.arnForExecuteApi('method', 'path', 'stage')) + .toThrow("Path must start with '/': path"); + }); + describe('grantManageConnections', () => { test('adds an IAM policy to the principal', () => { // GIVEN diff --git a/packages/aws-cdk-lib/aws-ecs/README.md b/packages/aws-cdk-lib/aws-ecs/README.md index 399ee801cd348..134101df92cd8 100644 --- a/packages/aws-cdk-lib/aws-ecs/README.md +++ b/packages/aws-cdk-lib/aws-ecs/README.md @@ -186,6 +186,22 @@ const capacityProvider = new ecs.AsgCapacityProvider(this, 'AsgCapacityProvider' cluster.addAsgCapacityProvider(capacityProvider); ``` +The following code retrieve the Amazon Resource Names (ARNs) of tasks that are a part of a specified ECS cluster. +It's useful when you want to grant permissions to a task to access other AWS resources. + +```ts +declare const cluster: ecs.Cluster; +declare const taskDefinition: ecs.TaskDefinition; +const taskARNs = cluster.arnForTasks('*'); // arn:aws:ecs:::task//* + +// Grant the task permission to access other AWS resources +taskDefinition.addToTaskRolePolicy( + new iam.PolicyStatement({ + actions: ['ecs:UpdateTaskProtection'], + resources: [taskARNs], + }) +) +``` ### Bottlerocket @@ -1600,4 +1616,4 @@ taskDefinition.addContainer('TheContainer', { softLimit: 128, }], }); -``` +``` \ No newline at end of file diff --git a/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts b/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts index f113c95e24ac7..cf469007614b5 100644 --- a/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts +++ b/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts @@ -583,6 +583,21 @@ export class Cluster extends Resource implements ICluster { } } + /** + * Returns an ARN that represents all tasks within the cluster that match + * the task pattern specified. To represent all tasks, specify ``"*"``. + * + * @param keyPattern Task id pattern + */ + public arnForTasks(keyPattern: string): string { + return Stack.of(this).formatArn({ + service: 'ecs', + resource: 'task', + resourceName: `${this.clusterName}/${keyPattern}`, + arnFormat: ArnFormat.SLASH_RESOURCE_NAME, + }); + } + private configureWindowsAutoScalingGroup(autoScalingGroup: autoscaling.AutoScalingGroup, options: AddAutoScalingGroupCapacityOptions = {}) { // clear the cache of the agent autoScalingGroup.addUserData('Remove-Item -Recurse C:\\ProgramData\\Amazon\\ECS\\Cache'); diff --git a/packages/aws-cdk-lib/aws-ecs/test/cluster.test.ts b/packages/aws-cdk-lib/aws-ecs/test/cluster.test.ts index b9dc6b9150447..aae6da1bad290 100644 --- a/packages/aws-cdk-lib/aws-ecs/test/cluster.test.ts +++ b/packages/aws-cdk-lib/aws-ecs/test/cluster.test.ts @@ -2,6 +2,7 @@ import { testDeprecated } from '@aws-cdk/cdk-build-tools'; import { Match, Template } from '../../assertions'; import * as autoscaling from '../../aws-autoscaling'; import * as ec2 from '../../aws-ec2'; +import * as iam from '../../aws-iam'; import * as kms from '../../aws-kms'; import * as logs from '../../aws-logs'; import * as s3 from '../../aws-s3'; @@ -1084,6 +1085,44 @@ describe('cluster', () => { expect(cluster.defaultCloudMapNamespace!.namespaceName).toBe('foo'); }); + test('arnForTasks returns a task arn from key pattern', () => { + // GIVEN + const stack = new cdk.Stack(); + const vpc = new ec2.Vpc(stack, 'MyVpc', {}); + const cluster = new ecs.Cluster(stack, 'EcsCluster', { vpc }); + const taskIdPattern = '*'; + + // WHEN + const policyStatement = new iam.PolicyStatement({ + resources: [cluster.arnForTasks(taskIdPattern)], + actions: ['ecs:RunTask'], + principals: [new iam.ServicePrincipal('ecs.amazonaws.com')], + }); + + // THEN + expect(stack.resolve(policyStatement.toStatementJson())).toEqual({ + Action: 'ecs:RunTask', + Effect: 'Allow', + Principal: { Service: 'ecs.amazonaws.com' }, + Resource: { + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':ecs:', + { Ref: 'AWS::Region' }, + ':', + { Ref: 'AWS::AccountId' }, + ':task/', + { Ref: 'EcsCluster97242B84' }, + `/${taskIdPattern}`, + ], + ], + }, + }); + }); + /* * TODO:v2.0.0 END OF OBSOLETE BLOCK */ diff --git a/packages/aws-cdk-lib/core/lib/adr/acknowledge-warnings.md b/packages/aws-cdk-lib/core/adr/acknowledge-warnings.md similarity index 100% rename from packages/aws-cdk-lib/core/lib/adr/acknowledge-warnings.md rename to packages/aws-cdk-lib/core/adr/acknowledge-warnings.md diff --git a/version.v2.json b/version.v2.json index fc6404509b98e..036be73a62de9 100644 --- a/version.v2.json +++ b/version.v2.json @@ -1,4 +1,4 @@ { - "version": "2.116.0", - "alphaVersion": "2.116.0-alpha.0" + "version": "2.116.1", + "alphaVersion": "2.116.1-alpha.0" } \ No newline at end of file